Files
sell/middlelayer/plugins/monitoring.ts

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
);
}
},
};
},
};
};