Course contentsShow
← C#
Lesson 1806 of 1,90816. Performance and DiagnosticsFree lesson

Troubleshooting Clock Drift in Distributed Logs

Learners will implement logical clocks or timestamp synchronization for cross-node log ordering.

In this lesson, you will learn how to maintain causal ordering of distributed logs when system clocks across multiple nodes fall out of synchronization.

The Problem: Asynchronous Realities

In a distributed system, relying on DateTime.UtcNow to order logs across different servers is dangerous. Even with NTP (Network Time Protocol) running, clocks inevitably drift, meaning a log entry generated at T1 on Node A might appear to occur after an entry generated at T2 on Node B, even if the reverse is true. When debugging, this makes reconstructing the true sequence of events impossible.

The Solution: Logical Clocks

Instead of trusting physical wall-clock time, we implement a Lamport Timestamp (or a simple monotonically increasing counter). Each node maintains a local integer counter that increments with every log event. When sending a message (or recording an interaction), the node attaches its current logical counter. If a node receives a message from another, it updates its own counter to max(local_counter, received_counter) + 1.

Implementation Illustration

By incorporating a logical sequence number into your log enrichment process, you ensure that even if the system time is skewed, the causal relationship remains intact:

public class LogSequencer
{
    private long _logicalClock = 0;
    private readonly object _lock = new();

    public long GetNextSequence(long receivedTimestamp = 0)
    {
        lock (_lock)
        {
            // Ensure local clock is ahead of received events
            _logicalClock = Math.Max(_logicalClock, receivedTimestamp) + 1;
            return _logicalClock;
        }
    }
}

// Usage in your log enricher
public void EnrichLog(LogEvent logEvent, LogSequencer sequencer)
{
    logEvent.AddOrUpdateProperty(new LogEventProperty("Sequence", 
        new ScalarValue(sequencer.GetNextSequence())));
}

By adding this Sequence property to your logs, your log aggregation tools can sort entries by the sequence ID rather than the potentially inaccurate Timestamp. This guarantees that if Event A happens before Event B on a single node, or if Event A triggers Event B across nodes, the logs will reflect that dependency accurately regardless of the underlying server clock drift.

Key Takeaway: Replace or augment wall-clock timestamps with monotonically increasing sequence IDs to guarantee causal ordering in distributed log streams.