UNPKG

@graphql-mesh/plugin-prometheus

Version:
231 lines (230 loc) • 9.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const prom_client_1 = require("prom-client"); const utils_1 = require("@graphql-mesh/utils"); const plugin_prometheus_1 = require("@graphql-yoga/plugin-prometheus"); const createHistogramForEnvelop_js_1 = require("./createHistogramForEnvelop.js"); async function useMeshPrometheus(pluginOptions) { const registry = pluginOptions.registry ? await (0, utils_1.loadFromModuleExportExpression)(pluginOptions.registry, { cwd: pluginOptions.baseDir, importFn: pluginOptions.importFn, defaultExportName: 'default', }) : prom_client_1.register; let fetchHistogram; if (pluginOptions.fetch) { const name = typeof pluginOptions.fetch === 'string' ? pluginOptions.fetch : 'graphql_mesh_fetch_duration'; const labelNames = ['url', 'method', 'statusCode', 'statusText']; if (pluginOptions.fetchRequestHeaders) { labelNames.push('requestHeaders'); } if (pluginOptions.fetchResponseHeaders) { labelNames.push('responseHeaders'); } fetchHistogram = new prom_client_1.Histogram({ name, help: 'Time spent on outgoing HTTP calls', labelNames, registers: [registry], }); } let delegateHistogram; if (pluginOptions.delegation) { const name = typeof pluginOptions.delegation === 'string' ? pluginOptions.delegation : 'graphql_mesh_delegate_duration'; delegateHistogram = new prom_client_1.Histogram({ name, help: 'Time spent on delegate execution', labelNames: ['sourceName', 'typeName', 'fieldName', 'args', 'key'], registers: [registry], }); } let httpHistogram; if (pluginOptions.http) { const labelNames = ['url', 'method', 'statusCode', 'statusText']; if (pluginOptions.httpRequestHeaders) { labelNames.push('requestHeaders'); } if (pluginOptions.httpResponseHeaders) { labelNames.push('responseHeaders'); } const name = typeof pluginOptions.http === 'string' ? pluginOptions.http : 'graphql_mesh_http_duration'; httpHistogram = { histogram: new prom_client_1.Histogram({ name, help: 'Time spent on incoming HTTP requests', labelNames, registers: [registry], }), fillLabelsFn(_, { request, response }) { const labels = { url: request.url, method: request.method, statusCode: response.status, statusText: response.statusText, }; if (pluginOptions.httpRequestHeaders) { labels.requestHeaders = JSON.stringify((0, utils_1.getHeadersObj)(request.headers)); } if (pluginOptions.httpResponseHeaders) { labels.responseHeaders = JSON.stringify((0, utils_1.getHeadersObj)(response.headers)); } return labels; }, }; } let requestCounter; if (pluginOptions.requestCount) { const name = typeof pluginOptions.requestCount === 'string' ? pluginOptions.requestCount : 'graphql_mesh_request_count'; requestCounter = { counter: new prom_client_1.Counter({ name, help: 'Counts the amount of GraphQL requests executed', labelNames: createHistogramForEnvelop_js_1.commonLabelsForEnvelop, registers: [registry], }), fillLabelsFn: createHistogramForEnvelop_js_1.commonFillLabelsFnForEnvelop, }; } let requestSummary; if (pluginOptions.requestSummary) { const name = typeof pluginOptions.requestSummary === 'string' ? pluginOptions.requestSummary : 'graphql_mesh_request_time_summary'; requestSummary = { summary: new prom_client_1.Summary({ name, help: 'Summary to measure the time to complete GraphQL operations', labelNames: createHistogramForEnvelop_js_1.commonLabelsForEnvelop, registers: [registry], }), fillLabelsFn: createHistogramForEnvelop_js_1.commonFillLabelsFnForEnvelop, }; } let errorsCounter; if (pluginOptions.errors) { const name = typeof pluginOptions.errors === 'string' ? pluginOptions.errors : 'graphql_mesh_error_result'; errorsCounter = { counter: new prom_client_1.Counter({ name, help: 'Counts the amount of errors reported from all phases', labelNames: ['operationType', 'operationName', 'path', 'phase'], registers: [registry], }), fillLabelsFn: params => ({ operationName: params.operationName, operationType: params.operationType, path: params.error?.path?.join('.'), phase: params.errorPhase, }), }; } let deprecatedCounter; if (pluginOptions.deprecatedFields) { const name = typeof pluginOptions.deprecatedFields === 'string' ? pluginOptions.deprecatedFields : 'graphql_mesh_deprecated_fields'; deprecatedCounter = { counter: new prom_client_1.Counter({ name, help: 'Counts the amount of deprecated fields used in selection sets', labelNames: ['operationType', 'operationName', 'fieldName', 'typeName'], registers: [registry], }), fillLabelsFn: params => ({ operationName: params.operationName, operationType: params.operationType, fieldName: params.deprecationInfo?.fieldName, typeName: params.deprecationInfo?.typeName, }), }; } return { onPluginInit({ addPlugin }) { addPlugin((0, plugin_prometheus_1.usePrometheus)({ ...pluginOptions, http: httpHistogram, requestCount: requestCounter, requestTotalDuration: (0, createHistogramForEnvelop_js_1.createHistogramForEnvelop)({ defaultName: 'graphql_mesh_request_duration', valueFromConfig: pluginOptions.requestTotalDuration, help: 'Time spent on running the GraphQL operation from parse to execute', registry, }), requestSummary, parse: (0, createHistogramForEnvelop_js_1.createHistogramForEnvelop)({ defaultName: 'graphql_mesh_parse_duration', valueFromConfig: pluginOptions.parse, help: 'Time spent on parsing the GraphQL operation', registry, }), validate: (0, createHistogramForEnvelop_js_1.createHistogramForEnvelop)({ defaultName: 'graphql_mesh_validate_duration', valueFromConfig: pluginOptions.validate, help: 'Time spent on validating the GraphQL operation', registry, }), contextBuilding: (0, createHistogramForEnvelop_js_1.createHistogramForEnvelop)({ defaultName: 'graphql_mesh_context_building_duration', valueFromConfig: pluginOptions.contextBuilding, help: 'Time spent on building the GraphQL context', registry, }), execute: (0, createHistogramForEnvelop_js_1.createHistogramForEnvelop)({ defaultName: 'graphql_mesh_execute_duration', valueFromConfig: pluginOptions.execute, help: 'Time spent on executing the GraphQL operation', registry, }), errors: errorsCounter, deprecatedFields: deprecatedCounter, registry, })); }, onDelegate({ sourceName, typeName, fieldName, args, key }) { if (delegateHistogram) { const start = Date.now(); return () => { const end = Date.now(); const duration = end - start; delegateHistogram.observe({ sourceName, typeName, fieldName, args: JSON.stringify(args), key: JSON.stringify(key), }, duration); }; } return undefined; }, onFetch({ url, options }) { if (fetchHistogram) { const start = Date.now(); return ({ response }) => { const end = Date.now(); const duration = end - start; const labels = { url, method: options.method, statusCode: response.status, statusText: response.statusText, }; if (pluginOptions.fetchRequestHeaders) { labels.requestHeaders = JSON.stringify(options.headers); } if (pluginOptions.fetchResponseHeaders) { labels.responseHeaders = JSON.stringify((0, utils_1.getHeadersObj)(response.headers)); } fetchHistogram.observe(labels, duration); }; } return undefined; }, }; } exports.default = useMeshPrometheus;