Design a Logger That Runs Each Message Through an Ordered List of Handlers

Read the full interview experience this question came from →

Quick Overview

Design a small object-oriented logging library in which a Logger passes every message through an ordered list of handlers, including one that truncates messages and one that stores them in memory instead of printing. It tests interface design, handler ordering, extensibility and testability.

Design a Logger That Runs Each Message Through an Ordered List of Handlers

Company: Oracle

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: easy

Interview Round: Onsite

Design a small logging library in an object-oriented way. A `Logger` is created with a list of handlers, and every message passed to `log` must go through all of the handlers. Implement two handlers: - `TruncateHandler`: shortens the message. - `StoreHandler`: saves the message into an internal list instead of printing it. The skeleton and the test provided: ```python class Logger: def __init__(self, handlers): # a list of handlers ... def log(self, message): # message should go through all handlers ... class TruncateHandler: ... class StoreHandler: # save the message into an internal list instead of printing ... # test logger = Logger([TruncateHandler(), StoreHandler()]) logger.log('abc') ``` The code does not need to run. The focus is the class design, the contract between the logger and its handlers, and how you would test it. ```hint Fix the contract first `Logger` should work with any handler without knowing its concrete type. Decide the single method every handler exposes, and what it hands back to the logger. ``` ```hint Let the order matter on purpose The test lists `TruncateHandler` before `StoreHandler`. Ask yourself what the stored list should contain if the two were swapped. ``` ### Clarifying Questions - Does each handler receive the output of the previous handler (a pipeline), or does every handler receive the original message? - What length does `TruncateHandler` cut to? The test constructs it without arguments, so what should the default be, and should a truncated message carry a marker such as an ellipsis? - "Instead of printing" suggests that other handlers print. Is a printing handler part of the expected design? - Can a handler stop a message from reaching the handlers after it? - How should a test read what `StoreHandler` has saved? ### What a Strong Answer Covers - A handler abstraction with one method, so `Logger` depends only on that contract and new handlers need no change to `Logger`. - Explicit ordering semantics: handlers run in list order, and it is stated whether each one sees the previous handler's output. - A `TruncateHandler` with a configurable limit and defined behavior for short and empty messages, and a `StoreHandler` that exposes its messages to tests without leaking its internal list. - Tests that pin down truncation, accumulation and the effect of handler order. ### Follow-up Questions - How would you add log levels so that a handler processes only messages at or above its own level? - If one handler raises an exception, should the remaining handlers still run, and should `log` raise? - How would you make the logger safe to call from several threads, and should `StoreHandler` be bounded? - How would you support structured messages (level, timestamp, fields) without breaking existing handlers?

Overview: Design a small object-oriented logging library in which a Logger passes every message through an ordered list of handlers, including one that truncates messages and one that stores them in memory instead of printing. It tests interface design, handler ordering, extensibility and testability.

Read the full Oracle Software Engineer interview experience this question came from

|Home/Software Engineering Fundamentals/Oracle
Oracle logo
Oracle
Sep 25, 2026
easySoftware EngineerOnsiteSoftware Engineering Fundamentals
0
0

Design a small logging library in an object-oriented way. A Logger is created with a list of handlers, and every message passed to log must go through all of the handlers. Implement two handlers:

  • TruncateHandler : shortens the message.
  • StoreHandler : saves the message into an internal list instead of printing it.

The skeleton and the test provided:

class Logger:
    def __init__(self, handlers):   # a list of handlers
        ...

    def log(self, message):
        # message should go through all handlers
        ...

class TruncateHandler:
    ...

class StoreHandler:
    # save the message into an internal list instead of printing
    ...

# test
logger = Logger([TruncateHandler(), StoreHandler()])
logger.log('abc')

The code does not need to run. The focus is the class design, the contract between the logger and its handlers, and how you would test it.

Clarifying Questions Guidance

  • Does each handler receive the output of the previous handler (a pipeline), or does every handler receive the original message?
  • What length does TruncateHandler cut to? The test constructs it without arguments, so what should the default be, and should a truncated message carry a marker such as an ellipsis?
  • "Instead of printing" suggests that other handlers print. Is a printing handler part of the expected design?
  • Can a handler stop a message from reaching the handlers after it?
  • How should a test read what StoreHandler has saved?

What a Strong Answer Covers Guidance

  • A handler abstraction with one method, so Logger depends only on that contract and new handlers need no change to Logger .
  • Explicit ordering semantics: handlers run in list order, and it is stated whether each one sees the previous handler's output.
  • A TruncateHandler with a configurable limit and defined behavior for short and empty messages, and a StoreHandler that exposes its messages to tests without leaking its internal list.
  • Tests that pin down truncation, accumulation and the effect of handler order.

Follow-up Questions Guidance

  • How would you add log levels so that a handler processes only messages at or above its own level?
  • If one handler raises an exception, should the remaining handlers still run, and should log raise?
  • How would you make the logger safe to call from several threads, and should StoreHandler be bounded?
  • How would you support structured messages (level, timestamp, fields) without breaking existing handlers?
Loading comments...