From 2c5d03ea15baeb658953f70fc637af63f1adc0f0 Mon Sep 17 00:00:00 2001 From: Matheus Zaniolo Date: Mon, 4 Aug 2025 10:23:36 +0200 Subject: [PATCH 1/2] feat: Add possibility to set level per dependency --- config-schema.yaml | 16 ++++++++++++++-- config.sample.yaml | 20 ++++++++++++++++++++ src/config.rs | 42 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/config-schema.yaml b/config-schema.yaml index 051dd45..fea6c97 100644 --- a/config-schema.yaml +++ b/config-schema.yaml @@ -59,12 +59,18 @@ definitions: description: Provider configuration for OpenTelemetry export type: object properties: + dependencies_levels: + description: Levels for the dependencies + default: {} + type: object + additionalProperties: + $ref: '#/definitions/LevelFilter' enabled: description: Enables provider default: false type: boolean general_level: - description: Level for the dependencies + description: General level default: info allOf: - $ref: '#/definitions/LevelFilter' @@ -77,12 +83,18 @@ definitions: description: Stdout logs configuration type: object properties: + dependencies_levels: + description: Level for the dependencies + default: {} + type: object + additionalProperties: + $ref: '#/definitions/LevelFilter' enabled: description: Enables the stdout logs default: true type: boolean general_level: - description: Level for the dependencies + description: General level default: info allOf: - $ref: '#/definitions/LevelFilter' diff --git a/config.sample.yaml b/config.sample.yaml index 1733d91..e20a7dd 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -15,6 +15,11 @@ stdout: # optional, default: info general_level: info + # Level for the dependencies + # optional, default: empty + dependencies_levels: + "famedly-rust-utils": debug + # Output structured JSON logs # optional, default: false json_output: false @@ -47,6 +52,11 @@ exporter: # optional, default: info general_level: LevelFilter, + # Level for the dependencies + # optional, default: empty + dependencies_levels: + "famedly-rust-utils": debug + # Traces exporting config # optional traces: @@ -61,6 +71,11 @@ exporter: # optional, default: info general_level: LevelFilter, + # Level for the dependencies + # optional, default: empty + dependencies_levels: + "famedly-rust-utils": debug + # Metrics exporting config # optional metrics: @@ -74,3 +89,8 @@ exporter: # Level for the dependencies # optional, default: info general_level: LevelFilter, + + # Level for the dependencies + # optional, default: empty + dependencies_levels: + "famedly-rust-utils": debug diff --git a/src/config.rs b/src/config.rs index 74a0843..c5b3ff8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,7 +6,7 @@ //! //! Module containing the configuration struct for the OpenTelemetry -use std::collections::BTreeMap as Map; +use std::collections::{BTreeMap as Map, HashMap}; use famedly_rust_utils::LevelFilter; use serde::Deserialize; @@ -57,6 +57,7 @@ impl OtelConfig { enabled: true, level: tracing_subscriber::filter::LevelFilter::TRACE.into(), general_level: tracing_subscriber::filter::LevelFilter::INFO.into(), + dependencies_levels: HashMap::new(), json_output: false, }), exporter: None, @@ -94,9 +95,12 @@ pub struct StdoutLogsConfig { /// Level for the crate #[serde(default = "default_level_filter")] pub level: LevelFilter, - /// Level for the dependencies + /// General level #[serde(default = "default_level_filter")] pub general_level: LevelFilter, + /// Level for the dependencies + #[serde(default)] + pub dependencies_levels: HashMap, /// Output structured JSON logs #[serde(default)] pub json_output: bool, @@ -112,22 +116,37 @@ pub struct ProviderConfig { /// Level for the crate #[serde(default = "default_level_filter")] pub level: LevelFilter, - /// Level for the dependencies + /// General level #[serde(default = "default_level_filter")] pub general_level: LevelFilter, + /// Levels for the dependencies + #[serde(default)] + pub dependencies_levels: HashMap, } impl ProviderConfig { /// Builds a trace filter pub(crate) fn get_filter(&self, crate_name: &'static str) -> String { - format!("{},{}={}", self.general_level, crate_name, self.level) + format!( + "{},{}{}={}", + self.general_level, + build_dependencies_level_string(&self.dependencies_levels), + crate_name, + self.level + ) } } impl StdoutLogsConfig { /// Builds a trace filter pub(crate) fn get_filter(&self, crate_name: &'static str) -> String { - format!("{},{}={}", self.general_level, crate_name, self.level) + format!( + "{},{}{}={}", + self.general_level, + build_dependencies_level_string(&self.dependencies_levels), + crate_name, + self.level + ) } } @@ -137,6 +156,7 @@ impl Default for StdoutLogsConfig { enabled: true, level: default_level_filter(), general_level: default_level_filter(), + dependencies_levels: HashMap::new(), json_output: false, } } @@ -148,6 +168,7 @@ impl Default for ProviderConfig { enabled: false, level: default_level_filter(), general_level: default_level_filter(), + dependencies_levels: HashMap::new(), } } } @@ -161,3 +182,14 @@ const fn default_level_filter() -> LevelFilter { const fn true_() -> bool { true } + +/// Builds a string that configures the filter level of each dependency on the +/// map +fn build_dependencies_level_string(dependencies_levels: &HashMap) -> String { + let mut dependencies_levels = + dependencies_levels.iter().map(|(k, v)| format!("{k}={v}")).collect::>().join(","); + if !dependencies_levels.is_empty() { + dependencies_levels.push(','); + } + dependencies_levels +} From ed535376a59658471902f4099a26d822926b64ef Mon Sep 17 00:00:00 2001 From: Matheus Zaniolo Date: Tue, 12 Aug 2025 08:50:45 +0200 Subject: [PATCH 2/2] chore: Bump dependencies --- Cargo.toml | 7 ++++-- config-schema.yaml | 54 ++++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a1805a..5b3f6de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,10 @@ required-features = ["schemars", "serde_yaml"] [dependencies] async-trait = { version = "^0.1.51" } -famedly_rust_utils = { version = "1.0.0", features = ["level_filter"] } +famedly_rust_utils = { version = "1.0.2", features = [ + "level_filter", + "schemars", +] } http = { version = "1.2.0" } once_cell = { version = "1.20.2" } opentelemetry = { version = "0.30.0" } @@ -33,7 +36,7 @@ tracing-subscriber = { version = "0.3.19", features = ["env-filter", "json"] } tracing = "0.1.40" serde = { version = "1.0.210", features = ["derive"] } url = { version = "2.5.2", features = ["serde"] } -schemars = { version = "0.8.22", optional = true } +schemars = { version = "1.0.4", optional = true, features = ["url2"] } serde_yaml = { version = "0.9.34", optional = true } # tracing-error diff --git a/config-schema.yaml b/config-schema.yaml index fea6c97..9d1d3b0 100644 --- a/config-schema.yaml +++ b/config-schema.yaml @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025 Famedly GmbH (info@famedly.com) # # SPDX-License-Identifier: Apache-2.0 -$schema: http://json-schema.org/draft-07/schema# +$schema: https://json-schema.org/draft/2020-12/schema title: OtelConfig description: OpenTelemetry configuration type: object @@ -9,42 +9,44 @@ properties: exporter: description: Configurations for exporting traces, metrics and logs anyOf: - - $ref: '#/definitions/ExporterConfig' + - $ref: '#/$defs/ExporterConfig' - type: 'null' stdout: description: Enables logs on stdout anyOf: - - $ref: '#/definitions/StdoutLogsConfig' + - $ref: '#/$defs/StdoutLogsConfig' - type: 'null' -definitions: +$defs: ExporterConfig: description: Configuration for exporting OpenTelemetry data type: object properties: endpoint: description: gRPC endpoint for exporting using OTELP - type: string - format: uri + $ref: '#/$defs/OtelUrl' logs: description: Logs exporting config anyOf: - - $ref: '#/definitions/ProviderConfig' + - $ref: '#/$defs/ProviderConfig' - type: 'null' metrics: description: Metrics exporting config anyOf: - - $ref: '#/definitions/ProviderConfig' + - $ref: '#/$defs/ProviderConfig' - type: 'null' resource_metadata: - description: Key value mapping of the OTEL resource. See [Resource semantic conventions](https://opentelemetry.io/docs/specs/semconv/resource/) for what can be set here. Only string values are supported now. This crate sets `service.name` and `service.version` by default. - default: {} + description: |- + Key value mapping of the OTEL resource. See [Resource semantic conventions](https://opentelemetry.io/docs/specs/semconv/resource/) for what can be set here. + Only string values are supported now. + This crate sets `service.name` and `service.version` by default. type: object additionalProperties: type: string + default: {} traces: description: Traces exporting config anyOf: - - $ref: '#/definitions/ProviderConfig' + - $ref: '#/$defs/ProviderConfig' - type: 'null' LevelFilter: type: string @@ -55,55 +57,55 @@ definitions: - info - debug - trace + OtelUrl: + description: Wrapper over [`Url`] with [`Default`] implementation `http://localhost:4317` + type: string + format: uri ProviderConfig: description: Provider configuration for OpenTelemetry export type: object properties: dependencies_levels: description: Levels for the dependencies - default: {} type: object additionalProperties: - $ref: '#/definitions/LevelFilter' + $ref: '#/$defs/LevelFilter' + default: {} enabled: description: Enables provider - default: false type: boolean + default: false general_level: description: General level + $ref: '#/$defs/LevelFilter' default: info - allOf: - - $ref: '#/definitions/LevelFilter' level: description: Level for the crate + $ref: '#/$defs/LevelFilter' default: info - allOf: - - $ref: '#/definitions/LevelFilter' StdoutLogsConfig: description: Stdout logs configuration type: object properties: dependencies_levels: description: Level for the dependencies - default: {} type: object additionalProperties: - $ref: '#/definitions/LevelFilter' + $ref: '#/$defs/LevelFilter' + default: {} enabled: description: Enables the stdout logs - default: true type: boolean + default: true general_level: description: General level + $ref: '#/$defs/LevelFilter' default: info - allOf: - - $ref: '#/definitions/LevelFilter' json_output: description: Output structured JSON logs - default: false type: boolean + default: false level: description: Level for the crate + $ref: '#/$defs/LevelFilter' default: info - allOf: - - $ref: '#/definitions/LevelFilter'