@graphql-yoga/plugin-prometheus
Version:
Prometheus plugin for GraphQL Yoga.
107 lines (106 loc) • 5.07 kB
JavaScript
;
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);
}
}
},
};
}