@@ -33,6 +33,7 @@ public class SentryTracingFilter extends OncePerRequestFilter {
3333 private static final String TRANSACTION_OP = "http.server" ;
3434
3535 private static final String TRACE_ORIGIN = "auto.http.spring.webmvc" ;
36+ private static final String TRANSACTION_ATTR = AsyncSentryTracingFilter .class .getName () + ".transaction" ;
3637
3738 private final @ NotNull TransactionNameProvider transactionNameProvider ;
3839 private final @ NotNull IHub hub ;
@@ -67,6 +68,11 @@ public SentryTracingFilter(final @NotNull IHub hub) {
6768 this (hub , new SpringMvcTransactionNameProvider ());
6869 }
6970
71+ @ Override
72+ protected boolean shouldNotFilterAsyncDispatch () {
73+ return false ;
74+ }
75+
7076 @ Override
7177 protected void doFilterInternal (
7278 final @ NotNull HttpServletRequest httpRequest ,
@@ -75,15 +81,8 @@ protected void doFilterInternal(
7581 throws ServletException , IOException {
7682
7783 if (hub .isEnabled ()) {
78- final @ Nullable String sentryTraceHeader =
79- httpRequest .getHeader (SentryTraceHeader .SENTRY_TRACE_HEADER );
80- final @ Nullable List <String > baggageHeader =
81- Collections .list (httpRequest .getHeaders (BaggageHeader .BAGGAGE_HEADER ));
82- final @ Nullable TransactionContext transactionContext =
83- hub .continueTrace (sentryTraceHeader , baggageHeader );
84-
8584 if (hub .getOptions ().isTracingEnabled () && shouldTraceRequest (httpRequest )) {
86- doFilterWithTransaction (httpRequest , httpResponse , filterChain , transactionContext );
85+ doFilterWithTransaction (httpRequest , httpResponse , filterChain );
8786 } else {
8887 filterChain .doFilter (httpRequest , httpResponse );
8988 }
@@ -95,12 +94,24 @@ protected void doFilterInternal(
9594 private void doFilterWithTransaction (
9695 HttpServletRequest httpRequest ,
9796 HttpServletResponse httpResponse ,
98- FilterChain filterChain ,
99- final @ Nullable TransactionContext transactionContext )
97+ FilterChain filterChain )
10098 throws IOException , ServletException {
101- // at this stage we are not able to get real transaction name
102- final ITransaction transaction = startTransaction (httpRequest , transactionContext );
103- transaction .getSpanContext ().setOrigin (TRACE_ORIGIN );
99+ final ITransaction transaction ;
100+ if (isAsyncDispatch (httpRequest )) {
101+ transaction = (ITransaction ) httpRequest .getAttribute (TRANSACTION_ATTR );
102+ } else {
103+ final @ Nullable String sentryTraceHeader =
104+ httpRequest .getHeader (SentryTraceHeader .SENTRY_TRACE_HEADER );
105+ final @ Nullable List <String > baggageHeader =
106+ Collections .list (httpRequest .getHeaders (BaggageHeader .BAGGAGE_HEADER ));
107+ final @ Nullable TransactionContext transactionContext =
108+ hub .continueTrace (sentryTraceHeader , baggageHeader );
109+
110+ // at this stage we are not able to get real transaction name
111+ transaction = startTransaction (httpRequest , transactionContext );
112+ transaction .getSpanContext ().setOrigin (TRACE_ORIGIN );
113+ httpRequest .setAttribute (TRANSACTION_ATTR , transaction );
114+ }
104115
105116 try {
106117 filterChain .doFilter (httpRequest , httpResponse );
@@ -109,21 +120,23 @@ private void doFilterWithTransaction(
109120 transaction .setStatus (SpanStatus .INTERNAL_ERROR );
110121 throw e ;
111122 } finally {
112- // after all filters run, templated path pattern is available in request attribute
113- final String transactionName = transactionNameProvider .provideTransactionName (httpRequest );
114- final TransactionNameSource transactionNameSource =
115- transactionNameProvider .provideTransactionSource ();
116- // if transaction name is not resolved, the request has not been processed by a controller
117- // and we should not report it to Sentry
118- if (transactionName != null ) {
119- transaction .setName (transactionName , transactionNameSource );
120- transaction .setOperation (TRANSACTION_OP );
121- // if exception has been thrown, transaction status is already set to INTERNAL_ERROR, and
122- // httpResponse.getStatus() returns 200.
123- if (transaction .getStatus () == null ) {
124- transaction .setStatus (SpanStatus .fromHttpStatusCode (httpResponse .getStatus ()));
123+ if (!isAsyncStarted (httpRequest )) {
124+ // after all filters run, templated path pattern is available in request attribute
125+ final String transactionName = transactionNameProvider .provideTransactionName (httpRequest );
126+ final TransactionNameSource transactionNameSource =
127+ transactionNameProvider .provideTransactionSource ();
128+ // if transaction name is not resolved, the request has not been processed by a controller
129+ // and we should not report it to Sentry
130+ if (transactionName != null ) {
131+ transaction .setName (transactionName , transactionNameSource );
132+ transaction .setOperation (TRANSACTION_OP );
133+ // if exception has been thrown, transaction status is already set to INTERNAL_ERROR, and
134+ // httpResponse.getStatus() returns 200.
135+ if (transaction .getStatus () == null ) {
136+ transaction .setStatus (SpanStatus .fromHttpStatusCode (httpResponse .getStatus ()));
137+ }
138+ transaction .finish ();
125139 }
126- transaction .finish ();
127140 }
128141 }
129142 }
0 commit comments