1818
1919use std:: collections:: { HashMap , HashSet } ;
2020
21- use actix_web:: web:: { Json , Path } ;
21+ use actix_web:: web:: { self , Json , Path } ;
2222use actix_web:: { HttpRequest , HttpResponse , http:: header:: ContentType } ;
2323use arrow_array:: RecordBatch ;
2424use bytes:: Bytes ;
@@ -33,20 +33,16 @@ use crate::handlers::http::modal::utils::ingest_utils::push_logs;
3333use crate :: handlers:: { EXTRACT_LOG_KEY , LOG_SOURCE_KEY , STREAM_NAME_HEADER_KEY } ;
3434use crate :: metadata:: SchemaVersion ;
3535use crate :: option:: Mode ;
36- use crate :: otel:: logs:: { flatten_otel_protobuf , OTEL_LOG_KNOWN_FIELD_LIST } ;
37- use crate :: otel:: metrics:: OTEL_METRICS_KNOWN_FIELD_LIST ;
38- use crate :: otel:: traces:: OTEL_TRACES_KNOWN_FIELD_LIST ;
36+ use crate :: otel:: logs:: { OTEL_LOG_KNOWN_FIELD_LIST , flatten_otel_protobuf } ;
37+ use crate :: otel:: metrics:: { OTEL_METRICS_KNOWN_FIELD_LIST , flatten_otel_metrics_protobuf } ;
38+ use crate :: otel:: traces:: { OTEL_TRACES_KNOWN_FIELD_LIST , flatten_otel_traces_protobuf } ;
3939use crate :: parseable:: { PARSEABLE , StreamNotFound } ;
4040use crate :: storage:: { ObjectStorageError , StreamType } ;
4141use crate :: utils:: header_parsing:: ParseHeaderError ;
4242use crate :: utils:: json:: { flatten:: JsonFlattenError , strict:: StrictValue } ;
43- use actix_web:: web:: { self , Json , Path } ;
44- use actix_web:: { http:: header:: ContentType , HttpRequest , HttpResponse } ;
45- use arrow_array:: RecordBatch ;
46- use bytes:: Bytes ;
47- use chrono:: Utc ;
48- use http:: StatusCode ;
4943use opentelemetry_proto:: tonic:: collector:: logs:: v1:: ExportLogsServiceRequest ;
44+ use opentelemetry_proto:: tonic:: collector:: metrics:: v1:: ExportMetricsServiceRequest ;
45+ use opentelemetry_proto:: tonic:: collector:: trace:: v1:: ExportTraceServiceRequest ;
5046use prost:: Message ;
5147
5248use super :: logstream:: error:: { CreateStreamError , StreamError } ;
@@ -229,14 +225,25 @@ pub async fn handle_otel_logs_ingestion(
229225 }
230226
231227 if content_type == "application/x-protobuf" {
228+ const MAX_PROTOBUF_SIZE : usize = 10 * 1024 * 1024 ; // 10MB limit
229+ if body. len ( ) > MAX_PROTOBUF_SIZE {
230+ return Err ( PostError :: Invalid ( anyhow:: anyhow!(
231+ "Protobuf message size {} exceeds maximum allowed size of {} bytes" ,
232+ body. len( ) ,
233+ MAX_PROTOBUF_SIZE
234+ ) ) ) ;
235+ }
232236 match ExportLogsServiceRequest :: decode ( body) {
233237 Ok ( json) => {
234238 for record in flatten_otel_protobuf ( & json) {
235239 push_logs ( & stream_name, record, & log_source, & p_custom_fields) . await ?;
236240 }
237241 }
238242 Err ( e) => {
239- return Err ( PostError :: Invalid ( e. into ( ) ) ) ;
243+ return Err ( PostError :: Invalid ( anyhow:: anyhow!(
244+ "Failed to decode protobuf message: {}" ,
245+ e
246+ ) ) ) ;
240247 }
241248 }
242249 }
@@ -254,7 +261,7 @@ pub async fn handle_otel_logs_ingestion(
254261// creates if stream does not exist
255262pub async fn handle_otel_metrics_ingestion (
256263 req : HttpRequest ,
257- Json ( json ) : Json < StrictValue > ,
264+ body : web :: Bytes ,
258265) -> Result < HttpResponse , PostError > {
259266 let Some ( stream_name) = req. headers ( ) . get ( STREAM_NAME_HEADER_KEY ) else {
260267 return Err ( PostError :: Header ( ParseHeaderError :: MissingStreamName ) ) ;
@@ -303,13 +310,35 @@ pub async fn handle_otel_metrics_ingestion(
303310
304311 let p_custom_fields = get_custom_fields_from_header ( & req) ;
305312
306- flatten_and_push_logs (
307- json. into_inner ( ) ,
308- & stream_name,
309- & log_source,
310- & p_custom_fields,
311- )
312- . await ?;
313+ match req. headers ( ) . get ( "Content-Type" ) {
314+ Some ( content_type) => {
315+ if content_type == "application/json" {
316+ flatten_and_push_logs (
317+ serde_json:: from_slice ( & body) ?,
318+ & stream_name,
319+ & log_source,
320+ & p_custom_fields,
321+ )
322+ . await ?;
323+ }
324+
325+ if content_type == "application/x-protobuf" {
326+ match ExportMetricsServiceRequest :: decode ( body) {
327+ Ok ( json) => {
328+ for record in flatten_otel_metrics_protobuf ( & json) {
329+ push_logs ( & stream_name, record, & log_source, & p_custom_fields) . await ?;
330+ }
331+ }
332+ Err ( e) => {
333+ return Err ( PostError :: Invalid ( e. into ( ) ) ) ;
334+ }
335+ }
336+ }
337+ }
338+ None => {
339+ return Err ( PostError :: Header ( ParseHeaderError :: InvalidValue ) ) ;
340+ }
341+ }
313342
314343 Ok ( HttpResponse :: Ok ( ) . finish ( ) )
315344}
@@ -319,7 +348,7 @@ pub async fn handle_otel_metrics_ingestion(
319348// creates if stream does not exist
320349pub async fn handle_otel_traces_ingestion (
321350 req : HttpRequest ,
322- Json ( json ) : Json < StrictValue > ,
351+ body : web :: Bytes ,
323352) -> Result < HttpResponse , PostError > {
324353 let Some ( stream_name) = req. headers ( ) . get ( STREAM_NAME_HEADER_KEY ) else {
325354 return Err ( PostError :: Header ( ParseHeaderError :: MissingStreamName ) ) ;
@@ -369,13 +398,35 @@ pub async fn handle_otel_traces_ingestion(
369398
370399 let p_custom_fields = get_custom_fields_from_header ( & req) ;
371400
372- flatten_and_push_logs (
373- json. into_inner ( ) ,
374- & stream_name,
375- & log_source,
376- & p_custom_fields,
377- )
378- . await ?;
401+ match req. headers ( ) . get ( "Content-Type" ) {
402+ Some ( content_type) => {
403+ if content_type == "application/json" {
404+ flatten_and_push_logs (
405+ serde_json:: from_slice ( & body) ?,
406+ & stream_name,
407+ & log_source,
408+ & p_custom_fields,
409+ )
410+ . await ?;
411+ }
412+
413+ if content_type == "application/x-protobuf" {
414+ match ExportTraceServiceRequest :: decode ( body) {
415+ Ok ( json) => {
416+ for record in flatten_otel_traces_protobuf ( & json) {
417+ push_logs ( & stream_name, record, & log_source, & p_custom_fields) . await ?;
418+ }
419+ }
420+ Err ( e) => {
421+ return Err ( PostError :: Invalid ( e. into ( ) ) ) ;
422+ }
423+ }
424+ }
425+ }
426+ None => {
427+ return Err ( PostError :: Header ( ParseHeaderError :: InvalidValue ) ) ;
428+ }
429+ }
379430
380431 Ok ( HttpResponse :: Ok ( ) . finish ( ) )
381432}
0 commit comments