Logging Framework
Prompt
"Design a logging library for a server. Code calls something like log.info('...'); the library decides whether to keep it and where it goes: console, a file, maybe a remote collector. Show me the classes and the path a message takes."
Clarifying questions
- What levels? DEBUG, INFO, WARN, ERROR. A message is emitted if its level is at or above the logger's threshold.
- Are loggers named and hierarchical? Yes:
app.db.poolinherits configuration fromapp.dbandappunless overridden, the way most production libraries work. - Can one message go to several destinations? Yes. Each logger can have multiple handlers, and a message propagates to ancestor loggers' handlers too.
- Synchronous or asynchronous writes? Both must be possible. The interviewer will ask what happens when the file system stalls.
- Formatting? Pluggable; a default line format with timestamp, level, logger name, message.
- Structured fields? Key-value pairs attached to a record are a follow-up. Design the record so they fit.
- Thread safety? Required; many request threads log concurrently.
Requirements
Functional
- Named loggers with level thresholds inherited from ancestors.
- Handlers attached to loggers; a record flows to the logger's handlers and up the ancestor chain.
- Filters on handlers to drop records selectively.
- Formatters to turn a record into a string.
- An asynchronous handler that decouples callers from slow sinks.
Non-functional
- A disabled level (
debugwhen the threshold is INFO) must cost almost nothing: no record allocation, no string formatting. - Emitting a record must not block the caller on I/O when the async handler is used, and must not lose records silently under normal operation.
- Ordering within one thread must be preserved.
- Clean shutdown flushes pending records.
Numbers
- A busy server: 2,000 requests per second x 5 log calls each = 10^4 calls per second, of which 90% are DEBUG and disabled. A disabled call at 100 ns is 1 ms per second total; at 5 microseconds (allocating and formatting) it is 50 ms per second, 5% of a core. That is the argument for the early level check.
- Enabled records: 10^3 per second x 200 bytes = 200 KB per second to disk. Trivial for a file, not trivial for a remote collector with 50 ms round trips, which is the argument for batching in the async handler.
Last reviewed 8 September 2026
Class design · Core interfaces · Deep dives · Failure modes & follow-ups · Extensibility · Level rubric · Company variations
The rest of this question — the worked approach, the design walkthrough, complexity, follow-ups and how each company frames it — is part of the guides.
Get the full guide
Pick the company you're interviewing with. Each guide has every question tiered for that loop — one-time purchase, lifetime access.
Also in: Apple, Google, Meta, Microsoft, Netflix
Interviewing at more than one? All 6 guides for $499 · save $395
Not ready to buy? Get the free starter pack — 13 questions with full solutions.