18
18
19
19
import graphql .ExecutionResult ;
20
20
import graphql .GraphQLContext ;
21
- import graphql .execution .DataFetcherResult ;
22
21
import graphql .execution .instrumentation .InstrumentationContext ;
23
22
import graphql .execution .instrumentation .InstrumentationState ;
24
23
import graphql .execution .instrumentation .SimpleInstrumentation ;
28
27
import graphql .execution .instrumentation .parameters .InstrumentationFieldFetchParameters ;
29
28
import graphql .schema .DataFetcher ;
30
29
import graphql .schema .DataFetchingEnvironment ;
30
+ import graphql .schema .DataFetchingEnvironmentImpl ;
31
31
import io .micrometer .observation .Observation ;
32
32
import io .micrometer .observation .ObservationRegistry ;
33
33
import io .micrometer .observation .contextpropagation .ObservationThreadLocalAccessor ;
34
- import org .apache .commons .logging .Log ;
35
- import org .apache .commons .logging .LogFactory ;
36
34
import org .springframework .lang .Nullable ;
37
35
38
36
import java .util .concurrent .CompletionException ;
57
55
*/
58
56
public class GraphQlObservationInstrumentation extends SimpleInstrumentation {
59
57
60
- private static final Log logger = LogFactory .getLog (GraphQlObservationInstrumentation .class );
61
-
62
58
private static final ExecutionRequestObservationConvention DEFAULT_REQUEST_CONVENTION =
63
59
new DefaultExecutionRequestObservationConvention ();
64
60
@@ -106,13 +102,11 @@ public InstrumentationState createState(InstrumentationCreateStateParameters par
106
102
@ Override
107
103
public InstrumentationContext <ExecutionResult > beginExecution (InstrumentationExecutionParameters parameters ,
108
104
InstrumentationState state ) {
109
- if (state instanceof RequestObservationInstrumentationState instrumentationState ) {
105
+ if (state == RequestObservationInstrumentationState . INSTANCE ) {
110
106
ExecutionRequestObservationContext observationContext = new ExecutionRequestObservationContext (parameters .getExecutionInput ());
111
107
Observation requestObservation = GraphQlObservationDocumentation .EXECUTION_REQUEST .observation (this .requestObservationConvention ,
112
108
DEFAULT_REQUEST_CONVENTION , () -> observationContext , this .observationRegistry );
113
- requestObservation .parentObservation (getCurrentObservation (parameters .getGraphQLContext ()));
114
- GraphQLContext graphQLContext = parameters .getGraphQLContext ();
115
- graphQLContext .put (ObservationThreadLocalAccessor .KEY , requestObservation );
109
+ setCurrentObservation (requestObservation , parameters .getGraphQLContext ());
116
110
requestObservation .start ();
117
111
return new SimpleInstrumentationContext <>() {
118
112
@ Override
@@ -128,24 +122,27 @@ public void onCompleted(ExecutionResult result, Throwable exc) {
128
122
return super .beginExecution (parameters , state );
129
123
}
130
124
131
- @ Nullable
132
- private static Observation getCurrentObservation (GraphQLContext graphQLContext ) {
133
- return graphQLContext .get (ObservationThreadLocalAccessor .KEY );
125
+ private static void setCurrentObservation (Observation currentObservation , GraphQLContext graphQlContext ) {
126
+ Observation parentObservation = graphQlContext .get (ObservationThreadLocalAccessor .KEY );
127
+ currentObservation .parentObservation (parentObservation );
128
+ graphQlContext .put (ObservationThreadLocalAccessor .KEY , currentObservation );
134
129
}
135
130
136
131
@ Override
137
132
public DataFetcher <?> instrumentDataFetcher (DataFetcher <?> dataFetcher ,
138
133
InstrumentationFieldFetchParameters parameters , InstrumentationState state ) {
139
134
if (!parameters .isTrivialDataFetcher ()
140
- && state instanceof RequestObservationInstrumentationState instrumentationState ) {
135
+ && state == RequestObservationInstrumentationState . INSTANCE ) {
141
136
return (environment ) -> {
142
- DataFetcherObservationContext observationContext = new DataFetcherObservationContext (parameters . getEnvironment () );
137
+ DataFetcherObservationContext observationContext = new DataFetcherObservationContext (environment );
143
138
Observation dataFetcherObservation = GraphQlObservationDocumentation .DATA_FETCHER .observation (this .dataFetcherObservationConvention ,
144
139
DEFAULT_DATA_FETCHER_CONVENTION , () -> observationContext , this .observationRegistry );
145
140
dataFetcherObservation .parentObservation (getCurrentObservation (environment ));
146
141
dataFetcherObservation .start ();
142
+
143
+ DataFetchingEnvironment dataFetchingEnvironment = wrapDataFetchingEnvironment (environment , dataFetcherObservation );
147
144
try {
148
- Object value = dataFetcher .get (environment );
145
+ Object value = dataFetcher .get (dataFetchingEnvironment );
149
146
if (value instanceof CompletionStage <?> completion ) {
150
147
return completion .handle ((result , error ) -> {
151
148
observationContext .setValue (result );
@@ -155,13 +152,13 @@ public DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher,
155
152
throw new CompletionException (error );
156
153
}
157
154
dataFetcherObservation .stop ();
158
- return wrapAsDataFetcherResult ( result , dataFetcherObservation , environment . getLocalContext ()) ;
155
+ return result ;
159
156
});
160
157
}
161
158
else {
162
159
observationContext .setValue (value );
163
160
dataFetcherObservation .stop ();
164
- return wrapAsDataFetcherResult ( value , dataFetcherObservation , environment . getLocalContext ()) ;
161
+ return value ;
165
162
}
166
163
}
167
164
catch (Throwable throwable ) {
@@ -177,39 +174,25 @@ public DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher,
177
174
@ Nullable
178
175
private static Observation getCurrentObservation (DataFetchingEnvironment environment ) {
179
176
Observation currentObservation = null ;
180
- if (environment .getLocalContext () != null && environment .getLocalContext () instanceof GraphQLContext ) {
181
- GraphQLContext localContext = environment .getLocalContext ();
177
+ if (environment .getLocalContext () instanceof GraphQLContext localContext ) {
182
178
currentObservation = localContext .get (ObservationThreadLocalAccessor .KEY );
183
179
}
184
180
if (currentObservation == null ) {
185
- return environment .getGraphQlContext ().get (ObservationThreadLocalAccessor .KEY );
181
+ currentObservation = environment .getGraphQlContext ().get (ObservationThreadLocalAccessor .KEY );
186
182
}
187
183
return currentObservation ;
188
184
}
189
185
190
- private static DataFetcherResult <?> wrapAsDataFetcherResult (Object value , Observation dataFetcherObservation ,
191
- @ Nullable GraphQLContext dataFetcherLocalContext ) {
192
- if (value instanceof DataFetcherResult <?> result ) {
193
- if (result .getLocalContext () == null ) {
194
- return result .transform (builder -> builder .localContext (GraphQLContext .newContext ().of (ObservationThreadLocalAccessor .KEY , dataFetcherObservation ).build ()));
195
- }
196
- else if (result .getLocalContext () instanceof GraphQLContext ) {
197
- ((GraphQLContext ) result .getLocalContext ()).put (ObservationThreadLocalAccessor .KEY , dataFetcherObservation );
198
- } else {
199
- logger .debug ("Cannot add observation to localContext as it is not a GraphQLContext but a "
200
- + result .getLocalContext ().getClass ().toString ());
201
- }
202
- return result ;
186
+ private static DataFetchingEnvironment wrapDataFetchingEnvironment (DataFetchingEnvironment environment , Observation dataFetcherObservation ) {
187
+ GraphQLContext .Builder localContextBuilder = GraphQLContext .newContext ();
188
+ if (environment .getLocalContext () instanceof GraphQLContext localContext ) {
189
+ localContextBuilder .of (localContext );
203
190
}
204
- else {
205
- GraphQLContext localContext = dataFetcherLocalContext == null ?
206
- GraphQLContext .newContext ().build () : GraphQLContext .newContext ().of (dataFetcherLocalContext ).build ();
207
- return DataFetcherResult .newResult ()
208
- .data (value )
209
- .localContext (localContext .put (ObservationThreadLocalAccessor .KEY , dataFetcherObservation ))
210
- .build ();
211
- }
212
-
191
+ localContextBuilder .of (ObservationThreadLocalAccessor .KEY , dataFetcherObservation );
192
+ return DataFetchingEnvironmentImpl
193
+ .newDataFetchingEnvironment (environment )
194
+ .localContext (localContextBuilder .build ())
195
+ .build ();
213
196
}
214
197
215
198
0 commit comments