# otel-log-wrapper
Zero-config OpenTelemetry setup for Rust services that use `tracing`.
This crate wraps `init-tracing-opentelemetry` with the one-line initialization
style used by `qrt-log-utils`.
## No-Brain Init
```rust
otel_log_wrapper::init!()?;
tracing::info!("service started");
```
The macro derives the service metadata from the calling crate:
- `service.name`: `env!("CARGO_PKG_NAME")`
- `service.version`: `env!("CARGO_PKG_VERSION")`
## Builder Init
Use the builder when you want an explicit service name or config.
```rust
use otel_log_wrapper::LoggerConfig;
LoggerConfig::builder("my-service").init()?;
```
With build metadata from `shadow-rs`:
```rust
shadow_rs::shadow!(build);
otel_log_wrapper::LoggerConfig::builder("my-service")
.service_version(build::PKG_VERSION)
.commit_short(build::SHORT_COMMIT)
.commit_hash(build::COMMIT_HASH)
.branch(build::BRANCH)
.build_time(build::BUILD_TIME)
.init()?;
```
`otel-log-wrapper` does not depend on `shadow-rs`; it only accepts the static
strings generated by the application.
Build metadata is merged into `OTEL_RESOURCE_ATTRIBUTES` before initialization,
so the OpenTelemetry SDK picks it up as resource attributes.
## Defaults
The default setup:
- sets `OTEL_SERVICE_NAME` from the service name when unset
- sets `OTEL_EXPORTER_OTLP_ENDPOINT` to `http://localhost:4317` when unset
- sets `OTEL_EXPORTER_OTLP_PROTOCOL` to `grpc` when unset
- respects `RUST_LOG`, then `OTEL_LOG_LEVEL`, then falls back to `info`
- uses human-readable stdout logs by default
- initializes a global `tracing-subscriber`
- exports OpenTelemetry traces and metrics
- prints a one-line startup message
Example startup message:
```text
otel-log-wrapper init service=my-service version=0.1.0 commit=abc1234 endpoint=http://localhost:4317 protocol=grpc format=human metrics=true level=RUST_LOG|OTEL_LOG_LEVEL|info
```
## Customization
```rust
use otel_log_wrapper::{LoggerConfig, LoggerFormat};
use tracing::level_filters::LevelFilter;
LoggerConfig::builder("my-service")
.endpoint("http://collector:4317")
.format(LoggerFormat::Json)
.default_level(LevelFilter::INFO)
.startup_message(false)
.init()?;
```
Available formats:
- `LoggerFormat::Human`
- `LoggerFormat::Pretty`
- `LoggerFormat::Full`
- `LoggerFormat::Compact`
- `LoggerFormat::Json`
If you want to own shutdown explicitly instead of storing a global guard:
```rust
let _guard = LoggerConfig::builder("my-service")
.global_subscriber(false)
.init_guard()?;
```