UNPKG

@pothos/plugin-tracing

Version:

A Pothos plugin for tracing and logging resolver invocations

118 lines (117 loc) 3.5 kB
import { isThenable } from '@pothos/core'; import { defaultFieldResolver } from 'graphql'; export function isRootField(config) { return config.parentType === "Query" || config.parentType === "Mutation" || config.parentType === "Subscription"; } export function isScalarField(config) { return resolveFieldType(config.type) === "Scalar"; } export function isEnumField(config) { return resolveFieldType(config.type) === "Enum"; } export function isExposedField(config) { var _config_extensions; return !!((_config_extensions = config.extensions) === null || _config_extensions === void 0 ? void 0 : _config_extensions.pothosExposedField) || !config.resolve || config.resolve === defaultFieldResolver; } export function resolveFieldType(type) { if (type.kind === "List") { return resolveFieldType(type.type); } return type.kind; } const spanCacheSymbol = Symbol.for("Pothos.tracing.spanCache"); export function pathToString(info) { let current = info.path; let path = String(current.key); while (current.prev) { current = current.prev; path = `${current.key}.${path}`; } return path; } function getParentPaths(path) { if (!path.prev) { return [ String(path.key) ]; } const parentPaths = getParentPaths(path.prev); return [ `${parentPaths[0]}.${path.key}`, ...parentPaths ]; } export function getParentSpan(context, info) { if (!info.path.prev) { return null; } const paths = getParentPaths(info.path.prev); const spanCache = context[spanCacheSymbol]; if (!spanCache) { return null; } for (const path of paths) { if (spanCache[path]) { return spanCache[path]; } } return null; } export function createSpanWithParent(context, info, createSpan) { const parentSpan = getParentSpan(context, info); const stringPath = pathToString(info); const span = createSpan(stringPath, parentSpan); if (!context[spanCacheSymbol]) { context[spanCacheSymbol] = {}; } context[spanCacheSymbol][stringPath] = span; return span; } const { performance } = globalThis; export function wrapResolver(resolver, end) { return (source, args, ctx, info) => { const start = performance.now(); let result; try { result = resolver(source, args, ctx, info); } catch (error) { end(error, performance.now() - start); throw error; } if (isThenable(result)) { return result.then((value) => { end(null, performance.now() - start); return value; }, (error) => { end(error, performance.now() - start); throw error; }); } end(null, performance.now() - start); return result; }; } export function runFunction(next, end) { const start = performance.now(); let result; try { result = next(); } catch (error) { end(error, performance.now() - start); throw error; } if (isThenable(result)) { return result.then((value) => { end(null, performance.now() - start); return value; }, (error) => { end(error, performance.now() - start); throw error; }); } end(null, performance.now() - start); return result; } //# sourceMappingURL=util.js.map