mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
149 lines
4.2 KiB
TypeScript
149 lines
4.2 KiB
TypeScript
import { defineConfig } from '@graphql-hive/gateway';
|
|
import { hiveTracingSetup } from '@graphql-hive/plugin-opentelemetry/setup';
|
|
import type { Context } from '@opentelemetry/api';
|
|
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
|
|
import { globalErrorHandler } from '@opentelemetry/core';
|
|
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
import {
|
|
BatchSpanProcessor,
|
|
SpanProcessor,
|
|
type ReadableSpan,
|
|
type Span,
|
|
} from '@opentelemetry/sdk-trace-base';
|
|
|
|
/** Note: this is inlined for now... */
|
|
class MultiSpanProcessor implements SpanProcessor {
|
|
constructor(private readonly _spanProcessors: SpanProcessor[]) {}
|
|
|
|
forceFlush(): Promise<void> {
|
|
const promises: Promise<void>[] = [];
|
|
|
|
for (const spanProcessor of this._spanProcessors) {
|
|
promises.push(spanProcessor.forceFlush());
|
|
}
|
|
return new Promise(resolve => {
|
|
Promise.all(promises)
|
|
.then(() => {
|
|
resolve();
|
|
})
|
|
.catch(error => {
|
|
globalErrorHandler(error || new Error('MultiSpanProcessor: forceFlush failed'));
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
onStart(span: Span, context: Context): void {
|
|
for (const spanProcessor of this._spanProcessors) {
|
|
spanProcessor.onStart(span, context);
|
|
}
|
|
}
|
|
|
|
onEnd(span: ReadableSpan): void {
|
|
for (const spanProcessor of this._spanProcessors) {
|
|
spanProcessor.onEnd(span);
|
|
}
|
|
}
|
|
|
|
shutdown(): Promise<void> {
|
|
const promises: Promise<void>[] = [];
|
|
|
|
for (const spanProcessor of this._spanProcessors) {
|
|
promises.push(spanProcessor.shutdown());
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
Promise.all(promises).then(() => {
|
|
resolve();
|
|
}, reject);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (
|
|
process.env['OPENTELEMETRY_COLLECTOR_ENDPOINT'] ||
|
|
process.env['HIVE_HIVE_TRACE_ACCESS_TOKEN']
|
|
) {
|
|
hiveTracingSetup({
|
|
// Noop is only there to not raise an exception in case we do not hive console tracing.
|
|
target: process.env['HIVE_HIVE_TARGET'] ?? 'noop',
|
|
contextManager: new AsyncLocalStorageContextManager(),
|
|
// @ts-expect-error console uses otel v1 and hive gateway uses v2
|
|
// TODO: upgrade console to otel v2
|
|
processor: new MultiSpanProcessor([
|
|
...(process.env['HIVE_HIVE_TRACE_ACCESS_TOKEN'] &&
|
|
process.env['HIVE_HIVE_TRACE_ENDPOINT'] &&
|
|
process.env['HIVE_HIVE_TARGET']
|
|
? [
|
|
new BatchSpanProcessor(
|
|
new OTLPTraceExporter({
|
|
url: process.env['HIVE_HIVE_TRACE_ENDPOINT'],
|
|
headers: {
|
|
Authorization: `Bearer ${process.env['HIVE_HIVE_TRACE_ACCESS_TOKEN']}`,
|
|
'X-Hive-Target-Ref': process.env['HIVE_HIVE_TARGET'],
|
|
},
|
|
}),
|
|
),
|
|
]
|
|
: []),
|
|
...(process.env['OPENTELEMETRY_COLLECTOR_ENDPOINT']
|
|
? [
|
|
new BatchSpanProcessor(
|
|
new OTLPTraceExporter({
|
|
url: process.env['OPENTELEMETRY_COLLECTOR_ENDPOINT']!,
|
|
}),
|
|
),
|
|
]
|
|
: []),
|
|
]),
|
|
});
|
|
}
|
|
|
|
const defaultQuery = `#
|
|
# Welcome to the Hive Console GraphQL API.
|
|
#
|
|
`;
|
|
|
|
export const gatewayConfig = defineConfig({
|
|
transportEntries: {
|
|
graphql: {
|
|
location: process.env['GRAPHQL_SERVICE_ENDPOINT'],
|
|
},
|
|
},
|
|
supergraph: {
|
|
type: 'hive',
|
|
endpoint: process.env['SUPERGRAPH_ENDPOINT'] || '',
|
|
key: process.env['HIVE_CDN_ACCESS_TOKEN'] || '',
|
|
},
|
|
graphiql: {
|
|
title: 'Hive Console - GraphQL API',
|
|
defaultQuery,
|
|
},
|
|
propagateHeaders: {
|
|
fromClientToSubgraphs({ request }) {
|
|
return {
|
|
'x-request-id': request.headers.get('x-request-id'),
|
|
authorization: request.headers.get('authorization'),
|
|
};
|
|
},
|
|
},
|
|
disableWebsockets: true,
|
|
prometheus: {
|
|
metrics: true,
|
|
},
|
|
openTelemetry:
|
|
process.env['OPENTELEMETRY_COLLECTOR_ENDPOINT'] || process.env['HIVE_HIVE_TRACE_ACCESS_TOKEN']
|
|
? {
|
|
traces: true,
|
|
}
|
|
: undefined,
|
|
demandControl: {
|
|
maxCost: 1000,
|
|
includeExtensionMetadata: true,
|
|
},
|
|
maxTokens: 1_000,
|
|
maxDepth: 20,
|
|
cors: {
|
|
origin: '*', // allow all origins
|
|
credentials: false, // do not allow credentials in cross-origin requests
|
|
},
|
|
});
|