UNPKG

apostrophe

Version:
146 lines (133 loc) 4.65 kB
// Initialize OpenTelemetry tracer singleton and export // the most useful API members, the tracer and some helper functions. // // The library shouldn't be used directly (although it's not fatal), // it is registered as self.apos.telemetry pseudo module (see index.js). const api = require('@opentelemetry/api'); const util = require('util'); const version = require('../package.json').version; /** @type {api.Tracer} */ let tracer; const Attributes = { SCENE: 'apos.scene', TEMPLATE: 'apos.template', EVENT_MODULE: 'apos.event.module', EVENT_NAME: 'apos.event.name', // The module and method targeted by the current operation (see doc module) TARGET_NAMESPACE: 'apos.target.namespace', TARGET_FUNCTION: 'apos.target.function', ARGV: 'apos.argv' }; module.exports = function (options = {}) { if (!tracer) { tracer = api.trace.getTracer('apostrophe', version); // This shouldn't be needed, but having it doesn't hurt if (options.openTelemetryProvider) { api.trace.setGlobalTracerProvider(options.openTelemetryProvider); } } /** * Start and return a new span. Optionally provide a parent span or allow the * parent span to be auto-detected. * Use this when the current code block does the tracing and it doesn't expect * more tracing to happen down the line. * * @param {String} name span name * @param {api.Span|Boolean} [parentSpan] optional parent span * @param {api.SpanOptions} [options] span options * @returns {api.Span} * @example * // Auto-merge with the currently active span context * const span = self.apos.telemetry.startSpan('event:someEvent'); * // Provide a parent span * const span = self.apos.telemetry.startSpan('event:someEvent', parent); * // Do not merge with any parent, start as a root * const span = self.apos.telemetry.startSpan('event:someEvent', false); * // Provide options for the newly created span * const span = self.apos.telemetry.startSpan('event:someEvent', true, { * attributes: [ * [SemanticAttributes.HTTP_METHOD]: "GET", * [SemanticAttributes.HTTP_FLAVOR]: "1.1", * [SemanticAttributes.HTTP_URL]: req.url * ] * }); */ function startSpan(name, parentSpan, options) { if ((!parentSpan || parentSpan === true) && parentSpan !== false) { parentSpan = api.trace.getSpan(api.context.active()); } if (parentSpan) { const ctx = api.trace.setSpan(api.context.active(), parentSpan); return tracer.startSpan(name, options || undefined, ctx); } return tracer.startSpan(name, options || undefined); } /** * Start span and make it active for all the nested spans. * Use this when the current code block does the tracing, but it also expects * more tracing to happen down the line (async calls). * * @param {String} name span name * @param {Function} fn handler function * @param {api.Span|Boolean} [parentSpan] optional parent span * @param {api.SpanOptions} [options] span options * @returns {api.Span|any} the return value of the handler or the newly created span * @example * // Activate span, return some value * const value = await self.apos.telemetry.startActiveSpan(spanName, async * (span) => { * // Use the span, do work, end span, return any value * span.end(); * return value; * }); * // Activate span, using the context of parent span, return the active span * const span = self.apos.telemetry.startActiveSpan(spanName, async (span) => { * // Use the span, do work, return the span * return span; * }); */ function startActiveSpan(name, fn, parentSpan, options) { if (parentSpan) { const ctx = api.trace.setSpan(api.context.active(), parentSpan); return tracer.startActiveSpan(name, options || undefined, ctx, fn); } return tracer.startActiveSpan(name, options || undefined, fn); } /** * Handle errors helper (catch block). * * @param {api.Span} span * @param {Error|String} err */ function handleError(span, err) { span.recordException(err); span.setStatus({ code: api.SpanStatusCode.ERROR, message: err ? typeof err === 'string' ? err : err.message : undefined }); } /** * Stringify object - helper to properly set * object as a span attribute value. * * @param {Object} obj * @returns {String} */ function stringify(obj) { return util.inspect(obj, { depth: 20, compact: false }); } return { api, tracer, Attributes, stringify, handleError, startSpan, startActiveSpan }; };