1
+ use super :: { default_headers, default_protocol, parse_header_string} ;
1
2
use crate :: {
2
3
ExportConfig , Protocol , OTEL_EXPORTER_OTLP_ENDPOINT , OTEL_EXPORTER_OTLP_HEADERS ,
3
4
OTEL_EXPORTER_OTLP_TIMEOUT ,
4
5
} ;
5
6
use http:: { HeaderName , HeaderValue , Uri } ;
6
7
use opentelemetry_http:: HttpClient ;
8
+ #[ cfg( feature = "logs" ) ]
9
+ use opentelemetry_sdk:: export:: logs:: LogData ;
10
+ #[ cfg( feature = "trace" ) ]
11
+ use opentelemetry_sdk:: export:: trace:: SpanData ;
12
+ #[ cfg( feature = "metrics" ) ]
13
+ use opentelemetry_sdk:: metrics:: data:: ResourceMetrics ;
14
+ use prost:: Message ;
7
15
use std:: collections:: HashMap ;
8
16
use std:: env;
9
17
use std:: str:: FromStr ;
10
18
use std:: sync:: { Arc , Mutex } ;
11
19
use std:: time:: Duration ;
12
20
13
- use super :: { default_headers, parse_header_string} ;
14
-
15
21
#[ cfg( feature = "metrics" ) ]
16
22
mod metrics;
17
23
@@ -22,7 +28,7 @@ mod logs;
22
28
mod trace;
23
29
24
30
/// Configuration of the http transport
25
- #[ cfg( feature = "http-proto" ) ]
31
+ #[ cfg( any ( feature = "http-proto" , feature = "http-json" ) ) ]
26
32
#[ derive( Debug ) ]
27
33
#[ cfg_attr(
28
34
all(
@@ -98,7 +104,7 @@ impl Default for HttpExporterBuilder {
98
104
fn default ( ) -> Self {
99
105
HttpExporterBuilder {
100
106
exporter_config : ExportConfig {
101
- protocol : Protocol :: HttpBinary ,
107
+ protocol : default_protocol ( ) ,
102
108
..ExportConfig :: default ( )
103
109
} ,
104
110
http_config : HttpConfig {
@@ -110,6 +116,12 @@ impl Default for HttpExporterBuilder {
110
116
}
111
117
112
118
impl HttpExporterBuilder {
119
+ /// Specify the OTLP protocol to be used by the exporter
120
+ pub fn with_protocol ( mut self , protocol : Protocol ) -> Self {
121
+ self . exporter_config . protocol = protocol;
122
+ self
123
+ }
124
+
113
125
/// Assign client implementation
114
126
pub fn with_http_client < T : HttpClient + ' static > ( mut self , client : T ) -> Self {
115
127
self . http_config . client = Some ( Arc :: new ( client) ) ;
@@ -181,7 +193,13 @@ impl HttpExporterBuilder {
181
193
add_header_from_string ( & input, & mut headers) ;
182
194
}
183
195
184
- Ok ( OtlpHttpClient :: new ( http_client, endpoint, headers, timeout) )
196
+ Ok ( OtlpHttpClient :: new (
197
+ http_client,
198
+ endpoint,
199
+ headers,
200
+ self . exporter_config . protocol ,
201
+ timeout,
202
+ ) )
185
203
}
186
204
187
205
/// Create a log exporter with the current configuration
@@ -254,6 +272,7 @@ struct OtlpHttpClient {
254
272
client : Mutex < Option < Arc < dyn HttpClient > > > ,
255
273
collector_endpoint : Uri ,
256
274
headers : HashMap < HeaderName , HeaderValue > ,
275
+ protocol : Protocol ,
257
276
_timeout : Duration ,
258
277
}
259
278
@@ -263,15 +282,76 @@ impl OtlpHttpClient {
263
282
client : Arc < dyn HttpClient > ,
264
283
collector_endpoint : Uri ,
265
284
headers : HashMap < HeaderName , HeaderValue > ,
285
+ protocol : Protocol ,
266
286
timeout : Duration ,
267
287
) -> Self {
268
288
OtlpHttpClient {
269
289
client : Mutex :: new ( Some ( client) ) ,
270
290
collector_endpoint,
271
291
headers,
292
+ protocol,
272
293
_timeout : timeout,
273
294
}
274
295
}
296
+
297
+ #[ cfg( feature = "trace" ) ]
298
+ fn build_trace_export_body (
299
+ & self ,
300
+ spans : Vec < SpanData > ,
301
+ ) -> opentelemetry:: trace:: TraceResult < ( Vec < u8 > , & ' static str ) > {
302
+ use opentelemetry_proto:: tonic:: collector:: trace:: v1:: ExportTraceServiceRequest ;
303
+
304
+ let req = ExportTraceServiceRequest {
305
+ resource_spans : spans. into_iter ( ) . map ( Into :: into) . collect ( ) ,
306
+ } ;
307
+ match self . protocol {
308
+ #[ cfg( feature = "http-json" ) ]
309
+ Protocol :: HttpJson => match serde_json:: to_string_pretty ( & req) {
310
+ Ok ( json) => Ok ( ( json. into ( ) , "application/json" ) ) ,
311
+ Err ( e) => Err ( opentelemetry:: trace:: TraceError :: from ( e. to_string ( ) ) ) ,
312
+ } ,
313
+ _ => Ok ( ( req. encode_to_vec ( ) , "application/x-protobuf" ) ) ,
314
+ }
315
+ }
316
+
317
+ #[ cfg( feature = "logs" ) ]
318
+ fn build_logs_export_body (
319
+ & self ,
320
+ logs : Vec < LogData > ,
321
+ ) -> opentelemetry:: logs:: LogResult < ( Vec < u8 > , & ' static str ) > {
322
+ use opentelemetry_proto:: tonic:: collector:: logs:: v1:: ExportLogsServiceRequest ;
323
+
324
+ let req = ExportLogsServiceRequest {
325
+ resource_logs : logs. into_iter ( ) . map ( Into :: into) . collect ( ) ,
326
+ } ;
327
+ match self . protocol {
328
+ #[ cfg( feature = "http-json" ) ]
329
+ Protocol :: HttpJson => match serde_json:: to_string_pretty ( & req) {
330
+ Ok ( json) => Ok ( ( json. into ( ) , "application/json" ) ) ,
331
+ Err ( e) => Err ( opentelemetry:: logs:: LogError :: from ( e. to_string ( ) ) ) ,
332
+ } ,
333
+ _ => Ok ( ( req. encode_to_vec ( ) , "application/x-protobuf" ) ) ,
334
+ }
335
+ }
336
+
337
+ #[ cfg( feature = "metrics" ) ]
338
+ fn build_metrics_export_body (
339
+ & self ,
340
+ metrics : & mut ResourceMetrics ,
341
+ ) -> opentelemetry:: metrics:: Result < ( Vec < u8 > , & ' static str ) > {
342
+ use opentelemetry_proto:: tonic:: collector:: metrics:: v1:: ExportMetricsServiceRequest ;
343
+
344
+ let req: ExportMetricsServiceRequest = ( & * metrics) . into ( ) ;
345
+
346
+ match self . protocol {
347
+ #[ cfg( feature = "http-json" ) ]
348
+ Protocol :: HttpJson => match serde_json:: to_string_pretty ( & req) {
349
+ Ok ( json) => Ok ( ( json. into ( ) , "application/json" ) ) ,
350
+ Err ( e) => Err ( opentelemetry:: metrics:: MetricsError :: Other ( e. to_string ( ) ) ) ,
351
+ } ,
352
+ _ => Ok ( ( req. encode_to_vec ( ) , "application/x-protobuf" ) ) ,
353
+ }
354
+ }
275
355
}
276
356
277
357
fn build_endpoint_uri ( endpoint : & str , path : & str ) -> Result < Uri , crate :: Error > {
0 commit comments