Logging
Purpose
Logging records operational information in named destinations with explicit configuration, filtering and sink lifetimes. Ordinary logs support diagnosis; required failure propagation and bounded emergency reporting remain independent.
Interface
Types below are in CE::Logging unless another namespace is shown.
Types and operations
API and purpose |
|---|
|
|
|
|
Levels and policy enums
Type |
Choices and details |
|---|---|
|
|
|
|
|
|
Compile-time severity bits used by logging policy; runtime thresholds cannot restore stripped calls. Compile policy; declarations. |
Usage
Application composition owns logging lifetime and configures each used category
before producers begin. Writers use a named
Logging::Logger; an explicitly owned
Logging::Log is another option when the caller
needs a separate facade/backend lifetime.
---
config:
theme: base
themeVariables:
fontFamily: system-ui, sans-serif
fontSize: 14px
flowchart:
htmlLabels: true
curve: linear
nodeSpacing: 22
rankSpacing: 38
padding: 12
---
flowchart TB
accTitle: Logging · application configuration and writers
accDescr: Local names omit Logging::; ambiguous nested namespaces remain qualified. Arrows point toward the API or type used, not call order or data flow. Methods beneath type names are selected application entry points; Implement hooks marks engine-invoked overrides. Dashed arrows mark optional choices.
k0(["Application<br/>composition"]):::app
k1["<b>ProcessLifetime</b><br/><br/>ProcessLifetime()"]:::focal
k2["<b>Config</b><br/><br/>for_logger(name, Profile): Config"]:::focal
k3["<b>Log</b><br/><br/>Log(FileEventHandlers, Config)<br/><br/>info(format, arguments...)<br/><br/>close(timeout)"]:::focal
k4["Profile"]:::focal
k5["Level"]:::focal
k6["OverflowPolicy"]:::focal
k7["FileEventHandlers"]:::focal
k8(["Application<br/>producer"]):::app
k9["<b>Logger</b><br/><br/>initialize(FileEventHandlers, Config): Log<name><br/><br/>info(fmt, args...)<br/><br/>warn(fmt, args...)"]:::focal
k10(["Application<br/>report"]):::app
k11["<b>LogHandle</b><br/><br/>shared_queue_stats(): QueueStats<br/><br/>backend_stats(): BackendStats<br/><br/>report_diagnostics()"]:::focal
k12["QueueStats"]:::neighbor
k13(["Application<br/>cleanup / quiesce()"]):::app
k14["BackendStats"]:::neighbor
k0 --> k1
k0 --> k2
k0 --> k3
k2 --> k4
k2 --> k5
k2 --> k6
k3 --> k7
k8 --> k9
k9 --> k3
k10 --> k11
k11 --> k12
k13 --> k3
k0 --> k9
k3 --> k2
k9 --> k7
k9 --> k2
k11 --> k14
classDef focal fill:#e7f3ef,stroke:#387d6b,color:#153d33,stroke-width:1.2px
classDef neighbor fill:#f0f3f8,stroke:#8c9bb1,color:#35445b,stroke-width:1px
classDef app fill:#fff2df,stroke:#c09452,color:#674515,stroke-dasharray:5 3
classDef system fill:#eaf0fc,stroke:#617fab,color:#263f69,stroke-width:1.2px
linkStyle default stroke:#7e8fa7,stroke-width:1.2px
Local names omit Logging:: where unambiguous. Explore this diagram and its other views →
The engine dependency view follows subsystem writers into the public logging interfaces.
Configure, write and finish
Boundary |
Application action |
Result or limit |
|---|---|---|
Process setup |
Keep |
Nested guards share the lifetime; the last guard closes live logs and joins the private worker. Shutdown is terminal. |
Before first category access |
Build |
Configuration is per category. Repeated explicit initialization rejects, including after lazy creation. |
Ordinary writes |
Use |
Compile policy and runtime gates run before guarded argument preparation; direct severity-call arguments are evaluated first. |
Investigation |
Read |
Queue loss spans categories; degradation/failure counters identify the individual log. Neither query proves output completion. |
Shutdown/recovery |
Stop producers, complete |
A timed-out close leaves Closing intact. |
Follow Enable useful output for a
complete category configuration. Choose Block when waiting for shared queue
capacity is acceptable, or DiscardNew when counting lost new records is
preferable; the latter can also discard a flush request.
Uses
Consumer |
Dependency |
Relationship |
|---|---|---|
Provides lazy named access to centrally registered state keyed by category text across libraries. |
||
Derives the public lifecycle/filtering/observation operations; it is not a |
||
Owns configured backend state and callbacks through final closure. Callback captures protect borrowed targets. |
||
|
Separates initial runtime thresholds and queue admission from the target’s compile mask. |
|
Guarded emission and backend failure paths |
Reports required failure context independently of ordinary log filtering or sink health. |
The compiled backend owns its queue, worker and sink graph. Applications do not replace native sinks or keep native logger owners through public API handles.
Used by
Consumer |
Named destination |
What to look for |
|---|---|---|
|
|
Session timing/lifecycle and explicit work/delivery summaries. Runtime, Workers, Dispatch, Events. |
|
|
Window/context/input capability and focus observations. Display, Input. |
|
|
Renderer, shader and native resource observations. Rendering, Resources. |
|
|
Preparation, upload/publication and reload outcomes. Assets. |
|
Explicit preallocation and copied bookkeeping reports. Memory. |
These files are separate destinations, not an aggregate mirror. Configuring
engine alone does not configure the other categories. The
category guide owns default paths and custom names.
Ordinary output and required failure context
Ordinary records can be compiled out, filtered, delayed, discarded or suppressed by degraded sinks. Preserve the owning exception/future independently. Native callbacks, final deleters and noexcept cleanup use the bounded emergency path, outside ordinary logger acquisition. Keep file callbacks free of logger lifecycle reentry and waits for work that needs the backend.
Contracts
Initialize explicitly before lazy access/writers when configuration matters. Severity filters cannot restore code removed by compilation policy. Queue admission, rotation and callback failures follow the configured contract; logging is not a substitute for the operation’s exception or future.
Sink callbacks must respect backend reentry guards and their documented borrowed arguments. Do not emit ordinary logging while holding sensitive subsystem locks or from native/noexcept failure paths that require bounded emergency reporting.
Lifecycle
Configure the used categories before starting producers, run those producers, stop/settle them, then flush and close logging. Close/reopen serializes state transitions; a timed close can report an incomplete operation rather than pretending all queued work has completed. Keep callback targets alive until the backend has finished with them. Startup composition owns its logging lifetime when using the supplied startup path.
Execution
Writers may enqueue from supported producer threads. Sink callbacks run according to synchronous/asynchronous configuration, not necessarily on simulation. Compile/filter checks should precede costly argument construction where the selected frontend supports that. Named logger registry state is separate from game/thread ownership.
Integration
The application can emit through a built-in named category after startup:
CE::Logging::Logger<CE::Logging::Categories::engine>::info("Game initialized");
Select the declared category spelling from the logging umbrella and configure it before producers. For a known file/console outcome, follow Enable useful output before this first write. If it is absent, use the missing-records checklist. The detailed guide also covers custom names, handlers, profiles and controlled shutdown.
Limits and further reading
Logging does not promise recovery from a native failure or durable completion merely because a write returned. Read configuration, emission and filtering, failure reporting, logging acceptance and the logger interface.