@graphql-yoga/plugin-prometheus
Version:
Prometheus plugin for GraphQL Yoga.
91 lines (90 loc) • 3.69 kB
JavaScript
import { getOperationAST } from 'graphql';
import { register as defaultRegistry } from 'prom-client';
import { createCounter, createHistogram, createSummary, usePrometheus as useEnvelopPrometheus, } from '@envelop/prometheus';
export { createCounter, createHistogram, createSummary, };
export function usePrometheus(options) {
const endpoint = options.endpoint || '/metrics';
const registry = options.registry || defaultRegistry;
let httpHistogram;
function labelExists(label) {
if (options.labels?.[label] == null) {
return true;
}
return options.labels[label];
}
if (options.http) {
const labelNames = ['method', 'statusCode'];
if (labelExists('operationName')) {
labelNames.push('operationName');
}
if (labelExists('operationType')) {
labelNames.push('operationType');
}
httpHistogram =
typeof options.http === 'object'
? options.http
: createHistogram({
registry,
histogram: {
name: typeof options.http === 'string' ? options.http : 'graphql_yoga_http_duration',
help: 'Time spent on HTTP connection',
labelNames,
},
fillLabelsFn(params, { request, response }) {
const labels = {
method: request.method,
statusCode: response.status,
};
if (labelExists('operationType') && params.operationType) {
labels.operationType = params.operationType;
}
if (labelExists('operationName')) {
labels.operationName = params.operationName || 'Anonymous';
}
return labels;
},
});
}
const startByRequest = new WeakMap();
const paramsByRequest = new WeakMap();
return {
onPluginInit({ addPlugin }) {
addPlugin(useEnvelopPrometheus({ ...options, registry }));
},
onRequest({ request, url, fetchAPI, endResponse }) {
startByRequest.set(request, Date.now());
if (endpoint && url.pathname === endpoint) {
return registry.metrics().then(metrics => {
endResponse(new fetchAPI.Response(metrics, {
headers: {
'Content-Type': registry.contentType,
},
}));
});
}
return undefined;
},
onParse() {
return ({ result: document, context: { params, request } }) => {
const operationAST = getOperationAST(document, params.operationName);
paramsByRequest.set(request, {
document,
operationName: operationAST?.name?.value,
operationType: operationAST?.operation,
});
};
},
onResponse({ request, response, serverContext }) {
const start = startByRequest.get(request);
if (start) {
const duration = Date.now() - start;
const params = paramsByRequest.get(request);
httpHistogram?.histogram.observe(httpHistogram.fillLabelsFn(params || {}, {
...serverContext,
request,
response,
}), duration);
}
},
};
}