@splunk/otel
Version:
The Splunk distribution of OpenTelemetry Node Instrumentation provides a Node agent that automatically instruments your Node application to capture and report distributed traces to Splunk APM.
496 lines • 22.3 kB
JavaScript
"use strict";
/*
* Copyright Splunk Inc.
*
* 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
*
* http://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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadConfiguration = loadConfiguration;
exports.setGlobalConfiguration = setGlobalConfiguration;
exports.configGetResource = configGetResource;
exports.getConfigResourceDetectors = getConfigResourceDetectors;
exports.configGetPropagators = configGetPropagators;
exports.configGetUriParameterCapture = configGetUriParameterCapture;
exports.configGetSampler = configGetSampler;
exports.getConfigLogger = getConfigLogger;
exports.getConfigTracerProvider = getConfigTracerProvider;
exports.getConfigMeterProvider = getConfigMeterProvider;
exports.getNonEmptyConfigVar = getNonEmptyConfigVar;
exports.getConfigBoolean = getConfigBoolean;
exports.getConfigNumber = getConfigNumber;
exports.getConfigArray = getConfigArray;
const utils_1 = require("./utils");
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
const node_fs_1 = require("node:fs");
const yaml_1 = require("yaml");
const instrumentations_1 = require("./instrumentations");
const resources_1 = require("@opentelemetry/resources");
const substitute_1 = require("./configuration/substitute");
function loadConfiguration(path) {
if (!(0, node_fs_1.existsSync)(path)) {
throw new Error(`Config file ${path} does not exist`);
}
const file = (0, node_fs_1.readFileSync)(path, { encoding: 'utf-8' });
const doc = (0, yaml_1.parseDocument)(file);
if (doc.errors.length > 0) {
throw doc.errors[0];
}
(0, yaml_1.visit)(doc, {
Scalar: (key, node) => {
if (key !== 'value') {
return undefined;
}
const value = node.value;
if (typeof value === 'string') {
const sub = (0, substitute_1.envSubstitute)(value, (key) => process.env[key]);
if (node.type !== 'QUOTE_DOUBLE') {
node.value = (0, substitute_1.convertSubstitution)(sub);
}
else {
node.value = sub;
}
}
return undefined;
},
});
return doc.toJS();
}
let globalConfiguration;
function setGlobalConfiguration(config) {
globalConfiguration = config;
}
function findAttributeValue(attributes, name) {
for (let i = 0; i < attributes.length; i++) {
const attrib = attributes[i];
if (attrib.name === name) {
return attrib.value;
}
}
return undefined;
}
function getInstrumentationConf(config, instrumentationName) {
var _a, _b;
const conf = (_b = (_a = splunkConfig(config)) === null || _a === void 0 ? void 0 : _a.instrumentations) === null || _b === void 0 ? void 0 : _b[instrumentationName];
if (conf === null || typeof conf !== 'object') {
return undefined;
}
return conf;
}
function splunkConfig(config) {
var _a;
return (_a = config.distribution) === null || _a === void 0 ? void 0 : _a.splunk;
}
function fetchConfigValue(key, config) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31;
switch (key) {
case 'OTEL_ATTRIBUTE_COUNT_LIMIT': {
return (_a = config.attribute_limits) === null || _a === void 0 ? void 0 : _a.attribute_count_limit;
}
case 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT': {
return (_b = config.attribute_limits) === null || _b === void 0 ? void 0 : _b.attribute_value_length_limit;
}
case 'OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT': {
return (_d = (_c = config.tracer_provider) === null || _c === void 0 ? void 0 : _c.limits) === null || _d === void 0 ? void 0 : _d.event_attribute_count_limit;
}
case 'OTEL_LINK_ATTRIBUTE_COUNT_LIMIT': {
return (_f = (_e = config.tracer_provider) === null || _e === void 0 ? void 0 : _e.limits) === null || _f === void 0 ? void 0 : _f.link_attribute_count_limit;
}
case 'OTEL_LOG_LEVEL': {
return config.log_level;
}
case 'OTEL_SERVICE_NAME': {
return findAttributeValue(((_g = config.resource) === null || _g === void 0 ? void 0 : _g.attributes) || [], 'service.name');
}
case 'OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT': {
return (_j = (_h = config.tracer_provider) === null || _h === void 0 ? void 0 : _h.limits) === null || _j === void 0 ? void 0 : _j.attribute_count_limit;
}
case 'OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT': {
return (_l = (_k = config.tracer_provider) === null || _k === void 0 ? void 0 : _k.limits) === null || _l === void 0 ? void 0 : _l.attribute_value_length_limit;
}
case 'OTEL_SPAN_EVENT_COUNT_LIMIT': {
return (_o = (_m = config.tracer_provider) === null || _m === void 0 ? void 0 : _m.limits) === null || _o === void 0 ? void 0 : _o.event_count_limit;
}
case 'OTEL_SPAN_LINK_COUNT_LIMIT': {
return (_q = (_p = config.tracer_provider) === null || _p === void 0 ? void 0 : _p.limits) === null || _q === void 0 ? void 0 : _q.link_count_limit;
}
case 'SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES': {
const filter = (_r = splunkConfig(config)) === null || _r === void 0 ? void 0 : _r.package_name_filter;
if (Array.isArray(filter)) {
return filter.map((v) => String(v));
}
return undefined;
}
case 'SPLUNK_AUTOMATIC_LOG_COLLECTION': {
return config.logger_provider !== undefined;
}
case 'SPLUNK_DEBUG_METRICS_ENABLED': {
return (_s = splunkConfig(config)) === null || _s === void 0 ? void 0 : _s.debug_metrics_enabled;
}
case 'SPLUNK_INSTRUMENTATION_METRICS_ENABLED': // TODO: Is this env var actually necessary?
case 'SPLUNK_METRICS_ENABLED': {
return config.meter_provider !== undefined;
}
case 'OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED': {
return (_t = splunkConfig(config)) === null || _t === void 0 ? void 0 : _t.use_bundled_instrumentations;
}
case 'SPLUNK_PROFILER_ENABLED': {
const cpuProfiler = (_w = (_v = (_u = splunkConfig(config)) === null || _u === void 0 ? void 0 : _u.profiling) === null || _v === void 0 ? void 0 : _v.always_on) === null || _w === void 0 ? void 0 : _w.cpu_profiler;
if (cpuProfiler === null || typeof cpuProfiler === 'object') {
return true;
}
return false;
}
case 'SPLUNK_PROFILER_LOGS_ENDPOINT': {
const endpoint = (_0 = (_z = (_y = (_x = splunkConfig(config)) === null || _x === void 0 ? void 0 : _x.profiling) === null || _y === void 0 ? void 0 : _y.exporter) === null || _z === void 0 ? void 0 : _z.otlp_log_http) === null || _0 === void 0 ? void 0 : _0.endpoint;
if (typeof endpoint === 'string') {
return endpoint;
}
return undefined;
}
case 'SPLUNK_SNAPSHOT_PROFILER_ENABLED': {
return ((_2 = (_1 = splunkConfig(config)) === null || _1 === void 0 ? void 0 : _1.profiling) === null || _2 === void 0 ? void 0 : _2.callgraphs) !== undefined;
}
case 'SPLUNK_PROFILER_CALL_STACK_INTERVAL': {
return (_6 = (_5 = (_4 = (_3 = splunkConfig(config)) === null || _3 === void 0 ? void 0 : _3.profiling) === null || _4 === void 0 ? void 0 : _4.always_on) === null || _5 === void 0 ? void 0 : _5.cpu_profiler) === null || _6 === void 0 ? void 0 : _6.sampling_interval;
}
case 'SPLUNK_CPU_PROFILER_COLLECTION_INTERVAL': {
return (_10 = (_9 = (_8 = (_7 = splunkConfig(config)) === null || _7 === void 0 ? void 0 : _7.profiling) === null || _8 === void 0 ? void 0 : _8.always_on) === null || _9 === void 0 ? void 0 : _9.cpu_profiler) === null || _10 === void 0 ? void 0 : _10.collection_interval;
}
case 'SPLUNK_PROFILER_MEMORY_ENABLED': {
return (((_13 = (_12 = (_11 = splunkConfig(config)) === null || _11 === void 0 ? void 0 : _11.profiling) === null || _12 === void 0 ? void 0 : _12.always_on) === null || _13 === void 0 ? void 0 : _13.memory_profiler) !==
undefined);
}
case 'SPLUNK_SNAPSHOT_PROFILER_SAMPLING_INTERVAL': {
return (_16 = (_15 = (_14 = splunkConfig(config)) === null || _14 === void 0 ? void 0 : _14.profiling) === null || _15 === void 0 ? void 0 : _15.callgraphs) === null || _16 === void 0 ? void 0 : _16.sampling_interval;
}
case 'SPLUNK_SNAPSHOT_SELECTION_PROBABILITY':
case 'SPLUNK_SNAPSHOT_SELECTION_RATE': {
return (_19 = (_18 = (_17 = splunkConfig(config)) === null || _17 === void 0 ? void 0 : _17.profiling) === null || _18 === void 0 ? void 0 : _18.callgraphs) === null || _19 === void 0 ? void 0 : _19.selection_probability;
}
case 'SPLUNK_REALM': {
return undefined;
}
case 'SPLUNK_TRACE_RESPONSE_HEADER_ENABLED': {
const httpConf = getInstrumentationConf(config, 'http');
const value = httpConf === null || httpConf === void 0 ? void 0 : httpConf['trace_response_header_enabled'];
if (typeof value === 'boolean') {
return value;
}
return undefined;
}
case 'OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT': {
return (_21 = (_20 = config === null || config === void 0 ? void 0 : config.logger_provider) === null || _20 === void 0 ? void 0 : _20.limits) === null || _21 === void 0 ? void 0 : _21.attribute_count_limit;
}
case 'OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT': {
return (_23 = (_22 = config === null || config === void 0 ? void 0 : config.logger_provider) === null || _22 === void 0 ? void 0 : _22.limits) === null || _23 === void 0 ? void 0 : _23.attribute_value_length_limit;
}
case 'SPLUNK_TRACING_ENABLED': {
return config.tracer_provider !== undefined;
}
case 'SPLUNK_NEXTJS_FIX_ENABLED': {
return ((_26 = (_25 = (_24 = config === null || config === void 0 ? void 0 : config.splunk) === null || _24 === void 0 ? void 0 : _24.general) === null || _25 === void 0 ? void 0 : _25.js) === null || _26 === void 0 ? void 0 : _26.nextjs_cardinality_reduction) === true;
}
case 'SPLUNK_ACCESS_TOKEN': {
return undefined;
}
case 'SPLUNK_RUNTIME_METRICS_ENABLED': {
return ((_27 = splunkConfig(config)) === null || _27 === void 0 ? void 0 : _27.runtime_metrics) !== undefined;
}
case 'SPLUNK_RUNTIME_METRICS_COLLECTION_INTERVAL': {
return (_29 = (_28 = splunkConfig(config)) === null || _28 === void 0 ? void 0 : _28.runtime_metrics) === null || _29 === void 0 ? void 0 : _29.collection_interval;
}
case 'SPLUNK_REDIS_INCLUDE_COMMAND_ARGS': {
const redisConf = getInstrumentationConf(config, 'redis');
const value = redisConf === null || redisConf === void 0 ? void 0 : redisConf['include_command_args'];
if (typeof value === 'boolean') {
return value;
}
return undefined;
}
case 'SPLUNK_GRAPHQL_RESOLVE_SPANS_ENABLED': {
const conf = getInstrumentationConf(config, 'graphql');
const value = conf === null || conf === void 0 ? void 0 : conf['resolve_spans_enabled'];
if (typeof value === 'boolean') {
return value;
}
return undefined;
}
default: {
const instrumentationPrefix = 'OTEL_INSTRUMENTATION_';
const instrumentationSuffix = '_ENABLED';
if (key.startsWith(instrumentationPrefix) &&
key.endsWith(instrumentationSuffix)) {
const shortName = key
.substring(instrumentationPrefix.length, key.length - instrumentationSuffix.length)
.toLowerCase();
for (const instr of instrumentations_1.bundledInstrumentations) {
if (instr.shortName === shortName) {
const instrumentation = (_31 = (_30 = splunkConfig(config)) === null || _30 === void 0 ? void 0 : _30.instrumentations) === null || _31 === void 0 ? void 0 : _31[shortName];
if (instrumentation !== null &&
typeof instrumentation === 'object' &&
instrumentation['disabled'] === true) {
return false;
}
return instr.disabledByDefault !== true;
}
}
}
return undefined;
}
}
}
function resourceFromString(resourceString) {
const values = resourceString.split(',');
const attributes = {};
for (const s of values) {
const assignment = s.trim().split('=');
if (assignment.length === 2) {
const [k, v] = assignment;
attributes[k] = v;
}
}
return (0, resources_1.resourceFromAttributes)(attributes);
}
function valueFromConfigAttributeNameValue(attr) {
switch (attr.type) {
case 'string': {
if (typeof attr.value === 'string') {
return attr.value;
}
break;
}
case 'int':
case 'double': {
if (typeof attr.value === 'number') {
return attr.value;
}
break;
}
case 'bool': {
if (typeof attr.value === 'boolean') {
return attr.value;
}
break;
}
case 'string_array': {
if (Array.isArray(attr.value)) {
const values = [];
for (const v of attr.value) {
values.push(String(v));
}
return values;
}
break;
}
case 'double_array':
case 'int_array': {
if (Array.isArray(attr.value)) {
const values = [];
for (const v of attr.value) {
values.push(Number(v));
}
return values;
}
break;
}
case 'bool_array': {
if (Array.isArray(attr.value)) {
const values = [];
for (const v of attr.value) {
values.push(Boolean(v));
}
return values;
}
break;
}
default:
return String(attr.value);
}
return String(attr.value);
}
function resourceFromConfigAttributes(configAttributes) {
if (configAttributes === undefined || configAttributes === null) {
return (0, resources_1.emptyResource)();
}
const attributes = {};
for (const attr of configAttributes) {
attributes[attr.name] = valueFromConfigAttributeNameValue(attr);
}
return (0, resources_1.resourceFromAttributes)(attributes);
}
function configGetResource() {
if (globalConfiguration === undefined) {
return (0, resources_1.emptyResource)();
}
const configResource = globalConfiguration.resource;
if (isNil(configResource)) {
return (0, resources_1.emptyResource)();
}
const attributesListResource = resourceFromString((configResource === null || configResource === void 0 ? void 0 : configResource.attributes_list) || '');
const attributesResource = resourceFromConfigAttributes(configResource === null || configResource === void 0 ? void 0 : configResource.attributes);
return attributesListResource.merge(attributesResource);
}
function getConfigResourceDetectors() {
var _a;
if (globalConfiguration === undefined) {
return undefined;
}
const detection = (_a = globalConfiguration.resource) === null || _a === void 0 ? void 0 : _a['detection/development'];
if (detection === undefined) {
return undefined;
}
return detection.detectors || [];
}
function configGetPropagators() {
var _a, _b;
if (globalConfiguration === undefined) {
return undefined;
}
const compositePropagators = (((_a = globalConfiguration.propagator) === null || _a === void 0 ? void 0 : _a.composite) || []).flatMap((v) => Object.keys(v));
const compositeListPropagators = (((_b = globalConfiguration.propagator) === null || _b === void 0 ? void 0 : _b.composite_list) || '')
.split(',')
.map((v) => v.trim());
return [...new Set([...compositePropagators, ...compositeListPropagators])];
}
function configGetUriParameterCapture() {
var _a;
if (globalConfiguration === undefined) {
return [];
}
const capture = (_a = getInstrumentationConf(globalConfiguration, 'http')) === null || _a === void 0 ? void 0 : _a['capture_uri_parameters'];
if (Array.isArray(capture)) {
return capture.map((v) => String(v));
}
return [];
}
function makeSampler(sampler) {
var _a;
if (sampler === null || sampler === undefined) {
return undefined;
}
if (sampler.always_on !== undefined) {
return new sdk_trace_base_1.AlwaysOnSampler();
}
if (sampler.always_off !== undefined) {
return new sdk_trace_base_1.AlwaysOffSampler();
}
if (sampler.trace_id_ratio_based !== undefined) {
const ratioBased = sampler.trace_id_ratio_based;
return new sdk_trace_base_1.TraceIdRatioBasedSampler((_a = ratioBased.ratio) !== null && _a !== void 0 ? _a : undefined);
}
// TODO: Support probability based sampler once available in OTel.
return undefined;
}
function configGetSampler() {
var _a, _b;
if (globalConfiguration === undefined) {
return undefined;
}
const sampler = (_a = globalConfiguration.tracer_provider) === null || _a === void 0 ? void 0 : _a.sampler;
if (sampler === undefined || sampler.always_on !== undefined) {
// We use AlwaysOnSampler by default instead of parent based.
return new sdk_trace_base_1.AlwaysOnSampler();
}
if (sampler.always_off !== undefined) {
return new sdk_trace_base_1.AlwaysOffSampler();
}
if (sampler.parent_based !== undefined) {
const parentBased = sampler.parent_based;
return new sdk_trace_base_1.ParentBasedSampler({
root: makeSampler(parentBased.root) || new sdk_trace_base_1.AlwaysOnSampler(),
remoteParentSampled: makeSampler(parentBased.remote_parent_sampled),
remoteParentNotSampled: makeSampler(parentBased.remote_parent_not_sampled),
localParentSampled: makeSampler(parentBased.local_parent_sampled),
localParentNotSampled: makeSampler(parentBased.local_parent_not_sampled),
});
}
if (sampler.trace_id_ratio_based !== undefined) {
const ratioBased = sampler.trace_id_ratio_based;
return new sdk_trace_base_1.TraceIdRatioBasedSampler((_b = ratioBased.ratio) !== null && _b !== void 0 ? _b : undefined);
}
// TODO: Should composite/development be supported?
return undefined;
}
function getConfigLogger() {
return globalConfiguration === null || globalConfiguration === void 0 ? void 0 : globalConfiguration.logger_provider;
}
function getConfigTracerProvider() {
return globalConfiguration === null || globalConfiguration === void 0 ? void 0 : globalConfiguration.tracer_provider;
}
function getConfigMeterProvider() {
return globalConfiguration === null || globalConfiguration === void 0 ? void 0 : globalConfiguration.meter_provider;
}
function getNonEmptyConfigVar(key) {
if (globalConfiguration === undefined) {
return (0, utils_1.getNonEmptyEnvVar)(key);
}
const value = fetchConfigValue(key, globalConfiguration);
if (value === undefined) {
return value;
}
return String(value);
}
function getConfigBoolean(key, defaultValue = true) {
if (globalConfiguration === undefined) {
return (0, utils_1.getEnvBoolean)(key, defaultValue);
}
const value = fetchConfigValue(key, globalConfiguration);
if (value === undefined) {
return defaultValue;
}
if (typeof value !== 'boolean') {
throw new Error(`Expected bool value, got ${typeof value}`);
}
return value;
}
function getConfigNumber(key, defaultValue) {
if (globalConfiguration === undefined) {
return (0, utils_1.getEnvNumber)(key, defaultValue);
}
let value;
if (Array.isArray(key)) {
for (const k of key) {
value = fetchConfigValue(k, globalConfiguration);
if (value !== undefined) {
break;
}
}
}
else {
value = fetchConfigValue(key, globalConfiguration);
}
if (value === undefined) {
return defaultValue;
}
if (typeof value !== 'number') {
throw new Error(`Expected number value, got ${typeof value}`);
}
return value;
}
function getConfigArray(key) {
if (globalConfiguration === undefined) {
return (0, utils_1.getEnvArray)(key);
}
const value = fetchConfigValue(key, globalConfiguration);
if (value === undefined) {
return undefined;
}
if (!Array.isArray(value)) {
throw new Error(`Expected array value, got ${typeof value}`);
}
return value.map((v) => String(v));
}
function isNil(v) {
return v === undefined || v === null;
}
//# sourceMappingURL=configuration.js.map