#observability #stderr #si-observability

si-observability

This crate provides a reusable basis for developing applications with strong, built-in observability

3 releases

Uses new Rust 2024

new 0.1.2 May 3, 2025
0.1.1 May 2, 2025
0.1.0 May 2, 2025

#20 in #stderr

Download history 103/week @ 2025-04-26

109 downloads per month

MIT/Apache

20KB
234 lines

This crate provides a reusable basis for developing applications with strong, built-in observability.

Note: This crate is intended for internal use within applications developed by Silitics. It is open-source and you are free to use it for whatever purpose you see fit, however, we will not accept any contributions other than bug fixes.

At Silitics, we consider observability a fundamental aspect of building reliable and maintainable systems. This crate builds upon the well-established tracing ecosystem, which we rely on for instrumentation and structured logging. On top of tracing, this crate provides a reusable basis for configuration and logging initialization—reducing boilerplate, promoting best practices, and supporting useful log output for users at the console and the integration with observability platforms. Most functionality provided by this crate is gated by feature flags and can be configured via environment variables at runtime.

The Initializer is the primary interface for setting everything up. Here is a minimal example:

si_observability::Initializer::new("APP").init();

In this example, the string APP is an application-defined prefix for configuration environment variables. In the following, we will use APP as a placeholder for the application-defined prefix defined via the Initializer.

Additional configurations can be applied to the Initializer via the sealed Configuration trait.

Upon initialization, the Initializer returns a FinalizeGuard which must be kept around for the lifetime of the application. When dropped, this guard will cleanup resources and flush internal buffers, e.g., containing logs.

Logging to Stderr

Logging to stderr is enabled by default for informational events. Applications should use informational events to communicate status information to the user. Applications should not use println! or eprintln! for that purpose.

Logging to stderr can be configured via the APP_LOG environment variable using EnvFilter directives.

Logging to stderr produces colorful output using ANSI codes in accordance with the clicolors specification.

The environment variable APP_LOG_FORMAT can be set to one of the following log formats:

  • compact: Compact format for everyday use (the default).
  • full: Verbose format with additional information like timestamps and span attributes.

In addition, an application may make logging to stderr configurable via standardized command line arguments. Command line arguments have the advantage that they are discoverable by users by calling the application with --help. To standardize the respective arguments, this crate provides pre-made integrations with clap. Here is an example:

use si_observability::clap4::LoggingArgs;

#[derive(Debug, Parser)]
pub struct AppArgs {
    #[clap(flatten)]
    logging: LoggingArgs,
}

let args = AppArgs::parse();

si_observability::Initializer::new("APP").apply(&args.logging).init();

Note that we consider adding arguments with the prefix --log- a non-breaking change.

OpenTelemetry

When the otlp feature is enabled, this crate supports exporting traces via OTLP to monitoring and observability tools. While primarily intended for monitoring cloud applications, this can also be useful for local debugging.

At runtime, OTLP export is enabled and configured via the APP_LOG_OTLP environment variable using EnvFilter directives. Additional environment variables, e.g., for the configuration of OTLP endpoints and headers, follow the OpenTelemetry standard. At the moment, trace export is limited to the http/protobuf protocol.

You can use the variable OTEL_RESOURCE_ATTRIBUTES to set OpenTelemetry resource attributes. For instance:

OTEL_RESOURCE_ATTRIBUTES="service.name=my-app,service.instance.id=my-app-instance-1"

For local development and debugging, you can run a Jaeger instance as follows:

docker run --rm -p 16686:16686 -p 4318:4318 jaegertracing/jaeger:latest

It then suffices to set APP_LOG_OTLP=info to send traces to Jaeger. To view the traces, go to http://localhost:16686.

Feature Flags

This crate has the following feature flags:

  • clap4: Support for [clap][clap4] (version 4) CLI arguments.
  • otlp: Support for exporting traces via OTLP.

Dependencies

~5–19MB
~233K SLoC