Summary
PR #2354 (issue #2049) added a structured component field to NICo's logfmt logging
layer, so logs can be filtered by the emitting component. A few services still don't
use the logfmt layer, so they carry no component and emit in a different format. There's
no good reason for services to diverge — they should move onto the shared logfmt
layer for consistent, filterable structured logging.
Services to migrate
Each migrated service gets a component default via
logfmt::layer().with_event_fields([logfmt::EventField::with_default("component", "nico-…")]).
Out of scope
nico-dpu-otel-agent — a custom build of the upstream OpenTelemetry Collector with
minimal plugin extensions; don't modify its logging.
- CLI / dev / mock / test / utility binaries (admin-cli, bmc-explorer-cli, bmc-mock,
mockdpa, machine-a-tron, mqttea-example, dpf api-harness, libmlx mlxconfig-*) — not
centralized-logging services.
Why
- One consistent, filterable structured-log format across NICo's Rust services in
centralized logging.
- Each service gets a
component value, so its lines can be selected directly instead of
relying on log-stream selectors.
Acceptance criteria
- Each in-scope service initializes the
logfmt layer at startup and emits
level=… component=nico-… … logfmt lines to stdout, with the correct per-binary default.
docs/observability/logging.md "Coverage" section updated as each lands: move the
migrated service out of the "do not use logfmt" list; keep nico-dpu-otel-agent listed
with its rationale.
References
Summary
PR #2354 (issue #2049) added a structured
componentfield to NICo'slogfmtlogginglayer, so logs can be filtered by the emitting component. A few services still don't
use the
logfmtlayer, so they carry nocomponentand emit in a different format. There'sno good reason for services to diverge — they should move onto the shared
logfmtlayer for consistent, filterable structured logging.
Services to migrate
nico-dns(carbide-dns) — currentlyfmt::layer().json()(JSON). Small swap:already on
tracing_subscriber, just replace the fmt layer withlogfmt::layer().nico-ssh-console(carbide-ssh-console) — currentlyfmt::Layer::default().compact(). Small swap, same as above.nico-pxe(carbide-pxe) — larger. It hand-rolls logging withprintln!/eprintln!and uses notracingat all, so this means first adoptingtracing(convert theprintln!/eprintln!call sites totracing::{info,warn,error}!)and then initializing the
logfmtlayer.Each migrated service gets a
componentdefault vialogfmt::layer().with_event_fields([logfmt::EventField::with_default("component", "nico-…")]).Out of scope
nico-dpu-otel-agent— a custom build of the upstream OpenTelemetry Collector withminimal plugin extensions; don't modify its logging.
mockdpa, machine-a-tron, mqttea-example, dpf api-harness, libmlx mlxconfig-*) — not
centralized-logging services.
Why
centralized logging.
componentvalue, so its lines can be selected directly instead ofrelying on log-stream selectors.
Acceptance criteria
logfmtlayer at startup and emitslevel=… component=nico-… …logfmt lines to stdout, with the correct per-binary default.docs/observability/logging.md"Coverage" section updated as each lands: move themigrated service out of the "do not use logfmt" list; keep
nico-dpu-otel-agentlistedwith its rationale.
References
componentfield); PR feat(logging): add a component field to log metadata #2354.