@@ -28,9 +28,12 @@ pub(super) struct AggregationKey<'a> {
2828 is_synthetics_request : bool ,
2929 peer_tags : Vec < ( Cow < ' a , str > , Cow < ' a , str > ) > ,
3030 is_trace_root : bool ,
31+ http_method : Cow < ' a , str > ,
32+ http_endpoint : Cow < ' a , str > ,
3133}
3234
3335/// Common representation of AggregationKey used to compare AggregationKey with different lifetimes
36+ /// field order must be the same as in AggregationKey, o/wise hashes will be different
3437#[ derive( Clone , Hash , PartialEq , Eq ) ]
3538pub ( super ) struct BorrowedAggregationKey < ' a > {
3639 resource_name : & ' a str ,
@@ -42,6 +45,8 @@ pub(super) struct BorrowedAggregationKey<'a> {
4245 is_synthetics_request : bool ,
4346 peer_tags : Vec < ( & ' a str , & ' a str ) > ,
4447 is_trace_root : bool ,
48+ http_method : & ' a str ,
49+ http_endpoint : & ' a str ,
4550}
4651
4752/// Trait used to define a common type (`dyn BorrowableAggregationKey`) for all AggregationKey
@@ -71,6 +76,8 @@ impl BorrowableAggregationKey for AggregationKey<'_> {
7176 . map ( |( tag, value) | ( tag. borrow ( ) , value. borrow ( ) ) )
7277 . collect ( ) ,
7378 is_trace_root : self . is_trace_root ,
79+ http_method : self . http_method . borrow ( ) ,
80+ http_endpoint : self . http_endpoint . borrow ( ) ,
7481 }
7582 }
7683}
@@ -124,13 +131,29 @@ impl<'a> AggregationKey<'a> {
124131 } else {
125132 vec ! [ ]
126133 } ;
134+
135+ let http_method = span
136+ . meta
137+ . get ( "http.method" )
138+ . map ( |s| s. borrow ( ) )
139+ . unwrap_or_default ( ) ;
140+
141+ let http_endpoint = span
142+ . meta
143+ . get ( "http.endpoint" )
144+ . or_else ( || span. meta . get ( "http.route" ) )
145+ . map ( |s| s. borrow ( ) )
146+ . unwrap_or_default ( ) ;
147+
127148 Self {
128149 resource_name : span. resource . borrow ( ) . into ( ) ,
129150 service_name : span. service . borrow ( ) . into ( ) ,
130151 operation_name : span. name . borrow ( ) . into ( ) ,
131152 span_type : span. r#type . borrow ( ) . into ( ) ,
132153 span_kind : span_kind. into ( ) ,
133154 http_status_code : get_status_code ( span) ,
155+ http_method : http_method. into ( ) ,
156+ http_endpoint : http_endpoint. into ( ) ,
134157 is_synthetics_request : span
135158 . meta
136159 . get ( TAG_ORIGIN )
@@ -153,6 +176,8 @@ impl<'a> AggregationKey<'a> {
153176 span_type : Cow :: Owned ( self . span_type . into_owned ( ) ) ,
154177 span_kind : Cow :: Owned ( self . span_kind . into_owned ( ) ) ,
155178 http_status_code : self . http_status_code ,
179+ http_method : Cow :: Owned ( self . http_method . into_owned ( ) ) ,
180+ http_endpoint : Cow :: Owned ( self . http_endpoint . into_owned ( ) ) ,
156181 is_synthetics_request : self . is_synthetics_request ,
157182 is_trace_root : self . is_trace_root ,
158183 peer_tags : self
@@ -183,6 +208,8 @@ impl From<pb::ClientGroupedStats> for AggregationKey<'static> {
183208 } )
184209 . collect ( ) ,
185210 is_trace_root : value. is_trace_root == 1 ,
211+ http_method : value. http_method . into ( ) ,
212+ http_endpoint : value. http_endpoint . into ( ) ,
186213 }
187214 }
188215}
@@ -335,6 +362,9 @@ fn encode_grouped_stats(key: AggregationKey, group: GroupedStats) -> pb::ClientG
335362 } else {
336363 pb:: Trilean :: False . into ( )
337364 } ,
365+ http_method : key. http_method . into_owned ( ) ,
366+ http_endpoint : key. http_endpoint . into_owned ( ) ,
367+ grpc_status_code : String :: new ( ) , // currently not used
338368 }
339369}
340370
@@ -541,6 +571,57 @@ mod tests {
541571 ..Default :: default ( )
542572 } ,
543573 ) ,
574+ // Span with http.method and http.route
575+ (
576+ SpanBytes {
577+ service: "service" . into( ) ,
578+ name: "op" . into( ) ,
579+ resource: "GET /api/v1/users" . into( ) ,
580+ span_id: 1 ,
581+ parent_id: 0 ,
582+ meta: HashMap :: from( [
583+ ( "http.method" . into( ) , "GET" . into( ) ) ,
584+ ( "http.route" . into( ) , "/api/v1/users" . into( ) ) ,
585+ ] ) ,
586+ ..Default :: default ( )
587+ } ,
588+ AggregationKey {
589+ service_name: "service" . into( ) ,
590+ operation_name: "op" . into( ) ,
591+ resource_name: "GET /api/v1/users" . into( ) ,
592+ http_method: "GET" . into( ) ,
593+ http_endpoint: "/api/v1/users" . into( ) ,
594+ is_synthetics_request: false ,
595+ is_trace_root: true ,
596+ ..Default :: default ( )
597+ } ,
598+ ) ,
599+ // Span with http.method and http.endpoint (http.endpoint takes precedence)
600+ (
601+ SpanBytes {
602+ service: "service" . into( ) ,
603+ name: "op" . into( ) ,
604+ resource: "POST /users/create" . into( ) ,
605+ span_id: 1 ,
606+ parent_id: 0 ,
607+ meta: HashMap :: from( [
608+ ( "http.method" . into( ) , "POST" . into( ) ) ,
609+ ( "http.route" . into( ) , "/users/create" . into( ) ) ,
610+ ( "http.endpoint" . into( ) , "/users/create2" . into( ) ) ,
611+ ] ) ,
612+ ..Default :: default ( )
613+ } ,
614+ AggregationKey {
615+ service_name: "service" . into( ) ,
616+ operation_name: "op" . into( ) ,
617+ resource_name: "POST /users/create" . into( ) ,
618+ http_method: "POST" . into( ) ,
619+ http_endpoint: "/users/create2" . into( ) ,
620+ is_synthetics_request: false ,
621+ is_trace_root: true ,
622+ ..Default :: default ( )
623+ } ,
624+ ) ,
544625 ] ;
545626
546627 let test_peer_tags = vec ! [
0 commit comments