Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[workspace]
members = [
"opentelemetry-aws",
"opentelemetry-config",
"opentelemetry-config-stdout",
"opentelemetry-contrib",
"opentelemetry-datadog",
"opentelemetry-etw-logs",
Expand Down
9 changes: 9 additions & 0 deletions opentelemetry-config-stdout/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## vNext

## v0.1.0

### Added

- Initial declarative configuration for stdout (console)
5 changes: 5 additions & 0 deletions opentelemetry-config-stdout/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Code owners file.
# This file controls who is tagged for review for any given pull request.

# For anything not explicitly taken by someone else:
* @open-telemetry/rust-approvers
12 changes: 12 additions & 0 deletions opentelemetry-config-stdout/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "opentelemetry-config-stdout"
version = "0.1.0"
description = "Declarative configuration for OpenTelemetry SDK using console (stdout) configuration"
license = "Apache-2.0"
edition = "2021"
rust-version = "1.75.0"

[dependencies]
opentelemetry-config = { path = "../opentelemetry-config" }
opentelemetry_sdk = { version = "0.31.0" }
opentelemetry-stdout = { version = "0.31.0" }
118 changes: 118 additions & 0 deletions opentelemetry-config-stdout/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# OpenTelemetry Declarative Configuration for stdout (console)

![OpenTelemetry — An observability framework for cloud-native software.][splash]

[splash]: https://raw.githubusercontent.com/open-telemetry/opentelemetry-rust/main/assets/logo-text.png

Declarative configuration for applications instrumented with [`OpenTelemetry`].

[`OpenTelemetry`]: https://crates.io/crates/opentelemetry

## Overview

This crate provides a declarative configuration extension for OpenTelemetry that enables stdout (console) metric exports. It integrates with the `opentelemetry-config` crate to allow YAML-based configuration of the console exporter.

### Features

- Console/stdout metrics exporter configuration via YAML
- Support for both Delta and Cumulative temporality
- Integration with OpenTelemetry declarative configuration
- Simple registration API for the configurator

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
opentelemetry-config-stdout = "0.1.0"
```

## Quick Start

### 1. Create a YAML Configuration File

Create a file named `otel-config.yaml`:

```yaml
metrics:
readers:
- periodic:
exporter:
console:
temporality: delta

resource:
service.name: "my-service"
service.version: "1.0.0"
```

### 2. Load and Apply Configuration

```rust
use opentelemetry_config::{ConfiguratorManager, TelemetryConfigurator};
use opentelemetry_config_stdout::ConsolePeriodicExporterConfigurator;

fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create configurator manager and register stdout exporter
let mut configurator_manager = ConfiguratorManager::new();
ConsolePeriodicExporterConfigurator::register_into(&mut configurator_manager);

// Load configuration from YAML file
let telemetry_configurator = TelemetryConfigurator::new();
let providers = telemetry_configurator
.configure_from_yaml_file(&configurator_manager, "otel-config.yaml")?;

// Use the configured providers
if let Some(meter_provider) = providers.meter_provider() {
// Your application code here
}

// Shutdown all providers
providers.shutdown()?;
Ok(())
}
```

## Examples

### Console Exporter Example

See the [examples/console](examples/console) directory for a complete working example that demonstrates:

- Setting up a console exporter configurator
- Loading configuration from a YAML file
- Configuring a meter provider
- Proper shutdown handling

To run the example:

```bash
cd examples/console
cargo run -- --file ../metrics_console.yaml
```

## Configuration Schema

### Metrics Configuration

```yaml
metrics:
readers:
- periodic:
exporter:
console:
temporality: delta # or cumulative
```

## Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

## License

This project is licensed under the Apache-2.0 license.

## Release Notes

You can find the release notes (changelog) [here](https://github.com/open-telemetry/opentelemetry-rust-contrib/tree/main/opentelemetry-config-stdout/CHANGELOG.md).
13 changes: 13 additions & 0 deletions opentelemetry-config-stdout/examples/console/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "opentelemetry-config-console-example"
version = "0.1.0"
description = "Declarative configuration for OpenTelemetry SDK example using console configuration"
license = "Apache-2.0"
edition = "2021"
rust-version = "1.75.0"

[workspace]

[dependencies]
opentelemetry-config-stdout = { path = "../../" }
opentelemetry-config = { path = " ../../../../../opentelemetry-config" }
52 changes: 52 additions & 0 deletions opentelemetry-config-stdout/examples/console/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! # Example OpenTelemetry Config Console
//!
//! This example demonstrates how to configure OpenTelemetry Metrics
//! using the OpenTelemetry Config crate with a Console Exporter.

use opentelemetry_config::{configurators::TelemetryConfigurator, ConfiguratorManager};
use opentelemetry_config_stdout::ConsolePeriodicExporterConfigurator;

use std::env;

pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();

if args.len() == 1 || (args.len() > 1 && args[1] == "--help") {
println!("Usage: cargo run -- --file ../metrics_console.yaml");
println!("This example demonstrates how to configure OpenTelemetry Metrics using the OpenTelemetry Config crate with a Console Exporter.");
return Ok(());
}
if args.len() < 3 || args[1] != "--file" {
println!("Error: Configuration file path not provided.");
println!("Usage: cargo run -- --file ../metrics_console.yaml");
return Ok(());
}
let config_file = &args[2];

// Setup configurator manager with console exporter configurator
let mut configurator_manager = ConfiguratorManager::new();
ConsolePeriodicExporterConfigurator::register_into(&mut configurator_manager);

let telemetry_configurator = TelemetryConfigurator::new();
let providers = telemetry_configurator
.configure_from_yaml_file(&configurator_manager, config_file)?;

println!("Metrics configured with Console Exporter successfully.");

println!(
"Meter provider configured: {}",
providers.meter_provider().is_some()
);
println!(
"Logs provider configured: {}",
providers.logs_provider().is_some()
);
println!(
"Traces provider configured: {}",
providers.traces_provider().is_some()
);

println!("Shutting down telemetry providers...");
providers.shutdown()?;
Ok(())
}
9 changes: 9 additions & 0 deletions opentelemetry-config-stdout/examples/metrics_console.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
metrics:
readers:
- periodic:
exporter:
console:
temporality: delta
resource:
service.name: "test-service"
service.version: "1.0.0"
157 changes: 157 additions & 0 deletions opentelemetry-config-stdout/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
//! # OpenTelemetry Dynamic Configurator module for Stdout (Console) exporter
//!
//! This module provides a configurator for OpenTelemetry Metrics
//! that enables exporting metrics to the console (stdout) using
//! the OpenTelemetry Config crate.

use opentelemetry_config::{
model::metrics::reader::PeriodicExporterConsole, MetricsReaderPeriodicExporterConfigurator,
};
use opentelemetry_sdk::metrics::MeterProviderBuilder;

#[derive(Clone)]
pub struct ConsolePeriodicExporterConfigurator {}

impl ConsolePeriodicExporterConfigurator {
pub fn new() -> Self {
Self {}
}

pub fn register_into(configurators_manager: &mut opentelemetry_config::ConfiguratorManager) {
let configurator = ConsolePeriodicExporterConfigurator::new();
configurators_manager
.metrics_mut()
.register_periodic_exporter_configurator::<PeriodicExporterConsole>(Box::new(
configurator.clone(),
));
// TODO: Add logs and traces configurator registration.
}
}

impl MetricsReaderPeriodicExporterConfigurator for ConsolePeriodicExporterConfigurator {
fn configure(
&self,
mut meter_provider_builder: MeterProviderBuilder,
config: &dyn std::any::Any,
) -> MeterProviderBuilder {
let mut exporter_builder = opentelemetry_stdout::MetricExporter::builder();

let config = config
.downcast_ref::<PeriodicExporterConsole>()
.expect("Invalid config type. Expected PeriodicExporterConsole.");

if let Some(temporality) = &config.temporality {
match temporality {
opentelemetry_config::model::metrics::reader::Temporality::Delta => {
exporter_builder = exporter_builder
.with_temporality(opentelemetry_sdk::metrics::Temporality::Delta);
}
opentelemetry_config::model::metrics::reader::Temporality::Cumulative => {
exporter_builder = exporter_builder
.with_temporality(opentelemetry_sdk::metrics::Temporality::Cumulative);
}
}
}

let exporter = exporter_builder.build();
meter_provider_builder = meter_provider_builder.with_periodic_exporter(exporter);
meter_provider_builder
}

fn as_any(&self) -> &dyn std::any::Any {
self
}
}

impl Default for ConsolePeriodicExporterConfigurator {
fn default() -> Self {
Self::new()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_console_configurator_registration() {
// Arrange
let mut configurator_manager = opentelemetry_config::ConfiguratorManager::new();

// Act
ConsolePeriodicExporterConfigurator::register_into(&mut configurator_manager);

let configurators_option = configurator_manager
.metrics()
.readers_periodic_exporter::<PeriodicExporterConsole>();

// Assert
assert!(configurators_option.is_some());
}

#[test]
fn test_console_configurator_configure_temporality_minimal() {
// Arrange
let configurator = ConsolePeriodicExporterConfigurator::new();
let meter_provider_builder = opentelemetry_sdk::metrics::SdkMeterProvider::builder();

let config = PeriodicExporterConsole { temporality: None };

// Act
let configured_builder = configurator.configure(meter_provider_builder, &config);

// Assert
// Since the MeterProviderBuilder does not expose its internal state,
// we will just ensure that the returned builder is not the same as the original.
assert!(!std::ptr::eq(
&configured_builder,
&opentelemetry_sdk::metrics::SdkMeterProvider::builder()
));
}

#[test]
fn test_console_configurator_configure_temporality_delta() {
// Arrange
let configurator = ConsolePeriodicExporterConfigurator::new();
let meter_provider_builder = opentelemetry_sdk::metrics::SdkMeterProvider::builder();

let config = PeriodicExporterConsole {
temporality: Some(opentelemetry_config::model::metrics::reader::Temporality::Delta),
};

// Act
let configured_builder = configurator.configure(meter_provider_builder, &config);

// Assert
// Since the MeterProviderBuilder does not expose its internal state,
// we will just ensure that the returned builder is not the same as the original.
assert!(!std::ptr::eq(
&configured_builder,
&opentelemetry_sdk::metrics::SdkMeterProvider::builder()
));
}

#[test]
fn test_console_configurator_configure_temporality_cumulative() {
// Arrange
let configurator = ConsolePeriodicExporterConfigurator::new();
let meter_provider_builder = opentelemetry_sdk::metrics::SdkMeterProvider::builder();

let config = PeriodicExporterConsole {
temporality: Some(
opentelemetry_config::model::metrics::reader::Temporality::Cumulative,
),
};

// Act
let configured_builder = configurator.configure(meter_provider_builder, &config);

// Assert
// Since the MeterProviderBuilder does not expose its internal state,
// we will just ensure that the returned builder is not the same as the original.
assert!(!std::ptr::eq(
&configured_builder,
&opentelemetry_sdk::metrics::SdkMeterProvider::builder()
));
}
}
Loading
Loading