UNPKG

@graphql-yoga/plugin-prometheus

Version:
107 lines (106 loc) 5.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSummaryFromConfig = exports.getCounterFromConfig = exports.getHistogramFromConfig = exports.createSummary = exports.createHistogram = exports.createCounter = void 0; exports.usePrometheus = usePrometheus; const graphql_1 = require("graphql"); const prom_client_1 = require("prom-client"); const prometheus_1 = require("@envelop/prometheus"); Object.defineProperty(exports, "createCounter", { enumerable: true, get: function () { return prometheus_1.createCounter; } }); Object.defineProperty(exports, "createHistogram", { enumerable: true, get: function () { return prometheus_1.createHistogram; } }); Object.defineProperty(exports, "createSummary", { enumerable: true, get: function () { return prometheus_1.createSummary; } }); Object.defineProperty(exports, "getCounterFromConfig", { enumerable: true, get: function () { return prometheus_1.getCounterFromConfig; } }); Object.defineProperty(exports, "getHistogramFromConfig", { enumerable: true, get: function () { return prometheus_1.getHistogramFromConfig; } }); Object.defineProperty(exports, "getSummaryFromConfig", { enumerable: true, get: function () { return prometheus_1.getSummaryFromConfig; } }); const DEFAULT_METRICS_CONFIG = { graphql_envelop_deprecated_field: true, graphql_envelop_request: true, graphql_envelop_request_duration: true, graphql_envelop_request_time_summary: true, graphql_envelop_phase_parse: true, graphql_envelop_phase_validate: true, graphql_envelop_phase_context: true, graphql_envelop_error_result: true, graphql_envelop_execute_resolver: false, graphql_envelop_phase_execute: true, graphql_envelop_phase_subscribe: true, graphql_envelop_schema_change: true, graphql_yoga_http_duration: true, }; function usePrometheus(options) { const endpoint = options.endpoint || '/metrics'; const registry = options.registry || prom_client_1.register; const resolvedOptions = { ...options, metrics: { ...DEFAULT_METRICS_CONFIG, ...options.metrics, }, }; const basePlugin = { onPluginInit({ addPlugin }) { addPlugin((0, prometheus_1.usePrometheus)({ ...resolvedOptions, registry })); addPlugin({ onRequest({ url, fetchAPI, endResponse }) { if (endpoint && url.pathname === endpoint) { return registry.metrics().then(metrics => { endResponse(new fetchAPI.Response(metrics, { headers: { 'Content-Type': registry.contentType, }, })); }); } return undefined; }, }); }, }; const httpHistogram = (0, prometheus_1.getHistogramFromConfig)(resolvedOptions, 'graphql_yoga_http_duration', ['request'], { help: 'Time spent on HTTP connection', labelNames: ['operationName', 'operationType', 'method', 'statusCode', 'url'], }, (params, { request, response }) => ({ method: request.method, statusCode: response.status, operationType: params.operationType || 'unknown', operationName: params.operationName || 'Anonymous', url: request.url, })); // We don't need to register any hooks if the metric is not enabled if (!httpHistogram) { return basePlugin; } const startByRequest = new WeakMap(); const paramsByRequest = new WeakMap(); return { ...basePlugin, onRequest({ request }) { startByRequest.set(request, Date.now()); }, onParse({ context }) { // If only it is Yoga, we calculate HTTP request time if (context.request) { return ({ result: document, context }) => { const operationAST = (0, graphql_1.getOperationAST)(document, context.params.operationName); const params = { document, operationName: operationAST?.name?.value, operationType: operationAST?.operation, }; paramsByRequest.set(context.request, params); }; } return undefined; }, onResponse({ request, response, serverContext }) { const start = startByRequest.get(request); const params = paramsByRequest.get(request); if (start && params) { const context = { ...serverContext, request, response }; const completeParams = { ...params, request, response }; if (httpHistogram.shouldObserve(completeParams, context)) { httpHistogram.histogram.observe(httpHistogram.fillLabelsFn(completeParams, context), (Date.now() - start) / 1000); } } }, }; }