scouter_tracing/exporter/
http.rs1use std::collections::HashMap;
2
3use crate::error::TraceError;
4use crate::exporter::traits::SpanExporterBuilder;
5use crate::exporter::ExporterType;
6use crate::utils::{ExportConfig, OtelHttpConfig, OtelProtocol};
7use opentelemetry_otlp::ExportConfig as OtlpExportConfig;
8use opentelemetry_otlp::SpanExporter as OtlpSpanExporter;
9use opentelemetry_otlp::WithExportConfig;
10use opentelemetry_otlp::WithHttpConfig;
11use pyo3::prelude::*;
12use scouter_types::{CompressionType, PyHelperFuncs};
13use serde::Serialize;
14use std::time::Duration;
15
16#[derive(Debug, Clone, Serialize)]
17#[pyclass]
18pub struct HttpSpanExporter {
19 #[pyo3(get)]
20 pub sample_ratio: Option<f64>,
21
22 #[pyo3(get)]
23 pub batch_export: bool,
24
25 #[pyo3(get)]
26 endpoint: Option<String>,
27
28 #[pyo3(get)]
29 protocol: OtelProtocol,
30
31 #[pyo3(get)]
32 timeout: Option<u64>,
33
34 #[pyo3(get)]
35 headers: Option<HashMap<String, String>>,
36
37 #[pyo3(get)]
38 compression: Option<CompressionType>,
39}
40
41#[pymethods]
42impl HttpSpanExporter {
43 #[new]
44 #[pyo3(signature = (batch_export=true, export_config=None, http_config=None, sample_ratio=None))]
45 pub fn new(
46 batch_export: bool,
47 export_config: Option<&ExportConfig>,
48 http_config: Option<&OtelHttpConfig>,
49 sample_ratio: Option<f64>,
50 ) -> Result<Self, TraceError> {
51 let (endpoint, protocol, timeout) = if let Some(config) = export_config {
52 (
53 config.endpoint.clone(),
54 config.protocol.clone(),
55 config.timeout,
56 )
57 } else {
58 (None, OtelProtocol::default(), None)
59 };
60
61 let headers = http_config.and_then(|cfg| cfg.headers.clone());
62 let compression = if let Some(http_config) = http_config {
63 http_config.compression.clone()
64 } else {
65 None
66 };
67
68 Ok(Self {
69 batch_export,
70 sample_ratio,
71 endpoint,
72 protocol,
73 timeout,
74 headers,
75 compression,
76 })
77 }
78
79 pub fn __str__(&self) -> String {
80 PyHelperFuncs::__str__(self)
81 }
82}
83
84impl SpanExporterBuilder for HttpSpanExporter {
85 type Exporter = OtlpSpanExporter;
86
87 fn export_type(&self) -> ExporterType {
88 ExporterType::Http
89 }
90
91 fn sample_ratio(&self) -> Option<f64> {
92 self.sample_ratio
93 }
94
95 fn batch_export(&self) -> bool {
96 self.batch_export
97 }
98
99 fn build_exporter(&self) -> Result<Self::Exporter, TraceError> {
100 let timeout = self.timeout.map(Duration::from_secs);
102 let export_config = OtlpExportConfig {
103 endpoint: self.endpoint.clone(),
104 protocol: self.protocol.to_otel_protocol(),
105 timeout,
106 };
107
108 let mut exporter = opentelemetry_otlp::SpanExporter::builder()
109 .with_http()
110 .with_export_config(export_config);
111
112 if let Some(headers) = &self.headers {
113 exporter = exporter.with_headers(headers.clone());
114 }
115
116 if let Some(compression) = &self.compression {
117 exporter = exporter.with_compression(compression.to_otel_compression()?);
118 }
119
120 Ok(exporter.build()?)
121 }
122}