102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
import type { ApolloServerPlugin } from '@apollo/server';
|
|
import { logger, logQuery, logError } from '../monitoring/logger.js';
|
|
import {
|
|
queryCounter,
|
|
queryDuration,
|
|
errorCounter,
|
|
queryComplexityGauge,
|
|
} from '../monitoring/metrics.js';
|
|
import { createTrace, endTrace } from '../monitoring/tracing.js';
|
|
|
|
/**
|
|
* Monitoring Plugin für Apollo Server
|
|
* Sammelt Logs, Metrics und Traces für jeden Request
|
|
*/
|
|
export const monitoringPlugin = (): ApolloServerPlugin => {
|
|
return {
|
|
async requestDidStart() {
|
|
return {
|
|
async didResolveOperation({ request, operationName }) {
|
|
// Erstelle Trace für Request
|
|
const traceId = createTrace().traceId;
|
|
(request as any).traceId = traceId;
|
|
|
|
logger.info('GraphQL operation started', {
|
|
operationName: operationName || 'unknown',
|
|
query: request.query,
|
|
variables: request.variables,
|
|
traceId,
|
|
});
|
|
},
|
|
|
|
async willSendResponse({ request, response }) {
|
|
const traceId = (request as any).traceId;
|
|
const operationName = request.operationName || 'unknown';
|
|
const duration = traceId ? endTrace(traceId) : 0;
|
|
|
|
// Log Query
|
|
logQuery(operationName, request.variables, duration);
|
|
|
|
// Metrics
|
|
const status = response.errors && response.errors.length > 0 ? 'error' : 'success';
|
|
queryCounter.inc({ operation: operationName, status });
|
|
queryDuration.observe({ operation: operationName }, duration / 1000);
|
|
|
|
// Log Errors
|
|
if (response.errors && response.errors.length > 0) {
|
|
response.errors.forEach((error) => {
|
|
logError(error as Error, {
|
|
operationName,
|
|
traceId,
|
|
});
|
|
errorCounter.inc({
|
|
type: error.extensions?.code as string || 'UNKNOWN',
|
|
operation: operationName,
|
|
});
|
|
});
|
|
}
|
|
},
|
|
|
|
async didEncounterErrors({ request, errors }) {
|
|
const traceId = (request as any).traceId;
|
|
const operationName = request.operationName || 'unknown';
|
|
|
|
errors.forEach((error) => {
|
|
logError(error as Error, {
|
|
operationName,
|
|
traceId,
|
|
});
|
|
errorCounter.inc({
|
|
type: error.extensions?.code as string || 'UNKNOWN',
|
|
operation: operationName,
|
|
});
|
|
});
|
|
},
|
|
};
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Plugin für Query Complexity Tracking
|
|
*/
|
|
export const queryComplexityMonitoringPlugin = (): ApolloServerPlugin => {
|
|
return {
|
|
async requestDidStart() {
|
|
return {
|
|
async didResolveOperation({ request, operationName }) {
|
|
// Wird vom queryComplexityPlugin gesetzt
|
|
const complexity = (request as any).complexity;
|
|
if (complexity) {
|
|
queryComplexityGauge.set(
|
|
{ operation: operationName || 'unknown' },
|
|
complexity
|
|
);
|
|
}
|
|
},
|
|
};
|
|
},
|
|
};
|
|
};
|
|
|