9
9
import io .opentelemetry .context .Scope ;
10
10
import io .opentelemetry .context .propagation .ContextPropagators ;
11
11
import io .opentelemetry .instrumentation .api .instrumenter .Instrumenter ;
12
+ import io .opentelemetry .instrumentation .api .semconv .http .HttpClientRequestResendCount ;
12
13
import java .io .IOException ;
13
- import javax .annotation .Nullable ;
14
14
import org .apache .http .HttpException ;
15
15
import org .apache .http .HttpHost ;
16
16
import org .apache .http .HttpResponse ;
17
- import org .apache .http .ProtocolException ;
18
- import org .apache .http .client .ClientProtocolException ;
19
17
import org .apache .http .client .methods .CloseableHttpResponse ;
20
18
import org .apache .http .client .methods .HttpExecutionAware ;
21
19
import org .apache .http .client .methods .HttpRequestWrapper ;
22
20
import org .apache .http .client .protocol .HttpClientContext ;
23
21
import org .apache .http .conn .routing .HttpRoute ;
24
- import org .apache .http .impl .client .DefaultRedirectStrategy ;
25
- import org .apache .http .impl .client .RedirectLocations ;
26
22
import org .apache .http .impl .execchain .ClientExecChain ;
27
23
28
24
final class TracingProtocolExec implements ClientExecChain {
29
25
30
- private static final String REQUEST_CONTEXT_ATTRIBUTE_ID =
26
+ private static final String REQUEST_PARENT_CONTEXT_ATTRIBUTE_ID =
31
27
TracingProtocolExec .class .getName () + ".context" ;
32
- private static final String REQUEST_WRAPPER_ATTRIBUTE_ID =
33
- TracingProtocolExec .class .getName () + ".requestWrapper" ;
34
- private static final String REDIRECT_COUNT_ATTRIBUTE_ID =
35
- TracingProtocolExec .class .getName () + ".redirectCount" ;
36
28
37
29
private final Instrumenter <ApacheHttpClientRequest , HttpResponse > instrumenter ;
38
30
private final ContextPropagators propagators ;
@@ -54,14 +46,12 @@ public CloseableHttpResponse execute(
54
46
HttpClientContext httpContext ,
55
47
HttpExecutionAware httpExecutionAware )
56
48
throws IOException , HttpException {
57
- Context context = httpContext .getAttribute (REQUEST_CONTEXT_ATTRIBUTE_ID , Context .class );
58
- if (context != null ) {
59
- ApacheHttpClientRequest instrumenterRequest =
60
- httpContext .getAttribute (REQUEST_WRAPPER_ATTRIBUTE_ID , ApacheHttpClientRequest .class );
61
- // Request already had a context so a redirect. Don't create a new span just inject and
62
- // execute.
63
- propagators .getTextMapPropagator ().inject (context , request , HttpHeaderSetter .INSTANCE );
64
- return execute (route , request , instrumenterRequest , httpContext , httpExecutionAware , context );
49
+
50
+ Context parentContext =
51
+ httpContext .getAttribute (REQUEST_PARENT_CONTEXT_ATTRIBUTE_ID , Context .class );
52
+ if (parentContext == null ) {
53
+ parentContext = HttpClientRequestResendCount .initialize (Context .current ());
54
+ httpContext .setAttribute (REQUEST_PARENT_CONTEXT_ATTRIBUTE_ID , parentContext );
65
55
}
66
56
67
57
HttpHost host = null ;
@@ -81,16 +71,11 @@ public CloseableHttpResponse execute(
81
71
}
82
72
ApacheHttpClientRequest instrumenterRequest = new ApacheHttpClientRequest (host , request );
83
73
84
- Context parentContext = Context .current ();
85
74
if (!instrumenter .shouldStart (parentContext , instrumenterRequest )) {
86
75
return exec .execute (route , request , httpContext , httpExecutionAware );
87
76
}
88
77
89
- context = instrumenter .start (parentContext , instrumenterRequest );
90
- httpContext .setAttribute (REQUEST_CONTEXT_ATTRIBUTE_ID , context );
91
- httpContext .setAttribute (REQUEST_WRAPPER_ATTRIBUTE_ID , instrumenterRequest );
92
- httpContext .setAttribute (REDIRECT_COUNT_ATTRIBUTE_ID , 0 );
93
-
78
+ Context context = instrumenter .start (parentContext , instrumenterRequest );
94
79
propagators .getTextMapPropagator ().inject (context , request , HttpHeaderSetter .INSTANCE );
95
80
96
81
return execute (route , request , instrumenterRequest , httpContext , httpExecutionAware , context );
@@ -113,63 +98,7 @@ private CloseableHttpResponse execute(
113
98
error = e ;
114
99
throw e ;
115
100
} finally {
116
- if (!pendingRedirect (context , httpContext , request , instrumenterRequest , response )) {
117
- instrumenter .end (context , instrumenterRequest , response , error );
118
- }
119
- }
120
- }
121
-
122
- private boolean pendingRedirect (
123
- Context context ,
124
- HttpClientContext httpContext ,
125
- HttpRequestWrapper request ,
126
- ApacheHttpClientRequest instrumenterRequest ,
127
- @ Nullable CloseableHttpResponse response ) {
128
- if (response == null ) {
129
- return false ;
130
- }
131
- if (!httpContext .getRequestConfig ().isRedirectsEnabled ()) {
132
- return false ;
101
+ instrumenter .end (context , instrumenterRequest , response , error );
133
102
}
134
-
135
- // TODO(anuraaga): Support redirect strategies other than the default. There is no way to get
136
- // the user defined redirect strategy without some tricks, but it's very rare to override
137
- // the strategy, usually it is either on or off as checked above. We can add support for this
138
- // later if needed.
139
- try {
140
- if (!DefaultRedirectStrategy .INSTANCE .isRedirected (request , response , httpContext )) {
141
- return false ;
142
- }
143
- } catch (ProtocolException e ) {
144
- // DefaultRedirectStrategy.isRedirected cannot throw this so just return a default.
145
- return false ;
146
- }
147
-
148
- // Very hacky and a bit slow, but the only way to determine whether the client will fail with
149
- // a circular redirect, which happens before exec decorators run.
150
- RedirectLocations redirectLocations =
151
- (RedirectLocations ) httpContext .getAttribute (HttpClientContext .REDIRECT_LOCATIONS );
152
- if (redirectLocations != null ) {
153
- RedirectLocations copy = new RedirectLocations ();
154
- copy .addAll (redirectLocations );
155
-
156
- try {
157
- DefaultRedirectStrategy .INSTANCE .getLocationURI (request , response , httpContext );
158
- } catch (ProtocolException e ) {
159
- // We will not be returning to the Exec, finish the span.
160
- instrumenter .end (context , instrumenterRequest , response , new ClientProtocolException (e ));
161
- return true ;
162
- } finally {
163
- httpContext .setAttribute (HttpClientContext .REDIRECT_LOCATIONS , copy );
164
- }
165
- }
166
-
167
- int redirectCount = httpContext .getAttribute (REDIRECT_COUNT_ATTRIBUTE_ID , Integer .class );
168
- if (++redirectCount > httpContext .getRequestConfig ().getMaxRedirects ()) {
169
- return false ;
170
- }
171
-
172
- httpContext .setAttribute (REDIRECT_COUNT_ATTRIBUTE_ID , redirectCount );
173
- return true ;
174
103
}
175
104
}
0 commit comments