44use std:: time:: { SystemTime , UNIX_EPOCH } ;
55
66use async_trait:: async_trait;
7- use ddcommon:: hyper_migration;
8- use hyper:: { http, StatusCode } ;
7+ use axum:: {
8+ extract:: Request ,
9+ http:: StatusCode ,
10+ response:: { IntoResponse , Response } ,
11+ } ;
912use tokio:: sync:: mpsc:: Sender ;
10- use tracing:: debug;
13+ use tracing:: { debug, error } ;
1114
1215use datadog_trace_protobuf:: pb;
1316use datadog_trace_utils:: stats_utils;
17+ use ddcommon:: hyper_migration;
1418
1519use super :: trace_agent:: MAX_CONTENT_LENGTH ;
16- use datadog_trace_agent :: http_utils :: { self , log_and_create_http_response } ;
20+ use crate :: http :: extract_request_body ;
1721
1822#[ async_trait]
1923pub trait StatsProcessor {
20- /// Deserializes trace stats from a hyper request body and sends them through
24+ /// Deserializes trace stats from a request body and sends them through
2125 /// the provided tokio mpsc Sender.
2226 async fn process_stats (
2327 & self ,
24- req : hyper_migration :: HttpRequest ,
28+ req : Request ,
2529 tx : Sender < pb:: ClientStatsPayload > ,
26- ) -> http :: Result < hyper_migration :: HttpResponse > ;
30+ ) -> Result < Response , Box < dyn std :: error :: Error + Send + Sync > > ;
2731}
2832
2933#[ derive( Clone , Copy ) ]
@@ -34,30 +38,43 @@ pub struct ServerlessStatsProcessor {}
3438impl StatsProcessor for ServerlessStatsProcessor {
3539 async fn process_stats (
3640 & self ,
37- req : hyper_migration :: HttpRequest ,
41+ req : Request ,
3842 tx : Sender < pb:: ClientStatsPayload > ,
39- ) -> http :: Result < hyper_migration :: HttpResponse > {
43+ ) -> Result < Response , Box < dyn std :: error :: Error + Send + Sync > > {
4044 debug ! ( "Received trace stats to process" ) ;
41- let ( parts, body) = req. into_parts ( ) ;
45+ let ( parts, body) = match extract_request_body ( req) . await {
46+ Ok ( r) => r,
47+ Err ( e) => {
48+ let error_msg = format ! ( "Error extracting request body: {e}" ) ;
49+ error ! ( "{}" , error_msg) ;
50+ return Ok ( ( StatusCode :: BAD_REQUEST , error_msg) . into_response ( ) ) ;
51+ }
52+ } ;
4253
43- if let Some ( response) = http_utils:: verify_request_content_length (
44- & parts. headers ,
45- MAX_CONTENT_LENGTH ,
46- "Error processing trace stats" ,
47- ) {
48- return response;
54+ if let Some ( content_length) = parts. headers . get ( "content-length" ) {
55+ if let Ok ( length_str) = content_length. to_str ( ) {
56+ if let Ok ( length) = length_str. parse :: < usize > ( ) {
57+ if length > MAX_CONTENT_LENGTH {
58+ let error_msg = format ! ( "Content-Length {length} exceeds maximum allowed size {MAX_CONTENT_LENGTH}" ) ;
59+ error ! ( "{}" , error_msg) ;
60+ return Ok ( ( StatusCode :: PAYLOAD_TOO_LARGE , error_msg) . into_response ( ) ) ;
61+ }
62+ }
63+ }
4964 }
5065
5166 // deserialize trace stats from the request body, convert to protobuf structs (see
5267 // trace-protobuf crate)
5368 let mut stats: pb:: ClientStatsPayload =
54- match stats_utils:: get_stats_from_request_body ( body) . await {
69+ match stats_utils:: get_stats_from_request_body ( hyper_migration:: Body :: from_bytes ( body) )
70+ . await
71+ {
5572 Ok ( result) => result,
5673 Err ( err) => {
57- return log_and_create_http_response (
58- & format ! ( "Error deserializing trace stats from request body: {err}" ) ,
59- StatusCode :: INTERNAL_SERVER_ERROR ,
60- ) ;
74+ let error_msg =
75+ format ! ( "Error deserializing trace stats from request body: {err}" ) ;
76+ error ! ( "{}" , error_msg ) ;
77+ return Ok ( ( StatusCode :: INTERNAL_SERVER_ERROR , error_msg ) . into_response ( ) ) ;
6178 }
6279 } ;
6380
@@ -66,29 +83,28 @@ impl StatsProcessor for ServerlessStatsProcessor {
6683 . duration_since ( UNIX_EPOCH )
6784 . unwrap_or_default ( )
6885 . as_nanos ( ) ;
69- stats. stats [ 0 ] . start = match u64:: try_from ( timestamp) {
70- Ok ( result) => result,
71- Err ( _) => {
72- return log_and_create_http_response (
73- "Error converting timestamp to u64" ,
74- StatusCode :: INTERNAL_SERVER_ERROR ,
75- ) ;
76- }
86+ stats. stats [ 0 ] . start = if let Ok ( result) = u64:: try_from ( timestamp) {
87+ result
88+ } else {
89+ let error_msg = "Error converting timestamp to u64" ;
90+ error ! ( "{}" , error_msg) ;
91+ return Ok ( ( StatusCode :: INTERNAL_SERVER_ERROR , error_msg) . into_response ( ) ) ;
7792 } ;
7893
7994 // send trace payload to our trace flusher
8095 match tx. send ( stats) . await {
8196 Ok ( ( ) ) => {
82- return log_and_create_http_response (
83- "Successfully buffered stats to be flushed." ,
97+ debug ! ( "Successfully buffered stats to be flushed." ) ;
98+ Ok ( (
8499 StatusCode :: ACCEPTED ,
85- ) ;
100+ "Successfully buffered stats to be flushed." ,
101+ )
102+ . into_response ( ) )
86103 }
87104 Err ( err) => {
88- return log_and_create_http_response (
89- & format ! ( "Error sending stats to the stats flusher: {err}" ) ,
90- StatusCode :: INTERNAL_SERVER_ERROR ,
91- ) ;
105+ let error_msg = format ! ( "Error sending stats to the stats flusher: {err}" ) ;
106+ error ! ( "{}" , error_msg) ;
107+ Ok ( ( StatusCode :: INTERNAL_SERVER_ERROR , error_msg) . into_response ( ) )
92108 }
93109 }
94110 }
0 commit comments