Skip to main content

Crate drmkit_log

Crate drmkit_log 

Source
Expand description

drmkit’s library-wide diagnostic surface.

Port of src/log.hpp from drm-cxx @ dc2915b. Two knobs are exposed, matching the C++ contract:

  1. set_log_level — process-wide threshold. Records at or below the active level are emitted; the rest are dropped before formatting cost is paid. A call below the threshold reduces to one relaxed atomic load and a branch.

  2. set_log_sink — process-wide redirection hook. The default sink writes to stderr (errors, warnings) or stdout (info, debug) prefixed with [drm:LEVEL] . Consumers can forward to tracing, journald, syslog, or an in-memory test buffer. reset_log_sink restores the default — the Rust spelling of the C++ set_log_sink(nullptr) path.

§Deviations from the C++ original

The C++ set_log_sink is documented thread-unsafe (“install once during application startup, before spinning up worker threads”), and its set_log_level is a plain unsynchronized write. Here both are genuinely thread-safe: the level is an AtomicU8 and the sink lives behind an RwLock whose guard is released before the sink runs, so a sink that logs cannot deadlock and a sink that panics cannot wedge logging for the rest of the process. The startup-only discipline remains good practice; it is no longer load-bearing.

§Untrusted content in log records

Records are delivered to the sink verbatim — no escaping, no newline stripping. That matters here more than in a typical library, because some of what drmkit will log is attacker-influenced: EDID monitor names and serial strings come off the wire from whatever display is plugged in, and a hostile or simply malformed EDID can carry newlines or ANSI escape sequences. Written straight to a terminal by the built-in sink, those can forge log lines or move the cursor.

The C++ original has the same property. Rather than diverge silently, the rule for the port is: sanitize at the point the untrusted string enters a record, not in the sink. Any crate that logs an EDID string must sanitize it before formatting – none currently logs one – because the sink cannot tell a monitor name from a driver name once they are one formatted string. Consumers who route this into a terminal and cannot trust their displays should install a sink that escapes control characters.

§Initial level

The C++ side bakes its default in at compile time via DRM_CXX_LOG_LEVEL. Here the initial level resolves once, on first use, from the DRMKIT_LOG_LEVEL environment variable (silent/error/warn/info/ debug, case-insensitive, or the numeric discriminant, plus the aliases off/none, warning and trace). An unset or unparseable value yields LogLevel::Info, matching the C++ default. An explicit set_log_level before first use always wins.

§Example

use drmkit_log::{LogLevel, log_warn, set_log_level};

set_log_level(LogLevel::Warn);
log_warn!("plane {} rejected modifier {:#x}", 31, 0x0100_0000_0000_0001_u64);

§A note on the examples

The level and the sink are process-global, and under edition 2024 every doctest in a crate is merged into one binary and run on parallel threads. Examples here therefore demonstrate the API but never assert on what a sink received: a concurrently running example would have replaced the sink or moved the threshold, and the assertion would fail for reasons having nothing to do with the code. The behavioral assertions live in the unit tests, which serialize on a mutex the way the C++ gtest fixture does.

Macros§

log_channel
Emit a line belonging to an opt-in diagnostic channel — one already gated by its own switch, such as the DRM_ALLOC_DEBUG / DRM_EXT_DMABUF_DEBUG environment variables on the C++ side.
log_debug
Emit at LogLevel::Debug.
log_error
Emit at LogLevel::Error.
log_info
Emit at LogLevel::Info.
log_warn
Emit at LogLevel::Warn.

Enums§

LogLevel
Severity of a diagnostic record.

Functions§

install_tracing_sink
Route every admitted record into tracing under the drmkit target.
log_level
The active process-wide threshold.
log_sink
The installed sink, or None when the built-in stdio sink is active.
reset_log_sink
Restore the built-in stdio sink — the Rust spelling of the C++ set_log_sink(nullptr) path.
set_log_level
Set the process-wide threshold.
set_log_sink
Install a sink, replacing whatever was there.

Type Aliases§

LogSink
A sink receives the record’s level and its fully formatted body — no level prefix, no trailing newline.