Skip to content

Commit 2c8e659

Browse files
authored
feature: JSON (#2)
* feature: JSON * feat: permissive bool * feat: ajj example * nit: blank line * chore: version
1 parent fc34a33 commit 2c8e659

File tree

4 files changed

+96
-12
lines changed

4 files changed

+96
-12
lines changed

Cargo.toml

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ name = "init4-bin-base"
44
description = "Internal utilities for binaries produced by the init4 team"
55
keywords = ["init4", "bin", "base"]
66

7-
version = "0.1.1"
7+
version = "0.1.2"
88
edition = "2021"
99
rust-version = "1.81"
1010
authors = ["init4", "James Prestwich"]
@@ -16,7 +16,7 @@ repository = "https://github.com/init4tech/bin-base"
1616
# Tracing
1717
tracing = "0.1.40"
1818
tracing-core = "0.1.33"
19-
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "registry"] }
19+
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json", "registry"] }
2020

2121
# OTLP
2222
opentelemetry_sdk = "0.28.0"
@@ -35,10 +35,12 @@ thiserror = "2.0.11"
3535
alloy = { version = "0.11.1", optional = true, default-features = false, features = ["std"] }
3636

3737
[dev-dependencies]
38+
ajj = "0.3.1"
39+
axum = "0.8.1"
3840
serial_test = "3.2.0"
3941
signal-hook = "0.3.17"
4042
tokio = { version = "1.43.0", features = ["macros"] }
4143

4244
[features]
4345
default = ["alloy"]
44-
alloy = ["dep:alloy"]
46+
alloy = ["dep:alloy"]

examples/ajj.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//! This example allows you to play with ajj instrumentation.
2+
//!
3+
//! ## Observing traces
4+
//!
5+
//! We recommend the following:
6+
//! - set `RUST_LOG=info` (or `trace` for more detail) to see log lines
7+
//! - use [otel-desktop-viewer](https://github.com/CtrlSpice/otel-desktop-viewer)
8+
//!
9+
//! ## Running this example
10+
//!
11+
//! ```no_compile
12+
//! export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
13+
//! export OTEL_TRACES_EXPORTER="otlp"
14+
//! export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
15+
//! export RUST_LOG=info
16+
//! cargo run --example ajj
17+
//! ```
18+
//!
19+
//! ```no_compile
20+
//! curl -X POST \
21+
//! -H 'Content-Type: application/json' \
22+
//! -d '{"jsonrpc":"2.0","id":"id","method":"helloWorld"}' \
23+
//! http://localhost:8080/rpc
24+
//! ```
25+
use ajj::Router;
26+
use init4_bin_base::init4;
27+
28+
#[tokio::main]
29+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
30+
let _guard = init4();
31+
32+
let router = Router::<()>::new()
33+
.route("helloWorld", || async {
34+
tracing::info!("serving hello world");
35+
Ok::<_, ()>("Hello, world!")
36+
})
37+
.into_axum("/rpc");
38+
39+
let listener = tokio::net::TcpListener::bind("localhost:8080")
40+
.await
41+
.unwrap();
42+
axum::serve(listener, router).await.unwrap();
43+
Ok(())
44+
}

src/utils/from_env.rs

+9
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,15 @@ impl<const N: usize> FromEnvVar for alloy::primitives::FixedBytes<N> {
179179
}
180180
}
181181

182+
impl FromEnvVar for bool {
183+
type Error = std::str::ParseBoolError;
184+
185+
fn from_env_var(env_var: &str) -> Result<Self, FromEnvErr<Self::Error>> {
186+
let s: String = std::env::var(env_var).map_err(|e| FromEnvErr::env_err(env_var, e))?;
187+
Ok(!s.is_empty())
188+
}
189+
}
190+
182191
#[cfg(test)]
183192
mod test {
184193
use std::time::Duration;

src/utils/tracing.rs

+38-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
1-
use crate::utils::otlp::{OtelConfig, OtelGuard};
2-
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
1+
use crate::utils::{
2+
from_env::FromEnvVar,
3+
otlp::{OtelConfig, OtelGuard},
4+
};
5+
use tracing_subscriber::{filter::EnvFilter, layer::SubscriberExt, util::SubscriberInitExt, Layer};
6+
7+
const TRACING_LOG_JSON: &str = "TRACING_LOG_JSON";
8+
9+
/// Install a format layer based on the `TRACING_LOG_JSON` environment
10+
/// variable, and then install the registr
11+
///
12+
macro_rules! install_fmt {
13+
(json @ $registry:ident, $filter:ident) => {{
14+
let fmt = tracing_subscriber::fmt::layer().json().with_filter($filter);
15+
$registry.with(fmt).init();
16+
}};
17+
(log @ $registry:ident, $filter:ident) => {{
18+
let fmt = tracing_subscriber::fmt::layer().with_filter($filter);
19+
$registry.with(fmt).init();
20+
}};
21+
($registry:ident) => {{
22+
let json = bool::from_env_var(TRACING_LOG_JSON).unwrap_or(false);
23+
let filter = EnvFilter::from_default_env();
24+
if json {
25+
install_fmt!(json @ $registry, filter);
26+
} else {
27+
install_fmt!(log @ $registry, filter);
28+
}
29+
}};
30+
}
331

432
/// Init tracing, returning an optional guard for the OTEL provider.
533
///
@@ -8,25 +36,26 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
836
/// environment variables are set, it will initialize the OTEL provider
937
/// with the specified configuration, as well as the `fmt` layer.
1038
///
11-
/// See [`OtelConfig`] documentation for env var information.
39+
/// ## Env Reads
40+
///
41+
/// - `TRACING_LOG_JSON` - If set, will enable JSON logging.
42+
/// - As [`OtelConfig`] documentation for env var information.
1243
///
1344
/// ## Panics
1445
///
1546
/// This function will panic if a global subscriber has already been set.
1647
///
1748
/// [`OtelConfig`]: crate::utils::otlp::OtelConfig
1849
pub fn init_tracing() -> Option<OtelGuard> {
19-
let registry = tracing_subscriber::registry().with(
20-
tracing_subscriber::fmt::layer()
21-
.with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()),
22-
);
50+
let registry = tracing_subscriber::registry();
2351

2452
if let Some(cfg) = OtelConfig::load() {
2553
let guard = cfg.provider();
26-
registry.with(guard.layer()).init();
54+
let registry = registry.with(guard.layer());
55+
install_fmt!(registry);
2756
Some(guard)
2857
} else {
29-
registry.init();
58+
install_fmt!(registry);
3059
None
3160
}
3261
}

0 commit comments

Comments
 (0)