Repository URL to install this package:
|
Version:
0.9.2-rc0 ▾
|
// (c) Copyright 2023 Supertenant Ltd. - all rights reserved.
// See LICENSE file in project root for license terms.
'use strict';
const sdk = require('./sdk');
const constants = require('./constants');
const tracingMetrics = require('./metrics');
const opentracing = require('./opentracing');
const spanHandle = require('./spanHandle');
const tracingHeaders = require('./tracingHeaders');
const tracingUtil = require('./tracingUtil');
const supportedVersion = require('./supportedVersion');
let tracingEnabled = false;
let tracingActivated = false;
let instrumenationsInitialized = false;
let automaticTracingEnabled = false;
/** @type {import('./cls')} */
let cls = null;
/** @type {import('../util/normalizeConfig').Config} */
let config = null;
/** @typedef {import('../../../collector/src/pidStore')} CollectorPIDStore */
/**
* @typedef {Object} TracingMetrics
* @property {number} pid
* @property {{opened: number, closed: number, dropped: number}} metrics
*/
/** @type {CollectorPIDStore} */
let processIdentityProvider = null;
// IMPORTANT: Update initializedTooLateHeuristic.js and its test when adding more instrumentations.
const instrumentations = [
'./instrumentation/control_flow/bluebird',
'./instrumentation/control_flow/clsHooked',
'./instrumentation/database/ioredis',
'./instrumentation/database/mongodb',
'./instrumentation/database/mysql',
'./instrumentation/database/redis',
'./instrumentation/frameworks/express',
'./instrumentation/protocols/http2Client',
'./instrumentation/protocols/http2Server',
'./instrumentation/protocols/httpClient',
'./instrumentation/protocols/httpServer'
];
/**
* This is a temporary type definition for instrumented modules until we get to add types to these modules.
* For now it is safe to say that these modules are objects with the following methods:
* @typedef {Object} InstrumentedModule
* @property {Function} init
* @property {Function} activate
* @property {Function} deactivate
* @property {Function} [updateConfig]
* @property {boolean} [batchable]
* @property {string} [spanName]
*/
/**
* @typedef {Object} KafkaTracingConfig
* @property {boolean} [traceCorrelation]
* @property {string} [headerFormat]
*/
/** @type {Array.<InstrumentedModule>} */
let additionalInstrumentationModules = [];
/** @type {Object.<string, InstrumentedModule>} */
const instrumentationModules = {};
exports.constants = constants;
exports.tracingHeaders = tracingHeaders;
exports.opentracing = opentracing;
exports.sdk = sdk;
exports.supportedVersion = supportedVersion;
exports.util = tracingUtil;
/**
* @param {Array.<InstrumentedModule>} _additionalInstrumentationModules
*/
exports.registerAdditionalInstrumentations = function registerAdditionalInstrumentations(
_additionalInstrumentationModules
) {
additionalInstrumentationModules = additionalInstrumentationModules.concat(_additionalInstrumentationModules);
};
/**
* @param {import('../util/normalizeConfig').Config} preliminaryConfig
*/
exports.preInit = function preInit(preliminaryConfig) {
initInstrumentations(preliminaryConfig);
};
/**
* @param {import('../util/normalizeConfig').Config} _config
* @param {CollectorPIDStore} _processIdentityProvider
*/
exports.init = function init(_config, _processIdentityProvider) {
config = _config;
processIdentityProvider = _processIdentityProvider;
tracingEnabled = config.tracing.enabled;
automaticTracingEnabled = config.tracing.automaticTracingEnabled;
if (tracingEnabled) {
tracingHeaders.init(config);
cls = require('./cls');
cls.init(config, processIdentityProvider);
sdk.init(cls);
if (automaticTracingEnabled) {
initInstrumentations(config);
exports.activate(config);
}
}
};
/**
* @param {import('../util/normalizeConfig').Config} _config
*/
function initInstrumentations(_config) {
// initialize all instrumentations
if (!instrumenationsInitialized) {
instrumentations.forEach(instrumentationKey => {
instrumentationModules[instrumentationKey] = require(instrumentationKey);
instrumentationModules[instrumentationKey].init(_config);
});
additionalInstrumentationModules.forEach(instrumentationModule => {
instrumentationModule.init(_config);
});
instrumenationsInitialized = true;
} else {
instrumentations.forEach(instrumentationKey => {
if (instrumentationModules[instrumentationKey].updateConfig) {
instrumentationModules[instrumentationKey].updateConfig(_config);
}
});
}
}
exports.activate = function activate(extraConfig = {}) {
if (tracingEnabled && !tracingActivated) {
tracingActivated = true;
if (process.env.ST_INSTANA_ENABLED === 'true') {
opentracing.activate();
sdk.activate();
}
if (automaticTracingEnabled) {
instrumentations.forEach(instrumentationKey => {
const instrumentationName = /.\/instrumentation\/[^/]*\/(.*)/.exec(instrumentationKey)[1];
const isDisabled =
config.tracing.disabledTracers.findIndex(disabledKey => instrumentationName.toLowerCase() === disabledKey) !==
-1;
if (!isDisabled) {
instrumentationModules[instrumentationKey].activate(extraConfig);
}
});
}
}
};
exports.deactivate = function deactivate() {
if (tracingEnabled && tracingActivated) {
tracingActivated = false;
if (automaticTracingEnabled) {
instrumentations.forEach(instrumentationKey => {
instrumentationModules[instrumentationKey].deactivate();
});
}
if (process.env.ST_INSTANA_ENABLED === 'true') {
opentracing.deactivate();
sdk.deactivate();
}
}
};
exports.getHandleForCurrentSpan = function getHandleForCurrentSpan() {
return spanHandle.getHandleForCurrentSpan(cls);
};
exports.getCls = function getCls() {
// This only provides a value if tracing is enabled, otherwise cls will not be required and is null.
return cls;
};
/**
* @returns {TracingMetrics}
*/
exports._getAndResetTracingMetrics = function _getAndResetTracingMetrics() {
return {
pid:
processIdentityProvider && typeof processIdentityProvider.getEntityId === 'function'
? processIdentityProvider.getEntityId()
: undefined,
metrics: tracingMetrics.getAndReset()
};
};
exports._debugCurrentSpanName = function _debugCurrentSpanName() {
if (!cls) {
return 'current: no cls';
}
const s = cls.ns.get('com.supertenant.span');
if (!s) {
return 'current: no span';
}
return `current: ${s.n}`;
};