Runtime view

arc42 §6 runtime scenarios for the logging stack. These flows are derived from the requirement prose and do not introduce new architectural elements — they make two behaviours concrete: how the facade selects a backend at one-shot init, and how the offline ring keeps the producer non-blocking across a daemon outage.


One-shot init and backend selection

taktora-log::init() runs once per process and picks the active log::Log by precedence: a pre-installed logger always wins (the swap path of Integrator may install any ... (REQ_0804)), then an explicitly-built LogSink such as the DLT backend (One-shot init builder selec... (REQ_0803)), and only when neither is present does the console dev fallback install itself (Console fallback installed ... (REQ_0816)). A second init() returns an error rather than overriding (One-shot init builder selec... (REQ_0803)). The bridge from tracing is installed on the same init path (tracing-log bridge installe... (REQ_0805)).

        flowchart TD
    Start["taktora-log::init()"]
    AlreadyInit{"global log::Log<br/>already set by init?"}
    PreExisting{"pre-existing log::Log<br/>(integrator-installed)?"}
    Sink{"explicit LogSink<br/>configured on builder?"}
    Bridge["install tracing-log bridge<br/>(LogTracer, once)"]
    UseDlt["register DLT backend<br/>(taktora-log-dlt)"]
    UseConsole["install console<br/>dev fallback (stderr)"]
    KeepExisting["keep pre-existing logger<br/>return PreExistingLogger"]
    Err["return AlreadyInitialized"]

    Start --> AlreadyInit
    AlreadyInit -->|yes| Err
    AlreadyInit -->|no| PreExisting
    PreExisting -->|yes| KeepExisting
    PreExisting -->|no| Sink
    Sink -->|"yes (e.g. DLT)"| UseDlt
    Sink -->|"no daemon, no sink"| UseConsole
    UseDlt --> Bridge
    UseConsole --> Bridge
    KeepExisting --> Bridge
    

Offline ring buffer and reconnect drain

The producer never blocks: log::* is a bounded-queue push only (Emission shall not block th... (REQ_0812)), and all socket I/O lives on the background flusher. While the daemon socket is down the flusher diverts encoded records into a bounded, pre-allocated ring (Bounded in-memory ring buff... (REQ_0814)); when the ring is full it drops the oldest record and bumps a drop counter (Drop-oldest overflow policy... (REQ_0815)). On reconnect the flusher drains the ring in FIFO order — leading with a single dropped-count summary record — before resuming live emission (Drop-oldest overflow policy... (REQ_0815)).

        sequenceDiagram
    participant P as producer (log::*)
    participant Q as bounded queue
    participant F as background flusher
    participant R as offline ring (bounded)
    participant D as dlt-daemon

    Note over P,Q: hot path never blocks
    P->>Q: push record (no I/O, no wait)
    Q->>F: dequeue

    alt daemon connected
        F->>D: encode + write
    else daemon down
        F->>R: buffer record (FIFO)
        Note over R: ring full → drop oldest,<br/>increment drop counter
    end

    Note over F,D: reconnect (bounded backoff)
    F->>D: summary record<br/>(taktora.log.dropped count=N)
    loop drain in FIFO order
        R-->>F: oldest buffered record
        F->>D: encode + write
    end
    Note over F: resume live emission