|
1 | 1 | //! OpenTelemetry configuration. |
2 | 2 |
|
3 | | -use serde::{Deserialize, Serialize}; |
| 3 | +use serde::{Deserialize, Deserializer, Serialize}; |
4 | 4 |
|
5 | 5 | /// OpenTelemetry settings. |
6 | 6 | #[derive(Debug, Clone, Serialize, Deserialize)] |
@@ -30,14 +30,28 @@ pub struct OtelSettings { |
30 | 30 | pub propagate_context: bool, |
31 | 31 |
|
32 | 32 | /// Sampling ratio (0.0 to 1.0). |
33 | | - #[serde(default = "default_sampling_ratio")] |
| 33 | + #[serde(default = "default_sampling_ratio", deserialize_with = "deserialize_sampling_ratio")] |
34 | 34 | pub sampling_ratio: f64, |
35 | 35 |
|
36 | 36 | /// Export timeout in seconds. |
37 | 37 | #[serde(default = "default_export_timeout")] |
38 | 38 | pub export_timeout_secs: u64, |
39 | 39 | } |
40 | 40 |
|
| 41 | +/// Deserialize sampling_ratio with validation (must be 0.0-1.0). |
| 42 | +fn deserialize_sampling_ratio<'de, D>(deserializer: D) -> Result<f64, D::Error> |
| 43 | +where |
| 44 | + D: Deserializer<'de>, |
| 45 | +{ |
| 46 | + let value = f64::deserialize(deserializer)?; |
| 47 | + if !(0.0..=1.0).contains(&value) { |
| 48 | + return Err(serde::de::Error::custom( |
| 49 | + "sampling_ratio must be between 0.0 and 1.0", |
| 50 | + )); |
| 51 | + } |
| 52 | + Ok(value) |
| 53 | +} |
| 54 | + |
41 | 55 | impl Default for OtelSettings { |
42 | 56 | fn default() -> Self { |
43 | 57 | OtelSettings { |
@@ -84,7 +98,8 @@ impl OtelSettings { |
84 | 98 | } |
85 | 99 |
|
86 | 100 | if let Ok(ratio) = std::env::var("OTEL_TRACES_SAMPLER_ARG") |
87 | | - && let Ok(ratio) = ratio.parse() |
| 101 | + && let Ok(ratio) = ratio.parse::<f64>() |
| 102 | + && (0.0..=1.0).contains(&ratio) |
88 | 103 | { |
89 | 104 | settings.sampling_ratio = ratio; |
90 | 105 | } |
|
0 commit comments