diff --git a/CHANGELOG.md b/CHANGELOG.md index 594c93f0a..20c21921b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,8 +93,12 @@ For semantic convention package changes, see the [semconv CHANGELOG](packages/se * (user-facing): `baggageUtils.parsePairKeyValue` was an internal utility function that was unintentionally exported. It has been removed without replacement. * (user-facing): `TimeOriginLegacy` has been removed without replacement. * (user-facing): `isAttributeKey` was an internal utility function that was unintentionally exported. It has been removed without replacement. +* feat(sdk-trace-base)!: do not read environment variables from window in browsers [#5445](https://github.com/open-telemetry/opentelemetry-js/pull/5455) @pichlermarc + * (user-facing): all configuration previously possible via `window.OTEL_*` is now not supported anymore, please pass configuration options to constructors instead. + * Note: Node.js environment variable configuration continues to work as-is. * feat(exporter-zipkin)!: do not read environment variables from window in browsers [#5465](https://github.com/open-telemetry/opentelemetry-js/pull/5465) @pichlermarc * (user-facing): all configuration previously possible via `window.OTEL_*` is now not supported anymore, please pass configuration options to constructors instead. + * Note: Node.js environment variable configuration continues to work as-is. * feat(resource)!: Remove resource class export in favor of functions and types only to aid in cross-version compatibility [#5421](https://github.com/open-telemetry/opentelemetry-js/pull/5421) * Renames `Resource` class to `ResourceImpl` and makes it package-private * Renames `IResource` interface to `Resource` diff --git a/packages/opentelemetry-sdk-trace-base/karma.conf.js b/packages/opentelemetry-sdk-trace-base/karma.conf.js index bf2a41b79..3d6b8b74f 100644 --- a/packages/opentelemetry-sdk-trace-base/karma.conf.js +++ b/packages/opentelemetry-sdk-trace-base/karma.conf.js @@ -1,11 +1,11 @@ -/*! +/* * Copyright The OpenTelemetry Authors * * 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 + * https://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, @@ -17,8 +17,12 @@ const karmaWebpackConfig = require('../../karma.webpack'); const karmaBaseConfig = require('../../karma.base'); -module.exports = (config) => { - config.set(Object.assign({}, karmaBaseConfig, { - webpack: karmaWebpackConfig, - })) +module.exports = config => { + config.set( + Object.assign({}, karmaBaseConfig, { + webpack: karmaWebpackConfig, + files: ['test/browser/index-webpack.ts'], + preprocessors: { 'test/browser/index-webpack.ts': ['webpack'] }, + }) + ); }; diff --git a/packages/opentelemetry-sdk-trace-base/karma.worker.js b/packages/opentelemetry-sdk-trace-base/karma.worker.js index a8d8e50e8..90fbe8739 100644 --- a/packages/opentelemetry-sdk-trace-base/karma.worker.js +++ b/packages/opentelemetry-sdk-trace-base/karma.worker.js @@ -1,11 +1,11 @@ -/*! +/* * Copyright The OpenTelemetry Authors * * 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 + * https://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, @@ -17,8 +17,17 @@ const karmaWebpackConfig = require('../../karma.webpack'); const karmaBaseConfig = require('../../karma.worker'); -module.exports = (config) => { - config.set(Object.assign({}, karmaBaseConfig, { - webpack: karmaWebpackConfig, - })) +module.exports = config => { + config.set( + Object.assign({}, karmaBaseConfig, { + webpack: karmaWebpackConfig, + files: [ + { + pattern: 'test/browser/index-webpack.worker.ts', + included: false, + }, + ], + preprocessors: { 'test/browser/index-webpack.worker.ts': ['webpack'] }, + }) + ); }; diff --git a/packages/opentelemetry-sdk-trace-base/src/config.ts b/packages/opentelemetry-sdk-trace-base/src/config.ts index 0756d00dd..d03e4e679 100644 --- a/packages/opentelemetry-sdk-trace-base/src/config.ts +++ b/packages/opentelemetry-sdk-trace-base/src/config.ts @@ -15,7 +15,7 @@ */ import { diag } from '@opentelemetry/api'; -import { getEnv, ENVIRONMENT } from '@opentelemetry/core'; +import { getNumberFromEnv, getStringFromEnv } from '@opentelemetry/core'; import { Sampler } from './Sampler'; import { AlwaysOffSampler } from './sampler/AlwaysOffSampler'; import { AlwaysOnSampler } from './sampler/AlwaysOnSampler'; @@ -44,35 +44,38 @@ const DEFAULT_RATIO = 1; // object needs to be wrapped in this function and called when needed otherwise // envs are parsed before tests are ran - causes tests using these envs to fail export function loadDefaultConfig() { - const env = getEnv(); - return { - sampler: buildSamplerFromEnv(env), + sampler: buildSamplerFromEnv(), forceFlushTimeoutMillis: 30000, generalLimits: { - attributeValueLengthLimit: env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, - attributeCountLimit: env.OTEL_ATTRIBUTE_COUNT_LIMIT, + attributeValueLengthLimit: + getNumberFromEnv('OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT') ?? Infinity, + attributeCountLimit: + getNumberFromEnv('OTEL_ATTRIBUTE_COUNT_LIMIT') ?? 128, }, spanLimits: { - attributeValueLengthLimit: env.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT, - attributeCountLimit: env.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, - linkCountLimit: env.OTEL_SPAN_LINK_COUNT_LIMIT, - eventCountLimit: env.OTEL_SPAN_EVENT_COUNT_LIMIT, + attributeValueLengthLimit: + getNumberFromEnv('OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT') ?? Infinity, + attributeCountLimit: + getNumberFromEnv('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT') ?? 128, + linkCountLimit: getNumberFromEnv('OTEL_SPAN_LINK_COUNT_LIMIT') ?? 128, + eventCountLimit: getNumberFromEnv('OTEL_SPAN_EVENT_COUNT_LIMIT') ?? 128, attributePerEventCountLimit: - env.OTEL_SPAN_ATTRIBUTE_PER_EVENT_COUNT_LIMIT, - attributePerLinkCountLimit: env.OTEL_SPAN_ATTRIBUTE_PER_LINK_COUNT_LIMIT, + getNumberFromEnv('OTEL_SPAN_ATTRIBUTE_PER_EVENT_COUNT_LIMIT') ?? 128, + attributePerLinkCountLimit: + getNumberFromEnv('OTEL_SPAN_ATTRIBUTE_PER_LINK_COUNT_LIMIT') ?? 128, }, }; } /** * Based on environment, builds a sampler, complies with specification. - * @param environment optional, by default uses getEnv(), but allows passing a value to reuse parsed environment */ -export function buildSamplerFromEnv( - environment: Required = getEnv() -): Sampler { - switch (environment.OTEL_TRACES_SAMPLER) { +export function buildSamplerFromEnv(): Sampler { + const sampler = + getStringFromEnv('OTEL_TRACES_SAMPLER') ?? + TracesSamplerValues.ParentBasedAlwaysOn; + switch (sampler) { case TracesSamplerValues.AlwaysOn: return new AlwaysOnSampler(); case TracesSamplerValues.AlwaysOff: @@ -86,48 +89,31 @@ export function buildSamplerFromEnv( root: new AlwaysOffSampler(), }); case TracesSamplerValues.TraceIdRatio: - return new TraceIdRatioBasedSampler( - getSamplerProbabilityFromEnv(environment) - ); + return new TraceIdRatioBasedSampler(getSamplerProbabilityFromEnv()); case TracesSamplerValues.ParentBasedTraceIdRatio: return new ParentBasedSampler({ - root: new TraceIdRatioBasedSampler( - getSamplerProbabilityFromEnv(environment) - ), + root: new TraceIdRatioBasedSampler(getSamplerProbabilityFromEnv()), }); default: diag.error( - `OTEL_TRACES_SAMPLER value "${environment.OTEL_TRACES_SAMPLER} invalid, defaulting to ${FALLBACK_OTEL_TRACES_SAMPLER}".` + `OTEL_TRACES_SAMPLER value "${sampler}" invalid, defaulting to "${FALLBACK_OTEL_TRACES_SAMPLER}".` ); return new AlwaysOnSampler(); } } -function getSamplerProbabilityFromEnv( - environment: Required -): number | undefined { - if ( - environment.OTEL_TRACES_SAMPLER_ARG === undefined || - environment.OTEL_TRACES_SAMPLER_ARG === '' - ) { +function getSamplerProbabilityFromEnv(): number | undefined { + const probability = getNumberFromEnv('OTEL_TRACES_SAMPLER_ARG'); + if (probability == null) { diag.error( `OTEL_TRACES_SAMPLER_ARG is blank, defaulting to ${DEFAULT_RATIO}.` ); return DEFAULT_RATIO; } - const probability = Number(environment.OTEL_TRACES_SAMPLER_ARG); - - if (isNaN(probability)) { - diag.error( - `OTEL_TRACES_SAMPLER_ARG=${environment.OTEL_TRACES_SAMPLER_ARG} was given, but it is invalid, defaulting to ${DEFAULT_RATIO}.` - ); - return DEFAULT_RATIO; - } - if (probability < 0 || probability > 1) { diag.error( - `OTEL_TRACES_SAMPLER_ARG=${environment.OTEL_TRACES_SAMPLER_ARG} was given, but it is out of range ([0..1]), defaulting to ${DEFAULT_RATIO}.` + `OTEL_TRACES_SAMPLER_ARG=${probability} was given, but it is out of range ([0..1]), defaulting to ${DEFAULT_RATIO}.` ); return DEFAULT_RATIO; } diff --git a/packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts b/packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts index 19e616dc0..46ac5335c 100644 --- a/packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts +++ b/packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts @@ -18,7 +18,7 @@ import { context, Context, diag, TraceFlags } from '@opentelemetry/api'; import { BindOnceFuture, ExportResultCode, - getEnv, + getNumberFromEnv, globalErrorHandler, suppressTracing, unrefTimer, @@ -51,23 +51,22 @@ export abstract class BatchSpanProcessorBase private readonly _exporter: SpanExporter, config?: T ) { - const env = getEnv(); this._maxExportBatchSize = typeof config?.maxExportBatchSize === 'number' ? config.maxExportBatchSize - : env.OTEL_BSP_MAX_EXPORT_BATCH_SIZE; + : (getNumberFromEnv('OTEL_BSP_MAX_EXPORT_BATCH_SIZE') ?? 512); this._maxQueueSize = typeof config?.maxQueueSize === 'number' ? config.maxQueueSize - : env.OTEL_BSP_MAX_QUEUE_SIZE; + : (getNumberFromEnv('OTEL_BSP_MAX_QUEUE_SIZE') ?? 2048); this._scheduledDelayMillis = typeof config?.scheduledDelayMillis === 'number' ? config.scheduledDelayMillis - : env.OTEL_BSP_SCHEDULE_DELAY; + : (getNumberFromEnv('OTEL_BSP_SCHEDULE_DELAY') ?? 5000); this._exportTimeoutMillis = typeof config?.exportTimeoutMillis === 'number' ? config.exportTimeoutMillis - : env.OTEL_BSP_EXPORT_TIMEOUT; + : (getNumberFromEnv('OTEL_BSP_EXPORT_TIMEOUT') ?? 30000); this._shutdownOnce = new BindOnceFuture(this._shutdown, this); diff --git a/packages/opentelemetry-sdk-trace-base/src/utility.ts b/packages/opentelemetry-sdk-trace-base/src/utility.ts index 819d725d4..c7830968f 100644 --- a/packages/opentelemetry-sdk-trace-base/src/utility.ts +++ b/packages/opentelemetry-sdk-trace-base/src/utility.ts @@ -20,7 +20,7 @@ import { SpanLimits, TracerConfig, GeneralLimits } from './types'; import { DEFAULT_ATTRIBUTE_COUNT_LIMIT, DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT, - getEnvWithoutDefaults, + getNumberFromEnv, } from '@opentelemetry/core'; /** @@ -68,16 +68,14 @@ export function mergeConfig(userConfig: TracerConfig): TracerConfig & { export function reconfigureLimits(userConfig: TracerConfig): TracerConfig { const spanLimits = Object.assign({}, userConfig.spanLimits); - const parsedEnvConfig = getEnvWithoutDefaults(); - /** * Reassign span attribute count limit to use first non null value defined by user or use default value */ spanLimits.attributeCountLimit = userConfig.spanLimits?.attributeCountLimit ?? userConfig.generalLimits?.attributeCountLimit ?? - parsedEnvConfig.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT ?? - parsedEnvConfig.OTEL_ATTRIBUTE_COUNT_LIMIT ?? + getNumberFromEnv('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT') ?? + getNumberFromEnv('OTEL_ATTRIBUTE_COUNT_LIMIT') ?? DEFAULT_ATTRIBUTE_COUNT_LIMIT; /** @@ -86,8 +84,8 @@ export function reconfigureLimits(userConfig: TracerConfig): TracerConfig { spanLimits.attributeValueLengthLimit = userConfig.spanLimits?.attributeValueLengthLimit ?? userConfig.generalLimits?.attributeValueLengthLimit ?? - parsedEnvConfig.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT ?? - parsedEnvConfig.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT ?? + getNumberFromEnv('OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT') ?? + getNumberFromEnv('OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT') ?? DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT; return Object.assign({}, userConfig, { spanLimits }); diff --git a/packages/opentelemetry-sdk-trace-base/test/index-webpack.ts b/packages/opentelemetry-sdk-trace-base/test/browser/index-webpack.ts similarity index 64% rename from packages/opentelemetry-sdk-trace-base/test/index-webpack.ts rename to packages/opentelemetry-sdk-trace-base/test/browser/index-webpack.ts index 802d6c405..99100a0f6 100644 --- a/packages/opentelemetry-sdk-trace-base/test/index-webpack.ts +++ b/packages/opentelemetry-sdk-trace-base/test/browser/index-webpack.ts @@ -13,8 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +const testsContext = require.context('../browser', true, /test$/); +testsContext.keys().forEach(testsContext); -{ - const testsContext = require.context('./', true, /test$/); - testsContext.keys().forEach(testsContext); -} +const testsContextCommon = require.context('../common', true, /test$/); +testsContextCommon.keys().forEach(testsContextCommon); + +const srcContext = require.context('.', true, /src$/); +srcContext.keys().forEach(srcContext); diff --git a/packages/opentelemetry-sdk-trace-base/test/index-webpack.worker.ts b/packages/opentelemetry-sdk-trace-base/test/browser/index-webpack.worker.ts similarity index 64% rename from packages/opentelemetry-sdk-trace-base/test/index-webpack.worker.ts rename to packages/opentelemetry-sdk-trace-base/test/browser/index-webpack.worker.ts index 802d6c405..99100a0f6 100644 --- a/packages/opentelemetry-sdk-trace-base/test/index-webpack.worker.ts +++ b/packages/opentelemetry-sdk-trace-base/test/browser/index-webpack.worker.ts @@ -13,8 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +const testsContext = require.context('../browser', true, /test$/); +testsContext.keys().forEach(testsContext); -{ - const testsContext = require.context('./', true, /test$/); - testsContext.keys().forEach(testsContext); -} +const testsContextCommon = require.context('../common', true, /test$/); +testsContextCommon.keys().forEach(testsContextCommon); + +const srcContext = require.context('.', true, /src$/); +srcContext.keys().forEach(srcContext); diff --git a/packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts b/packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts index dfd380294..8d845c49f 100644 --- a/packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts @@ -62,16 +62,9 @@ class DummyPropagator implements TextMapPropagator { } describe('BasicTracerProvider', () => { - let envSource: Record; let setGlobalPropagatorStub: sinon.SinonSpy<[TextMapPropagator], boolean>; let setGlobalContextManagerStub: sinon.SinonSpy<[ContextManager], boolean>; - if (global.process?.versions?.node === undefined) { - envSource = globalThis as unknown as Record; - } else { - envSource = process.env as Record; - } - beforeEach(() => { // to avoid actually registering the TraceProvider and leaking env to other tests sinon.stub(trace, 'setGlobalTracerProvider'); @@ -237,56 +230,7 @@ describe('BasicTracerProvider', () => { }); }); - describe('when attribute value length limit is defined via env', () => { - it('should have general attribute value length limits value as defined with env', () => { - envSource.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '115'; - const tracer = new BasicTracerProvider().getTracer( - 'default' - ) as Tracer; - const generalLimits = tracer.getGeneralLimits(); - assert.strictEqual(generalLimits.attributeValueLengthLimit, 115); - delete envSource.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT; - }); - it('should have span attribute value length limit value same as general limit value', () => { - envSource.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '125'; - const tracer = new BasicTracerProvider().getTracer( - 'default' - ) as Tracer; - const generalLimits = tracer.getGeneralLimits(); - const spanLimits = tracer.getSpanLimits(); - assert.strictEqual(generalLimits.attributeValueLengthLimit, 125); - assert.strictEqual(spanLimits.attributeValueLengthLimit, 125); - delete envSource.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT; - }); - it('should have span and general attribute value length limits as defined in env', () => { - envSource.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '125'; - envSource.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT = '109'; - const tracer = new BasicTracerProvider().getTracer( - 'default' - ) as Tracer; - const spanLimits = tracer.getSpanLimits(); - const generalLimits = tracer.getGeneralLimits(); - assert.strictEqual(generalLimits.attributeValueLengthLimit, 125); - assert.strictEqual(spanLimits.attributeValueLengthLimit, 109); - delete envSource.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT; - delete envSource.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT; - }); - it('should have span attribute value length limit as default of Infinity', () => { - envSource.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '125'; - envSource.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT = 'Infinity'; - const tracer = new BasicTracerProvider().getTracer( - 'default' - ) as Tracer; - const spanLimits = tracer.getSpanLimits(); - const generalLimits = tracer.getGeneralLimits(); - assert.strictEqual(generalLimits.attributeValueLengthLimit, 125); - assert.strictEqual(spanLimits.attributeValueLengthLimit, Infinity); - delete envSource.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT; - delete envSource.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT; - }); - }); - - describe('when attribute value length limit is not defined via env', () => { + describe('when attribute value length limit is not defined', () => { it('should use default value of Infinity', () => { const tracer = new BasicTracerProvider().getTracer( 'default' @@ -298,56 +242,7 @@ describe('BasicTracerProvider', () => { }); }); - describe('when attribute count limit is defined via env', () => { - it('should general attribute count limit as defined with env', () => { - envSource.OTEL_ATTRIBUTE_COUNT_LIMIT = '25'; - const tracer = new BasicTracerProvider({}).getTracer( - 'default' - ) as Tracer; - const generalLimits = tracer.getGeneralLimits(); - assert.strictEqual(generalLimits.attributeCountLimit, 25); - delete envSource.OTEL_ATTRIBUTE_COUNT_LIMIT; - }); - it('should have span attribute count limit value same as general limit value', () => { - envSource.OTEL_ATTRIBUTE_COUNT_LIMIT = '20'; - const tracer = new BasicTracerProvider().getTracer( - 'default' - ) as Tracer; - const generalLimits = tracer.getGeneralLimits(); - const spanLimits = tracer.getSpanLimits(); - assert.strictEqual(generalLimits.attributeCountLimit, 20); - assert.strictEqual(spanLimits.attributeCountLimit, 20); - delete envSource.OTEL_ATTRIBUTE_COUNT_LIMIT; - }); - it('should have span and general attribute count limits as defined in env', () => { - envSource.OTEL_ATTRIBUTE_COUNT_LIMIT = '20'; - envSource.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT = '35'; - const tracer = new BasicTracerProvider().getTracer( - 'default' - ) as Tracer; - const spanLimits = tracer.getSpanLimits(); - const generalLimits = tracer.getGeneralLimits(); - assert.strictEqual(generalLimits.attributeCountLimit, 20); - assert.strictEqual(spanLimits.attributeCountLimit, 35); - delete envSource.OTEL_ATTRIBUTE_COUNT_LIMIT; - delete envSource.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT; - }); - it('should have span attribute count limit as default of 128', () => { - envSource.OTEL_ATTRIBUTE_COUNT_LIMIT = '20'; - envSource.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT = '128'; - const tracer = new BasicTracerProvider().getTracer( - 'default' - ) as Tracer; - const spanLimits = tracer.getSpanLimits(); - const generalLimits = tracer.getGeneralLimits(); - assert.strictEqual(generalLimits.attributeCountLimit, 20); - assert.strictEqual(spanLimits.attributeCountLimit, 128); - delete envSource.OTEL_ATTRIBUTE_COUNT_LIMIT; - delete envSource.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT; - }); - }); - - describe('when attribute count limit is not defined via env', () => { + describe('when attribute count limit is not defined', () => { it('should use default value of 128', () => { const tracer = new BasicTracerProvider().getTracer( 'default' diff --git a/packages/opentelemetry-sdk-trace-base/test/common/Tracer.test.ts b/packages/opentelemetry-sdk-trace-base/test/common/Tracer.test.ts index 6881fbf39..634301ffa 100644 --- a/packages/opentelemetry-sdk-trace-base/test/common/Tracer.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/common/Tracer.test.ts @@ -50,12 +50,6 @@ import { Tracer } from '../../src/Tracer'; describe('Tracer', () => { const tracerProvider = new BasicTracerProvider(); - let envSource: Record; - if (global.process?.versions?.node === undefined) { - envSource = globalThis as unknown as Record; - } else { - envSource = process.env as Record; - } class TestSampler implements Sampler { constructor(private readonly traceState?: TraceState) {} @@ -106,8 +100,6 @@ describe('Tracer', () => { afterEach(() => { context.disable(); - delete envSource.OTEL_TRACES_SAMPLER; - delete envSource.OTEL_TRACES_SAMPLER_ARG; }); it('should create a Tracer instance', () => { @@ -327,51 +319,6 @@ describe('Tracer', () => { assert.strictEqual(trace.getSpan(samplerContext), undefined); }); - it('should sample a trace when OTEL_TRACES_SAMPLER_ARG is unset', () => { - envSource.OTEL_TRACES_SAMPLER = 'traceidratio'; - envSource.OTEL_TRACES_SAMPLER_ARG = ''; - const tracer = new Tracer( - { name: 'default', version: '0.0.1' }, - {}, - tracerProvider['_resource'], - tracerProvider['_activeSpanProcessor'] - ); - const span = tracer.startSpan('my-span'); - const context = span.spanContext(); - assert.strictEqual(context.traceFlags, TraceFlags.SAMPLED); - span.end(); - }); - - it('should not sample a trace when OTEL_TRACES_SAMPLER_ARG is out of range', () => { - envSource.OTEL_TRACES_SAMPLER = 'traceidratio'; - envSource.OTEL_TRACES_SAMPLER_ARG = '2'; - const tracer = new Tracer( - { name: 'default', version: '0.0.1' }, - {}, - tracerProvider['_resource'], - tracerProvider['_activeSpanProcessor'] - ); - const span = tracer.startSpan('my-span'); - const context = span.spanContext(); - assert.strictEqual(context.traceFlags, TraceFlags.SAMPLED); - span.end(); - }); - - it('should not sample a trace when OTEL_TRACES_SAMPLER_ARG is 0', () => { - envSource.OTEL_TRACES_SAMPLER = 'traceidratio'; - envSource.OTEL_TRACES_SAMPLER_ARG = '0'; - const tracer = new Tracer( - { name: 'default', version: '0.0.1' }, - {}, - tracerProvider['_resource'], - tracerProvider['_activeSpanProcessor'] - ); - const span = tracer.startSpan('my-span'); - const context = span.spanContext(); - assert.strictEqual(context.traceFlags, TraceFlags.NONE); - span.end(); - }); - it('should start an active span with name and function args', () => { const tracer = new Tracer( { name: 'default', version: '0.0.1' }, diff --git a/packages/opentelemetry-sdk-trace-base/test/common/export/BatchSpanProcessorBase.test.ts b/packages/opentelemetry-sdk-trace-base/test/common/export/BatchSpanProcessorBase.test.ts index 657bbd724..4d3814825 100644 --- a/packages/opentelemetry-sdk-trace-base/test/common/export/BatchSpanProcessorBase.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/common/export/BatchSpanProcessorBase.test.ts @@ -97,32 +97,6 @@ describe('BatchSpanProcessorBase', () => { assert.ok(processor instanceof BatchSpanProcessor); processor.shutdown(); }); - - it('should read defaults from environment', () => { - const bspConfig = { - OTEL_BSP_MAX_EXPORT_BATCH_SIZE: 256, - OTEL_BSP_SCHEDULE_DELAY: 2500, - }; - - let env: Record; - if (global.process?.versions?.node === undefined) { - env = globalThis as unknown as Record; - } else { - env = process.env as Record; - } - - Object.entries(bspConfig).forEach(([k, v]) => { - env[k] = v; - }); - - const processor = new BatchSpanProcessor(exporter); - assert.ok(processor instanceof BatchSpanProcessor); - assert.strictEqual(processor['_maxExportBatchSize'], 256); - assert.strictEqual(processor['_scheduledDelayMillis'], 2500); - processor.shutdown(); - - Object.keys(bspConfig).forEach(k => delete env[k]); - }); }); describe('.onStart/.onEnd/.shutdown', () => { diff --git a/packages/opentelemetry-sdk-trace-base/test/node/BasicTracerProvider.test.ts b/packages/opentelemetry-sdk-trace-base/test/node/BasicTracerProvider.test.ts new file mode 100644 index 000000000..d1fd13b44 --- /dev/null +++ b/packages/opentelemetry-sdk-trace-base/test/node/BasicTracerProvider.test.ts @@ -0,0 +1,109 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { context, trace } from '@opentelemetry/api'; +import * as assert from 'assert'; +import * as sinon from 'sinon'; +import { BasicTracerProvider } from '../../src'; +import { Tracer } from '../../src/Tracer'; + +describe('BasicTracerProvider - Node', () => { + beforeEach(() => { + // to avoid actually registering the TraceProvider and leaking env to other tests + sinon.stub(trace, 'setGlobalTracerProvider'); + context.disable(); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe('constructor', () => { + describe('spanLimits', () => { + describe('when attribute value length limit is defined via env', () => { + it('should have general attribute value length limits value as defined with env', () => { + process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '115'; + const tracer = new BasicTracerProvider().getTracer( + 'default' + ) as Tracer; + const generalLimits = tracer.getGeneralLimits(); + assert.strictEqual(generalLimits.attributeValueLengthLimit, 115); + delete process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT; + }); + it('should have span attribute value length limit value same as general limit value', () => { + process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '125'; + const tracer = new BasicTracerProvider().getTracer( + 'default' + ) as Tracer; + const generalLimits = tracer.getGeneralLimits(); + const spanLimits = tracer.getSpanLimits(); + assert.strictEqual(generalLimits.attributeValueLengthLimit, 125); + assert.strictEqual(spanLimits.attributeValueLengthLimit, 125); + delete process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT; + }); + it('should have span and general attribute value length limits as defined in env', () => { + process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '125'; + process.env.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT = '109'; + const tracer = new BasicTracerProvider().getTracer( + 'default' + ) as Tracer; + const spanLimits = tracer.getSpanLimits(); + const generalLimits = tracer.getGeneralLimits(); + assert.strictEqual(generalLimits.attributeValueLengthLimit, 125); + assert.strictEqual(spanLimits.attributeValueLengthLimit, 109); + delete process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT; + delete process.env.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT; + }); + }); + + describe('when attribute count limit is defined via env', () => { + it('should general attribute count limit as defined with env', () => { + process.env.OTEL_ATTRIBUTE_COUNT_LIMIT = '25'; + const tracer = new BasicTracerProvider({}).getTracer( + 'default' + ) as Tracer; + const generalLimits = tracer.getGeneralLimits(); + assert.strictEqual(generalLimits.attributeCountLimit, 25); + delete process.env.OTEL_ATTRIBUTE_COUNT_LIMIT; + }); + it('should have span attribute count limit value same as general limit value', () => { + process.env.OTEL_ATTRIBUTE_COUNT_LIMIT = '20'; + const tracer = new BasicTracerProvider().getTracer( + 'default' + ) as Tracer; + const generalLimits = tracer.getGeneralLimits(); + const spanLimits = tracer.getSpanLimits(); + assert.strictEqual(generalLimits.attributeCountLimit, 20); + assert.strictEqual(spanLimits.attributeCountLimit, 20); + delete process.env.OTEL_ATTRIBUTE_COUNT_LIMIT; + }); + it('should have span and general attribute count limits as defined in env', () => { + process.env.OTEL_ATTRIBUTE_COUNT_LIMIT = '20'; + process.env.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT = '35'; + const tracer = new BasicTracerProvider().getTracer( + 'default' + ) as Tracer; + const spanLimits = tracer.getSpanLimits(); + const generalLimits = tracer.getGeneralLimits(); + assert.strictEqual(generalLimits.attributeCountLimit, 20); + assert.strictEqual(spanLimits.attributeCountLimit, 35); + delete process.env.OTEL_ATTRIBUTE_COUNT_LIMIT; + delete process.env.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT; + }); + }); + }); + }); +}); diff --git a/packages/opentelemetry-sdk-trace-base/test/node/Tracer.test.ts b/packages/opentelemetry-sdk-trace-base/test/node/Tracer.test.ts new file mode 100644 index 000000000..7b042c185 --- /dev/null +++ b/packages/opentelemetry-sdk-trace-base/test/node/Tracer.test.ts @@ -0,0 +1,80 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ +import { context, TraceFlags } from '@opentelemetry/api'; +import * as assert from 'assert'; +import { BasicTracerProvider } from '../../src'; +import { TestStackContextManager } from '../common/export/TestStackContextManager'; +import { Tracer } from '../../src/Tracer'; + +describe('Tracer', () => { + const tracerProvider = new BasicTracerProvider(); + + beforeEach(() => { + const contextManager = new TestStackContextManager().enable(); + context.setGlobalContextManager(contextManager); + }); + + afterEach(() => { + context.disable(); + delete process.env.OTEL_TRACES_SAMPLER; + delete process.env.OTEL_TRACES_SAMPLER_ARG; + }); + + it('should sample a trace when OTEL_TRACES_SAMPLER_ARG is unset', () => { + process.env.OTEL_TRACES_SAMPLER = 'traceidratio'; + process.env.OTEL_TRACES_SAMPLER_ARG = ''; + const tracer = new Tracer( + { name: 'default', version: '0.0.1' }, + {}, + tracerProvider['_resource'], + tracerProvider['_activeSpanProcessor'] + ); + const span = tracer.startSpan('my-span'); + const context = span.spanContext(); + assert.strictEqual(context.traceFlags, TraceFlags.SAMPLED); + span.end(); + }); + + it('should not sample a trace when OTEL_TRACES_SAMPLER_ARG is out of range', () => { + process.env.OTEL_TRACES_SAMPLER = 'traceidratio'; + process.env.OTEL_TRACES_SAMPLER_ARG = '2'; + const tracer = new Tracer( + { name: 'default', version: '0.0.1' }, + {}, + tracerProvider['_resource'], + tracerProvider['_activeSpanProcessor'] + ); + const span = tracer.startSpan('my-span'); + const context = span.spanContext(); + assert.strictEqual(context.traceFlags, TraceFlags.SAMPLED); + span.end(); + }); + + it('should not sample a trace when OTEL_TRACES_SAMPLER_ARG is 0', () => { + process.env.OTEL_TRACES_SAMPLER = 'traceidratio'; + process.env.OTEL_TRACES_SAMPLER_ARG = '0'; + const tracer = new Tracer( + { name: 'default', version: '0.0.1' }, + {}, + tracerProvider['_resource'], + tracerProvider['_activeSpanProcessor'] + ); + const span = tracer.startSpan('my-span'); + const context = span.spanContext(); + assert.strictEqual(context.traceFlags, TraceFlags.NONE); + span.end(); + }); +}); diff --git a/packages/opentelemetry-sdk-trace-base/test/common/config.test.ts b/packages/opentelemetry-sdk-trace-base/test/node/config.test.ts similarity index 82% rename from packages/opentelemetry-sdk-trace-base/test/common/config.test.ts rename to packages/opentelemetry-sdk-trace-base/test/node/config.test.ts index 615749a55..63b279045 100644 --- a/packages/opentelemetry-sdk-trace-base/test/common/config.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/node/config.test.ts @@ -24,34 +24,27 @@ import { import { buildSamplerFromEnv } from '../../src/config'; describe('config', () => { - let envSource: Record; - if (global.process?.versions?.node === undefined) { - envSource = globalThis as unknown as Record; - } else { - envSource = process.env as Record; - } - describe('buildSamplerFromEnv()', () => { afterEach(() => { - delete envSource.OTEL_TRACES_SAMPLER; - delete envSource.OTEL_TRACES_SAMPLER_ARG; + delete process.env.OTEL_TRACES_SAMPLER; + delete process.env.OTEL_TRACES_SAMPLER_ARG; }); it('should handle always_on case', () => { - envSource.OTEL_TRACES_SAMPLER = 'always_on'; + process.env.OTEL_TRACES_SAMPLER = 'always_on'; assert.ok(buildSamplerFromEnv() instanceof AlwaysOnSampler); assert.strictEqual(buildSamplerFromEnv().toString(), 'AlwaysOnSampler'); }); it('should handle always_off case', () => { - envSource.OTEL_TRACES_SAMPLER = 'always_off'; + process.env.OTEL_TRACES_SAMPLER = 'always_off'; assert.ok(buildSamplerFromEnv() instanceof AlwaysOffSampler); assert.strictEqual(buildSamplerFromEnv().toString(), 'AlwaysOffSampler'); }); it('should handle traceidratio case', () => { - envSource.OTEL_TRACES_SAMPLER = 'traceidratio'; - envSource.OTEL_TRACES_SAMPLER_ARG = '0.1'; + process.env.OTEL_TRACES_SAMPLER = 'traceidratio'; + process.env.OTEL_TRACES_SAMPLER_ARG = '0.1'; assert.ok(buildSamplerFromEnv() instanceof TraceIdRatioBasedSampler); assert.strictEqual( buildSamplerFromEnv().toString(), @@ -60,7 +53,7 @@ describe('config', () => { }); it('should handle parentbased_always_on case', () => { - envSource.OTEL_TRACES_SAMPLER = 'parentbased_always_on'; + process.env.OTEL_TRACES_SAMPLER = 'parentbased_always_on'; assert.ok(buildSamplerFromEnv() instanceof ParentBasedSampler); assert.strictEqual( buildSamplerFromEnv().toString(), @@ -69,7 +62,7 @@ describe('config', () => { }); it('should handle parentbased_always_off case', () => { - envSource.OTEL_TRACES_SAMPLER = 'parentbased_always_off'; + process.env.OTEL_TRACES_SAMPLER = 'parentbased_always_off'; assert.ok(buildSamplerFromEnv() instanceof ParentBasedSampler); assert.strictEqual( buildSamplerFromEnv().toString(), @@ -78,8 +71,8 @@ describe('config', () => { }); it('should handle parentbased_traceidratio case', () => { - envSource.OTEL_TRACES_SAMPLER = 'parentbased_traceidratio'; - envSource.OTEL_TRACES_SAMPLER_ARG = '0.2'; + process.env.OTEL_TRACES_SAMPLER = 'parentbased_traceidratio'; + process.env.OTEL_TRACES_SAMPLER_ARG = '0.2'; assert.ok(buildSamplerFromEnv() instanceof ParentBasedSampler); assert.strictEqual( buildSamplerFromEnv().toString(), diff --git a/packages/opentelemetry-sdk-trace-base/test/node/export/BatchSpanProcessorBase.test.ts b/packages/opentelemetry-sdk-trace-base/test/node/export/BatchSpanProcessorBase.test.ts new file mode 100644 index 000000000..ec7c935d0 --- /dev/null +++ b/packages/opentelemetry-sdk-trace-base/test/node/export/BatchSpanProcessorBase.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import * as assert from 'assert'; +import { BufferConfig, InMemorySpanExporter } from '../../../src'; +import { BatchSpanProcessorBase } from '../../../src/export/BatchSpanProcessorBase'; + +class BatchSpanProcessor extends BatchSpanProcessorBase { + onShutdown() {} +} + +describe('BatchSpanProcessorBase', () => { + describe('constructor', () => { + it('should read defaults from environment', () => { + const exporter = new InMemorySpanExporter(); + const bspConfig = { + OTEL_BSP_MAX_EXPORT_BATCH_SIZE: 256, + OTEL_BSP_SCHEDULE_DELAY: 2500, + }; + + let env: Record; + if (global.process?.versions?.node === undefined) { + env = globalThis as unknown as Record; + } else { + env = process.env as Record; + } + + Object.entries(bspConfig).forEach(([k, v]) => { + env[k] = v; + }); + + const processor = new BatchSpanProcessor(exporter); + assert.ok(processor instanceof BatchSpanProcessor); + assert.strictEqual(processor['_maxExportBatchSize'], 256); + assert.strictEqual(processor['_scheduledDelayMillis'], 2500); + processor.shutdown(); + + Object.keys(bspConfig).forEach(k => delete env[k]); + }); + }); +});