@@ -237,12 +237,10 @@ where
237237 . as_ref ( )
238238 . map_or ( false , |client| client. options ( ) . send_default_pii ) ;
239239
240- let ( mut tx, sentry_req) = sentry_request_from_http ( & req, with_pii) ;
240+ let sentry_req = sentry_request_from_http ( & req, with_pii) ;
241+ let name = transaction_name_from_http ( & req) ;
241242
242243 let transaction = if inner. start_transaction {
243- let name = std:: mem:: take ( & mut tx)
244- . unwrap_or_else ( || format ! ( "{} {}" , req. method( ) , req. uri( ) ) ) ;
245-
246244 let headers = req. headers ( ) . iter ( ) . flat_map ( |( header, value) | {
247245 value. to_str ( ) . ok ( ) . map ( |value| ( header. as_str ( ) , value) )
248246 } ) ;
@@ -262,7 +260,7 @@ where
262260 if let Some ( transaction) = transaction. as_ref ( ) {
263261 scope. set_span ( Some ( transaction. clone ( ) . into ( ) ) ) ;
264262 } else {
265- scope. set_transaction ( tx . as_deref ( ) ) ;
263+ scope. set_transaction ( ( !inner . start_transaction ) . then_some ( & name ) ) ;
266264 }
267265 scope. add_event_processor ( move |event| Some ( process_event ( event, & sentry_req) ) ) ;
268266 parent_span
@@ -336,14 +334,14 @@ fn map_status(status: StatusCode) -> protocol::SpanStatus {
336334 }
337335}
338336
339- /// Build a Sentry request struct from the HTTP request
340- fn sentry_request_from_http ( request : & ServiceRequest , with_pii : bool ) -> ( Option < String > , Request ) {
341- let transaction = if let Some ( name) = request. match_name ( ) {
342- Some ( String :: from ( name) )
343- } else {
344- request. match_pattern ( )
345- } ;
337+ /// Extract a transaction name from the HTTP request
338+ fn transaction_name_from_http ( req : & ServiceRequest ) -> String {
339+ let path_part = req. match_pattern ( ) . unwrap_or_else ( || "<none>" . to_string ( ) ) ;
340+ format ! ( "{} {}" , req. method( ) , path_part)
341+ }
346342
343+ /// Build a Sentry request struct from the HTTP request
344+ fn sentry_request_from_http ( request : & ServiceRequest , with_pii : bool ) -> Request {
347345 let mut sentry_req = Request {
348346 url : format ! (
349347 "{}://{}{}" ,
@@ -369,7 +367,7 @@ fn sentry_request_from_http(request: &ServiceRequest, with_pii: bool) -> (Option
369367 }
370368 } ;
371369
372- ( transaction , sentry_req)
370+ sentry_req
373371}
374372
375373/// Add request data to a Sentry event
@@ -451,13 +449,56 @@ mod tests {
451449 assert_eq ! ( events. len( ) , 2 ) ;
452450 for event in events {
453451 let request = event. request . expect ( "Request should be set." ) ;
454- assert_eq ! ( event. transaction, Some ( "/test" . into( ) ) ) ;
452+ assert_eq ! ( event. transaction, Some ( "GET /test" . into( ) ) ) ;
455453 assert_eq ! ( event. message, Some ( "Message" . into( ) ) ) ;
456454 assert_eq ! ( event. level, Level :: Warning ) ;
457455 assert_eq ! ( request. method, Some ( "GET" . into( ) ) ) ;
458456 }
459457 }
460458
459+ /// Test transaction name HTTP verb.
460+ #[ actix_web:: test]
461+ async fn test_match_pattern ( ) {
462+ let events = sentry:: test:: with_captured_events ( || {
463+ block_on ( async {
464+ let service = |_name : String | {
465+ // Current Hub should have no events
466+ _assert_hub_no_events ( ) ;
467+
468+ sentry:: capture_message ( "Message" , Level :: Warning ) ;
469+
470+ // Current Hub should have the event
471+ _assert_hub_has_events ( ) ;
472+
473+ HttpResponse :: Ok ( )
474+ } ;
475+
476+ let app = init_service (
477+ App :: new ( )
478+ . wrap ( Sentry :: builder ( ) . with_hub ( Hub :: current ( ) ) . finish ( ) )
479+ . service ( web:: resource ( "/test/{name}" ) . route ( web:: post ( ) . to ( service) ) ) ,
480+ )
481+ . await ;
482+
483+ // Call the service twice (sequentially) to ensure the middleware isn't sticky
484+ for _ in 0 ..2 {
485+ let req = TestRequest :: post ( ) . uri ( "/test/fake_name" ) . to_request ( ) ;
486+ let res = call_service ( & app, req) . await ;
487+ assert ! ( res. status( ) . is_success( ) ) ;
488+ }
489+ } )
490+ } ) ;
491+
492+ assert_eq ! ( events. len( ) , 2 ) ;
493+ for event in events {
494+ let request = event. request . expect ( "Request should be set." ) ;
495+ assert_eq ! ( event. transaction, Some ( "POST /test/{name}" . into( ) ) ) ;
496+ assert_eq ! ( event. message, Some ( "Message" . into( ) ) ) ;
497+ assert_eq ! ( event. level, Level :: Warning ) ;
498+ assert_eq ! ( request. method, Some ( "POST" . into( ) ) ) ;
499+ }
500+ }
501+
461502 /// Ensures errors returned in the Actix service trigger an event.
462503 #[ actix_web:: test]
463504 async fn test_response_errors ( ) {
@@ -490,7 +531,7 @@ mod tests {
490531 assert_eq ! ( events. len( ) , 2 ) ;
491532 for event in events {
492533 let request = event. request . expect ( "Request should be set." ) ;
493- assert_eq ! ( event. transaction, Some ( "failing " . into( ) ) ) ; // Transaction name is the name of the function
534+ assert_eq ! ( event. transaction, Some ( "GET /test " . into( ) ) ) ; // Transaction name is the matcher of the route
494535 assert_eq ! ( event. message, None ) ;
495536 assert_eq ! ( event. exception. values[ 0 ] . ty, String :: from( "Custom" ) ) ;
496537 assert_eq ! ( event. exception. values[ 0 ] . value, Some ( "Test Error" . into( ) ) ) ;
0 commit comments