209 lines
7.5 KiB
TypeScript
209 lines
7.5 KiB
TypeScript
/*
|
|
* 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 { diag } from '@opentelemetry/api';
|
|
import { HttpInstrumentationConfig } from '@tachybase/opentelemetry-instrumentation-http';
|
|
import * as assert from 'assert';
|
|
import * as sinon from 'sinon';
|
|
import { getNodeAutoInstrumentations } from '../src';
|
|
import { getResourceDetectorsFromEnv } from '../src/utils';
|
|
|
|
describe('utils', () => {
|
|
describe('getNodeAutoInstrumentations', () => {
|
|
it('should include all installed instrumentations', () => {
|
|
const instrumentations = getNodeAutoInstrumentations();
|
|
const installedInstrumentations = Object.keys(
|
|
require('../package.json').dependencies
|
|
).filter(depName => {
|
|
return depName.startsWith('@opentelemetry/instrumentation-');
|
|
});
|
|
|
|
assert.deepStrictEqual(
|
|
new Set(instrumentations.map(i => i.instrumentationName)),
|
|
new Set(installedInstrumentations)
|
|
);
|
|
});
|
|
|
|
it('should use user config', () => {
|
|
function applyCustomAttributesOnSpan() {}
|
|
|
|
const instrumentations = getNodeAutoInstrumentations({
|
|
'@tachybase/opentelemetry-instrumentation-http': {
|
|
applyCustomAttributesOnSpan,
|
|
},
|
|
});
|
|
const instrumentation = instrumentations.find(
|
|
instr =>
|
|
instr.instrumentationName === '@tachybase/opentelemetry-instrumentation-http'
|
|
) as any;
|
|
const configHttp = instrumentation._config as HttpInstrumentationConfig;
|
|
|
|
assert.strictEqual(
|
|
configHttp.applyCustomAttributesOnSpan,
|
|
applyCustomAttributesOnSpan
|
|
);
|
|
});
|
|
|
|
it('should not return disabled instrumentation', () => {
|
|
const instrumentations = getNodeAutoInstrumentations({
|
|
'@opentelemetry/instrumentation-grpc': {
|
|
enabled: false,
|
|
},
|
|
});
|
|
const instrumentation = instrumentations.find(
|
|
instr =>
|
|
instr.instrumentationName === '@opentelemetry/instrumentation-grpc'
|
|
);
|
|
assert.strictEqual(instrumentation, undefined);
|
|
});
|
|
|
|
it('should return only instrumentations enabled via OTEL_NODE_ENABLED_INSTRUMENTATIONS environment variable', () => {
|
|
process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS =
|
|
'http,aws-sdk, nestjs-core'; // separator with and without whitespaces should be allowed
|
|
try {
|
|
const instrumentations = getNodeAutoInstrumentations();
|
|
|
|
assert.deepStrictEqual(
|
|
new Set(instrumentations.map(i => i.instrumentationName)),
|
|
new Set([
|
|
'@tachybase/opentelemetry-instrumentation-http',
|
|
'@opentelemetry/instrumentation-aws-sdk',
|
|
'@opentelemetry/instrumentation-nestjs-core',
|
|
])
|
|
);
|
|
} finally {
|
|
delete process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS;
|
|
}
|
|
});
|
|
|
|
it('should include all instrumentations except those disabled via OTEL_NODE_DISABLED_INSTRUMENTATIONS environment variable', () => {
|
|
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS =
|
|
'fs,aws-sdk, aws-lambda'; // separator with and without whitespaces should be allowed
|
|
try {
|
|
const instrumentations = getNodeAutoInstrumentations();
|
|
const disabledInstrumentations = new Set([
|
|
'@opentelemetry/instrumentation-fs',
|
|
'@opentelemetry/instrumentation-aws-sdk',
|
|
'@opentelemetry/instrumentation-aws-lambda',
|
|
]);
|
|
const enabledInstrumentationNames = new Set(
|
|
instrumentations.map(i => i.instrumentationName)
|
|
);
|
|
|
|
for (const disabledInstrumentation of disabledInstrumentations) {
|
|
assert.strictEqual(
|
|
enabledInstrumentationNames.has(disabledInstrumentation),
|
|
false
|
|
);
|
|
}
|
|
} finally {
|
|
delete process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS;
|
|
}
|
|
});
|
|
|
|
it('should disable any instrumentations from OTEL_NODE_ENABLED_INSTRUMENTATIONS if set in OTEL_NODE_DISABLED_INSTRUMENTATIONS', () => {
|
|
process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS = 'http,express,net';
|
|
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS = 'fs,net'; // fs is no-op here, already disabled
|
|
try {
|
|
const instrumentations = getNodeAutoInstrumentations();
|
|
|
|
assert.deepStrictEqual(
|
|
new Set(instrumentations.map(i => i.instrumentationName)),
|
|
new Set([
|
|
'@tachybase/opentelemetry-instrumentation-http',
|
|
'@opentelemetry/instrumentation-express',
|
|
])
|
|
);
|
|
} finally {
|
|
delete process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS;
|
|
delete process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS;
|
|
}
|
|
});
|
|
|
|
it('should show error for none existing instrumentation', () => {
|
|
const spy = sinon.stub(diag, 'error');
|
|
const name = '@tachybase/opentelemetry-instrumentation-http2';
|
|
const instrumentations = getNodeAutoInstrumentations({
|
|
// @ts-expect-error verify that wrong name works
|
|
[name]: {
|
|
enabled: false,
|
|
},
|
|
});
|
|
const instrumentation = instrumentations.find(
|
|
instr => instr.instrumentationName === name
|
|
);
|
|
assert.strictEqual(instrumentation, undefined);
|
|
|
|
assert.strictEqual(
|
|
spy.args[0][0],
|
|
`Provided instrumentation name "${name}" not found`
|
|
);
|
|
|
|
spy.restore();
|
|
});
|
|
});
|
|
|
|
describe('getResourceDetectorsFromEnv', () => {
|
|
it('should return all resource detectors by default', () => {
|
|
assert.equal(getResourceDetectorsFromEnv().length, 16);
|
|
});
|
|
|
|
it('should return all resource detectors when OTEL_NODE_RESOURCE_DETECTORS contains "all"', () => {
|
|
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'all';
|
|
assert.equal(getResourceDetectorsFromEnv().length, 16);
|
|
|
|
delete process.env.OTEL_NODE_RESOURCE_DETECTORS;
|
|
});
|
|
|
|
it('should return specific resource detectors depending on OTEL_NODE_RESOURCE_DETECTORS', () => {
|
|
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'env,host,serviceinstance';
|
|
|
|
const resourceDetectors = getResourceDetectorsFromEnv();
|
|
|
|
assert.equal(resourceDetectors.length, 3);
|
|
assert.equal(resourceDetectors[0].constructor.name, 'EnvDetectorSync');
|
|
assert.equal(resourceDetectors[1].constructor.name, 'HostDetectorSync');
|
|
assert.equal(
|
|
resourceDetectors[2].constructor.name,
|
|
'ServiceInstanceIdDetectorSync'
|
|
);
|
|
|
|
delete process.env.OTEL_NODE_RESOURCE_DETECTORS;
|
|
});
|
|
|
|
it('should return no resource detectors when OTEL_NODE_RESOURCE_DETECTORS contains "none" or a typo', () => {
|
|
const spy = sinon.stub(diag, 'error');
|
|
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'none';
|
|
|
|
assert.equal(getResourceDetectorsFromEnv().length, 0);
|
|
|
|
assert.strictEqual(spy.callCount, 0);
|
|
|
|
process.env.OTEL_NODE_RESOURCE_DETECTORS = 'test';
|
|
|
|
assert.equal(getResourceDetectorsFromEnv().length, 0);
|
|
|
|
assert.strictEqual(
|
|
spy.args[0][0],
|
|
'Invalid resource detector "test" specified in the environment variable OTEL_NODE_RESOURCE_DETECTORS'
|
|
);
|
|
|
|
spy.restore();
|
|
delete process.env.OTEL_NODE_RESOURCE_DETECTORS;
|
|
});
|
|
});
|
|
});
|