UNPKG

@envelop/statsd

Version:

This plugin tracks the complete execution flow, and reports metrics using StatsD (based on `hot-shots`).

95 lines (94 loc) 3.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useStatsD = exports.metricNames = void 0; const core_1 = require("@envelop/core"); exports.metricNames = { operationCount: 'operations.count', errorCount: 'operations.error_count', latency: 'operations.latency', }; const statsDPluginTagsSymbol = Symbol('statsDPluginTagsSymbol'); const statsDPluginExecutionStartTimeSymbol = Symbol('statsDPluginExecutionStartTimeSymbol'); function getOperation(document) { return document.definitions.find((def) => def.kind === 'OperationDefinition'); } function isParseFailure(parseResult) { return parseResult === null || parseResult instanceof Error; } function getTags(context) { return context[statsDPluginTagsSymbol]; } const useStatsD = (options) => { const { client, prefix = 'graphql', skipIntrospection = false } = options; function createMetricName(name) { return `${prefix}.${name}`; } function increaseErrorCount(tags) { client.increment(createMetricName(exports.metricNames.errorCount), tags); } function increaseOperationCount(tags) { client.increment(createMetricName(exports.metricNames.operationCount), tags); } return { onEnveloped({ extendContext }) { extendContext({ [statsDPluginExecutionStartTimeSymbol]: Date.now(), }); }, onParse({ extendContext, params }) { if (skipIntrospection && (0, core_1.isIntrospectionOperationString)(params.source)) { return; } return function onParseDone(payload) { if (isParseFailure(payload.result)) { increaseErrorCount(); increaseOperationCount(); } else { const operation = getOperation(payload.result); extendContext({ [statsDPluginTagsSymbol]: { operation: operation?.name?.value || 'anonymous', }, }); } }; }, onValidate({ context }) { const tags = getTags(context); if (!tags) { return undefined; } return function onValidateDone({ valid }) { if (!valid) { increaseErrorCount(tags); increaseOperationCount(tags); } }; }, onExecute({ args }) { const tags = getTags(args.contextValue); if (!tags) { return undefined; } return { onExecuteDone({ result }) { const latency = Date.now() - args.contextValue[statsDPluginExecutionStartTimeSymbol]; if ((0, core_1.isAsyncIterable)(result)) { // eslint-disable-next-line no-console console.warn(`Plugin "statsd" encountered a AsyncIterator which is not supported yet, so tracing data is not available for the operation.`); return; } increaseOperationCount(tags); if (result.errors && Array.isArray(result.errors)) { increaseErrorCount(tags); } else { client.histogram(createMetricName(exports.metricNames.latency), latency, tags); } }, }; }, }; }; exports.useStatsD = useStatsD;