graphql-hive / graphql-hive/envelop

OpenTelemetry plugin

Open
#2,255 1 comment 3 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
827
Forks
132
PR merge metrics
No merged PRs in 30d

Description

### Summary
The current implementation of the OpenTelemetry plugin can lead to confusing spans because the execution span starts within the OpenTelemetry plugin but these do not wrap each other and instead run as part of an iteration over the plugins.

I think the correct way to handle OpenTelemetry traces within envelop is to wrap the GraphQL functions with spans, for example the executeFn and subscribeFn, this will effectively instrument the GraphQL phases.

A plugin that wants to add instrumentation can pick up the parent context and add a span which will appear alongside any other instrumented plugin in terms of the traces.

An example of wrapping the execute function would be like so:

```ts
setExecuteFn(async () => {
const span = tracer.startSpan(`${operationType}.${operationName}`, {}) // todo: fill in attrbutes.

return await opentelemetry.context.with(api.context.active(), async () => {
let result: ExecutionResult;
try {
result = await execute(args);
if (isAsyncIterable(result)) {
return mapAsyncIterator(result[Symbol.asyncIterator](), (next: ExecutionResult) => next, (error: GraphQLError) => markError(executionSpan, {errors: [error]}), () => span.end());
}
}finally {
if (!isAsyncIterable(result)){
span.end();
}
}
return result;
});
});
```

This could be repeated for all phases of the GraphQL request and gives a more realistic view of how the process is executed.

Further to this we could create a Yoga Plugin that takes this further and wraps the request handler so that the parent context is set through all phases.

```ts
onRequest: ({ request, setRequestHandler, requestHandler }) => {
setRequestHandler((req, serverCtx) => {
const span = tracer.startSpan("yoga.request");
const result = api.context.with(api.trace.setSpan(api.context.active(), span), () => requestHandler(req, serverCtx));
span.end();
})
},
```

I think this would provide a much better instrumentation of GraphQL and how it is executed.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.