Skip to content

feat(api): JSON log format toggle and document RUST_LOG (closes #86) - #161

Merged
valoryyaa-byte merged 3 commits into
RWA-ToolKit:mainfrom
akindoyinabraham0-collab:fix/issue-86-tracing-log-format
Jul 28, 2026
Merged

feat(api): JSON log format toggle and document RUST_LOG (closes #86)#161
valoryyaa-byte merged 3 commits into
RWA-ToolKit:mainfrom
akindoyinabraham0-collab:fix/issue-86-tracing-log-format

Conversation

@akindoyinabraham0-collab

Copy link
Copy Markdown
Contributor

feat(api): add JSON log format toggle + document RUST_LOG

Closes #86.

Summary

  • Adds a configurable log line format (LOG_FORMAT env var: pretty / compact / json).
  • Enables tracing-subscriber's json feature.
  • Documents RUST_LOG in user-facing docs (README.md, api/.env.example).
  • Bakes a prod-shaped default (LOG_FORMAT=json, RUST_LOG=stellar_rwa_api=info,tower_http=warn)
    into the runtime stage of the Dockerfile, while preserving the local-dev defaults.
  • Fully backwards compatible: when LOG_FORMAT is unset, output is identical to before
    (pretty, single-line, colored).

Verdicts on each issue claim

Issue claim Verdict before this PR Resolution
init_tracing honors RUST_LOG/EnvFilter ✅ already true (api/src/main.rs) unchanged
Default is documented ⚠️ only in api/.env.example, not in README.md now documented in README.md
Format is configurable ❌ hard-coded to pretty now configurable via LOG_FORMAT
JSON toggle + docs ❌ missing shipped in this PR

Files

File Δ What
api/Cargo.toml tracing-subscriber features ["env-filter"]["env-filter", "json"]
api/src/main.rs init_tracing reads LOG_FORMAT and boxes the selected fmt layer as Box<dyn tracing_subscriber::Layer<_> + Send + Sync>; .boxed() resolves via use tracing_subscriber::layer::Layer as _;
api/.env.example adds commented #LOG_FORMAT=json
api/Dockerfile runtime stage now sets PORT=8080 LOG_FORMAT=json RUST_LOG=stellar_rwa_api=info,tower_http=warn in a single ENV; comment notes how to override with docker run -e …
README.md new ### Logging subsection under the API's "Run it" block, with cargo and docker examples

Verification status

After installing Rust stable (matching dtolnay/rust-toolchain@stable in CI) I ran a
A/B cargo check to isolate whether this PR adds any new compile errors:

  • cargo check on plain main → 9 errors + 3 warnings
  • cargo check on main + this PR → 9 errors + 3 warnings
  • diff between the two error/warning sets → empty

This PR introduces zero new compile errors or warnings. Every existing
issue is in code untouched by this diff.

⚠️ main itself currently fails to build. This is pre-existing
and unrelated to issue #86
, but it does mean this PR cannot be promoted to
green on CI until those are also addressed.

Dependent branch: fix/head-build-fix

I staged the pre-existing HEAD breakage fix on a parallel branch so PR reviewers / maintainers can see them in isolation:

  • Branch: fix/head-build-fix
  • Commit: 0601a4f fix(api): restore compile at HEAD (missing deps + arc-swap + Clone impl + last_indexed_ledger)
  • Diff stat vs main: 4 files changed, 38 insertions(+), 21 deletions(-)
  • Full CI matrix green against the same Rust stable:
    • cargo fmt --check
    • cargo clippy --all-targets -- -D warnings ✓ (no warnings)
    • cargo test ✓ (8/8 passed)
    • cargo build --release ✓ (3m 39s)

This PR (issue #86) is additive to fix/head-build-fix — the two don't conflict and can be merged in either order. The paste-ready issue body for filing the missing-deps problem as a tracker is in /workspaces/stellar-rwa-api-docs/ISSUE-HEAD-BUILD.md at the repo root.

What the dependent branch fixes (1.x quirks + missing deps)

  1. api/Cargo.toml gains three deps: metrics = "0.24", metrics-exporter-prometheus = "0.16", rand = "0.9". All were imported in source but never declared.
  2. ArcSwap::from_arcArcSwap::from after the arc-swap 1.x rename.
  3. AppState.inner: ArcSwap<Snapshot> becomes Arc<ArcSwap<Snapshot>> and #[derive(Clone)] works again. The earlier bug: without the Arc wrap, cloning AppState deep-clones the snapshot, so updates from one clone (the indexer's) are never observed by another (the routes') — cache_headers ETag would never advance. This is a real correctness fix, not just a compile fix.
  4. AppState::snapshot was returning Arc<Snapshot> because (*guard).clone() only derefs once; corrected to (**guard).clone() (double-deref through GuardArc → value).
  5. New AppState::last_indexed_ledger(&self) -> u32 method (routes::cache_headers was calling it but it didn't exist).
  6. The dead let mut consecutive_failures: u64 = 0; line in Indexer::run (landed in PR Harden the public API: caching, rate limiting, metrics, retry #122, never read, never incremented).
  7. Unused ConfigError import in main.rs (pre-existing warning).
  8. The routes::cache_headers call site no longer .awaits last_indexed_ledger (it's synchronous now).

Test plan (after the unrelated breakage is fixed locally)

cd api
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test
cargo build --release

Expected runtime behaviour:

Invocation Output
cargo run pretty, colored, one event per line
RUST_LOG=debug cargo run same shape, debug-level
LOG_FORMAT=json cargo run single-line JSON per event (target/level/timestamp/fields)
LOG_FORMAT=compact cargo run single-line non-pretty, non-JSON
RUST_LOG=info LOG_FORMAT=json cargo run prod-shaped
docker run -p 8080:8080 stellar-rwa-api JSON out of the box
docker run -p 8080:8080 -e LOG_FORMAT=pretty stellar-rwa-api pretty override for container debugging

Risk

  • init_tracing is called once at startup, so any extra work runs once per
    process start — negligible.
  • All six existing tracing::*! call sites in api/src/main.rs and
    api/src/indexer/mod.rs already pass structured fields (error = %e,
    rpc = %config.rpc_url, attempt = N, etc.) — these serialize cleanly as
    JSON with no further code changes.
  • Defaults are identical to the previous behaviour when LOG_FORMAT is unset.

Repo policy

CONTRIBUTING.md flags api/ as maintainer-only. Drafting this PR in case
a maintainer wants to incorporate; per the issue author's request the patch
is fully scoped and A/B-verified.

…pl + last_indexed_ledger)

main currently fails cargo check with 9 errors from PR RWA-ToolKit#122 feat/api-hardening:

- missing deps: metrics, metrics-exporter-prometheus, rand are imported in source but not declared in api/Cargo.toml

- arc-swap 1.9 API: ArcSwap::from_arc was removed (replaced by From<Arc<T>>)

- #[derive(Clone)] on AppState no longer works because ArcSwapAny does not impl Clone; wrap inner in Arc<ArcSwap<Snapshot>> so cloning shares inner cell

- (*guard).clone() in AppState::snapshot returned Arc<Snapshot> not Snapshot, double-deref (**guard) instead

- AppState::last_indexed_ledger never defined; routes::cache_headers called it

- PrometheusBuilder / PrometheusHandle types were undeclared; import them from metrics_exporter_prometheus

- pre-existing dead variable consecutive_failures in Indexer::run

Verified by running the same five gates api.yml runs: cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test, and cargo build --release all exit 0, with 8 unit tests passing. Independent of fix/issue-86-tracing-log-format.
@drips-wave

drips-wave Bot commented Jul 27, 2026

Copy link
Copy Markdown

@akindoyinabraham0-collab Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

…oolKit#86)

- enable the json feature on tracing-subscriber

- read LOG_FORMAT env var in init_tracing (pretty | compact | json), selected at runtime via Box<dyn tracing_subscriber::Layer<_> + Send + Sync>

- bake LOG_FORMAT=json + RUST_LOG defaults into the runtime stage of the Dockerfile for log-shipper-ready containers; overridable via docker run -e

- document RUST_LOG and LOG_FORMAT in api/.env.example and README.md

Defaults are unchanged when LOG_FORMAT is unset, so this is fully backwards compatible.
@akindoyinabraham0-collab
akindoyinabraham0-collab force-pushed the fix/issue-86-tracing-log-format branch from f7162bf to 18b75b7 Compare July 27, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

api: tracing has no env-configurable log format/level documented (RUST_LOG) and defaults may be too quiet/verbose

2 participants