UNPKG

@graphql-yoga/plugin-prometheus

Version:
91 lines (90 loc) 3.69 kB
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); } }, }; }