UNPKG

@sentry/node

Version:

Sentry Node SDK using OpenTelemetry for performance instrumentation

136 lines (121 loc) 3.83 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const api = require('@opentelemetry/api'); const constants = require('./constants.js'); // Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/blob/407f61591ba69a39a6908264379d4d98a48dbec4/plugins/node/opentelemetry-instrumentation-fastify/src/utils.ts /* eslint-disable jsdoc/require-jsdoc */ /* eslint-disable @typescript-eslint/no-dynamic-delete */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/explicit-function-return-type */ /* * Copyright The OpenTelemetry Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Starts Span * @param reply - reply function * @param tracer - tracer * @param spanName - span name * @param spanAttributes - span attributes */ function startSpan( reply, tracer, spanName, spanAttributes = {}, ) { const span = tracer.startSpan(spanName, { attributes: spanAttributes }); const spans = reply[constants.spanRequestSymbol] || []; spans.push(span); // eslint-disable-next-line @typescript-eslint/no-floating-promises Object.defineProperty(reply, constants.spanRequestSymbol, { enumerable: false, configurable: true, value: spans, }); return span; } /** * Ends span * @param reply - reply function * @param err - error */ function endSpan(reply, err) { const spans = reply[constants.spanRequestSymbol] || []; // there is no active span, or it has already ended if (!spans.length) { return; } // biome-ignore lint/complexity/noForEach: <explanation> spans.forEach((span) => { if (err) { span.setStatus({ code: api.SpanStatusCode.ERROR, message: err.message, }); span.recordException(err); } span.end(); }); delete reply[constants.spanRequestSymbol]; } // @TODO after approve add this to instrumentation package and replace usage // when it will be released /** * This function handles the missing case from instrumentation package when * execute can either return a promise or void. And using async is not an * option as it is producing unwanted side effects. * @param execute - function to be executed * @param onFinish - function called when function executed * @param preventThrowingError - prevent to throw error when execute * function fails */ function safeExecuteInTheMiddleMaybePromise( execute, onFinish, preventThrowingError, ) { let error; let result = undefined; try { result = execute(); if (isPromise(result)) { result.then( res => onFinish(undefined, res), err => onFinish(err), ); } } catch (e) { error = e; } finally { if (!isPromise(result)) { onFinish(error, result); if (error && true) { // eslint-disable-next-line no-unsafe-finally throw error; } } // eslint-disable-next-line no-unsafe-finally return result; } } function isPromise(val) { return ( (typeof val === 'object' && val && typeof Object.getOwnPropertyDescriptor(val, 'then')?.value === 'function') || false ); } exports.endSpan = endSpan; exports.safeExecuteInTheMiddleMaybePromise = safeExecuteInTheMiddleMaybePromise; exports.startSpan = startSpan; //# sourceMappingURL=utils.js.map