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