UNPKG

@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
"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