feat(metapackage): copy official metapackage
last commit in official: 0e96b2acdb
This commit is contained in:
parent
e05fa1cf0f
commit
094e4d5813
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"Metapackage",
|
||||
"Tachy",
|
||||
"tachybase"
|
||||
]
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
# opentelemetry-instrumentation-tachybase
|
||||
# opentelemetry-auto-instrumentations
|
||||
|
||||
TachyBase 专属的 OpenTelemetry 插桩库
|
||||
TachyBase 专属的 OpenTelemetry 自动插桩库
|
||||
|
105
package.json
Normal file
105
package.json
Normal file
@ -0,0 +1,105 @@
|
||||
{
|
||||
"name": "@tachybase/opentelemetry-auto-instrumentations",
|
||||
"version": "0.0.1",
|
||||
"description": "Metapackage of telemetry for TachyBase which bundles OpenTelemetry node core and instrumentations",
|
||||
"author": "TachyBase Team",
|
||||
"homepage": "https://git.daoyoucloud.com/TomyJan/opentelemetry-auto-instrumentations",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"main": "build/src/index.js",
|
||||
"types": "build/src/index.d.ts",
|
||||
"exports": {
|
||||
".": "./build/src/index.js",
|
||||
"./register": "./build/src/register.js"
|
||||
},
|
||||
"repository": "https://git.daoyoucloud.com/TomyJan/opentelemetry-auto-instrumentations",
|
||||
"scripts": {
|
||||
"clean": "rimraf build/*",
|
||||
"compile": "tsc -p .",
|
||||
"lint": "eslint . --ext .ts",
|
||||
"lint:fix": "eslint . --ext .ts --fix",
|
||||
"precompile": "tsc --version && lerna run version:update --scope @opentelemetry/auto-instrumentations-node --include-dependencies",
|
||||
"prewatch": "npm run precompile",
|
||||
"prepublishOnly": "npm run compile",
|
||||
"tdd": "yarn test -- --watch-extensions ts --watch",
|
||||
"test": "nyc ts-mocha -p tsconfig.json 'test/**/*.ts'",
|
||||
"watch": "tsc -w"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://git.daoyoucloud.com/TomyJan/opentelemetry-auto-instrumentations/issues"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "^1.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opentelemetry/api": "^1.4.1",
|
||||
"@types/mocha": "7.0.2",
|
||||
"@types/node": "18.6.5",
|
||||
"@types/sinon": "10.0.18",
|
||||
"mocha": "7.2.0",
|
||||
"nyc": "15.1.0",
|
||||
"rimraf": "5.0.5",
|
||||
"sinon": "15.2.0",
|
||||
"ts-mocha": "10.0.0",
|
||||
"typescript": "4.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentelemetry/instrumentation": "^0.52.0",
|
||||
"@opentelemetry/instrumentation-amqplib": "^0.40.0",
|
||||
"@opentelemetry/instrumentation-aws-lambda": "^0.43.0",
|
||||
"@opentelemetry/instrumentation-aws-sdk": "^0.43.1",
|
||||
"@opentelemetry/instrumentation-bunyan": "^0.40.0",
|
||||
"@opentelemetry/instrumentation-cassandra-driver": "^0.40.0",
|
||||
"@opentelemetry/instrumentation-connect": "^0.38.0",
|
||||
"@opentelemetry/instrumentation-cucumber": "^0.8.0",
|
||||
"@opentelemetry/instrumentation-dataloader": "^0.11.0",
|
||||
"@opentelemetry/instrumentation-dns": "^0.38.0",
|
||||
"@opentelemetry/instrumentation-express": "^0.41.1",
|
||||
"@opentelemetry/instrumentation-fastify": "^0.38.0",
|
||||
"@opentelemetry/instrumentation-fs": "^0.14.0",
|
||||
"@opentelemetry/instrumentation-generic-pool": "^0.38.0",
|
||||
"@opentelemetry/instrumentation-graphql": "^0.42.0",
|
||||
"@opentelemetry/instrumentation-grpc": "^0.52.0",
|
||||
"@opentelemetry/instrumentation-hapi": "^0.40.0",
|
||||
"@opentelemetry/instrumentation-http": "^0.52.0",
|
||||
"@opentelemetry/instrumentation-ioredis": "^0.42.0",
|
||||
"@opentelemetry/instrumentation-kafkajs": "^0.2.0",
|
||||
"@opentelemetry/instrumentation-knex": "^0.39.0",
|
||||
"@opentelemetry/instrumentation-koa": "^0.42.0",
|
||||
"@opentelemetry/instrumentation-lru-memoizer": "^0.39.0",
|
||||
"@opentelemetry/instrumentation-memcached": "^0.38.0",
|
||||
"@opentelemetry/instrumentation-mongodb": "^0.46.0",
|
||||
"@opentelemetry/instrumentation-mongoose": "^0.40.0",
|
||||
"@opentelemetry/instrumentation-mysql": "^0.40.0",
|
||||
"@opentelemetry/instrumentation-mysql2": "^0.40.0",
|
||||
"@opentelemetry/instrumentation-nestjs-core": "^0.39.0",
|
||||
"@opentelemetry/instrumentation-net": "^0.38.0",
|
||||
"@opentelemetry/instrumentation-pg": "^0.43.0",
|
||||
"@opentelemetry/instrumentation-pino": "^0.41.0",
|
||||
"@opentelemetry/instrumentation-redis": "^0.41.0",
|
||||
"@opentelemetry/instrumentation-redis-4": "^0.41.0",
|
||||
"@opentelemetry/instrumentation-restify": "^0.40.0",
|
||||
"@opentelemetry/instrumentation-router": "^0.39.0",
|
||||
"@opentelemetry/instrumentation-socket.io": "^0.41.0",
|
||||
"@opentelemetry/instrumentation-tedious": "^0.12.0",
|
||||
"@opentelemetry/instrumentation-undici": "^0.4.0",
|
||||
"@opentelemetry/instrumentation-winston": "^0.39.0",
|
||||
"@opentelemetry/resource-detector-alibaba-cloud": "^0.28.10",
|
||||
"@opentelemetry/resource-detector-aws": "^1.5.2",
|
||||
"@opentelemetry/resource-detector-azure": "^0.2.9",
|
||||
"@opentelemetry/resource-detector-container": "^0.3.11",
|
||||
"@opentelemetry/resource-detector-gcp": "^0.29.10",
|
||||
"@opentelemetry/resources": "^1.24.0",
|
||||
"@opentelemetry/sdk-node": "^0.52.0"
|
||||
},
|
||||
"files": [
|
||||
"build/src/**/*.js",
|
||||
"build/src/**/*.js.map",
|
||||
"build/src/**/*.d.ts"
|
||||
]
|
||||
}
|
21
src/index.ts
Normal file
21
src/index.ts
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
getNodeAutoInstrumentations,
|
||||
getResourceDetectorsFromEnv as getResourceDetectors,
|
||||
InstrumentationConfigMap,
|
||||
} from './utils';
|
48
src/register.ts
Normal file
48
src/register.ts
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 opentelemetry from '@opentelemetry/sdk-node';
|
||||
import { diag, DiagConsoleLogger } from '@opentelemetry/api';
|
||||
import {
|
||||
getNodeAutoInstrumentations,
|
||||
getResourceDetectorsFromEnv,
|
||||
} from './utils';
|
||||
|
||||
diag.setLogger(
|
||||
new DiagConsoleLogger(),
|
||||
opentelemetry.core.getEnv().OTEL_LOG_LEVEL
|
||||
);
|
||||
|
||||
const sdk = new opentelemetry.NodeSDK({
|
||||
instrumentations: getNodeAutoInstrumentations(),
|
||||
resourceDetectors: getResourceDetectorsFromEnv(),
|
||||
});
|
||||
|
||||
try {
|
||||
sdk.start();
|
||||
diag.info('OpenTelemetry automatic instrumentation started successfully');
|
||||
} catch (error) {
|
||||
diag.error(
|
||||
'Error initializing OpenTelemetry SDK. Your application is not instrumented and will not produce telemetry',
|
||||
error
|
||||
);
|
||||
}
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
sdk
|
||||
.shutdown()
|
||||
.then(() => diag.debug('OpenTelemetry SDK terminated'))
|
||||
.catch(error => diag.error('Error terminating OpenTelemetry SDK', error));
|
||||
});
|
286
src/utils.ts
Normal file
286
src/utils.ts
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* 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 { Instrumentation } from '@opentelemetry/instrumentation';
|
||||
|
||||
import { AmqplibInstrumentation } from '@opentelemetry/instrumentation-amqplib';
|
||||
import { AwsLambdaInstrumentation } from '@opentelemetry/instrumentation-aws-lambda';
|
||||
import { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk';
|
||||
import { BunyanInstrumentation } from '@opentelemetry/instrumentation-bunyan';
|
||||
import { CassandraDriverInstrumentation } from '@opentelemetry/instrumentation-cassandra-driver';
|
||||
import { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect';
|
||||
import { CucumberInstrumentation } from '@opentelemetry/instrumentation-cucumber';
|
||||
import { DataloaderInstrumentation } from '@opentelemetry/instrumentation-dataloader';
|
||||
import { DnsInstrumentation } from '@opentelemetry/instrumentation-dns';
|
||||
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
|
||||
import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify';
|
||||
import { FsInstrumentation } from '@opentelemetry/instrumentation-fs';
|
||||
import { GenericPoolInstrumentation } from '@opentelemetry/instrumentation-generic-pool';
|
||||
import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';
|
||||
import { GrpcInstrumentation } from '@opentelemetry/instrumentation-grpc';
|
||||
import { HapiInstrumentation } from '@opentelemetry/instrumentation-hapi';
|
||||
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
|
||||
import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';
|
||||
import { KafkaJsInstrumentation } from '@opentelemetry/instrumentation-kafkajs';
|
||||
import { KnexInstrumentation } from '@opentelemetry/instrumentation-knex';
|
||||
import { KoaInstrumentation } from '@opentelemetry/instrumentation-koa';
|
||||
import { LruMemoizerInstrumentation } from '@opentelemetry/instrumentation-lru-memoizer';
|
||||
import { MemcachedInstrumentation } from '@opentelemetry/instrumentation-memcached';
|
||||
import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb';
|
||||
import { MongooseInstrumentation } from '@opentelemetry/instrumentation-mongoose';
|
||||
import { MySQL2Instrumentation } from '@opentelemetry/instrumentation-mysql2';
|
||||
import { MySQLInstrumentation } from '@opentelemetry/instrumentation-mysql';
|
||||
import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core';
|
||||
import { NetInstrumentation } from '@opentelemetry/instrumentation-net';
|
||||
import { PgInstrumentation } from '@opentelemetry/instrumentation-pg';
|
||||
import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino';
|
||||
import { RedisInstrumentation as RedisInstrumentationV2 } from '@opentelemetry/instrumentation-redis';
|
||||
import { RedisInstrumentation as RedisInstrumentationV4 } from '@opentelemetry/instrumentation-redis-4';
|
||||
import { RestifyInstrumentation } from '@opentelemetry/instrumentation-restify';
|
||||
import { RouterInstrumentation } from '@opentelemetry/instrumentation-router';
|
||||
import { SocketIoInstrumentation } from '@opentelemetry/instrumentation-socket.io';
|
||||
import { TediousInstrumentation } from '@opentelemetry/instrumentation-tedious';
|
||||
import { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici';
|
||||
import { WinstonInstrumentation } from '@opentelemetry/instrumentation-winston';
|
||||
|
||||
import { alibabaCloudEcsDetector } from '@opentelemetry/resource-detector-alibaba-cloud';
|
||||
import {
|
||||
awsBeanstalkDetector,
|
||||
awsEc2Detector,
|
||||
awsEcsDetector,
|
||||
awsEksDetector,
|
||||
awsLambdaDetector,
|
||||
} from '@opentelemetry/resource-detector-aws';
|
||||
import { containerDetector } from '@opentelemetry/resource-detector-container';
|
||||
import { gcpDetector } from '@opentelemetry/resource-detector-gcp';
|
||||
import {
|
||||
Detector,
|
||||
DetectorSync,
|
||||
envDetectorSync,
|
||||
hostDetectorSync,
|
||||
osDetectorSync,
|
||||
processDetectorSync,
|
||||
serviceInstanceIdDetectorSync,
|
||||
} from '@opentelemetry/resources';
|
||||
import {
|
||||
azureAppServiceDetector,
|
||||
azureFunctionsDetector,
|
||||
azureVmDetector,
|
||||
} from '@opentelemetry/resource-detector-azure';
|
||||
|
||||
const RESOURCE_DETECTOR_CONTAINER = 'container';
|
||||
const RESOURCE_DETECTOR_ENVIRONMENT = 'env';
|
||||
const RESOURCE_DETECTOR_HOST = 'host';
|
||||
const RESOURCE_DETECTOR_OS = 'os';
|
||||
const RESOURCE_DETECTOR_SERVICE_INSTANCE_ID = 'serviceinstance';
|
||||
const RESOURCE_DETECTOR_PROCESS = 'process';
|
||||
const RESOURCE_DETECTOR_ALIBABA = 'alibaba';
|
||||
const RESOURCE_DETECTOR_AWS = 'aws';
|
||||
const RESOURCE_DETECTOR_AZURE = 'azure';
|
||||
const RESOURCE_DETECTOR_GCP = 'gcp';
|
||||
|
||||
const InstrumentationMap = {
|
||||
'@opentelemetry/instrumentation-amqplib': AmqplibInstrumentation,
|
||||
'@opentelemetry/instrumentation-aws-lambda': AwsLambdaInstrumentation,
|
||||
'@opentelemetry/instrumentation-aws-sdk': AwsInstrumentation,
|
||||
'@opentelemetry/instrumentation-bunyan': BunyanInstrumentation,
|
||||
'@opentelemetry/instrumentation-cassandra-driver':
|
||||
CassandraDriverInstrumentation,
|
||||
'@opentelemetry/instrumentation-connect': ConnectInstrumentation,
|
||||
'@opentelemetry/instrumentation-cucumber': CucumberInstrumentation,
|
||||
'@opentelemetry/instrumentation-dataloader': DataloaderInstrumentation,
|
||||
'@opentelemetry/instrumentation-dns': DnsInstrumentation,
|
||||
'@opentelemetry/instrumentation-express': ExpressInstrumentation,
|
||||
'@opentelemetry/instrumentation-fastify': FastifyInstrumentation,
|
||||
'@opentelemetry/instrumentation-fs': FsInstrumentation,
|
||||
'@opentelemetry/instrumentation-generic-pool': GenericPoolInstrumentation,
|
||||
'@opentelemetry/instrumentation-graphql': GraphQLInstrumentation,
|
||||
'@opentelemetry/instrumentation-grpc': GrpcInstrumentation,
|
||||
'@opentelemetry/instrumentation-hapi': HapiInstrumentation,
|
||||
'@opentelemetry/instrumentation-http': HttpInstrumentation,
|
||||
'@opentelemetry/instrumentation-ioredis': IORedisInstrumentation,
|
||||
'@opentelemetry/instrumentation-kafkajs': KafkaJsInstrumentation,
|
||||
'@opentelemetry/instrumentation-knex': KnexInstrumentation,
|
||||
'@opentelemetry/instrumentation-koa': KoaInstrumentation,
|
||||
'@opentelemetry/instrumentation-lru-memoizer': LruMemoizerInstrumentation,
|
||||
'@opentelemetry/instrumentation-memcached': MemcachedInstrumentation,
|
||||
'@opentelemetry/instrumentation-mongodb': MongoDBInstrumentation,
|
||||
'@opentelemetry/instrumentation-mongoose': MongooseInstrumentation,
|
||||
'@opentelemetry/instrumentation-mysql2': MySQL2Instrumentation,
|
||||
'@opentelemetry/instrumentation-mysql': MySQLInstrumentation,
|
||||
'@opentelemetry/instrumentation-nestjs-core': NestInstrumentation,
|
||||
'@opentelemetry/instrumentation-net': NetInstrumentation,
|
||||
'@opentelemetry/instrumentation-pg': PgInstrumentation,
|
||||
'@opentelemetry/instrumentation-pino': PinoInstrumentation,
|
||||
'@opentelemetry/instrumentation-redis': RedisInstrumentationV2,
|
||||
'@opentelemetry/instrumentation-redis-4': RedisInstrumentationV4,
|
||||
'@opentelemetry/instrumentation-restify': RestifyInstrumentation,
|
||||
'@opentelemetry/instrumentation-router': RouterInstrumentation,
|
||||
'@opentelemetry/instrumentation-socket.io': SocketIoInstrumentation,
|
||||
'@opentelemetry/instrumentation-tedious': TediousInstrumentation,
|
||||
'@opentelemetry/instrumentation-undici': UndiciInstrumentation,
|
||||
'@opentelemetry/instrumentation-winston': WinstonInstrumentation,
|
||||
};
|
||||
|
||||
// Config types inferred automatically from the first argument of the constructor
|
||||
type ConfigArg<T> = T extends new (...args: infer U) => unknown ? U[0] : never;
|
||||
export type InstrumentationConfigMap = {
|
||||
[Name in keyof typeof InstrumentationMap]?: ConfigArg<
|
||||
(typeof InstrumentationMap)[Name]
|
||||
>;
|
||||
};
|
||||
|
||||
export function getNodeAutoInstrumentations(
|
||||
inputConfigs: InstrumentationConfigMap = {}
|
||||
): Instrumentation[] {
|
||||
checkManuallyProvidedInstrumentationNames(Object.keys(inputConfigs));
|
||||
const enabledInstrumentationsFromEnv = getEnabledInstrumentationsFromEnv();
|
||||
const disabledInstrumentationsFromEnv = getDisabledInstrumentationsFromEnv();
|
||||
|
||||
const instrumentations: Instrumentation[] = [];
|
||||
|
||||
for (const name of Object.keys(InstrumentationMap) as Array<
|
||||
keyof typeof InstrumentationMap
|
||||
>) {
|
||||
const Instance = InstrumentationMap[name];
|
||||
// Defaults are defined by the instrumentation itself
|
||||
const userConfig: any = inputConfigs[name] ?? {};
|
||||
|
||||
if (
|
||||
userConfig.enabled === false ||
|
||||
!enabledInstrumentationsFromEnv.includes(name) ||
|
||||
disabledInstrumentationsFromEnv.includes(name)
|
||||
) {
|
||||
diag.debug(`Disabling instrumentation for ${name}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
diag.debug(`Loading instrumentation for ${name}`);
|
||||
instrumentations.push(new Instance(userConfig));
|
||||
} catch (e: any) {
|
||||
diag.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return instrumentations;
|
||||
}
|
||||
|
||||
function checkManuallyProvidedInstrumentationNames(
|
||||
manuallyProvidedInstrumentationNames: string[]
|
||||
) {
|
||||
for (const name of manuallyProvidedInstrumentationNames) {
|
||||
if (!Object.prototype.hasOwnProperty.call(InstrumentationMap, name)) {
|
||||
diag.error(`Provided instrumentation name "${name}" not found`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getInstrumentationsFromEnv(envVar: string): string[] {
|
||||
const envVarValue = process.env[envVar];
|
||||
if (envVarValue == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const instrumentationsFromEnv = envVarValue
|
||||
?.split(',')
|
||||
.map(
|
||||
instrumentationPkgSuffix =>
|
||||
`@opentelemetry/instrumentation-${instrumentationPkgSuffix.trim()}`
|
||||
);
|
||||
checkManuallyProvidedInstrumentationNames(instrumentationsFromEnv);
|
||||
return instrumentationsFromEnv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of instrumentations that are enabled based on the environment variable.
|
||||
*/
|
||||
function getEnabledInstrumentationsFromEnv() {
|
||||
if (!process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS) {
|
||||
return Object.keys(InstrumentationMap);
|
||||
}
|
||||
|
||||
const instrumentationsFromEnv = getInstrumentationsFromEnv(
|
||||
'OTEL_NODE_ENABLED_INSTRUMENTATIONS'
|
||||
);
|
||||
return instrumentationsFromEnv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of instrumentations that are disabled based on the environment variable.
|
||||
*/
|
||||
function getDisabledInstrumentationsFromEnv() {
|
||||
if (!process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const instrumentationsFromEnv = getInstrumentationsFromEnv(
|
||||
'OTEL_NODE_DISABLED_INSTRUMENTATIONS'
|
||||
);
|
||||
return instrumentationsFromEnv;
|
||||
}
|
||||
|
||||
export function getResourceDetectorsFromEnv(): Array<Detector | DetectorSync> {
|
||||
const resourceDetectors = new Map<
|
||||
string,
|
||||
Detector | DetectorSync | Detector[] | DetectorSync[]
|
||||
>([
|
||||
[RESOURCE_DETECTOR_CONTAINER, containerDetector],
|
||||
[RESOURCE_DETECTOR_ENVIRONMENT, envDetectorSync],
|
||||
[RESOURCE_DETECTOR_HOST, hostDetectorSync],
|
||||
[RESOURCE_DETECTOR_OS, osDetectorSync],
|
||||
[RESOURCE_DETECTOR_SERVICE_INSTANCE_ID, serviceInstanceIdDetectorSync],
|
||||
[RESOURCE_DETECTOR_PROCESS, processDetectorSync],
|
||||
[RESOURCE_DETECTOR_ALIBABA, alibabaCloudEcsDetector],
|
||||
[RESOURCE_DETECTOR_GCP, gcpDetector],
|
||||
[
|
||||
RESOURCE_DETECTOR_AWS,
|
||||
[
|
||||
awsEc2Detector,
|
||||
awsEcsDetector,
|
||||
awsEksDetector,
|
||||
awsBeanstalkDetector,
|
||||
awsLambdaDetector,
|
||||
],
|
||||
],
|
||||
[
|
||||
RESOURCE_DETECTOR_AZURE,
|
||||
[azureAppServiceDetector, azureFunctionsDetector, azureVmDetector],
|
||||
],
|
||||
]);
|
||||
|
||||
const resourceDetectorsFromEnv =
|
||||
process.env.OTEL_NODE_RESOURCE_DETECTORS?.split(',') ?? ['all'];
|
||||
|
||||
if (resourceDetectorsFromEnv.includes('all')) {
|
||||
return [...resourceDetectors.values()].flat();
|
||||
}
|
||||
|
||||
if (resourceDetectorsFromEnv.includes('none')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return resourceDetectorsFromEnv.flatMap(detector => {
|
||||
const resourceDetector = resourceDetectors.get(detector);
|
||||
if (!resourceDetector) {
|
||||
diag.error(
|
||||
`Invalid resource detector "${detector}" specified in the environment variable OTEL_NODE_RESOURCE_DETECTORS`
|
||||
);
|
||||
}
|
||||
return resourceDetector || [];
|
||||
});
|
||||
}
|
55
test/register.test.ts
Normal file
55
test/register.test.ts
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 { spawnSync } from 'child_process';
|
||||
import * as assert from 'assert';
|
||||
|
||||
describe('Register', function () {
|
||||
it('can load auto instrumentation from command line', () => {
|
||||
const proc = spawnSync(
|
||||
process.execPath,
|
||||
['--require', '../build/src/register.js', './test-app/app.js'],
|
||||
{
|
||||
cwd: __dirname,
|
||||
timeout: 5000,
|
||||
killSignal: 'SIGKILL', // SIGTERM is not sufficient to terminate some hangs
|
||||
env: Object.assign({}, process.env, {
|
||||
OTEL_NODE_RESOURCE_DETECTORS: 'none',
|
||||
OTEL_TRACES_EXPORTER: 'console',
|
||||
// nx (used by lerna run) defaults `FORCE_COLOR=true`, which in
|
||||
// node v18.17.0, v20.3.0 and later results in ANSI color escapes
|
||||
// in the ConsoleSpanExporter output that is checked below.
|
||||
FORCE_COLOR: '0',
|
||||
}),
|
||||
}
|
||||
);
|
||||
assert.ifError(proc.error);
|
||||
assert.equal(proc.status, 0, `proc.status (${proc.status})`);
|
||||
assert.equal(proc.signal, null, `proc.signal (${proc.signal})`);
|
||||
|
||||
assert.ok(
|
||||
proc.stdout.includes(
|
||||
'OpenTelemetry automatic instrumentation started successfully'
|
||||
)
|
||||
);
|
||||
|
||||
// Check a span has been generated for the GET request done in app.js
|
||||
assert.ok(
|
||||
proc.stdout.includes("name: 'GET'"),
|
||||
'console span output in stdout'
|
||||
);
|
||||
});
|
||||
});
|
29
test/test-app/app.js
Normal file
29
test/test-app/app.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//Used in register.test.ts to mimic a JS app.
|
||||
const http = require('http');
|
||||
|
||||
const options = {
|
||||
hostname: 'example.com',
|
||||
port: 80,
|
||||
path: '/',
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
const req = http.request(options);
|
||||
|
||||
req.end();
|
208
test/utils.test.ts
Normal file
208
test/utils.test.ts
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 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 '@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({
|
||||
'@opentelemetry/instrumentation-http': {
|
||||
applyCustomAttributesOnSpan,
|
||||
},
|
||||
});
|
||||
const instrumentation = instrumentations.find(
|
||||
instr =>
|
||||
instr.instrumentationName === '@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([
|
||||
'@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([
|
||||
'@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 = '@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;
|
||||
});
|
||||
});
|
||||
});
|
26
tsconfig.base.json
Normal file
26
tsconfig.base.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowUnreachableCode": false,
|
||||
"allowUnusedLabels": false,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"inlineSources": true,
|
||||
"module": "commonjs",
|
||||
"noEmitOnError": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"pretty": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"target": "es2017",
|
||||
"incremental": true,
|
||||
"newLine": "LF"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "build"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"test/**/*.ts"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user