hero_archipelagos_core: drop tracing/release_max_level_warn — propagates via feature unification, kills info!/debug! logs in unrelated workspace consumers #212

Open
opened 2026-05-06 14:17:51 +00:00 by mik-tf · 0 comments
Owner

Summary

hero_archipelagos_core's Cargo.toml enables tracing/release_max_level_warn. Because Cargo features unify across a workspace, this turns on STATIC_MAX_LEVEL = WARN in any workspace that transitively depends on hero_archipelagos_core from any one of its members. Every info! and debug! call site is then statically replaced by a no-op in release builds — across the whole workspace, not just the archipelagos app.

Setting release_max_level_* on a library crate is a well-known Rust anti-pattern; only end-binary crates should set static max levels.

Reproduction (in lhumina_code/hero_browser)

$ cargo metadata --format-version 1 --filter-platform x86_64-unknown-linux-gnu \
    | jq -r '.resolve.nodes[] | select(.id|test("tracing\\b")) | .features'
["attributes","default","log","release_max_level_warn","std","tracing-attributes"]

And which crate enabled it:

hero_archipelagos_core 0.1.0  features=['release_max_level_warn']

The hero_browser workspace pulls archipelagos in only via crates/hero_browser_app (the Archipelagos integration crate), but cargo build --workspace --release unifies features across all members, so the daemon binary hero_browser_server — which has nothing to do with archipelagos — ends up with all info-level logs erased at compile time.

User-visible symptom

Every release run of hero_browser_server prints this on startup, then proceeds with no info logs at all:

warning: some trace filter directives would enable traces that are disabled statically
  | `hero_browser=info` would enable the INFO level for the `hero_browser` target
  = note: the static max level is `warn`
  = help: to enable INFO logging, remove the `max_level_warn` feature from the `tracing` crate

This warning is emitted by tracing-subscriber (filter/env/builder.rs:284), telling us correctly that the runtime filter hero_browser=info is asking for traces that the compile-time STATIC_MAX_LEVEL = WARN has already deleted.

Why this is hero_archipelagos's bug, not the consumer's

  • A binary crate setting release_max_level_warn is a legitimate end-app choice — it shrinks the binary by erasing trace points.
  • A library crate setting it forces every downstream consumer into the same choice, even ones that legitimately want info logs in production.
  • hero_archipelagos_core is a library. Its consumers should choose their own static max level (or leave it alone for the binary).

Proposed fix

  1. Remove release_max_level_warn (and any other max_level_*/release_max_level_*) from hero_archipelagos_core's tracing dependency features.
  2. If specific archipelagos binary crates (the ones that produce executables) want a static max level, set it there — at the binary level, not in the shared library. This keeps the choice scoped.
  3. Optionally: add a CI check (cargo metadata parse) that fails when any non-binary workspace member adds a max_level_* feature on tracing. Cheap, prevents recurrence.

Impact

Fixes silent info/debug log loss in every Hero workspace that links archipelagos through any path. For hero_browser this means production observability comes back (log levels currently visible: WARN and ERROR only). Also silences the startup warning that's been tagging along forever.

## Summary `hero_archipelagos_core`'s `Cargo.toml` enables `tracing/release_max_level_warn`. Because Cargo features unify across a workspace, this turns on `STATIC_MAX_LEVEL = WARN` in any workspace that **transitively** depends on `hero_archipelagos_core` from any one of its members. Every `info!` and `debug!` call site is then statically replaced by a no-op in release builds — across the whole workspace, not just the archipelagos app. Setting `release_max_level_*` on a *library* crate is a well-known Rust anti-pattern; only end-binary crates should set static max levels. ## Reproduction (in `lhumina_code/hero_browser`) ``` $ cargo metadata --format-version 1 --filter-platform x86_64-unknown-linux-gnu \ | jq -r '.resolve.nodes[] | select(.id|test("tracing\\b")) | .features' ["attributes","default","log","release_max_level_warn","std","tracing-attributes"] ``` And which crate enabled it: ``` hero_archipelagos_core 0.1.0 features=['release_max_level_warn'] ``` The `hero_browser` workspace pulls archipelagos in only via `crates/hero_browser_app` (the Archipelagos integration crate), but `cargo build --workspace --release` unifies features across all members, so the daemon binary `hero_browser_server` — which has nothing to do with archipelagos — ends up with all info-level logs erased at compile time. ## User-visible symptom Every release run of `hero_browser_server` prints this on startup, then proceeds with no info logs at all: ``` warning: some trace filter directives would enable traces that are disabled statically | `hero_browser=info` would enable the INFO level for the `hero_browser` target = note: the static max level is `warn` = help: to enable INFO logging, remove the `max_level_warn` feature from the `tracing` crate ``` This warning is emitted by `tracing-subscriber` (`filter/env/builder.rs:284`), telling us correctly that the runtime filter `hero_browser=info` is asking for traces that the compile-time `STATIC_MAX_LEVEL = WARN` has already deleted. ## Why this is `hero_archipelagos`'s bug, not the consumer's - A *binary* crate setting `release_max_level_warn` is a legitimate end-app choice — it shrinks the binary by erasing trace points. - A *library* crate setting it forces every downstream consumer into the same choice, even ones that legitimately want info logs in production. - `hero_archipelagos_core` is a library. Its consumers should choose their own static max level (or leave it alone for the binary). ## Proposed fix 1. Remove `release_max_level_warn` (and any other `max_level_*`/`release_max_level_*`) from `hero_archipelagos_core`'s `tracing` dependency features. 2. If specific archipelagos *binary* crates (the ones that produce executables) want a static max level, set it there — at the binary level, not in the shared library. This keeps the choice scoped. 3. Optionally: add a CI check (`cargo metadata` parse) that fails when any non-binary workspace member adds a `max_level_*` feature on `tracing`. Cheap, prevents recurrence. ## Impact Fixes silent info/debug log loss in **every** Hero workspace that links archipelagos through any path. For `hero_browser` this means production observability comes back (log levels currently visible: WARN and ERROR only). Also silences the startup warning that's been tagging along forever.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_archipelagos#212
No description provided.