19
19
20
20
use std:: collections:: HashMap ;
21
21
22
+ use quickwit_common:: rate_limited_warn;
22
23
use quickwit_config:: { validate_identifier, validate_index_id_pattern, INGEST_V2_SOURCE_ID } ;
23
24
use quickwit_ingest:: { CommitType , IngestServiceError } ;
24
25
use quickwit_proto:: ingest:: router:: {
@@ -119,46 +120,54 @@ pub(crate) fn extract_attributes(attributes: Vec<OtlpKeyValue>) -> HashMap<Strin
119
120
if let Some ( value) = attribute
120
121
. value
121
122
. and_then ( |any_value| any_value. value )
122
- . and_then ( to_json_value )
123
+ . and_then ( oltp_value_to_json_value )
123
124
{
124
125
attrs. insert ( attribute. key , value) ;
125
126
}
126
127
}
127
128
attrs
128
129
}
129
130
130
- fn to_json_value ( value : OtlpValue ) -> Option < JsonValue > {
131
+ fn oltp_value_to_json_value ( value : OtlpValue ) -> Option < JsonValue > {
131
132
match value {
132
133
OtlpValue :: ArrayValue ( OtlpArrayValue { values } ) => Some (
133
134
values
134
135
. into_iter ( )
135
- . flat_map ( to_json_value_from_primitive_any_value)
136
+ . filter_map ( |value| match value. value {
137
+ Some ( value) => oltp_value_to_json_value ( value) ,
138
+ None => None ,
139
+ } )
136
140
. collect ( ) ,
137
141
) ,
138
- OtlpValue :: BoolValue ( value) => Some ( JsonValue :: Bool ( value) ) ,
139
- OtlpValue :: DoubleValue ( value) => JsonNumber :: from_f64 ( value) . map ( JsonValue :: Number ) ,
140
- OtlpValue :: IntValue ( value) => Some ( JsonValue :: Number ( JsonNumber :: from ( value) ) ) ,
141
- OtlpValue :: StringValue ( value) => Some ( JsonValue :: String ( value) ) ,
142
- OtlpValue :: BytesValue ( _) | OtlpValue :: KvlistValue ( _) => {
143
- // These attribute types are not supported for attributes according to the OpenTelemetry
144
- // specification.
142
+ OtlpValue :: BoolValue ( bool_value) => Some ( JsonValue :: Bool ( bool_value) ) ,
143
+ OtlpValue :: DoubleValue ( double_value) => {
144
+ JsonNumber :: from_f64 ( double_value) . map ( JsonValue :: Number )
145
+ }
146
+ OtlpValue :: IntValue ( int_value) => Some ( JsonValue :: Number ( JsonNumber :: from ( int_value) ) ) ,
147
+ OtlpValue :: KvlistValue ( key_values) => {
148
+ let mut map = serde_json:: Map :: with_capacity ( key_values. values . len ( ) ) ;
149
+
150
+ for key_value in key_values. values {
151
+ if let Some ( value) = key_value
152
+ . value
153
+ . and_then ( |any_value| any_value. value )
154
+ . and_then ( oltp_value_to_json_value)
155
+ {
156
+ map. insert ( key_value. key , value) ;
157
+ }
158
+ }
159
+ Some ( JsonValue :: Object ( map) )
160
+ }
161
+ OtlpValue :: StringValue ( string_value) => Some ( JsonValue :: String ( string_value) ) ,
162
+ OtlpValue :: BytesValue ( _) => {
163
+ rate_limited_warn ! ( limit_per_min = 10 , "ignoring unsupported OTLP bytes value" ) ;
145
164
None
146
165
}
147
166
}
148
167
}
149
168
150
- fn to_json_value_from_primitive_any_value ( any_value : OtlpAnyValue ) -> Option < JsonValue > {
151
- match any_value. value {
152
- Some ( OtlpValue :: BoolValue ( value) ) => Some ( JsonValue :: Bool ( value) ) ,
153
- Some ( OtlpValue :: DoubleValue ( value) ) => JsonNumber :: from_f64 ( value) . map ( JsonValue :: Number ) ,
154
- Some ( OtlpValue :: IntValue ( value) ) => Some ( JsonValue :: Number ( JsonNumber :: from ( value) ) ) ,
155
- Some ( OtlpValue :: StringValue ( value) ) => Some ( JsonValue :: String ( value) ) ,
156
- _ => None ,
157
- }
158
- }
159
-
160
169
pub ( crate ) fn parse_log_record_body ( body : OtlpAnyValue ) -> Option < JsonValue > {
161
- body. value . and_then ( to_json_value ) . map ( |value| {
170
+ body. value . and_then ( oltp_value_to_json_value ) . map ( |value| {
162
171
if value. is_string ( ) {
163
172
let mut map = serde_json:: Map :: with_capacity ( 1 ) ;
164
173
map. insert ( "message" . to_string ( ) , value) ;
@@ -211,15 +220,13 @@ pub(crate) fn extract_otel_index_id_from_metadata(
211
220
. transpose ( )
212
221
. map_err ( |error| {
213
222
Status :: internal ( format ! (
214
- "failed to extract index ID from request metadata: {}" ,
215
- error
223
+ "failed to extract index ID from request metadata: {error}" ,
216
224
) )
217
225
} ) ?
218
226
. unwrap_or_else ( || otel_signal. default_index_id ( ) ) ;
219
227
validate_identifier ( "index_id" , index_id) . map_err ( |error| {
220
228
Status :: internal ( format ! (
221
- "invalid index ID pattern in request metadata: {}" ,
222
- error
229
+ "invalid index ID pattern in request metadata: {error}" ,
223
230
) )
224
231
} ) ?;
225
232
Ok ( index_id. to_string ( ) )
@@ -241,14 +248,11 @@ async fn ingest_doc_batch_v2(
241
248
commit_type : commit_type. into ( ) ,
242
249
subrequests : vec ! [ subrequest] ,
243
250
} ;
244
- let mut response = ingest_router
245
- . ingest ( request)
246
- . await
247
- . map_err ( IngestServiceError :: from) ?;
251
+ let mut response = ingest_router. ingest ( request) . await ?;
248
252
let num_responses = response. successes . len ( ) + response. failures . len ( ) ;
249
253
if num_responses != 1 {
250
254
return Err ( IngestServiceError :: Internal ( format ! (
251
- "Expected a single failure/ success, got {}. " ,
255
+ "expected a single failure or success, got {}" ,
252
256
num_responses
253
257
) ) ) ;
254
258
}
@@ -264,34 +268,75 @@ mod tests {
264
268
use quickwit_proto:: opentelemetry:: proto:: common:: v1:: any_value:: {
265
269
Value as OtlpValue , Value as OtlpAnyValueValue ,
266
270
} ;
267
- use quickwit_proto:: opentelemetry:: proto:: common:: v1:: ArrayValue as OtlpArrayValue ;
271
+ use quickwit_proto:: opentelemetry:: proto:: common:: v1:: {
272
+ ArrayValue as OtlpArrayValue , KeyValueList as OtlpKeyValueList ,
273
+ } ;
268
274
use serde_json:: { json, Value as JsonValue } ;
269
275
270
276
use super :: * ;
271
- use crate :: otlp:: { extract_attributes, parse_log_record_body , to_json_value } ;
277
+ use crate :: otlp:: { extract_attributes, oltp_value_to_json_value , parse_log_record_body } ;
272
278
273
279
#[ test]
274
- fn test_to_json_value ( ) {
280
+ fn test_oltp_value_to_json_value ( ) {
275
281
assert_eq ! (
276
- to_json_value ( OtlpValue :: ArrayValue ( OtlpArrayValue { values: Vec :: new( ) } ) ) ,
282
+ oltp_value_to_json_value ( OtlpValue :: ArrayValue ( OtlpArrayValue { values: Vec :: new( ) } ) ) ,
277
283
Some ( json!( [ ] ) )
278
284
) ;
279
285
assert_eq ! (
280
- to_json_value( OtlpValue :: ArrayValue ( OtlpArrayValue {
281
- values: vec![ OtlpAnyValue {
282
- value: Some ( OtlpAnyValueValue :: IntValue ( 1337 ) )
283
- } ]
286
+ oltp_value_to_json_value( OtlpValue :: ArrayValue ( OtlpArrayValue {
287
+ values: vec![
288
+ OtlpAnyValue {
289
+ value: Some ( OtlpAnyValueValue :: IntValue ( 1337 ) )
290
+ } ,
291
+ OtlpAnyValue {
292
+ value: Some ( OtlpAnyValueValue :: StringValue ( "1337" . to_string( ) ) )
293
+ }
294
+ ]
284
295
} ) ) ,
285
- Some ( json!( [ 1337 ] ) )
296
+ Some ( json!( [ 1337 , "1337" ] ) )
297
+ ) ;
298
+ assert_eq ! (
299
+ oltp_value_to_json_value( OtlpValue :: BoolValue ( true ) ) ,
300
+ Some ( json!( true ) )
286
301
) ;
287
- assert_eq ! ( to_json_value( OtlpValue :: BoolValue ( true ) ) , Some ( json!( true ) ) ) ;
288
302
assert_eq ! (
289
- to_json_value ( OtlpValue :: DoubleValue ( 12.0 ) ) ,
303
+ oltp_value_to_json_value ( OtlpValue :: DoubleValue ( 12.0 ) ) ,
290
304
Some ( json!( 12.0 ) )
291
305
) ;
292
- assert_eq ! ( to_json_value( OtlpValue :: IntValue ( 42 ) ) , Some ( json!( 42 ) ) ) ;
293
306
assert_eq ! (
294
- to_json_value( OtlpValue :: StringValue ( "foo" . to_string( ) ) ) ,
307
+ oltp_value_to_json_value( OtlpValue :: IntValue ( 42 ) ) ,
308
+ Some ( json!( 42 ) )
309
+ ) ;
310
+ assert_eq ! (
311
+ oltp_value_to_json_value( OtlpValue :: KvlistValue ( OtlpKeyValueList {
312
+ values: Vec :: new( )
313
+ } ) ) ,
314
+ Some ( json!( { } ) )
315
+ ) ;
316
+ assert_eq ! (
317
+ oltp_value_to_json_value( OtlpValue :: KvlistValue ( OtlpKeyValueList {
318
+ values: vec![
319
+ OtlpKeyValue {
320
+ key: "foo" . to_string( ) ,
321
+ value: Some ( OtlpAnyValue {
322
+ value: Some ( OtlpAnyValueValue :: IntValue ( 1337 ) )
323
+ } )
324
+ } ,
325
+ OtlpKeyValue {
326
+ key: "bar" . to_string( ) ,
327
+ value: Some ( OtlpAnyValue {
328
+ value: Some ( OtlpAnyValueValue :: StringValue ( "1337" . to_string( ) ) )
329
+ } )
330
+ }
331
+ ]
332
+ } ) ) ,
333
+ Some ( json!( {
334
+ "foo" : 1337 ,
335
+ "bar" : "1337"
336
+ } ) )
337
+ ) ;
338
+ assert_eq ! (
339
+ oltp_value_to_json_value( OtlpValue :: StringValue ( "foo" . to_string( ) ) ) ,
295
340
Some ( json!( "foo" ) )
296
341
) ;
297
342
}
@@ -358,7 +403,7 @@ mod tests {
358
403
} ) ,
359
404
} ,
360
405
] ;
361
- let expected_attributes = std :: collections :: HashMap :: from_iter ( [
406
+ let expected_attributes = HashMap :: from_iter ( [
362
407
( "array_key" . to_string ( ) , json ! ( [ 1337 ] ) ) ,
363
408
( "bool_key" . to_string ( ) , json ! ( true ) ) ,
364
409
( "double_key" . to_string ( ) , json ! ( 12.0 ) ) ,
0 commit comments