Skip to content

Commit 915da21

Browse files
authored
Merge branch 'main' into http-debug-enrich-logger
2 parents 60e8845 + feea516 commit 915da21

File tree

13 files changed

+606
-13
lines changed

13 files changed

+606
-13
lines changed

packages/opentelemetry-core/src/utils/environment.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ const ENVIRONMENT_NUMBERS_KEYS = [
2828
'OTEL_BSP_MAX_EXPORT_BATCH_SIZE',
2929
'OTEL_BSP_MAX_QUEUE_SIZE',
3030
'OTEL_BSP_SCHEDULE_DELAY',
31+
'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT',
32+
'OTEL_ATTRIBUTE_COUNT_LIMIT',
3133
'OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT',
3234
'OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT',
3335
'OTEL_SPAN_EVENT_COUNT_LIMIT',
@@ -88,6 +90,10 @@ export type RAW_ENVIRONMENT = {
8890
[key: string]: string | number | undefined | string[];
8991
};
9092

93+
export const DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT = Infinity;
94+
95+
export const DEFAULT_ATTRIBUTE_COUNT_LIMIT = 128;
96+
9197
/**
9298
* Default environment variables
9399
*/
@@ -118,8 +124,10 @@ export const DEFAULT_ENVIRONMENT: Required<ENVIRONMENT> = {
118124
OTEL_PROPAGATORS: ['tracecontext', 'baggage'],
119125
OTEL_RESOURCE_ATTRIBUTES: '',
120126
OTEL_SERVICE_NAME: '',
121-
OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: Infinity,
122-
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT: 128,
127+
OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT: DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT,
128+
OTEL_ATTRIBUTE_COUNT_LIMIT: DEFAULT_ATTRIBUTE_COUNT_LIMIT,
129+
OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT ,
130+
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT: DEFAULT_ATTRIBUTE_COUNT_LIMIT,
123131
OTEL_SPAN_EVENT_COUNT_LIMIT: 128,
124132
OTEL_SPAN_LINK_COUNT_LIMIT: 128,
125133
OTEL_TRACES_EXPORTER: 'none',

packages/opentelemetry-core/test/utils/environment.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ describe('environment', () => {
8484
OTEL_LOG_LEVEL: 'ERROR',
8585
OTEL_NO_PATCH_MODULES: 'a,b,c',
8686
OTEL_RESOURCE_ATTRIBUTES: '<attrs>',
87+
OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT: 40,
88+
OTEL_ATTRIBUTE_COUNT_LIMIT: 50,
8789
OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT: 100,
8890
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT: 10,
8991
OTEL_SPAN_EVENT_COUNT_LIMIT: 20,
@@ -94,6 +96,8 @@ describe('environment', () => {
9496
const env = getEnv();
9597
assert.deepStrictEqual(env.OTEL_NO_PATCH_MODULES, ['a', 'b', 'c']);
9698
assert.strictEqual(env.OTEL_LOG_LEVEL, DiagLogLevel.ERROR);
99+
assert.strictEqual(env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, 40);
100+
assert.strictEqual(env.OTEL_ATTRIBUTE_COUNT_LIMIT, 50);
97101
assert.strictEqual(env.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT, 100);
98102
assert.strictEqual(env.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, 10);
99103
assert.strictEqual(env.OTEL_SPAN_EVENT_COUNT_LIMIT, 20);

packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts

+19-4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ export abstract class InstrumentationBase<T = any>
5959
}
6060
}
6161

62+
private _extractPackageVersion(baseDir: string): string | undefined {
63+
try {
64+
// eslint-disable-next-line @typescript-eslint/no-var-requires
65+
const version = require(path.join(baseDir, 'package.json')).version;
66+
return typeof version === 'string' ? version : undefined;
67+
} catch (error) {
68+
diag.warn('Failed extracting version', baseDir);
69+
}
70+
71+
return undefined;
72+
}
73+
6274
private _onRequire<T>(
6375
module: InstrumentationModuleDefinition<T>,
6476
exports: T,
@@ -73,13 +85,11 @@ export abstract class InstrumentationBase<T = any>
7385
return exports;
7486
}
7587

76-
// eslint-disable-next-line @typescript-eslint/no-var-requires
77-
const version = require(path.join(baseDir, 'package.json')).version;
88+
const version = this._extractPackageVersion(baseDir);
7889
module.moduleVersion = version;
7990
if (module.name === name) {
8091
// main module
8192
if (
82-
typeof version === 'string' &&
8393
isSupported(module.supportedVersions, version, module.includePrerelease)
8494
) {
8595
if (typeof module.patch === 'function') {
@@ -167,7 +177,12 @@ export abstract class InstrumentationBase<T = any>
167177
}
168178
}
169179

170-
function isSupported(supportedVersions: string[], version: string, includePrerelease?: boolean): boolean {
180+
function isSupported(supportedVersions: string[], version?: string, includePrerelease?: boolean): boolean {
181+
if (typeof version === 'undefined') {
182+
// If we don't have the version, accept the wildcard case only
183+
return supportedVersions.includes('*');
184+
}
185+
171186
return supportedVersions.some(supportedVersion => {
172187
return satisfies(version, supportedVersion, { includePrerelease });
173188
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as assert from 'assert';
18+
import * as sinon from 'sinon';
19+
import { InstrumentationBase, InstrumentationModuleDefinition } from '../../src';
20+
21+
const MODULE_NAME = 'test-module';
22+
const MODULE_FILE_NAME = 'test-module-file';
23+
const MODULE_VERSION = '0.1.0';
24+
const WILDCARD_VERSION = '*';
25+
const MODULE_DIR = '/random/dir';
26+
27+
class TestInstrumentation extends InstrumentationBase {
28+
constructor() {
29+
super(MODULE_NAME, MODULE_VERSION);
30+
}
31+
32+
init() {}
33+
}
34+
35+
describe('InstrumentationBase', () => {
36+
describe('_onRequire - module version is not available', () => {
37+
// For all of these cases, there is no indication of the actual module version,
38+
// so we require there to be a wildcard supported version.
39+
40+
let instrumentation: TestInstrumentation;
41+
let modulePatchSpy: sinon.SinonSpy;
42+
43+
beforeEach(() => {
44+
instrumentation = new TestInstrumentation();
45+
// @ts-expect-error access internal property for testing
46+
instrumentation._enabled = true;
47+
modulePatchSpy = sinon.spy();
48+
});
49+
50+
describe('when patching a module', () => {
51+
describe('AND there is no wildcard supported version', () => {
52+
it('should not patch module', () => {
53+
const moduleExports = {};
54+
const instrumentationModule = {
55+
supportedVersions: [`^${MODULE_VERSION}`],
56+
name: MODULE_NAME,
57+
patch: modulePatchSpy as unknown,
58+
} as InstrumentationModuleDefinition<unknown>;
59+
60+
// @ts-expect-error access internal property for testing
61+
instrumentation._onRequire<unknown>(
62+
instrumentationModule,
63+
moduleExports,
64+
MODULE_NAME,
65+
MODULE_DIR
66+
);
67+
68+
assert.strictEqual(instrumentationModule.moduleVersion, undefined);
69+
assert.strictEqual(instrumentationModule.moduleExports, undefined);
70+
sinon.assert.notCalled(modulePatchSpy);
71+
});
72+
});
73+
74+
describe('AND there is a wildcard supported version', () => {
75+
it('should patch module', () => {
76+
const moduleExports = {};
77+
const instrumentationModule = {
78+
supportedVersions: [`^${MODULE_VERSION}`, WILDCARD_VERSION],
79+
name: MODULE_NAME,
80+
patch: modulePatchSpy as unknown,
81+
} as InstrumentationModuleDefinition<unknown>;
82+
83+
// @ts-expect-error access internal property for testing
84+
instrumentation._onRequire<unknown>(
85+
instrumentationModule,
86+
moduleExports,
87+
MODULE_NAME,
88+
MODULE_DIR
89+
);
90+
91+
assert.strictEqual(instrumentationModule.moduleVersion, undefined);
92+
assert.strictEqual(instrumentationModule.moduleExports, moduleExports);
93+
sinon.assert.calledOnceWithExactly(modulePatchSpy, moduleExports, undefined);
94+
});
95+
});
96+
});
97+
98+
describe('when patching module files', () => {
99+
let filePatchSpy: sinon.SinonSpy;
100+
101+
beforeEach(() => {
102+
filePatchSpy = sinon.spy();
103+
})
104+
105+
describe('AND there is no wildcard supported version', () => {
106+
it('should not patch module file', () => {
107+
const moduleExports = {};
108+
const supportedVersions = [`^${MODULE_VERSION}`];
109+
const instrumentationModule = {
110+
supportedVersions,
111+
name: MODULE_NAME,
112+
patch: modulePatchSpy as unknown,
113+
files: [{
114+
name: MODULE_FILE_NAME,
115+
supportedVersions,
116+
patch: filePatchSpy as unknown
117+
}]
118+
} as InstrumentationModuleDefinition<unknown>;
119+
120+
// @ts-expect-error access internal property for testing
121+
instrumentation._onRequire<unknown>(
122+
instrumentationModule,
123+
moduleExports,
124+
MODULE_FILE_NAME,
125+
MODULE_DIR
126+
);
127+
128+
assert.strictEqual(instrumentationModule.moduleVersion, undefined);
129+
assert.strictEqual(instrumentationModule.moduleExports, undefined);
130+
sinon.assert.notCalled(modulePatchSpy);
131+
sinon.assert.notCalled(filePatchSpy);
132+
});
133+
});
134+
135+
describe('AND there is a wildcard supported version', () => {
136+
it('should patch module file', () => {
137+
const moduleExports = {};
138+
const supportedVersions = [`^${MODULE_VERSION}`, WILDCARD_VERSION];
139+
const instrumentationModule = {
140+
supportedVersions,
141+
name: MODULE_NAME,
142+
patch: modulePatchSpy as unknown,
143+
files: [{
144+
name: MODULE_FILE_NAME,
145+
supportedVersions,
146+
patch: filePatchSpy as unknown
147+
}]
148+
} as InstrumentationModuleDefinition<unknown>;
149+
150+
// @ts-expect-error access internal property for testing
151+
instrumentation._onRequire<unknown>(
152+
instrumentationModule,
153+
moduleExports,
154+
MODULE_FILE_NAME,
155+
MODULE_DIR
156+
);
157+
158+
assert.strictEqual(instrumentationModule.moduleVersion, undefined);
159+
assert.strictEqual(instrumentationModule.files[0].moduleExports, moduleExports);
160+
sinon.assert.notCalled(modulePatchSpy);
161+
sinon.assert.calledOnceWithExactly(filePatchSpy, moduleExports, undefined);
162+
});
163+
});
164+
});
165+
});
166+
});

packages/opentelemetry-sdk-trace-base/src/Tracer.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
import { Resource } from '@opentelemetry/resources';
2626
import { BasicTracerProvider } from './BasicTracerProvider';
2727
import { Span } from './Span';
28-
import { SpanLimits, TracerConfig } from './types';
28+
import { GeneralLimits, SpanLimits, TracerConfig } from './types';
2929
import { mergeConfig } from './utility';
3030
import { SpanProcessor } from './SpanProcessor';
3131

@@ -34,6 +34,7 @@ import { SpanProcessor } from './SpanProcessor';
3434
*/
3535
export class Tracer implements api.Tracer {
3636
private readonly _sampler: api.Sampler;
37+
private readonly _generalLimits: GeneralLimits;
3738
private readonly _spanLimits: SpanLimits;
3839
private readonly _idGenerator: IdGenerator;
3940
readonly resource: Resource;
@@ -49,6 +50,7 @@ export class Tracer implements api.Tracer {
4950
) {
5051
const localConfig = mergeConfig(config);
5152
this._sampler = localConfig.sampler;
53+
this._generalLimits = localConfig.generalLimits;
5254
this._spanLimits = localConfig.spanLimits;
5355
this._idGenerator = config.idGenerator || new RandomIdGenerator();
5456
this.resource = _tracerProvider.resource;
@@ -212,6 +214,11 @@ export class Tracer implements api.Tracer {
212214
return api.context.with(contextWithSpanSet, fn, undefined, span);
213215
}
214216

217+
/** Returns the active {@link GeneralLimits}. */
218+
getGeneralLimits(): GeneralLimits {
219+
return this._generalLimits;
220+
}
221+
215222
/** Returns the active {@link SpanLimits}. */
216223
getSpanLimits(): SpanLimits {
217224
return this._spanLimits;

packages/opentelemetry-sdk-trace-base/src/config.ts

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ const DEFAULT_RATIO = 1;
3838
export const DEFAULT_CONFIG = {
3939
sampler: buildSamplerFromEnv(env),
4040
forceFlushTimeoutMillis: 30000,
41+
generalLimits: {
42+
attributeValueLengthLimit: getEnv().OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT,
43+
attributeCountLimit: getEnv().OTEL_ATTRIBUTE_COUNT_LIMIT,
44+
},
4145
spanLimits: {
4246
attributeValueLengthLimit: getEnv().OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT,
4347
attributeCountLimit: getEnv().OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT,

packages/opentelemetry-sdk-trace-base/src/types.ts

+11
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export interface TracerConfig {
2929
*/
3030
sampler?: Sampler;
3131

32+
/** General Limits */
33+
generalLimits?: GeneralLimits;
34+
3235
/** Span Limits */
3336
spanLimits?: SpanLimits;
3437

@@ -61,6 +64,14 @@ export interface SDKRegistrationConfig {
6164
contextManager?: ContextManager | null;
6265
}
6366

67+
/** Global configuration limits of trace service */
68+
export interface GeneralLimits {
69+
/** attributeValueLengthLimit is maximum allowed attribute value size */
70+
attributeValueLengthLimit?: number;
71+
/** attributeCountLimit is number of attributes per trace */
72+
attributeCountLimit?: number;
73+
}
74+
6475
/** Global configuration of trace service */
6576
export interface SpanLimits {
6677
/** attributeValueLengthLimit is maximum allowed attribute value size */

packages/opentelemetry-sdk-trace-base/src/utility.ts

+30-2
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,21 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT, DEFAULT_ATTRIBUTE_COUNT_LIMIT } from '@opentelemetry/core';
18+
1719
import { Sampler } from '@opentelemetry/api';
1820
import { buildSamplerFromEnv, DEFAULT_CONFIG } from './config';
19-
import { SpanLimits, TracerConfig } from './types';
21+
import { SpanLimits, TracerConfig, GeneralLimits } from './types';
2022

2123
/**
2224
* Function to merge Default configuration (as specified in './config') with
2325
* user provided configurations.
2426
*/
25-
export function mergeConfig(userConfig: TracerConfig): TracerConfig & { sampler: Sampler; spanLimits: SpanLimits } {
27+
export function mergeConfig(userConfig: TracerConfig): TracerConfig & {
28+
sampler: Sampler;
29+
spanLimits: SpanLimits;
30+
generalLimits: GeneralLimits;
31+
} {
2632
const perInstanceDefaults: Partial<TracerConfig> = {
2733
sampler: buildSamplerFromEnv(),
2834
};
@@ -34,11 +40,33 @@ export function mergeConfig(userConfig: TracerConfig): TracerConfig & { sampler:
3440
userConfig
3541
);
3642

43+
target.generalLimits = Object.assign(
44+
{},
45+
DEFAULT_CONFIG.generalLimits,
46+
userConfig.generalLimits || {}
47+
);
48+
3749
target.spanLimits = Object.assign(
3850
{},
3951
DEFAULT_CONFIG.spanLimits,
4052
userConfig.spanLimits || {}
4153
);
4254

55+
/**
56+
* When span attribute count limit is not defined, but general attribute count limit is defined
57+
* Then, span attribute count limit will be same as general one
58+
*/
59+
if (target.spanLimits.attributeCountLimit === DEFAULT_ATTRIBUTE_COUNT_LIMIT && target.generalLimits.attributeCountLimit !== DEFAULT_ATTRIBUTE_COUNT_LIMIT) {
60+
target.spanLimits.attributeCountLimit = target.generalLimits.attributeCountLimit;
61+
}
62+
63+
/**
64+
* When span attribute value length limit is not defined, but general attribute value length limit is defined
65+
* Then, span attribute value length limit will be same as general one
66+
*/
67+
if (target.spanLimits.attributeValueLengthLimit === DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT && target.generalLimits.attributeValueLengthLimit !== DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT) {
68+
target.spanLimits.attributeValueLengthLimit = target.generalLimits.attributeValueLengthLimit;
69+
}
70+
4371
return target;
4472
}

0 commit comments

Comments
 (0)