@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.
238 lines • 10.4 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports._setDefaultOptions = _setDefaultOptions;
exports.defaultSpanExporterFactory = defaultSpanExporterFactory;
exports.otlpSpanExporterFactory = otlpSpanExporterFactory;
exports.consoleSpanExporterFactory = consoleSpanExporterFactory;
exports.defaultSpanProcessorFactory = defaultSpanProcessorFactory;
exports.defaultPropagatorFactory = defaultPropagatorFactory;
/*
* 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.
*/
const util = require("util");
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
const propagator_b3_1 = require("@opentelemetry/propagator-b3");
const propagator_aws_xray_1 = require("@opentelemetry/propagator-aws-xray");
const instrumentations_1 = require("../instrumentations");
const exporter_trace_otlp_proto_1 = require("@opentelemetry/exporter-trace-otlp-proto");
const resource_1 = require("../resource");
const utils_1 = require("../utils");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const api_1 = require("@opentelemetry/api");
const core_1 = require("@opentelemetry/core");
const SplunkBatchSpanProcessor_1 = require("./SplunkBatchSpanProcessor");
const resources_1 = require("@opentelemetry/resources");
const NextJsSpanProcessor_1 = require("./NextJsSpanProcessor");
function defaultSampler(config) {
if (config.sampler === undefined &&
(0, utils_1.getNonEmptyEnvVar)('OTEL_TRACES_SAMPLER') === undefined) {
return new sdk_trace_base_1.AlwaysOnSampler();
}
return undefined;
}
function _setDefaultOptions(options = {}) {
var _a, _b;
process.env.OTEL_SPAN_LINK_COUNT_LIMIT =
(_a = (0, utils_1.getNonEmptyEnvVar)('OTEL_SPAN_LINK_COUNT_LIMIT')) !== null && _a !== void 0 ? _a : '1000';
process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT =
(_b = (0, utils_1.getNonEmptyEnvVar)('OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT')) !== null && _b !== void 0 ? _b : '12000';
const accessToken = options.accessToken || (0, utils_1.getNonEmptyEnvVar)('SPLUNK_ACCESS_TOKEN') || '';
const realm = options.realm || (0, utils_1.getNonEmptyEnvVar)('SPLUNK_REALM');
if (realm) {
if (!accessToken) {
throw new Error('Splunk realm is set, but access token is unset. To send traces to the Observability Cloud, both need to be set');
}
}
const envResource = (0, resource_1.getDetectedResource)();
const resourceFactory = options.resourceFactory || ((r) => r);
let resource = resourceFactory((0, resources_1.resourceFromAttributes)(envResource.attributes || {}));
const serviceName = options.serviceName ||
(0, utils_1.getNonEmptyEnvVar)('OTEL_SERVICE_NAME') ||
resource.attributes[semantic_conventions_1.ATTR_SERVICE_NAME];
resource = resource.merge((0, resources_1.resourceFromAttributes)({
[semantic_conventions_1.ATTR_SERVICE_NAME]: serviceName || (0, utils_1.defaultServiceName)(),
}));
const extraTracerConfig = options.tracerConfig || {};
const sampler = defaultSampler(extraTracerConfig);
const tracerConfig = Object.assign({ resource,
sampler }, extraTracerConfig);
const instrumentations = options.instrumentations || (0, instrumentations_1.getInstrumentations)();
if (instrumentations.length === 0) {
api_1.diag.warn('No instrumentations set to be loaded. Install an instrumentation package to enable auto-instrumentation.');
}
return {
realm,
endpoint: options.endpoint,
serviceName: String(resource.attributes[semantic_conventions_1.ATTR_SERVICE_NAME]),
accessToken,
serverTimingEnabled: options.serverTimingEnabled ||
(0, utils_1.getEnvBoolean)('SPLUNK_TRACE_RESPONSE_HEADER_ENABLED', true),
captureHttpRequestUriParams: options.captureHttpRequestUriParams || [],
instrumentations,
tracerConfig,
spanExporterFactory: options.spanExporterFactory || defaultSpanExporterFactory(realm),
spanProcessorFactory: options.spanProcessorFactory || defaultSpanProcessorFactory,
propagatorFactory: options.propagatorFactory || defaultPropagatorFactory,
};
}
const SUPPORTED_EXPORTER_TYPES = ['console', 'otlp', 'none'];
const SpanExporterMap = {
console: consoleSpanExporterFactory,
otlp: otlpSpanExporterFactory,
none: () => [],
};
function containsSupportedRealmExporter(exporterTypes) {
return exporterTypes.includes('otlp');
}
function areValidExporterTypes(types) {
for (const t of types) {
if (!SUPPORTED_EXPORTER_TYPES.includes(t)) {
return false;
}
}
return true;
}
function getExporterTypes(realm) {
const traceExporters = (0, utils_1.getEnvArray)('OTEL_TRACES_EXPORTER', [
'otlp',
]);
if (realm) {
if (!containsSupportedRealmExporter(traceExporters)) {
throw new Error('Setting the Splunk realm with an explicit OTEL_TRACES_EXPORTER requires OTEL_TRACES_EXPORTER to be either otlp or be left undefined');
}
}
if (!areValidExporterTypes(traceExporters)) {
throw new Error(`Invalid value for OTEL_TRACES_EXPORTER env variable: ${util.inspect(process.env.OTEL_TRACES_EXPORTER)}. Choose from ${util.inspect(SUPPORTED_EXPORTER_TYPES, {
compact: true,
})} or leave undefined.`);
}
return traceExporters;
}
function defaultSpanExporterFactory(realm) {
const exporterTypes = getExporterTypes(realm);
return (options) => {
const factories = exporterTypes.map((t) => SpanExporterMap[t]);
return factories.flatMap((factory) => factory(options));
};
}
function otlpSpanExporterFactory(options) {
let protocol = (0, utils_1.getEnvValueByPrecedence)([
'OTEL_EXPORTER_OTLP_TRACES_PROTOCOL',
'OTEL_EXPORTER_OTLP_PROTOCOL',
]);
let endpoint = options.endpoint;
const accessToken = options.accessToken;
if (options.realm !== undefined) {
if (protocol !== undefined && protocol !== 'http/protobuf') {
api_1.diag.warn(`OTLP span exporter factory: defaulting protocol to 'http/protobuf' instead of ${protocol} due to realm being defined.`);
}
const envEndpoint = (0, utils_1.getEnvValueByPrecedence)([
'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT',
'OTEL_EXPORTER_OTLP_ENDPOINT',
]);
if (endpoint === undefined && envEndpoint === undefined) {
endpoint = `https://ingest.${options.realm}.signalfx.com/v2/trace/otlp`;
protocol = 'http/protobuf';
}
else {
api_1.diag.warn('OTLP span exporter factory: Realm value ignored (full endpoint URL has been specified).');
}
}
protocol = protocol !== null && protocol !== void 0 ? protocol : 'http/protobuf';
switch (protocol) {
case 'grpc': {
const grpcModule = require('@grpc/grpc-js');
const otlpGrpc = require('@opentelemetry/exporter-trace-otlp-grpc');
const metadata = new grpcModule.Metadata();
if (accessToken) {
// for forward compatibility, is not currently supported
metadata.set('X-SF-TOKEN', accessToken);
}
return new otlpGrpc.OTLPTraceExporter({
url: endpoint,
metadata,
});
}
case 'http/protobuf': {
const headers = accessToken
? {
'X-SF-TOKEN': accessToken,
}
: undefined;
const url = (0, utils_1.ensureResourcePath)(endpoint, '/v1/traces');
return new exporter_trace_otlp_proto_1.OTLPTraceExporter({
url,
headers,
});
}
default:
throw new Error(`Expected OTLP protocol to be either grpc or http/protobuf, got ${protocol}.`);
}
}
function consoleSpanExporterFactory() {
return new sdk_trace_base_1.ConsoleSpanExporter();
}
function defaultSpanProcessorFactory(options) {
let exporters = [];
const spanExporters = options.spanExporterFactory(options);
if (!Array.isArray(spanExporters)) {
exporters = [spanExporters];
}
else {
exporters = spanExporters;
}
const nextJsFixEnabled = (0, utils_1.getEnvBoolean)('SPLUNK_NEXTJS_FIX_ENABLED', false);
const processors = [];
if (nextJsFixEnabled) {
processors.push(new NextJsSpanProcessor_1.NextJsSpanProcessor());
}
for (const exporter of exporters) {
processors.push(new SplunkBatchSpanProcessor_1.SplunkBatchSpanProcessor(exporter));
}
return processors;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function defaultPropagatorFactory(_options) {
const envPropagators = (0, utils_1.getEnvArray)('OTEL_PROPAGATORS', [
'tracecontext',
'baggage',
]);
const propagators = [];
for (const propagator of envPropagators) {
switch (propagator) {
case 'baggage':
propagators.push(new core_1.W3CBaggagePropagator());
break;
case 'tracecontext':
propagators.push(new core_1.W3CTraceContextPropagator());
break;
case 'b3multi':
propagators.push(new propagator_b3_1.B3Propagator({ injectEncoding: propagator_b3_1.B3InjectEncoding.MULTI_HEADER }));
break;
case 'b3':
propagators.push(new propagator_b3_1.B3Propagator());
break;
case 'xray':
propagators.push(new propagator_aws_xray_1.AWSXRayPropagator());
break;
default:
break;
}
}
return new core_1.CompositePropagator({
propagators,
});
}
//# sourceMappingURL=options.js.map
;