@opentelemetry/instrumentation-runtime-node
Version:
OpenTelemetry instrumentation for Node.js Performance measurement API
136 lines • 5.35 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RuntimeNodeInstrumentation = void 0;
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
const instrumentation_1 = require("@opentelemetry/instrumentation");
const api_logs_1 = require("@opentelemetry/api-logs");
const core_1 = require("@opentelemetry/core");
const eventLoopUtilizationCollector_1 = require("./metrics/eventLoopUtilizationCollector");
const eventLoopDelayCollector_1 = require("./metrics/eventLoopDelayCollector");
const gcCollector_1 = require("./metrics/gcCollector");
const heapSpacesSizeAndUsedCollector_1 = require("./metrics/heapSpacesSizeAndUsedCollector");
const eventLoopTimeCollector_1 = require("./metrics/eventLoopTimeCollector");
const activeResourcesCollector_1 = require("./metrics/activeResourcesCollector");
/** @knipignore */
const version_1 = require("./version");
const DEFAULT_CONFIG = {
monitoringPrecision: 10,
captureUncaughtException: false,
};
class RuntimeNodeInstrumentation extends instrumentation_1.InstrumentationBase {
_collectors = [];
_loggerProvider;
_onUncaughtExceptionHandler;
constructor(config = {}) {
super(version_1.PACKAGE_NAME, version_1.PACKAGE_VERSION, Object.assign({}, DEFAULT_CONFIG, config));
this._collectors = [
new eventLoopUtilizationCollector_1.EventLoopUtilizationCollector(this._config),
new eventLoopTimeCollector_1.EventLoopTimeCollector(this._config),
new eventLoopDelayCollector_1.EventLoopDelayCollector(this._config),
new gcCollector_1.GCCollector(this._config),
new heapSpacesSizeAndUsedCollector_1.HeapSpacesSizeAndUsedCollector(this._config),
new activeResourcesCollector_1.ActiveResourcesCollector(this._config),
];
if (this._config.enabled) {
for (const collector of this._collectors) {
collector.enable();
}
this._registerExceptionHandlers();
}
}
// Called when a new `MeterProvider` is set
// the Meter (result of @opentelemetry/api's getMeter) is available as this.meter within this method
_updateMetricInstruments() {
if (!this._collectors)
return;
for (const collector of this._collectors) {
collector.updateMetricInstruments(this.meter);
}
}
init() {
// Not instrumenting or patching a Node.js module
}
enable() {
super.enable();
if (!this._collectors)
return;
for (const collector of this._collectors) {
collector.enable();
}
this._registerExceptionHandlers();
}
disable() {
super.disable();
for (const collector of this._collectors) {
collector.disable();
}
this._unregisterExceptionHandlers();
}
setLoggerProvider(loggerProvider) {
super.setLoggerProvider(loggerProvider);
this._loggerProvider = loggerProvider;
}
_registerExceptionHandlers() {
const config = this.getConfig();
if (config.captureUncaughtException && !this._onUncaughtExceptionHandler) {
this._onUncaughtExceptionHandler =
this._handleUncaughtException.bind(this);
process.on('uncaughtExceptionMonitor', this._onUncaughtExceptionHandler);
}
}
_unregisterExceptionHandlers() {
if (this._onUncaughtExceptionHandler) {
process.removeListener('uncaughtExceptionMonitor', this._onUncaughtExceptionHandler);
this._onUncaughtExceptionHandler = undefined;
}
}
_handleUncaughtException(error, _origin) {
this._emitExceptionLog(error, api_logs_1.SeverityNumber.FATAL, 'uncaughtException');
}
_emitExceptionLog(error, severityNumber, eventType) {
if (!this.isEnabled()) {
return;
}
const config = this.getConfig();
let customAttributes = {};
if (config.applyCustomExceptionAttributes) {
try {
customAttributes =
config.applyCustomExceptionAttributes(error, eventType) ?? {};
}
catch (err) {
this._diag.error('applyCustomExceptionAttributes threw while handling an exception', err);
}
}
const timestamp = (0, core_1.hrTime)();
const errorLog = {
body: 'exception',
exception: error,
severityNumber,
attributes: customAttributes,
timestamp,
observedTimestamp: timestamp,
};
this.logger.emit(errorLog);
this._forceFlushLogs();
}
_forceFlushLogs() {
const loggerProvider = this._loggerProvider;
if (typeof loggerProvider?.forceFlush !== 'function') {
return;
}
try {
void loggerProvider.forceFlush().catch(err => {
this._diag.error('loggerProvider.forceFlush failed while handling an exception', err);
});
}
catch (err) {
this._diag.error('loggerProvider.forceFlush threw while handling an exception', err);
}
}
}
exports.RuntimeNodeInstrumentation = RuntimeNodeInstrumentation;
//# sourceMappingURL=instrumentation.js.map