@effect-gql/opentelemetry 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -0
- package/index.cjs +374 -0
- package/index.cjs.map +1 -0
- package/index.d.cts +416 -0
- package/index.d.ts +416 -0
- package/index.js +358 -0
- package/index.js.map +1 -0
- package/package.json +14 -30
- package/dist/context-propagation.d.ts +0 -78
- package/dist/context-propagation.d.ts.map +0 -1
- package/dist/context-propagation.js +0 -125
- package/dist/context-propagation.js.map +0 -1
- package/dist/index.d.ts +0 -111
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -120
- package/dist/index.js.map +0 -1
- package/dist/traced-router.d.ts +0 -90
- package/dist/traced-router.d.ts.map +0 -1
- package/dist/traced-router.js +0 -154
- package/dist/traced-router.js.map +0 -1
- package/dist/tracing-extension.d.ts +0 -52
- package/dist/tracing-extension.d.ts.map +0 -1
- package/dist/tracing-extension.js +0 -110
- package/dist/tracing-extension.js.map +0 -1
- package/dist/tracing-middleware.d.ts +0 -78
- package/dist/tracing-middleware.d.ts.map +0 -1
- package/dist/tracing-middleware.js +0 -96
- package/dist/tracing-middleware.js.map +0 -1
- package/dist/utils.d.ts +0 -19
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -47
- package/dist/utils.js.map +0 -1
- package/src/context-propagation.ts +0 -177
- package/src/index.ts +0 -139
- package/src/traced-router.ts +0 -240
- package/src/tracing-extension.ts +0 -175
- package/src/tracing-middleware.ts +0 -177
- package/src/utils.ts +0 -48
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatTraceParent = exports.extractTraceContext = exports.isSampled = exports.parseTraceParent = exports.TraceContextTag = exports.TRACESTATE_HEADER = exports.TRACEPARENT_HEADER = void 0;
|
|
4
|
-
const effect_1 = require("effect");
|
|
5
|
-
const platform_1 = require("@effect/platform");
|
|
6
|
-
/**
|
|
7
|
-
* W3C Trace Context header names
|
|
8
|
-
* @see https://www.w3.org/TR/trace-context/
|
|
9
|
-
*/
|
|
10
|
-
exports.TRACEPARENT_HEADER = "traceparent";
|
|
11
|
-
exports.TRACESTATE_HEADER = "tracestate";
|
|
12
|
-
/**
|
|
13
|
-
* Context tag for TraceContext
|
|
14
|
-
*/
|
|
15
|
-
class TraceContextTag extends effect_1.Context.Tag("@effect-gql/opentelemetry/TraceContext")() {
|
|
16
|
-
}
|
|
17
|
-
exports.TraceContextTag = TraceContextTag;
|
|
18
|
-
/**
|
|
19
|
-
* Parse a W3C traceparent header value.
|
|
20
|
-
*
|
|
21
|
-
* Format: {version}-{trace-id}-{parent-id}-{trace-flags}
|
|
22
|
-
* Example: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
23
|
-
*
|
|
24
|
-
* @see https://www.w3.org/TR/trace-context/#traceparent-header
|
|
25
|
-
*
|
|
26
|
-
* @param header - The traceparent header value
|
|
27
|
-
* @returns Parsed trace context or null if invalid
|
|
28
|
-
*/
|
|
29
|
-
const parseTraceParent = (header) => {
|
|
30
|
-
const trimmed = header.trim().toLowerCase();
|
|
31
|
-
const parts = trimmed.split("-");
|
|
32
|
-
if (parts.length !== 4) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
const [version, traceId, parentSpanId, flagsHex] = parts;
|
|
36
|
-
// Validate version (2 hex chars)
|
|
37
|
-
if (version.length !== 2 || !/^[0-9a-f]{2}$/.test(version)) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
// Validate trace ID (32 hex chars, not all zeros)
|
|
41
|
-
if (traceId.length !== 32 || !/^[0-9a-f]{32}$/.test(traceId)) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
if (traceId === "00000000000000000000000000000000") {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
// Validate parent span ID (16 hex chars, not all zeros)
|
|
48
|
-
if (parentSpanId.length !== 16 || !/^[0-9a-f]{16}$/.test(parentSpanId)) {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
if (parentSpanId === "0000000000000000") {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
// Validate trace flags (2 hex chars)
|
|
55
|
-
if (flagsHex.length !== 2 || !/^[0-9a-f]{2}$/.test(flagsHex)) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
const traceFlags = parseInt(flagsHex, 16);
|
|
59
|
-
return {
|
|
60
|
-
version,
|
|
61
|
-
traceId,
|
|
62
|
-
parentSpanId,
|
|
63
|
-
traceFlags,
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
exports.parseTraceParent = parseTraceParent;
|
|
67
|
-
/**
|
|
68
|
-
* Check if a trace context is sampled (should be recorded)
|
|
69
|
-
*/
|
|
70
|
-
const isSampled = (context) => {
|
|
71
|
-
return (context.traceFlags & 0x01) === 0x01;
|
|
72
|
-
};
|
|
73
|
-
exports.isSampled = isSampled;
|
|
74
|
-
/**
|
|
75
|
-
* Extract trace context from HTTP request headers.
|
|
76
|
-
*
|
|
77
|
-
* Looks for the W3C Trace Context headers:
|
|
78
|
-
* - `traceparent`: Required, contains trace ID, span ID, and flags
|
|
79
|
-
* - `tracestate`: Optional, vendor-specific trace data
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* ```typescript
|
|
83
|
-
* const context = yield* extractTraceContext
|
|
84
|
-
* if (context) {
|
|
85
|
-
* console.log(`Continuing trace: ${context.traceId}`)
|
|
86
|
-
* }
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
exports.extractTraceContext = effect_1.Effect.gen(function* () {
|
|
90
|
-
const request = yield* platform_1.HttpServerRequest.HttpServerRequest;
|
|
91
|
-
const headers = request.headers;
|
|
92
|
-
// Get traceparent header (case-insensitive)
|
|
93
|
-
const traceparentKey = Object.keys(headers).find((k) => k.toLowerCase() === exports.TRACEPARENT_HEADER);
|
|
94
|
-
if (!traceparentKey) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
const traceparentValue = headers[traceparentKey];
|
|
98
|
-
const traceparent = Array.isArray(traceparentValue) ? traceparentValue[0] : traceparentValue;
|
|
99
|
-
if (!traceparent) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
const context = (0, exports.parseTraceParent)(traceparent);
|
|
103
|
-
if (!context) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
// Get optional tracestate header
|
|
107
|
-
const tracestateKey = Object.keys(headers).find((k) => k.toLowerCase() === exports.TRACESTATE_HEADER);
|
|
108
|
-
if (tracestateKey) {
|
|
109
|
-
const tracestateValue = headers[tracestateKey];
|
|
110
|
-
const tracestate = Array.isArray(tracestateValue) ? tracestateValue[0] : tracestateValue;
|
|
111
|
-
if (tracestate) {
|
|
112
|
-
return { ...context, traceState: tracestate };
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return context;
|
|
116
|
-
});
|
|
117
|
-
/**
|
|
118
|
-
* Format a trace context as a traceparent header value
|
|
119
|
-
*/
|
|
120
|
-
const formatTraceParent = (context) => {
|
|
121
|
-
const flags = context.traceFlags.toString(16).padStart(2, "0");
|
|
122
|
-
return `${context.version}-${context.traceId}-${context.parentSpanId}-${flags}`;
|
|
123
|
-
};
|
|
124
|
-
exports.formatTraceParent = formatTraceParent;
|
|
125
|
-
//# sourceMappingURL=context-propagation.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context-propagation.js","sourceRoot":"","sources":["../src/context-propagation.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @effect-gql/opentelemetry
|
|
3
|
-
*
|
|
4
|
-
* OpenTelemetry tracing integration for Effect GraphQL.
|
|
5
|
-
*
|
|
6
|
-
* Provides distributed tracing using Effect's native OpenTelemetry support.
|
|
7
|
-
* Works with any OpenTelemetry-compatible backend (Jaeger, Tempo, Honeycomb, etc.).
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* import { GraphQLSchemaBuilder } from "@effect-gql/core"
|
|
12
|
-
* import { serve } from "@effect-gql/node"
|
|
13
|
-
* import { withTracing } from "@effect-gql/opentelemetry"
|
|
14
|
-
* import { NodeSdk } from "@effect/opentelemetry"
|
|
15
|
-
* import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base"
|
|
16
|
-
* import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
|
|
17
|
-
*
|
|
18
|
-
* // Add tracing to schema
|
|
19
|
-
* const builder = GraphQLSchemaBuilder.empty
|
|
20
|
-
* .query("users", { ... })
|
|
21
|
-
* .pipe(withTracing({
|
|
22
|
-
* extension: { exposeTraceIdInResponse: true },
|
|
23
|
-
* resolver: { excludePatterns: [/^Query\.__/] }
|
|
24
|
-
* }))
|
|
25
|
-
*
|
|
26
|
-
* // Configure OpenTelemetry
|
|
27
|
-
* const TracingLayer = NodeSdk.layer(() => ({
|
|
28
|
-
* resource: { serviceName: "my-graphql-api" },
|
|
29
|
-
* spanProcessor: new BatchSpanProcessor(
|
|
30
|
-
* new OTLPTraceExporter({ url: "http://localhost:4318/v1/traces" })
|
|
31
|
-
* )
|
|
32
|
-
* }))
|
|
33
|
-
*
|
|
34
|
-
* // Serve with tracing
|
|
35
|
-
* serve(builder, TracingLayer.pipe(Layer.merge(serviceLayer)))
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* @packageDocumentation
|
|
39
|
-
*/
|
|
40
|
-
import type { GraphQLSchemaBuilder } from "@effect-gql/core";
|
|
41
|
-
import { type TracingExtensionConfig } from "./tracing-extension";
|
|
42
|
-
import { type ResolverTracingConfig } from "./tracing-middleware";
|
|
43
|
-
/**
|
|
44
|
-
* Complete configuration for GraphQL tracing
|
|
45
|
-
*/
|
|
46
|
-
export interface GraphQLTracingConfig {
|
|
47
|
-
/**
|
|
48
|
-
* Configuration for phase-level tracing (parse, validate, execute).
|
|
49
|
-
* Uses the Extensions system.
|
|
50
|
-
*/
|
|
51
|
-
readonly extension?: TracingExtensionConfig;
|
|
52
|
-
/**
|
|
53
|
-
* Configuration for resolver-level tracing.
|
|
54
|
-
* Uses the Middleware system.
|
|
55
|
-
*/
|
|
56
|
-
readonly resolver?: ResolverTracingConfig;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Add OpenTelemetry tracing to a GraphQL schema builder.
|
|
60
|
-
*
|
|
61
|
-
* This is a convenience function that registers both the tracing extension
|
|
62
|
-
* (for phase-level spans) and resolver middleware (for field-level spans).
|
|
63
|
-
*
|
|
64
|
-
* **Span Hierarchy:**
|
|
65
|
-
* ```
|
|
66
|
-
* graphql.request (if using traced router)
|
|
67
|
-
* ├── graphql.parse
|
|
68
|
-
* ├── graphql.validate
|
|
69
|
-
* └── graphql.execute
|
|
70
|
-
* ├── graphql.resolve Query.users
|
|
71
|
-
* ├── graphql.resolve User.posts
|
|
72
|
-
* └── graphql.resolve Post.author
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* **Requirements:**
|
|
76
|
-
* - An OpenTelemetry tracer must be provided via Effect's tracing layer
|
|
77
|
-
* - Use `@effect/opentelemetry` NodeSdk.layer or OtlpTracer.layer
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* ```typescript
|
|
81
|
-
* import { GraphQLSchemaBuilder } from "@effect-gql/core"
|
|
82
|
-
* import { withTracing } from "@effect-gql/opentelemetry"
|
|
83
|
-
*
|
|
84
|
-
* const builder = GraphQLSchemaBuilder.empty
|
|
85
|
-
* .query("hello", {
|
|
86
|
-
* type: S.String,
|
|
87
|
-
* resolve: () => Effect.succeed("world")
|
|
88
|
-
* })
|
|
89
|
-
* .pipe(withTracing({
|
|
90
|
-
* extension: {
|
|
91
|
-
* exposeTraceIdInResponse: true, // Add traceId to response extensions
|
|
92
|
-
* includeQuery: false, // Don't include query in spans (security)
|
|
93
|
-
* },
|
|
94
|
-
* resolver: {
|
|
95
|
-
* minDepth: 0, // Trace all resolvers
|
|
96
|
-
* excludePatterns: [/^Query\.__/], // Skip introspection
|
|
97
|
-
* includeArgs: false, // Don't include args (security)
|
|
98
|
-
* }
|
|
99
|
-
* }))
|
|
100
|
-
* ```
|
|
101
|
-
*
|
|
102
|
-
* @param config - Optional tracing configuration
|
|
103
|
-
* @returns A function that adds tracing to a GraphQLSchemaBuilder
|
|
104
|
-
*/
|
|
105
|
-
export declare const withTracing: <R>(config?: GraphQLTracingConfig) => (builder: GraphQLSchemaBuilder<R>) => GraphQLSchemaBuilder<R>;
|
|
106
|
-
export { tracingExtension, type TracingExtensionConfig } from "./tracing-extension";
|
|
107
|
-
export { resolverTracingMiddleware, type ResolverTracingConfig } from "./tracing-middleware";
|
|
108
|
-
export { extractTraceContext, parseTraceParent, formatTraceParent, isSampled, TraceContextTag, TRACEPARENT_HEADER, TRACESTATE_HEADER, type TraceContext, } from "./context-propagation";
|
|
109
|
-
export { pathToString, getFieldDepth, isIntrospectionField } from "./utils";
|
|
110
|
-
export { makeTracedGraphQLRouter, withTracedRouter, type TracedRouterOptions, } from "./traced-router";
|
|
111
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAoB,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACnF,OAAO,EAA6B,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAE5F;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,sBAAsB,CAAA;IAE3C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,qBAAqB,CAAA;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,eAAO,MAAM,WAAW,GACrB,CAAC,EAAE,SAAS,oBAAoB,MAChC,SAAS,oBAAoB,CAAC,CAAC,CAAC,KAAG,oBAAoB,CAAC,CAAC,CAQzD,CAAA;AAGH,OAAO,EAAE,gBAAgB,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACnF,OAAO,EAAE,yBAAyB,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5F,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAC3E,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAA"}
|
package/dist/index.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @effect-gql/opentelemetry
|
|
4
|
-
*
|
|
5
|
-
* OpenTelemetry tracing integration for Effect GraphQL.
|
|
6
|
-
*
|
|
7
|
-
* Provides distributed tracing using Effect's native OpenTelemetry support.
|
|
8
|
-
* Works with any OpenTelemetry-compatible backend (Jaeger, Tempo, Honeycomb, etc.).
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* import { GraphQLSchemaBuilder } from "@effect-gql/core"
|
|
13
|
-
* import { serve } from "@effect-gql/node"
|
|
14
|
-
* import { withTracing } from "@effect-gql/opentelemetry"
|
|
15
|
-
* import { NodeSdk } from "@effect/opentelemetry"
|
|
16
|
-
* import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base"
|
|
17
|
-
* import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
|
|
18
|
-
*
|
|
19
|
-
* // Add tracing to schema
|
|
20
|
-
* const builder = GraphQLSchemaBuilder.empty
|
|
21
|
-
* .query("users", { ... })
|
|
22
|
-
* .pipe(withTracing({
|
|
23
|
-
* extension: { exposeTraceIdInResponse: true },
|
|
24
|
-
* resolver: { excludePatterns: [/^Query\.__/] }
|
|
25
|
-
* }))
|
|
26
|
-
*
|
|
27
|
-
* // Configure OpenTelemetry
|
|
28
|
-
* const TracingLayer = NodeSdk.layer(() => ({
|
|
29
|
-
* resource: { serviceName: "my-graphql-api" },
|
|
30
|
-
* spanProcessor: new BatchSpanProcessor(
|
|
31
|
-
* new OTLPTraceExporter({ url: "http://localhost:4318/v1/traces" })
|
|
32
|
-
* )
|
|
33
|
-
* }))
|
|
34
|
-
*
|
|
35
|
-
* // Serve with tracing
|
|
36
|
-
* serve(builder, TracingLayer.pipe(Layer.merge(serviceLayer)))
|
|
37
|
-
* ```
|
|
38
|
-
*
|
|
39
|
-
* @packageDocumentation
|
|
40
|
-
*/
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.withTracedRouter = exports.makeTracedGraphQLRouter = exports.isIntrospectionField = exports.getFieldDepth = exports.pathToString = exports.TRACESTATE_HEADER = exports.TRACEPARENT_HEADER = exports.TraceContextTag = exports.isSampled = exports.formatTraceParent = exports.parseTraceParent = exports.extractTraceContext = exports.resolverTracingMiddleware = exports.tracingExtension = exports.withTracing = void 0;
|
|
43
|
-
const tracing_extension_1 = require("./tracing-extension");
|
|
44
|
-
const tracing_middleware_1 = require("./tracing-middleware");
|
|
45
|
-
/**
|
|
46
|
-
* Add OpenTelemetry tracing to a GraphQL schema builder.
|
|
47
|
-
*
|
|
48
|
-
* This is a convenience function that registers both the tracing extension
|
|
49
|
-
* (for phase-level spans) and resolver middleware (for field-level spans).
|
|
50
|
-
*
|
|
51
|
-
* **Span Hierarchy:**
|
|
52
|
-
* ```
|
|
53
|
-
* graphql.request (if using traced router)
|
|
54
|
-
* ├── graphql.parse
|
|
55
|
-
* ├── graphql.validate
|
|
56
|
-
* └── graphql.execute
|
|
57
|
-
* ├── graphql.resolve Query.users
|
|
58
|
-
* ├── graphql.resolve User.posts
|
|
59
|
-
* └── graphql.resolve Post.author
|
|
60
|
-
* ```
|
|
61
|
-
*
|
|
62
|
-
* **Requirements:**
|
|
63
|
-
* - An OpenTelemetry tracer must be provided via Effect's tracing layer
|
|
64
|
-
* - Use `@effect/opentelemetry` NodeSdk.layer or OtlpTracer.layer
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* ```typescript
|
|
68
|
-
* import { GraphQLSchemaBuilder } from "@effect-gql/core"
|
|
69
|
-
* import { withTracing } from "@effect-gql/opentelemetry"
|
|
70
|
-
*
|
|
71
|
-
* const builder = GraphQLSchemaBuilder.empty
|
|
72
|
-
* .query("hello", {
|
|
73
|
-
* type: S.String,
|
|
74
|
-
* resolve: () => Effect.succeed("world")
|
|
75
|
-
* })
|
|
76
|
-
* .pipe(withTracing({
|
|
77
|
-
* extension: {
|
|
78
|
-
* exposeTraceIdInResponse: true, // Add traceId to response extensions
|
|
79
|
-
* includeQuery: false, // Don't include query in spans (security)
|
|
80
|
-
* },
|
|
81
|
-
* resolver: {
|
|
82
|
-
* minDepth: 0, // Trace all resolvers
|
|
83
|
-
* excludePatterns: [/^Query\.__/], // Skip introspection
|
|
84
|
-
* includeArgs: false, // Don't include args (security)
|
|
85
|
-
* }
|
|
86
|
-
* }))
|
|
87
|
-
* ```
|
|
88
|
-
*
|
|
89
|
-
* @param config - Optional tracing configuration
|
|
90
|
-
* @returns A function that adds tracing to a GraphQLSchemaBuilder
|
|
91
|
-
*/
|
|
92
|
-
const withTracing = (config) => (builder) => {
|
|
93
|
-
// Add tracing extension for phase-level spans
|
|
94
|
-
let result = builder.extension((0, tracing_extension_1.tracingExtension)(config?.extension));
|
|
95
|
-
// Add resolver tracing middleware for field-level spans
|
|
96
|
-
result = result.middleware((0, tracing_middleware_1.resolverTracingMiddleware)(config?.resolver));
|
|
97
|
-
return result;
|
|
98
|
-
};
|
|
99
|
-
exports.withTracing = withTracing;
|
|
100
|
-
// Re-export components for individual use
|
|
101
|
-
var tracing_extension_2 = require("./tracing-extension");
|
|
102
|
-
Object.defineProperty(exports, "tracingExtension", { enumerable: true, get: function () { return tracing_extension_2.tracingExtension; } });
|
|
103
|
-
var tracing_middleware_2 = require("./tracing-middleware");
|
|
104
|
-
Object.defineProperty(exports, "resolverTracingMiddleware", { enumerable: true, get: function () { return tracing_middleware_2.resolverTracingMiddleware; } });
|
|
105
|
-
var context_propagation_1 = require("./context-propagation");
|
|
106
|
-
Object.defineProperty(exports, "extractTraceContext", { enumerable: true, get: function () { return context_propagation_1.extractTraceContext; } });
|
|
107
|
-
Object.defineProperty(exports, "parseTraceParent", { enumerable: true, get: function () { return context_propagation_1.parseTraceParent; } });
|
|
108
|
-
Object.defineProperty(exports, "formatTraceParent", { enumerable: true, get: function () { return context_propagation_1.formatTraceParent; } });
|
|
109
|
-
Object.defineProperty(exports, "isSampled", { enumerable: true, get: function () { return context_propagation_1.isSampled; } });
|
|
110
|
-
Object.defineProperty(exports, "TraceContextTag", { enumerable: true, get: function () { return context_propagation_1.TraceContextTag; } });
|
|
111
|
-
Object.defineProperty(exports, "TRACEPARENT_HEADER", { enumerable: true, get: function () { return context_propagation_1.TRACEPARENT_HEADER; } });
|
|
112
|
-
Object.defineProperty(exports, "TRACESTATE_HEADER", { enumerable: true, get: function () { return context_propagation_1.TRACESTATE_HEADER; } });
|
|
113
|
-
var utils_1 = require("./utils");
|
|
114
|
-
Object.defineProperty(exports, "pathToString", { enumerable: true, get: function () { return utils_1.pathToString; } });
|
|
115
|
-
Object.defineProperty(exports, "getFieldDepth", { enumerable: true, get: function () { return utils_1.getFieldDepth; } });
|
|
116
|
-
Object.defineProperty(exports, "isIntrospectionField", { enumerable: true, get: function () { return utils_1.isIntrospectionField; } });
|
|
117
|
-
var traced_router_1 = require("./traced-router");
|
|
118
|
-
Object.defineProperty(exports, "makeTracedGraphQLRouter", { enumerable: true, get: function () { return traced_router_1.makeTracedGraphQLRouter; } });
|
|
119
|
-
Object.defineProperty(exports, "withTracedRouter", { enumerable: true, get: function () { return traced_router_1.withTracedRouter; } });
|
|
120
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;;;AAGH,2DAAmF;AACnF,6DAA4F;AAmB5F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACI,MAAM,WAAW,GACtB,CAAI,MAA6B,EAAE,EAAE,CACrC,CAAC,OAAgC,EAA2B,EAAE;IAC5D,8CAA8C;IAC9C,IAAI,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAA,oCAAgB,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;IAEnE,wDAAwD;IACxD,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,IAAA,8CAAyB,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEvE,OAAO,MAAiC,CAAA;AAC1C,CAAC,CAAA;AAVU,QAAA,WAAW,eAUrB;AAEH,0CAA0C;AAC1C,yDAAmF;AAA1E,qHAAA,gBAAgB,OAAA;AACzB,2DAA4F;AAAnF,+HAAA,yBAAyB,OAAA;AAClC,6DAS8B;AAR5B,0HAAA,mBAAmB,OAAA;AACnB,uHAAA,gBAAgB,OAAA;AAChB,wHAAA,iBAAiB,OAAA;AACjB,gHAAA,SAAS,OAAA;AACT,sHAAA,eAAe,OAAA;AACf,yHAAA,kBAAkB,OAAA;AAClB,wHAAA,iBAAiB,OAAA;AAGnB,iCAA2E;AAAlE,qGAAA,YAAY,OAAA;AAAE,sGAAA,aAAa,OAAA;AAAE,6GAAA,oBAAoB,OAAA;AAC1D,iDAIwB;AAHtB,wHAAA,uBAAuB,OAAA;AACvB,iHAAA,gBAAgB,OAAA"}
|
package/dist/traced-router.d.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { HttpRouter } from "@effect/platform";
|
|
2
|
-
import { Layer } from "effect";
|
|
3
|
-
import type { GraphQLSchema } from "graphql";
|
|
4
|
-
import { type MakeGraphQLRouterOptions } from "@effect-gql/core/server";
|
|
5
|
-
/**
|
|
6
|
-
* Options for the traced GraphQL router
|
|
7
|
-
*/
|
|
8
|
-
export interface TracedRouterOptions extends MakeGraphQLRouterOptions {
|
|
9
|
-
/**
|
|
10
|
-
* Name for the root HTTP span.
|
|
11
|
-
* Default: "graphql.http"
|
|
12
|
-
*/
|
|
13
|
-
readonly rootSpanName?: string;
|
|
14
|
-
/**
|
|
15
|
-
* Additional attributes to add to the root span.
|
|
16
|
-
*/
|
|
17
|
-
readonly rootSpanAttributes?: Record<string, string | number | boolean>;
|
|
18
|
-
/**
|
|
19
|
-
* Whether to propagate trace context from incoming HTTP headers.
|
|
20
|
-
* Uses W3C Trace Context (traceparent header).
|
|
21
|
-
* Default: true
|
|
22
|
-
*/
|
|
23
|
-
readonly propagateContext?: boolean;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Creates a GraphQL router with OpenTelemetry tracing at the HTTP level.
|
|
27
|
-
*
|
|
28
|
-
* This wraps the standard makeGraphQLRouter to:
|
|
29
|
-
* 1. Extract trace context from incoming HTTP headers (W3C Trace Context)
|
|
30
|
-
* 2. Create a root span for the entire HTTP request
|
|
31
|
-
* 3. Propagate trace context to child spans created by extensions/middleware
|
|
32
|
-
*
|
|
33
|
-
* **Span Hierarchy:**
|
|
34
|
-
* ```
|
|
35
|
-
* graphql.http (created by this router)
|
|
36
|
-
* ├── graphql.parse (from tracing extension)
|
|
37
|
-
* ├── graphql.validate (from tracing extension)
|
|
38
|
-
* └── graphql.resolve Query.* (from tracing middleware)
|
|
39
|
-
* ```
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* ```typescript
|
|
43
|
-
* import { makeTracedGraphQLRouter } from "@effect-gql/opentelemetry"
|
|
44
|
-
* import { NodeSdk } from "@effect/opentelemetry"
|
|
45
|
-
*
|
|
46
|
-
* const router = makeTracedGraphQLRouter(schema, serviceLayer, {
|
|
47
|
-
* path: "/graphql",
|
|
48
|
-
* graphiql: { path: "/graphiql" },
|
|
49
|
-
* rootSpanName: "graphql.http",
|
|
50
|
-
* rootSpanAttributes: {
|
|
51
|
-
* "service.name": "my-api"
|
|
52
|
-
* }
|
|
53
|
-
* })
|
|
54
|
-
*
|
|
55
|
-
* // Provide OpenTelemetry layer when serving
|
|
56
|
-
* const TracingLayer = NodeSdk.layer(() => ({
|
|
57
|
-
* resource: { serviceName: "my-graphql-api" },
|
|
58
|
-
* spanProcessor: new BatchSpanProcessor(new OTLPTraceExporter())
|
|
59
|
-
* }))
|
|
60
|
-
* ```
|
|
61
|
-
*
|
|
62
|
-
* @param schema - The GraphQL schema
|
|
63
|
-
* @param layer - Effect layer providing services required by resolvers
|
|
64
|
-
* @param options - Router and tracing configuration
|
|
65
|
-
* @returns An HttpRouter with tracing enabled
|
|
66
|
-
*/
|
|
67
|
-
export declare const makeTracedGraphQLRouter: <R>(schema: GraphQLSchema, layer: Layer.Layer<R>, options?: TracedRouterOptions) => HttpRouter.HttpRouter<never, never>;
|
|
68
|
-
/**
|
|
69
|
-
* Wrap an existing HttpRouter with OpenTelemetry tracing.
|
|
70
|
-
*
|
|
71
|
-
* This is useful when you already have a router and want to add
|
|
72
|
-
* request-level tracing without recreating it.
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```typescript
|
|
76
|
-
* import { toRouter } from "@effect-gql/core/server"
|
|
77
|
-
* import { withTracedRouter } from "@effect-gql/opentelemetry"
|
|
78
|
-
*
|
|
79
|
-
* const baseRouter = toRouter(builder, serviceLayer)
|
|
80
|
-
* const tracedRouter = withTracedRouter(baseRouter, {
|
|
81
|
-
* rootSpanName: "graphql.http"
|
|
82
|
-
* })
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
85
|
-
export declare const withTracedRouter: (router: HttpRouter.HttpRouter<any, any>, options?: {
|
|
86
|
-
rootSpanName?: string;
|
|
87
|
-
rootSpanAttributes?: Record<string, string | number | boolean>;
|
|
88
|
-
propagateContext?: boolean;
|
|
89
|
-
}) => HttpRouter.HttpRouter<any, any>;
|
|
90
|
-
//# sourceMappingURL=traced-router.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"traced-router.d.ts","sourceRoot":"","sources":["../src/traced-router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAyC,MAAM,kBAAkB,CAAA;AACpF,OAAO,EAAU,KAAK,EAAU,MAAM,QAAQ,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,EAAqB,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAA;AAG1F;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,wBAAwB;IACnE;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAE9B;;OAEG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;IAEvE;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACpC;AAkCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,MAAM,uBAAuB,GAAI,CAAC,EACvC,QAAQ,aAAa,EACrB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EACrB,UAAS,mBAAwB,KAChC,UAAU,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAmDpC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EACvC,UAAS;IACP,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;IAC9D,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACtB,KACL,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAuDhC,CAAA"}
|
package/dist/traced-router.js
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.withTracedRouter = exports.makeTracedGraphQLRouter = void 0;
|
|
4
|
-
const platform_1 = require("@effect/platform");
|
|
5
|
-
const effect_1 = require("effect");
|
|
6
|
-
const server_1 = require("@effect-gql/core/server");
|
|
7
|
-
const context_propagation_1 = require("./context-propagation");
|
|
8
|
-
/**
|
|
9
|
-
* Create an Effect span options object from trace context
|
|
10
|
-
*/
|
|
11
|
-
const createSpanOptions = (traceContext, request, config) => {
|
|
12
|
-
const attributes = {
|
|
13
|
-
"http.method": request.method,
|
|
14
|
-
"http.url": request.url,
|
|
15
|
-
"http.target": request.url,
|
|
16
|
-
...config.rootSpanAttributes,
|
|
17
|
-
};
|
|
18
|
-
if (traceContext && config.propagateContext !== false) {
|
|
19
|
-
return {
|
|
20
|
-
attributes,
|
|
21
|
-
parent: effect_1.Tracer.externalSpan({
|
|
22
|
-
traceId: traceContext.traceId,
|
|
23
|
-
spanId: traceContext.parentSpanId,
|
|
24
|
-
sampled: (traceContext.traceFlags & 0x01) === 0x01,
|
|
25
|
-
}),
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
return { attributes };
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* Creates a GraphQL router with OpenTelemetry tracing at the HTTP level.
|
|
32
|
-
*
|
|
33
|
-
* This wraps the standard makeGraphQLRouter to:
|
|
34
|
-
* 1. Extract trace context from incoming HTTP headers (W3C Trace Context)
|
|
35
|
-
* 2. Create a root span for the entire HTTP request
|
|
36
|
-
* 3. Propagate trace context to child spans created by extensions/middleware
|
|
37
|
-
*
|
|
38
|
-
* **Span Hierarchy:**
|
|
39
|
-
* ```
|
|
40
|
-
* graphql.http (created by this router)
|
|
41
|
-
* ├── graphql.parse (from tracing extension)
|
|
42
|
-
* ├── graphql.validate (from tracing extension)
|
|
43
|
-
* └── graphql.resolve Query.* (from tracing middleware)
|
|
44
|
-
* ```
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```typescript
|
|
48
|
-
* import { makeTracedGraphQLRouter } from "@effect-gql/opentelemetry"
|
|
49
|
-
* import { NodeSdk } from "@effect/opentelemetry"
|
|
50
|
-
*
|
|
51
|
-
* const router = makeTracedGraphQLRouter(schema, serviceLayer, {
|
|
52
|
-
* path: "/graphql",
|
|
53
|
-
* graphiql: { path: "/graphiql" },
|
|
54
|
-
* rootSpanName: "graphql.http",
|
|
55
|
-
* rootSpanAttributes: {
|
|
56
|
-
* "service.name": "my-api"
|
|
57
|
-
* }
|
|
58
|
-
* })
|
|
59
|
-
*
|
|
60
|
-
* // Provide OpenTelemetry layer when serving
|
|
61
|
-
* const TracingLayer = NodeSdk.layer(() => ({
|
|
62
|
-
* resource: { serviceName: "my-graphql-api" },
|
|
63
|
-
* spanProcessor: new BatchSpanProcessor(new OTLPTraceExporter())
|
|
64
|
-
* }))
|
|
65
|
-
* ```
|
|
66
|
-
*
|
|
67
|
-
* @param schema - The GraphQL schema
|
|
68
|
-
* @param layer - Effect layer providing services required by resolvers
|
|
69
|
-
* @param options - Router and tracing configuration
|
|
70
|
-
* @returns An HttpRouter with tracing enabled
|
|
71
|
-
*/
|
|
72
|
-
const makeTracedGraphQLRouter = (schema, layer, options = {}) => {
|
|
73
|
-
const rootSpanName = options.rootSpanName ?? "graphql.http";
|
|
74
|
-
// Create the base router (handles GraphQL logic)
|
|
75
|
-
const baseRouter = (0, server_1.makeGraphQLRouter)(schema, layer, options);
|
|
76
|
-
// Convert base router to an HttpApp for Effect-based handling
|
|
77
|
-
const baseApp = platform_1.HttpRouter.toHttpApp(baseRouter);
|
|
78
|
-
// Wrap with tracing
|
|
79
|
-
return platform_1.HttpRouter.empty.pipe(platform_1.HttpRouter.all("*", effect_1.Effect.gen(function* () {
|
|
80
|
-
const request = yield* platform_1.HttpServerRequest.HttpServerRequest;
|
|
81
|
-
// Extract trace context from headers (if enabled)
|
|
82
|
-
const traceContext = options.propagateContext !== false
|
|
83
|
-
? yield* context_propagation_1.extractTraceContext.pipe(effect_1.Effect.catchAll(() => effect_1.Effect.succeed(null)))
|
|
84
|
-
: null;
|
|
85
|
-
// Create span options with parent context if available
|
|
86
|
-
const spanOptions = createSpanOptions(traceContext, request, options);
|
|
87
|
-
// Execute the request inside a root span
|
|
88
|
-
return yield* effect_1.Effect.withSpan(rootSpanName, spanOptions)(effect_1.Effect.gen(function* () {
|
|
89
|
-
// Delegate to the base app (which handles the request from context)
|
|
90
|
-
const app = yield* baseApp;
|
|
91
|
-
const response = yield* app.pipe(effect_1.Effect.catchTag("RouteNotFound", () => platform_1.HttpServerResponse.text(JSON.stringify({ errors: [{ message: "Not Found" }] }), {
|
|
92
|
-
status: 404,
|
|
93
|
-
headers: { "content-type": "application/json" },
|
|
94
|
-
})));
|
|
95
|
-
// Annotate span with response info
|
|
96
|
-
yield* effect_1.Effect.annotateCurrentSpan("http.status_code", response.status);
|
|
97
|
-
return response;
|
|
98
|
-
}));
|
|
99
|
-
})));
|
|
100
|
-
};
|
|
101
|
-
exports.makeTracedGraphQLRouter = makeTracedGraphQLRouter;
|
|
102
|
-
/**
|
|
103
|
-
* Wrap an existing HttpRouter with OpenTelemetry tracing.
|
|
104
|
-
*
|
|
105
|
-
* This is useful when you already have a router and want to add
|
|
106
|
-
* request-level tracing without recreating it.
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
* ```typescript
|
|
110
|
-
* import { toRouter } from "@effect-gql/core/server"
|
|
111
|
-
* import { withTracedRouter } from "@effect-gql/opentelemetry"
|
|
112
|
-
*
|
|
113
|
-
* const baseRouter = toRouter(builder, serviceLayer)
|
|
114
|
-
* const tracedRouter = withTracedRouter(baseRouter, {
|
|
115
|
-
* rootSpanName: "graphql.http"
|
|
116
|
-
* })
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
const withTracedRouter = (router, options = {}) => {
|
|
120
|
-
const rootSpanName = options.rootSpanName ?? "graphql.http";
|
|
121
|
-
// Convert router to an HttpApp for Effect-based handling
|
|
122
|
-
const baseApp = platform_1.HttpRouter.toHttpApp(router);
|
|
123
|
-
return platform_1.HttpRouter.empty.pipe(platform_1.HttpRouter.all("*", effect_1.Effect.gen(function* () {
|
|
124
|
-
const request = yield* platform_1.HttpServerRequest.HttpServerRequest;
|
|
125
|
-
// Extract trace context from headers
|
|
126
|
-
const traceContext = options.propagateContext !== false
|
|
127
|
-
? yield* context_propagation_1.extractTraceContext.pipe(effect_1.Effect.catchAll(() => effect_1.Effect.succeed(null)))
|
|
128
|
-
: null;
|
|
129
|
-
const spanOptions = {
|
|
130
|
-
attributes: {
|
|
131
|
-
"http.method": request.method,
|
|
132
|
-
"http.url": request.url,
|
|
133
|
-
...options.rootSpanAttributes,
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
if (traceContext && options.propagateContext !== false) {
|
|
137
|
-
spanOptions.parent = effect_1.Tracer.externalSpan({
|
|
138
|
-
traceId: traceContext.traceId,
|
|
139
|
-
spanId: traceContext.parentSpanId,
|
|
140
|
-
sampled: (traceContext.traceFlags & 0x01) === 0x01,
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
return yield* effect_1.Effect.withSpan(rootSpanName, spanOptions)(effect_1.Effect.gen(function* () {
|
|
144
|
-
// Delegate to the base app (which handles the request from context)
|
|
145
|
-
const app = yield* baseApp;
|
|
146
|
-
const response = yield* app;
|
|
147
|
-
// Annotate span with response info
|
|
148
|
-
yield* effect_1.Effect.annotateCurrentSpan("http.status_code", response.status);
|
|
149
|
-
return response;
|
|
150
|
-
}));
|
|
151
|
-
})));
|
|
152
|
-
};
|
|
153
|
-
exports.withTracedRouter = withTracedRouter;
|
|
154
|
-
//# sourceMappingURL=traced-router.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"traced-router.js","sourceRoot":"","sources":["../src/traced-router.ts"],"names":[],"mappings":"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"}
|