Skip to content

Commit 2a0390f

Browse files
committed
feat(opentelemetry): remove auto-setup from configuration
1 parent 35a3e29 commit 2a0390f

33 files changed

+2262
-969
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
'@graphql-hive/gateway': patch
3+
---
4+
5+
dependencies updates:
6+
7+
- Added dependency [`@opentelemetry/api@^1.9.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/api/v/1.9.0) (to `dependencies`)
8+
- Added dependency [`@opentelemetry/auto-instrumentations-node@^0.59.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node/v/0.59.0) (to `dependencies`)
9+
- Added dependency [`@opentelemetry/context-zone@^2.0.1` ↗︎](https://www.npmjs.com/package/@opentelemetry/context-zone/v/2.0.1) (to `dependencies`)
10+
- Added dependency [`@opentelemetry/core@^2.0.0` ↗︎](https://www.npmjs.com/package/@opentelemetry/core/v/2.0.0) (to `dependencies`)
11+
- Added dependency [`@opentelemetry/exporter-jaeger@^2.0.1` ↗︎](https://www.npmjs.com/package/@opentelemetry/exporter-jaeger/v/2.0.1) (to `dependencies`)
12+
- Added dependency [`@opentelemetry/exporter-zipkin@^2.0.1` ↗︎](https://www.npmjs.com/package/@opentelemetry/exporter-zipkin/v/2.0.1) (to `dependencies`)
13+
- Added dependency [`@opentelemetry/propagator-b3@^2.0.1` ↗︎](https://www.npmjs.com/package/@opentelemetry/propagator-b3/v/2.0.1) (to `dependencies`)
14+
- Added dependency [`@opentelemetry/propagator-jaeger@^2.0.1` ↗︎](https://www.npmjs.com/package/@opentelemetry/propagator-jaeger/v/2.0.1) (to `dependencies`)
15+
- Added dependency [`@opentelemetry/sampler-jaeger-remote@^0.201.1` ↗︎](https://www.npmjs.com/package/@opentelemetry/sampler-jaeger-remote/v/0.201.1) (to `dependencies`)
16+
- Added dependency [`@opentelemetry/sdk-node@^0.201.1` ↗︎](https://www.npmjs.com/package/@opentelemetry/sdk-node/v/0.201.1) (to `dependencies`)
17+
- Added dependency [`@opentelemetry/sdk-trace-node@^2.0.1` ↗︎](https://www.npmjs.com/package/@opentelemetry/sdk-trace-node/v/2.0.1) (to `dependencies`)

.yarn/patches/@opentelemetry-exporter-trace-otlp-http-npm-0.202.0-8ec36b4f28.patch

Whitespace-only changes.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
diff --git a/build/esnext/transport/http-exporter-transport.js b/build/esnext/transport/http-exporter-transport.js
2+
index 7977489487a2236fbd0e4c2273ef53fd3c7b93a8..93e9701d10f6aea530f38330daea87199e514452 100644
3+
--- a/build/esnext/transport/http-exporter-transport.js
4+
+++ b/build/esnext/transport/http-exporter-transport.js
5+
@@ -20,7 +20,7 @@ class HttpExporterTransport {
6+
this._parameters = _parameters;
7+
}
8+
async send(data, timeoutMillis) {
9+
- const { agent, send } = this._loadUtils();
10+
+ const { agent, send } = await this._loadUtils();
11+
return new Promise(resolve => {
12+
send(this._parameters, agent, data, result => {
13+
resolve(result);
14+
@@ -30,13 +30,11 @@ class HttpExporterTransport {
15+
shutdown() {
16+
// intentionally left empty, nothing to do.
17+
}
18+
- _loadUtils() {
19+
+ async _loadUtils() {
20+
let utils = this._utils;
21+
if (utils === null) {
22+
// Lazy require to ensure that http/https is not required before instrumentations can wrap it.
23+
- const { sendWithHttp, createHttpAgent,
24+
- // eslint-disable-next-line @typescript-eslint/no-var-requires
25+
- } = require('./http-transport-utils');
26+
+ const { sendWithHttp, createHttpAgent } = await import('./http-transport-utils');
27+
utils = this._utils = {
28+
agent: createHttpAgent(this._parameters.url, this._parameters.agentOptions),
29+
send: sendWithHttp,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
diff --git a/dist/es/index.js b/dist/es/index.js
2+
index 505218ea7b14fb8773fe805b622f9071d5da59dd..263631008120b7bf2bd678220dca6394ed30c026 100644
3+
--- a/dist/es/index.js
4+
+++ b/dist/es/index.js
5+
@@ -478,28 +478,10 @@ async function resolvePackageTarget(context, { target, patternMatch, isImports }
6+
}
7+
// Otherwise, if target is a non-null Object, then
8+
if (target && typeof target === 'object') {
9+
- // For each property of target
10+
- for (const [key, value] of Object.entries(target)) {
11+
- // If exports contains any index property keys, as defined in ECMA-262 6.1.7 Array Index, throw an Invalid Package Configuration error.
12+
- // TODO: We do not check if the key is a number here...
13+
- // If key equals "default" or conditions contains an entry for the key, then
14+
- if (key === 'default' || context.conditions.includes(key)) {
15+
- // Let targetValue be the value of the property in target.
16+
- // Let resolved be the result of PACKAGE_TARGET_RESOLVE of the targetValue
17+
- const resolved = await resolvePackageTarget(context, {
18+
- target: value,
19+
- patternMatch,
20+
- isImports
21+
- });
22+
- // If resolved is equal to undefined, continue the loop.
23+
- // Return resolved.
24+
- if (resolved !== undefined) {
25+
- return resolved;
26+
- }
27+
- }
28+
- }
29+
- // Return undefined.
30+
- return undefined;
31+
+ const key = context.conditions.find(condition => condition in target) ?? 'default';
32+
+ return key in target
33+
+ ? resolvePackageTarget(context, { target: target[key], patternMatch, isImports })
34+
+ : undefined;
35+
}
36+
// Otherwise, if target is null, return null.
37+
if (target === null) {
38+
@@ -1072,8 +1054,8 @@ function nodeResolve(opts = {}) {
39+
? 'development'
40+
: 'production'
41+
];
42+
- const conditionsEsm = [...baseConditionsEsm, ...exportConditions, ...devProdCondition];
43+
- const conditionsCjs = [...baseConditionsCjs, ...exportConditions, ...devProdCondition];
44+
+ const conditionsEsm = [...baseConditionsEsm, ...exportConditions, ...devProdCondition].reverse();
45+
+ const conditionsCjs = [...baseConditionsCjs, ...exportConditions, ...devProdCondition].reverse();
46+
const packageInfoCache = new Map();
47+
const idToPackageInfo = new Map();
48+
const mainFields = getMainFields(options);

e2e/cloudflare-workers/cloudflare-workers.e2e.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,18 @@ describe.skipIf(gatewayRunner !== 'node' || process.version.startsWith('v1'))(
4141
type JaegerTracesApiResponse = {
4242
data: Array<{
4343
traceID: string;
44-
spans: Array<{
45-
traceID: string;
46-
spanID: string;
47-
operationName: string;
48-
tags: Array<{ key: string; value: string; type: string }>;
49-
}>;
44+
spans: JaegerTraceSpan[];
5045
}>;
5146
};
5247

48+
type JaegerTraceSpan = {
49+
traceID: string;
50+
spanID: string;
51+
operationName: string;
52+
tags: Array<{ key: string; value: string; type: string }>;
53+
references: Array<{ refType: string; spanID: string; traceID: string }>;
54+
};
55+
5356
async function getJaegerTraces(
5457
service: string,
5558
expectedDataLength: number,

e2e/cloudflare-workers/src/index.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@ import {
44
GatewayPlugin,
55
} from '@graphql-hive/gateway-runtime';
66
import {
7-
createOtlpHttpExporter,
7+
SEMRESATTRS_SERVICE_NAME,
88
useOpenTelemetry,
99
} from '@graphql-mesh/plugin-opentelemetry';
1010
import http from '@graphql-mesh/transport-http';
11+
import { diag } from '@opentelemetry/api';
12+
import { setGlobalErrorHandler } from '@opentelemetry/core';
13+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
14+
import { resourceFromAttributes } from '@opentelemetry/resources';
15+
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
16+
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
1117

1218
interface Env {
1319
OTLP_EXPORTER_URL: string;
@@ -38,28 +44,38 @@ const useOnFetchTracer = (): GatewayPlugin => {
3844
let runtime: ReturnType<typeof createGatewayRuntime>;
3945
function getRuntime(env: Env) {
4046
if (!runtime) {
47+
setGlobalErrorHandler((err) => diag.error('Uncaught Error', err));
48+
49+
new WebTracerProvider({
50+
resource: resourceFromAttributes({
51+
[SEMRESATTRS_SERVICE_NAME]: env.OTLP_SERVICE_NAME,
52+
}),
53+
spanProcessors: [
54+
// Do not batch for test
55+
new SimpleSpanProcessor(
56+
new OTLPTraceExporter({
57+
url: env.OTLP_EXPORTER_URL,
58+
}),
59+
),
60+
],
61+
}).register();
62+
4163
console.log(env);
4264
runtime = createGatewayRuntime({
4365
proxy: { endpoint: 'https://countries.trevorblades.com' },
4466
transports: { http },
4567
plugins: (ctx) => [
4668
useOpenTelemetry({
4769
...ctx,
48-
exporters: [
49-
createOtlpHttpExporter(
50-
{ url: env['OTLP_EXPORTER_URL'] },
51-
// Batching config is set in order to make it easier to test.
52-
false,
53-
),
54-
],
55-
serviceName: env['OTLP_SERVICE_NAME'],
70+
traces: true,
5671
}),
5772
useOnFetchTracer(),
5873
],
5974
});
6075
}
6176
return runtime;
6277
}
78+
6379
export default {
6480
async fetch(req, env, ctx) {
6581
const res = await getRuntime(env)(req, env, ctx);

e2e/graphos-polling/services/gateway-fastify.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1+
import './otel-setup.js';
12
import { createGatewayRuntime, Logger } from '@graphql-hive/gateway-runtime';
23
import { PinoLogWriter } from '@graphql-hive/logger/writers/pino';
3-
import {
4-
createOtlpHttpExporter,
5-
useOpenTelemetry,
6-
} from '@graphql-mesh/plugin-opentelemetry';
4+
import { useOpenTelemetry } from '@graphql-mesh/plugin-opentelemetry';
75
import { Opts } from '@internal/testing';
86
import fastify, { type FastifyReply, type FastifyRequest } from 'fastify';
97

@@ -71,16 +69,7 @@ const gw = createGatewayRuntime<FastifyContext>({
7169
plugins: (ctx) => [
7270
useOpenTelemetry({
7371
...ctx,
74-
exporters: [
75-
createOtlpHttpExporter(
76-
{
77-
url: process.env['OTLP_EXPORTER_URL'],
78-
},
79-
{
80-
scheduledDelayMillis: 1,
81-
},
82-
),
83-
],
72+
traces: true,
8473
}),
8574
],
8675
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { SEMRESATTRS_SERVICE_NAME } from '@graphql-mesh/plugin-opentelemetry';
2+
import { diag } from '@opentelemetry/api';
3+
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
4+
import { setGlobalErrorHandler } from '@opentelemetry/core';
5+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
6+
import { resourceFromAttributes } from '@opentelemetry/resources';
7+
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
8+
import {
9+
AlwaysOnSampler,
10+
WebTracerProvider,
11+
} from '@opentelemetry/sdk-trace-web';
12+
13+
setGlobalErrorHandler((err) => diag.error('Uncaught Error', err));
14+
15+
const tracerProvider = new WebTracerProvider({
16+
resource: resourceFromAttributes({
17+
[SEMRESATTRS_SERVICE_NAME]: process.env['OTLP_SERVICE_NAME'],
18+
}),
19+
spanProcessors: [
20+
// Do not batch for test
21+
new SimpleSpanProcessor(
22+
new OTLPTraceExporter({
23+
url: process.env['OTLP_EXPORTER_URL'],
24+
}),
25+
),
26+
],
27+
sampler: new AlwaysOnSampler(),
28+
});
29+
30+
tracerProvider.register({
31+
contextManager: new AsyncLocalStorageContextManager(),
32+
});
33+
34+
export { tracerProvider };
Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import {
2-
createOtlpGrpcExporter,
3-
createOtlpHttpExporter,
42
defineConfig,
53
GatewayPlugin,
6-
OpenTelemetryDiagLogLevel,
4+
SEMRESATTRS_SERVICE_NAME,
75
} from '@graphql-hive/gateway';
6+
import { AsyncLocalStorageContextManager } from '@graphql-mesh/plugin-opentelemetry/async-context-manager';
7+
import { opentelemetrySetup } from '@graphql-mesh/plugin-opentelemetry/setup';
88
import type { MeshFetchRequestInit } from '@graphql-mesh/types';
9+
import { trace } from '@opentelemetry/api';
10+
import { resourceFromAttributes } from '@opentelemetry/resources';
911

1012
// The following plugin is used to trace the fetch calls made by Mesh.
1113
const useOnFetchTracer = (): GatewayPlugin => {
@@ -27,38 +29,39 @@ const useOnFetchTracer = (): GatewayPlugin => {
2729
};
2830
};
2931

32+
const exporterModule =
33+
process.env['OTLP_EXPORTER_TYPE'] === 'http'
34+
? await import(`@opentelemetry/exporter-trace-otlp-http`)
35+
: await import(`@opentelemetry/exporter-trace-otlp-grpc`);
36+
37+
const OTLPTraceExporter =
38+
exporterModule.OTLPTraceExporter ?? exporterModule.default.OTLPTraceExporter;
39+
40+
opentelemetrySetup({
41+
contextManager: new AsyncLocalStorageContextManager(),
42+
resource: resourceFromAttributes({
43+
[SEMRESATTRS_SERVICE_NAME]: process.env['OTLP_SERVICE_NAME'],
44+
}),
45+
traces: {
46+
exporter: new OTLPTraceExporter({ url: process.env['OTLP_EXPORTER_URL'] }),
47+
batching: { maxExportBatchSize: 1, scheduledDelayMillis: 1 },
48+
},
49+
});
50+
3051
export const gatewayConfig = defineConfig({
3152
openTelemetry: {
32-
diagLevel: OpenTelemetryDiagLogLevel.INFO,
33-
exporters: [
34-
process.env['OTLP_EXPORTER_TYPE'] === 'grpc'
35-
? createOtlpGrpcExporter(
36-
{
37-
url: process.env['OTLP_EXPORTER_URL'],
38-
},
39-
// Batching config is set in order to make it easier to test.
40-
{
41-
maxExportBatchSize: 1,
42-
scheduledDelayMillis: 1,
43-
},
44-
)
45-
: createOtlpHttpExporter(
46-
{
47-
url: process.env['OTLP_EXPORTER_URL'],
48-
},
49-
// Batching config is set in order to make it easier to test.
50-
{
51-
maxExportBatchSize: 1,
52-
scheduledDelayMillis: 1,
53-
},
54-
),
55-
],
56-
serviceName: process.env['OTLP_SERVICE_NAME'],
53+
traces: true,
5754
},
58-
plugins: () =>
59-
process.env['MEMTEST']
55+
plugins: () => [
56+
{
57+
onExecute() {
58+
trace.getActiveSpan()?.setAttribute('custom.attribute', 'custom value');
59+
},
60+
},
61+
...(process.env['MEMTEST']
6062
? [
6163
// disable the plugin in memtests because the upstreamCallHeaders will grew forever reporting a false positive leak
6264
]
63-
: [useOnFetchTracer()],
65+
: [useOnFetchTracer()]),
66+
],
6467
});

0 commit comments

Comments
 (0)