Design a logger system that receives stream of messages along with its timestamps. Each message should be printed if and only if it is not printed in the last 10
seconds.
Given a message and a timestamp (in seconds granularity), return true
if the message should be printed in the given timestamp, otherwise return false
.
It is possible that several messages arrive roughly at the same time.
For example:
Logger logger = new Logger();
// logging string "foo" at timestamp 1
logger.shouldPrintMessage(1, "foo"); returns true;
// logging string "bar" at timestamp 2
logger.shouldPrintMessage(2,"bar"); returns true;
// logging string "foo" at timestamp 3
logger.shouldPrintMessage(3,"foo"); returns false;
// logging string "bar" at timestamp 8
logger.shouldPrintMessage(8,"bar"); returns false;
// logging string "foo" at timestamp 10
logger.shouldPrintMessage(10,"foo"); returns false;
// logging string "foo" at timestamp 11
logger.shouldPrintMessage(11,"foo"); returns true;
Constraints:
[0, 109]
.[1, 30]
.104
calls will be made to shouldPrintMessage
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The logger rate limiter problem asks us to only print a message if it hasn't been printed in the last ten seconds. The brute force method essentially remembers every message that has ever appeared and checks each new message against this complete history.
Here's how the algorithm would work step-by-step:
class Logger:
def __init__(self):
self.message_history = []
def shouldPrintMessage(self, timestamp: int, message: str) -> bool:
# Check against the entire history to enforce rate limiting
for previous_timestamp, previous_message in self.message_history:
if message == previous_message and timestamp - previous_timestamp < 10:
return False
# If no duplicates found, print and record the message
self.message_history.append((timestamp, message))
# Clean up old messages to save space.
self.message_history = [(time, msg) for time, msg in self.message_history if timestamp - time < 10]
return True
# Your Logger object will be instantiated and called as such:
# obj = Logger()
# param_1 = obj.shouldPrintMessage(timestamp,message)
The key to solving the logger problem efficiently is to remember the last time a message was printed. We can then quickly check if a new message is allowed based on this stored information. This avoids unnecessary computations and makes the process very fast.
Here's how the algorithm would work step-by-step:
class Logger:
def __init__(self):
self.message_timestamps = {}
def shouldPrintMessage(self, timestamp: int, message: str) -> bool:
if message in self.message_timestamps:
last_timestamp = self.message_timestamps[message]
# Check if the message was printed within the last 10 seconds.
if timestamp - last_timestamp < 10:
return False
# If the message is new or not recent, update the timestamp.
self.message_timestamps[message] = timestamp
# Store the current timestamp for the message.
# Ensures we only print if it's a new message or outside the rate limit.
return True
Case | How to Handle |
---|---|
Null or empty message | Treat an empty message as a valid, distinct message or reject it based on requirements; the important thing is to define the expected behavior. |
Zero timestamp | Timestamp of 0 should be a valid timestamp and handled like any other timestamp (no special casing needed). |
Very large timestamp values (potential for integer overflow) | Use a 64-bit integer to store the timestamps to avoid potential overflows, or use a different data type if necessary. |
Messages arriving out of order (timestamp decreasing) | The problem doesn't explicitly forbid out-of-order timestamps, so ensure the solution correctly handles this case, potentially by not assuming increasing order. |
Same message arriving multiple times within 10 seconds | The solution must correctly return false for subsequent calls with the same message within the 10-second window, utilizing the stored timestamp. |
Different messages arriving at the same timestamp | Handle collisions by treating different messages at the same timestamp as separate events in the logger's message history. |
Maximum number of unique messages being logged causing memory exhaustion | Consider a bounded cache to limit the memory usage; this could evict the oldest or least frequently used messages. |
Negative timestamps | The problem doesn't explicitly state timestamps must be non-negative; either allow them or throw an exception based on the problem requirements. |