@pothos/plugin-tracing
Version:
A Pothos plugin for tracing and logging resolver invocations
118 lines (117 loc) • 3.5 kB
JavaScript
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