matrix-public-archive/server/tracing/trace-utilities.js

63 lines
1.8 KiB
JavaScript

'use strict';
const assert = require('assert');
const opentelemetryApi = require('@opentelemetry/api');
const packageInfo = require('../../package.json');
assert(packageInfo.name);
assert(packageInfo.version);
const tracer = opentelemetryApi.trace.getTracer(packageInfo.name, packageInfo.version);
/**
* Wraps an existing function to instrument it with OpenTelemetry tracing. Now
* whenever the function runs, it will create a span with the given name. It's
* basically `tracer.startActiveSpan` with some sensible default behaviors to
* automatically end spans:
* - when function completes successfully, status of span also set
* - when function throws (exception recorded against span)
* - if function returns a Promise, the promise is resolved
* @param name Span name, passed through to `tracer.startActiveSpan`
* @param fn The function to wrap
* @returns The wrapped function
*
* via
* https://github.com/open-telemetry/opentelemetry-js-api/issues/164#issuecomment-1174925516
*/
function trace(name, fn) {
return function (...args) {
return tracer.startActiveSpan(name, async (span) => {
try {
const result = await Promise.resolve(fn(...args));
span.setStatus({
code: opentelemetryApi.SpanStatusCode.OK,
});
return result;
} catch (e) {
const err = e;
span.recordException(err);
span.setStatus({
code: opentelemetryApi.SpanStatusCode.ERROR,
message: err.message,
});
throw err;
} finally {
span.end();
}
});
};
}
/**
* Wraps an existing function to instrument it with OpenTelemetry tracing. The
* span name will be the name of the function.
*/
function traceFunction(fn) {
return trace(fn.name, fn);
}
module.exports = {
trace,
traceFunction,
};