@graphql-mesh/plugin-prometheus
Version:
183 lines (182 loc) • 7.58 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const graphql_yoga_1 = require("graphql-yoga");
const prom_client_1 = require("prom-client");
const utils_1 = require("@graphql-mesh/utils");
const plugin_prometheus_1 = require("@graphql-yoga/plugin-prometheus");
function useMeshPrometheus(pluginOptions) {
let registry;
if (pluginOptions.registry) {
if (typeof pluginOptions.registry === 'string') {
const registry$ = (0, utils_1.loadFromModuleExportExpression)(pluginOptions.registry, {
cwd: pluginOptions.baseDir || globalThis.process?.cwd(),
importFn: pluginOptions.importFn || utils_1.defaultImportFn,
defaultExportName: 'default',
});
const registryProxy = Proxy.revocable(prom_client_1.register, {
get(target, prop, receiver) {
if (typeof target[prop] === 'function') {
return function (...args) {
return registry$.then(registry => registry[prop](...args));
};
}
return Reflect.get(target, prop, receiver);
},
});
registry = registryProxy.proxy;
registry$.then(() => registryProxy.revoke()).catch(e => pluginOptions.logger.error(e));
}
else {
registry = pluginOptions.registry;
}
}
else {
registry = prom_client_1.register;
}
let fetchHistogram;
if (pluginOptions.fetchMetrics) {
const name = typeof pluginOptions.fetchMetrics === 'string'
? pluginOptions.fetchMetrics
: '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';
const delegationLabelNames = ['sourceName', 'typeName', 'fieldName'];
if (pluginOptions.delegationArgs) {
delegationLabelNames.push('args');
}
if (pluginOptions.delegationKey) {
delegationLabelNames.push('key');
}
delegateHistogram = new prom_client_1.Histogram({
name,
help: 'Time spent on delegate execution',
labelNames: delegationLabelNames,
registers: [registry],
});
}
let subgraphExecuteHistogram;
let subgraphExecuteErrorCounter;
if (pluginOptions.subgraphExecute !== false) {
const name = typeof pluginOptions.subgraphExecute === 'string'
? pluginOptions.subgraphExecute
: 'graphql_mesh_subgraph_execute_duration';
const subgraphExecuteLabelNames = ['subgraphName', 'operationType'];
subgraphExecuteHistogram = new prom_client_1.Histogram({
name,
help: 'Time spent on subgraph execution',
labelNames: subgraphExecuteLabelNames,
registers: [registry],
});
subgraphExecuteErrorCounter = new prom_client_1.Counter({
name: `graphql_mesh_subgraph_execute_errors`,
help: 'Number of errors on subgraph execution',
labelNames: subgraphExecuteLabelNames,
registers: [registry],
});
}
return {
onPluginInit({ addPlugin }) {
addPlugin((0, plugin_prometheus_1.usePrometheus)({
...pluginOptions,
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: pluginOptions.delegationArgs ? JSON.stringify(args) : undefined,
key: pluginOptions.delegationKey ? JSON.stringify(key) : undefined,
}, duration);
};
}
return undefined;
},
onSubgraphExecute({ subgraphName, executionRequest: { operationType = 'query' } }) {
if (subgraphExecuteHistogram) {
const start = Date.now();
return ({ result }) => {
if ((0, graphql_yoga_1.isAsyncIterable)(result)) {
return {
onNext({ result }) {
if (result.errors) {
result.errors.forEach(() => {
subgraphExecuteErrorCounter?.inc({ subgraphName, operationType });
});
}
},
onEnd: () => {
const end = Date.now();
const duration = end - start;
subgraphExecuteHistogram.observe({
subgraphName,
operationType,
}, duration);
},
};
}
if (result.errors) {
result.errors.forEach(() => {
subgraphExecuteErrorCounter?.inc({ subgraphName, operationType });
});
}
const end = Date.now();
const duration = end - start;
subgraphExecuteHistogram.observe({
subgraphName,
operationType,
}, duration);
return undefined;
};
}
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;