Merge branch 'main' into next-main-2024-09-23

This commit is contained in:
Marc Pichler 2024-09-23 16:27:31 +02:00
commit f4d0dcf45d
144 changed files with 10690 additions and 10764 deletions

View File

@ -43,8 +43,9 @@ jobs:
export NODE_OPTIONS=--openssl-legacy-provider
npm run test
- name: Report Coverage
run: npm run codecov
if: ${{ matrix.node_version == '18' }}
uses: codecov/codecov-action@v4
with:
verbose: true
node-windows-tests:
runs-on: windows-latest
env:
@ -98,7 +99,9 @@ jobs:
- name: Unit tests
run: npm run test:browser
- name: Report Coverage
run: npm run codecov:browser
uses: codecov/codecov-action@v4
with:
verbose: true
webworker-tests:
runs-on: ubuntu-latest
env:
@ -122,7 +125,9 @@ jobs:
- name: Unit tests
run: npm run test:webworker
- name: Report Coverage
run: npm run codecov:webworker
uses: codecov/codecov-action@v4
with:
verbose: true
api-eol-node-test:
strategy:
fail-fast: false

1
.nycrc
View File

@ -3,6 +3,7 @@
"extension": [
".ts"
],
"reporter": ["text", "json"],
"exclude": [
"**/*.d.ts",
"build/**/*.*",

View File

@ -17,6 +17,21 @@ For semantic convention package changes, see the [semconv CHANGELOG](packages/se
### :rocket: (Enhancement)
* feat: add processors for adding session.id attribute to spans and logs [#4972](https://github.com/open-telemetry/opentelemetry-js/pull/4972)
### :bug: (Bug Fix)
### :books: (Refine Doc)
### :house: (Internal)
* deps: set `@opentelemetry/api` dependency min version to 1.3.0 in `examples`, `experimental/packages`, `integration-tests` and `selenium-tests`
[#4992](https://github.com/open-telemetry/opentelemetry-js/pull/4992)
## 1.26.0
### :rocket: (Enhancement)
* feat: include instrumentation scope info in console span and log record exporters [#4848](https://github.com/open-telemetry/opentelemetry-js/pull/4848) @blumamir
* feat(semconv): update semantic conventions to 1.27 (from 1.7.0) [#4690](https://github.com/open-telemetry/opentelemetry-js/pull/4690) @dyladan
* Exported names have changed to `ATTR_{name}` for attributes (e.g. `ATTR_HTTP_REQUEST_METHOD`), `{name}_VALUE_{value}` for enumeration values (e.g. `HTTP_REQUEST_METHOD_VALUE_POST`), and `METRIC_{name}` for metrics. Exported names from previous versions are deprecated.
@ -28,8 +43,7 @@ For semantic convention package changes, see the [semconv CHANGELOG](packages/se
* fix(sdk-node): avoid spurious diag errors for unknown OTEL_NODE_RESOURCE_DETECTORS values [#4879](https://github.com/open-telemetry/opentelemetry-js/pull/4879) @trentm
* deps(opentelemetry-instrumentation): Bump `shimmer` types to 1.2.0 [#4865](https://github.com/open-telemetry/opentelemetry-js/pull/4865) @lforst
* fix(instrumentation): Fix optional property types [#4833](https://github.com/open-telemetry/opentelemetry-js/pull/4833) @alecmev
### :books: (Refine Doc)
* fix(sdk-metrics): fix(sdk-metrics): use inclusive upper bounds in histogram [#4829](https://github.com/open-telemetry/opentelemetry-js/pull/4829)
### :house: (Internal)

View File

@ -29,9 +29,6 @@
"repository": "open-telemetry/opentelemetry-js",
"scripts": {
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../",
"codecov:webworker": "nyc report --reporter=json && codecov -f coverage/*.json -p ../",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"docs": "typedoc",
@ -86,7 +83,6 @@
"@types/webpack": "5.28.5",
"@types/webpack-env": "1.16.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"dpdm": "3.13.1",
"karma": "6.4.4",
@ -104,7 +100,7 @@
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"unionfs": "4.5.4",
"webpack": "5.89.0"
"webpack": "5.94.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/api",
"sideEffects": false

View File

@ -88,9 +88,10 @@ describe('tree-shaking', () => {
const fs = new Union();
fs.use(mfs as any).use(realFs);
//direct webpack to use unionfs for file input
compiler.inputFileSystem = fs;
//direct webpack to output to memoryfs rather than to disk
// direct webpack to use unionfs for file input
// needs workaround from https://github.com/webpack/webpack/issues/18242#issuecomment-2018116985 since webpack 5.91.0
compiler.inputFileSystem = fs as any as typeof compiler.inputFileSystem;
// direct webpack to output to memoryfs rather than to disk
compiler.outputFileSystem = {
...mfs,
join: path.join,

131
doc/esm-support.md Normal file
View File

@ -0,0 +1,131 @@
# ECMAScript Modules vs. CommonJS
Node.js uses a different module loader for ECMAScript Modules (ESM) vs. CommonJS (CJS).
To verify whether your application is ESM or CJS, refer to [Node.js docs for Determining Module System](https://nodejs.org/api/packages.html#determining-module-system).
An `.mjs` extension or `type:module` in the built app's `package.json` indicates the app is ESM.
**Much of OpenTelemetry JS documentation is written assuming the compiled application is run as CJS.**
ESM support is ongoing; a few adjustments are needed for configuration and startup commands.
For more explanation about CJS and ESM, see the [Node.js docs](https://nodejs.org/api/modules.html#enabling).
## TypeScript
Many TypeScript projects today are written using ESM syntax, regardless of how they are compiled.
In the `tsconfig.json`, there is an option to compile to ESM or CJS.
If the compiled code is ESM, those import statements will remain the same (e.g. `import { foo } from 'bar';`).
If the compiled code is CJS, those import statements will become `require()` statements (e.g. `const { foo } = require('bar');`)
## Initializing the SDK
Instrumentation setup and configuration must be run before your application code.
If the SDK is initialized in a separate file (recommended), ensure it is imported first in application startup, or use the `--require` or `--import` flag during startup to preload the module.
For CJS, the `NODE_OPTIONS` for the startup command should include `--require ./telemetry.js`.
For ESM, minimum Node.js version of `18.19.0` is required.
The `NODE_OPTIONS` for the startup command should include `--import ./telemetry.js`.
## Instrumentation Hook Required for ESM
If your application is written in JavaScript as ESM, or compiled to ESM from TypeScript, then a loader hook is required to properly patch instrumentation.
The custom hook for ESM instrumentation is `--experimental-loader=@opentelemetry/instrumentation/hook.mjs`.
This flag must be passed to the `node` binary, which is often done as a startup command and/or in the `NODE_OPTIONS` environment variable.
### Additional Notes on Experimental Loaders
Though the OpenTelemetry loader currently relies on `import-in-the-middle`, direct usage of `import-in-the-middle/hook.mjs` may cease to work in the future.
The only currently supported loader hook is `@opentelemetry/instrumentation/hook.mjs`.
**Note:** Eventually the recommendation for how to setup OpenTelemetry for usage with ESM will change to no longer require `--experimental-loader=@opentelemetry/instrumentation/hook.mjs`.
Instead the bootstrap code (in `./telemetry.js`) will use Node.js's newer `module.register(...)`.
Refer to this [issue](https://github.com/open-telemetry/opentelemetry-js/issues/4933) for details.
Because of ongoing issues with loaders running TypeScript code as ESM in development environments, results may vary.
To use `ts-node` to run the uncompiled TypeScript code, the module must be CJS.
To use `tsx` to run the uncompiled TypeScript code as ESM, the `--import` flag must be used.
## Using the Zero Code Option with `auto-instrumentations-node`
The `auto-instrumentations-node` package contains a `register` entry-point that can be used with `--require` or `--import` to setup and start the SDK easily, without application code changes.
For ESM, the package also requires the usage of the loader hook.
Startup command for CJS:
```sh
node --require @opentelemetry/auto-instrumentations-node/register app.js
```
Startup command for ESM:
```sh
node --experimental-loader=@opentelemetry/instrumentation/hook.mjs --import @opentelemetry/auto-instrumentations-node/register app.js
```
## Examples
### Example Written in JavaScript as CJS
```javascript
/*telemetry.cjs*/
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { ConsoleSpanExporter } = require('@opentelemetry/sdk-trace-node');
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const sdk = new NodeSDK({
traceExporter: new ConsoleSpanExporter(),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
```
Startup command:
```sh
node --require ./telemetry.cjs app.js
```
### Example Written in JavaScript as ESM or TypeScript
```typescript
/*telemetry.ts | telemetry.mjs*/
import { NodeSDK } from '@opentelemetry/sdk-node';
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
const sdk = new NodeSDK({
traceExporter: new ConsoleSpanExporter(),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
```
Startup command for compiled CJS:
```sh
node --require ./telemetry.js app.js
```
Startup command for compiled ESM:
```sh
node --experimental-loader=@opentelemetry/instrumentation/hook.mjs --import ./telemetry.js app.js
```
### ESM Options for Different Versions of Node.js
The entire startup command should include the following `NODE_OPTIONS`:
| Node.js Version | NODE_OPTIONS |
| ----------------- | ----------------------------------------------------------------------------------------- |
| 16.x | `--require ./telemetry.cjs --experimental-loader=@opentelemetry/instrumentation/hook.mjs` |
| >=18.1.0 <18.19.0 | `--require ./telemetry.cjs --experimental-loader=@opentelemetry/instrumentation/hook.mjs` |
| ^18.19.0 | `--import ./telemetry.mjs --experimental-loader=@opentelemetry/instrumentation/hook.mjs` |
| 20.x | `--import ./telemetry.mjs --experimental-loader=@opentelemetry/instrumentation/hook.mjs` |
| 22.x | `--import ./telemetry.mjs --experimental-loader=@opentelemetry/instrumentation/hook.mjs` |

View File

@ -24,7 +24,7 @@
"url": "https://github.com/open-telemetry/opentelemetry-js/issues"
},
"dependencies": {
"@opentelemetry/api": "^1.0.2",
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/exporter-jaeger": "0.25.0",
"@opentelemetry/resources": "0.25.0",
"@opentelemetry/semantic-conventions": "^1.22.0",

View File

@ -1,7 +1,7 @@
{
"name": "esm-http-ts",
"private": true,
"version": "0.52.1",
"version": "0.53.0",
"description": "Example of HTTP integration with OpenTelemetry using ESM and TypeScript",
"main": "build/index.js",
"type": "module",
@ -32,12 +32,12 @@
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/",
"dependencies": {
"@opentelemetry/api": "1.9.0",
"@opentelemetry/exporter-trace-otlp-proto": "0.52.1",
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/instrumentation-http": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/sdk-trace-node": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/exporter-trace-otlp-proto": "0.53.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/instrumentation-http": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@opentelemetry/sdk-trace-node": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
}
}

View File

@ -29,7 +29,7 @@
},
"dependencies": {
"@grpc/grpc-js": "^1.3.7",
"@opentelemetry/api": "^1.0.2",
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/exporter-jaeger": "^1.0.1",
"@opentelemetry/exporter-zipkin": "^1.0.1",
"@opentelemetry/instrumentation": "^0.27.0",

View File

@ -1,7 +1,7 @@
{
"name": "http-example",
"private": true,
"version": "0.52.1",
"version": "0.53.0",
"description": "Example of HTTP integration with OpenTelemetry",
"main": "index.js",
"scripts": {
@ -30,14 +30,14 @@
},
"dependencies": {
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/exporter-jaeger": "1.25.1",
"@opentelemetry/exporter-zipkin": "1.25.1",
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/instrumentation-http": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/sdk-trace-node": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/exporter-jaeger": "1.26.0",
"@opentelemetry/exporter-zipkin": "1.26.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/instrumentation-http": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@opentelemetry/sdk-trace-node": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/http",
"devDependencies": {

View File

@ -1,7 +1,7 @@
{
"name": "https-example",
"private": true,
"version": "0.52.1",
"version": "0.53.0",
"description": "Example of HTTPs integration with OpenTelemetry",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -33,15 +33,15 @@
"url": "https://github.com/open-telemetry/opentelemetry-js/issues"
},
"dependencies": {
"@opentelemetry/api": "^1.0.0",
"@opentelemetry/exporter-jaeger": "1.25.1",
"@opentelemetry/exporter-zipkin": "1.25.1",
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/instrumentation-http": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/sdk-trace-node": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/exporter-jaeger": "1.26.0",
"@opentelemetry/exporter-zipkin": "1.26.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/instrumentation-http": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@opentelemetry/sdk-trace-node": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/https",
"devDependencies": {

View File

@ -1,7 +1,7 @@
{
"name": "web-opentelemetry-example",
"private": true,
"version": "0.52.1",
"version": "0.53.0",
"description": "Example of using @opentelemetry/sdk-trace-web and @opentelemetry/sdk-metrics in browser",
"main": "index.js",
"scripts": {
@ -45,20 +45,20 @@
},
"dependencies": {
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/context-zone": "1.25.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/exporter-metrics-otlp-http": "0.52.1",
"@opentelemetry/exporter-trace-otlp-http": "0.52.1",
"@opentelemetry/exporter-trace-otlp-proto": "0.52.1",
"@opentelemetry/exporter-zipkin": "1.25.1",
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/instrumentation-fetch": "0.52.1",
"@opentelemetry/instrumentation-xml-http-request": "0.52.1",
"@opentelemetry/propagator-b3": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/sdk-trace-web": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/context-zone": "1.26.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/exporter-metrics-otlp-http": "0.53.0",
"@opentelemetry/exporter-trace-otlp-http": "0.53.0",
"@opentelemetry/exporter-trace-otlp-proto": "0.53.0",
"@opentelemetry/exporter-zipkin": "1.26.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/instrumentation-fetch": "0.53.0",
"@opentelemetry/instrumentation-xml-http-request": "0.53.0",
"@opentelemetry/propagator-b3": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@opentelemetry/sdk-trace-web": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/tracer-web"
}

View File

@ -30,7 +30,7 @@
"url": "https://github.com/open-telemetry/opentelemetry-js/issues"
},
"dependencies": {
"@opentelemetry/api": "^1.0.2",
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/exporter-jaeger": "0.25.0",
"@opentelemetry/exporter-zipkin": "0.25.0",
"@opentelemetry/instrumentation": "0.25.0",

View File

@ -1,7 +1,7 @@
{
"name": "example-otlp-exporter-node",
"private": true,
"version": "0.52.1",
"version": "0.53.0",
"description": "Example of using @opentelemetry/collector-exporter in Node.js",
"main": "index.js",
"scripts": {
@ -30,17 +30,17 @@
},
"dependencies": {
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/exporter-metrics-otlp-grpc": "0.52.1",
"@opentelemetry/exporter-metrics-otlp-http": "0.52.1",
"@opentelemetry/exporter-metrics-otlp-proto": "0.52.1",
"@opentelemetry/exporter-trace-otlp-grpc": "0.52.1",
"@opentelemetry/exporter-trace-otlp-http": "0.52.1",
"@opentelemetry/exporter-trace-otlp-proto": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "0.53.0",
"@opentelemetry/exporter-metrics-otlp-http": "0.53.0",
"@opentelemetry/exporter-metrics-otlp-proto": "0.53.0",
"@opentelemetry/exporter-trace-otlp-grpc": "0.53.0",
"@opentelemetry/exporter-trace-otlp-http": "0.53.0",
"@opentelemetry/exporter-trace-otlp-proto": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/otlp-exporter-node"
}

View File

@ -7,6 +7,29 @@ All notable changes to experimental packages in this project will be documented
### :boom: Breaking Change
### :rocket: (Enhancement)
* feat(api-logs): Add delegating no-op logger provider [#4861](https://github.com/open-telemetry/opentelemetry-js/pull/4861) @hectorhdzg
* feat(instrumentation-http): Add support for client span semantic conventions 1.27 [#4940](https://github.com/open-telemetry/opentelemetry-js/pull/4940) @dyladan
### :bug: (Bug Fix)
* fix(sampler-jaeger-remote): fixes an issue where package could emit unhandled promise rejections @Just-Sieb
* fix(otlp-grpc-exporter-base): default compression to `'none'` if env vars `OTEL_EXPORTER_OTLP_TRACES_COMPRESSION` and `OTEL_EXPORTER_OTLP_COMPRESSION` are falsy @sjvans
### :books: (Refine Doc)
### :house: (Internal)
* refactor(exporter-prometheus): replace `MetricAttributes` and `MetricAttributeValues` with `Attributes` and `AttributeValues` [#4993](https://github.com/open-telemetry/opentelemetry-js/pull/4993)
* refactor(browser-detector): replace `ResourceAttributes` with `Attributes` [#5004](https://github.com/open-telemetry/opentelemetry-js/pull/5004)
* refactor(sdk-logs): replace `ResourceAttributes` with `Attributes` [#5005](https://github.com/open-telemetry/opentelemetry-js/pull/5005) @david-luna
## 0.53.0
### :boom: Breaking Change
* fix(instrumentation)!:remove unused description property from interface [#4847](https://github.com/open-telemetry/opentelemetry-js/pull/4847) @blumamir
* feat(exporter-*-otlp-*)!: use transport interface in node.js exporters [#4743](https://github.com/open-telemetry/opentelemetry-js/pull/4743) @pichlermarc
* (user-facing) `headers` was intended for internal use has been removed from all exporters
@ -24,15 +47,15 @@ All notable changes to experimental packages in this project will be documented
* feat(otlp-transformer): Do not limit @opentelemetry/api upper range peerDependency [#4816](https://github.com/open-telemetry/opentelemetry-js/pull/4816) @mydea
* feat(instrumentation-http): Allow to opt-out of instrumenting incoming/outgoing requests [#4643](https://github.com/open-telemetry/opentelemetry-js/pull/4643) @mydea
* feat(sampler-jaeger-remote): added support of jaeger-remote-sampler according to this [spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#jaegerremotesampler) [#4534](https://github.com/open-telemetry/opentelemetry-js/pull/4589) @legalimpurity
### :bug: (Bug Fix)
* fix(instrumentation): ensure .setConfig() results in config.enabled defaulting to true [#4941](https://github.com/open-telemetry/opentelemetry-js/pull/4941) @trentm
* fix(instrumentation-http): Ensure instrumentation of `http.get` and `https.get` work when used in ESM code [#4857](https://github.com/open-telemetry/opentelemetry-js/issues/4857) @trentm
* fix(api-logs): align AnyValue to spec [#4893](https://github.com/open-telemetry/opentelemetry-js/pull/4893) @blumamir
* fix(instrumentation): remove diag.debug() message for instrumentations that do not patch modules [#4925](https://github.com/open-telemetry/opentelemetry-js/pull/4925) @trentm
### :books: (Refine Doc)
### :house: (Internal)
* refactor: Simplify the code for the `getEnv` function [#4799](https://github.com/open-telemetry/opentelemetry-js/pull/4799) @danstarns

View File

@ -1,6 +1,6 @@
{
"name": "backcompat-node14",
"version": "0.52.1",
"version": "0.53.0",
"private": true,
"description": "Backwards compatibility app for node 14 types and the OpenTelemetry Node.js SDK",
"main": "index.js",
@ -10,8 +10,8 @@
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"dependencies": {
"@opentelemetry/sdk-node": "0.52.1",
"@opentelemetry/sdk-trace-base": "1.25.1"
"@opentelemetry/sdk-node": "0.53.0",
"@opentelemetry/sdk-trace-base": "1.26.0"
},
"devDependencies": {
"@types/node": "14.18.25",

View File

@ -1,6 +1,6 @@
{
"name": "backcompat-node16",
"version": "0.52.1",
"version": "0.53.0",
"private": true,
"description": "Backwards compatibility app for node 16 types and the OpenTelemetry Node.js SDK",
"main": "index.js",
@ -10,8 +10,8 @@
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"dependencies": {
"@opentelemetry/sdk-node": "0.52.1",
"@opentelemetry/sdk-trace-base": "1.25.1"
"@opentelemetry/sdk-node": "0.53.0",
"@opentelemetry/sdk-trace-base": "1.26.0"
},
"devDependencies": {
"@types/node": "16.11.52",

View File

@ -1,17 +1,17 @@
{
"name": "events-example",
"version": "0.52.1",
"version": "0.53.0",
"private": true,
"scripts": {
"start": "ts-node index.ts"
},
"dependencies": {
"@opentelemetry/api": "^1.7.0",
"@opentelemetry/api-events": "0.52.1",
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/exporter-logs-otlp-http": "0.52.1",
"@opentelemetry/sdk-events": "0.52.1",
"@opentelemetry/sdk-logs": "0.52.1"
"@opentelemetry/api-events": "0.53.0",
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/exporter-logs-otlp-http": "0.53.0",
"@opentelemetry/sdk-events": "0.53.0",
"@opentelemetry/sdk-logs": "0.53.0"
},
"devDependencies": {
"@types/node": "18.6.5",

View File

@ -1,6 +1,6 @@
{
"name": "logs-example",
"version": "0.52.1",
"version": "0.53.0",
"private": true,
"scripts": {
"start": "ts-node index.ts",
@ -8,8 +8,8 @@
},
"dependencies": {
"@opentelemetry/api": "^1.7.0",
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/sdk-logs": "0.52.1"
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/sdk-logs": "0.53.0"
},
"devDependencies": {
"@types/node": "18.6.5",

View File

@ -1,7 +1,7 @@
{
"name": "opencensus-shim",
"private": true,
"version": "0.52.1",
"version": "0.53.0",
"description": "Example of using @opentelemetry/shim-opencensus in Node.js",
"main": "index.js",
"scripts": {
@ -32,13 +32,13 @@
"@opencensus/instrumentation-http": "0.1.0",
"@opencensus/nodejs-base": "0.1.0",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/exporter-prometheus": "0.52.1",
"@opentelemetry/exporter-trace-otlp-grpc": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1",
"@opentelemetry/sdk-trace-node": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1",
"@opentelemetry/shim-opencensus": "0.52.1"
"@opentelemetry/exporter-prometheus": "0.53.0",
"@opentelemetry/exporter-trace-otlp-grpc": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0",
"@opentelemetry/sdk-trace-node": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0",
"@opentelemetry/shim-opencensus": "0.53.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/examples/opencensus-shim"
}

View File

@ -1,6 +1,6 @@
{
"name": "prometheus-example",
"version": "0.52.1",
"version": "0.53.0",
"private": true,
"description": "Example of using @opentelemetry/sdk-metrics and @opentelemetry/exporter-prometheus",
"main": "index.js",
@ -12,7 +12,7 @@
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/exporter-prometheus": "0.52.1",
"@opentelemetry/sdk-metrics": "1.25.1"
"@opentelemetry/exporter-prometheus": "0.53.0",
"@opentelemetry/sdk-metrics": "1.26.0"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/api-events",
"version": "0.52.1",
"version": "0.53.0",
"description": "Public events API for OpenTelemetry",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -16,8 +16,6 @@
"scripts": {
"build": "npm run compile",
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
@ -62,15 +60,14 @@
"access": "public"
},
"dependencies": {
"@opentelemetry/api": "^1.0.0",
"@opentelemetry/api-logs": "0.52.1"
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/api-logs": "0.53.0"
},
"devDependencies": {
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/webpack-env": "1.16.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -83,7 +80,7 @@
"nyc": "15.1.0",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0"
"webpack": "5.94.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/api-events",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/api-logs",
"version": "0.52.1",
"version": "0.53.0",
"description": "Public logs API for OpenTelemetry",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -19,8 +19,6 @@
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"test": "nyc mocha test/**/*.test.ts",
"test:browser": "karma start --single-run",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"build": "npm run compile",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
@ -62,14 +60,13 @@
"access": "public"
},
"dependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"devDependencies": {
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/webpack-env": "1.16.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -82,7 +79,7 @@
"nyc": "15.1.0",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0"
"webpack": "5.94.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/api-logs",
"sideEffects": false

View File

@ -0,0 +1,69 @@
/*
* 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 { NOOP_LOGGER } from './NoopLogger';
import { Logger } from './types/Logger';
import { LoggerOptions } from './types/LoggerOptions';
import { LogRecord } from './types/LogRecord';
export class ProxyLogger implements Logger {
// When a real implementation is provided, this will be it
private _delegate?: Logger;
constructor(
private _provider: LoggerDelegator,
public readonly name: string,
public readonly version?: string | undefined,
public readonly options?: LoggerOptions | undefined
) {}
/**
* Emit a log record. This method should only be used by log appenders.
*
* @param logRecord
*/
emit(logRecord: LogRecord): void {
this._getLogger().emit(logRecord);
}
/**
* Try to get a logger from the proxy logger provider.
* If the proxy logger provider has no delegate, return a noop logger.
*/
private _getLogger() {
if (this._delegate) {
return this._delegate;
}
const logger = this._provider.getDelegateLogger(
this.name,
this.version,
this.options
);
if (!logger) {
return NOOP_LOGGER;
}
this._delegate = logger;
return this._delegate;
}
}
export interface LoggerDelegator {
getDelegateLogger(
name: string,
version?: string,
options?: LoggerOptions
): Logger | undefined;
}

View 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 { LoggerProvider } from './types/LoggerProvider';
import { Logger } from './types/Logger';
import { LoggerOptions } from './types/LoggerOptions';
import { NOOP_LOGGER_PROVIDER } from './NoopLoggerProvider';
import { ProxyLogger } from './ProxyLogger';
export class ProxyLoggerProvider implements LoggerProvider {
private _delegate?: LoggerProvider;
getLogger(
name: string,
version?: string | undefined,
options?: LoggerOptions | undefined
): Logger {
return (
this.getDelegateLogger(name, version, options) ??
new ProxyLogger(this, name, version, options)
);
}
getDelegate(): LoggerProvider {
return this._delegate ?? NOOP_LOGGER_PROVIDER;
}
/**
* Set the delegate logger provider
*/
setDelegate(delegate: LoggerProvider) {
this._delegate = delegate;
}
getDelegateLogger(
name: string,
version?: string | undefined,
options?: LoggerOptions | undefined
): Logger | undefined {
return this._delegate?.getLogger(name, version, options);
}
}

View File

@ -24,10 +24,13 @@ import { LoggerProvider } from '../types/LoggerProvider';
import { NOOP_LOGGER_PROVIDER } from '../NoopLoggerProvider';
import { Logger } from '../types/Logger';
import { LoggerOptions } from '../types/LoggerOptions';
import { ProxyLoggerProvider } from '../ProxyLoggerProvider';
export class LogsAPI {
private static _instance?: LogsAPI;
private _proxyLoggerProvider = new ProxyLoggerProvider();
private constructor() {}
public static getInstance(): LogsAPI {
@ -48,6 +51,7 @@ export class LogsAPI {
provider,
NOOP_LOGGER_PROVIDER
);
this._proxyLoggerProvider.setDelegate(provider);
return provider;
}
@ -60,7 +64,7 @@ export class LogsAPI {
public getLoggerProvider(): LoggerProvider {
return (
_global[GLOBAL_LOGS_API_KEY]?.(API_BACKWARDS_COMPATIBILITY_VERSION) ??
NOOP_LOGGER_PROVIDER
this._proxyLoggerProvider
);
}
@ -80,5 +84,6 @@ export class LogsAPI {
/** Remove the global logger provider */
public disable(): void {
delete _global[GLOBAL_LOGS_API_KEY];
this._proxyLoggerProvider = new ProxyLoggerProvider();
}
}

View File

@ -26,6 +26,8 @@ export { LoggerOptions } from './types/LoggerOptions';
export { AnyValue, AnyValueMap } from './types/AnyValue';
export { NOOP_LOGGER, NoopLogger } from './NoopLogger';
export { NOOP_LOGGER_PROVIDER, NoopLoggerProvider } from './NoopLoggerProvider';
export { ProxyLogger } from './ProxyLogger';
export { ProxyLoggerProvider } from './ProxyLoggerProvider';
import { LogsAPI } from './api/logs';
export const logs = LogsAPI.getInstance();

View File

@ -15,7 +15,7 @@
*/
import * as assert from 'assert';
import { Logger, logs } from '../../src';
import { Logger, ProxyLoggerProvider, logs } from '../../src';
import { NoopLogger } from '../../src/NoopLogger';
import { NoopLoggerProvider } from '../../src/NoopLoggerProvider';
@ -23,9 +23,11 @@ describe('API', () => {
const dummyLogger = new NoopLogger();
it('should expose a logger provider via getLoggerProvider', () => {
const provider = logs.getLoggerProvider();
assert.ok(provider);
assert.strictEqual(typeof provider, 'object');
assert.ok(logs.getLoggerProvider() instanceof ProxyLoggerProvider);
assert.ok(
(logs.getLoggerProvider() as ProxyLoggerProvider).getDelegate() instanceof
NoopLoggerProvider
);
});
describe('GlobalLoggerProvider', () => {

View File

@ -17,6 +17,7 @@
import * as assert from 'assert';
import { _global, GLOBAL_LOGS_API_KEY } from '../../src/internal/global-utils';
import { NoopLoggerProvider } from '../../src/NoopLoggerProvider';
import { ProxyLoggerProvider } from '../../src';
const api1 = require('../../src') as typeof import('../../src');
@ -66,11 +67,10 @@ describe('Global Utils', () => {
assert.strictEqual(original, api1.logs.getLoggerProvider());
});
it('should return the module NoOp implementation if the version is a mismatch', () => {
const original = api1.logs.getLoggerProvider();
api1.logs.setGlobalLoggerProvider(new NoopLoggerProvider());
it('should return the module no op implementation if the version is a mismatch', () => {
api1.logs.setGlobalLoggerProvider(new ProxyLoggerProvider());
const afterSet = _global[GLOBAL_LOGS_API_KEY]!(-1);
assert.strictEqual(original, afterSet);
assert.ok(afterSet instanceof NoopLoggerProvider);
});
});

View File

@ -0,0 +1,117 @@
/*
* 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 * as sinon from 'sinon';
import {
Logger,
LoggerProvider,
ProxyLogger,
ProxyLoggerProvider,
} from '../../src';
import { NoopLogger } from '../../src/NoopLogger';
describe('ProxyLogger', () => {
let provider: ProxyLoggerProvider;
const sandbox = sinon.createSandbox();
beforeEach(() => {
provider = new ProxyLoggerProvider();
});
afterEach(() => {
sandbox.restore();
});
describe('when no delegate is set', () => {
it('should return proxy loggers', () => {
const logger = provider.getLogger('test');
assert.ok(logger instanceof ProxyLogger);
});
});
describe('when delegate is set before getLogger', () => {
let delegate: LoggerProvider;
let getLoggerStub: sinon.SinonStub;
beforeEach(() => {
getLoggerStub = sandbox.stub().returns(new NoopLogger());
delegate = {
getLogger: getLoggerStub,
};
provider.setDelegate(delegate);
});
it('should return loggers directly from the delegate', () => {
const logger = provider.getLogger('test', 'v0');
sandbox.assert.calledOnce(getLoggerStub);
assert.strictEqual(getLoggerStub.firstCall.returnValue, logger);
assert.deepStrictEqual(getLoggerStub.firstCall.args, [
'test',
'v0',
undefined,
]);
});
it('should return loggers directly from the delegate with schema url', () => {
const logger = provider.getLogger('test', 'v0', {
schemaUrl: 'https://opentelemetry.io/schemas/1.7.0',
});
sandbox.assert.calledOnce(getLoggerStub);
assert.strictEqual(getLoggerStub.firstCall.returnValue, logger);
assert.deepStrictEqual(getLoggerStub.firstCall.args, [
'test',
'v0',
{ schemaUrl: 'https://opentelemetry.io/schemas/1.7.0' },
]);
});
});
describe('when delegate is set after getLogger', () => {
let logger: Logger;
let delegateProvider: LoggerProvider;
let delegateLogger: Logger;
let emitCalled: boolean;
beforeEach(() => {
emitCalled = false;
delegateLogger = {
emit() {
emitCalled = true;
},
};
logger = provider.getLogger('test');
delegateProvider = {
getLogger() {
return delegateLogger;
},
};
provider.setDelegate(delegateProvider);
});
it('should emit from the delegate logger', () => {
logger.emit({
body: 'Test',
});
assert.ok(emitCalled);
});
});
});

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-logs-otlp-grpc",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Collector Exporter allows user to send collected log records to the OpenTelemetry Collector",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -18,7 +18,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js",
"maint:regenerate-test-certs": "cd test/certs && ./regenerate.sh"
},
@ -52,13 +51,12 @@
"devDependencies": {
"@grpc/proto-loader": "^0.7.10",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -68,14 +66,14 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@grpc/grpc-js": "^1.7.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-grpc-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/sdk-logs": "0.52.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-grpc-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/sdk-logs": "0.53.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-logs-otlp-grpc",
"sideEffects": false

View File

@ -109,12 +109,17 @@ const testCollectorExporter = (params: TestParams) => {
server.bindAsync(
serverAddr.protocol === 'https:' ? serverAddr.host : address,
credentials,
() => {
server.start();
done();
err => {
if (err) {
done(err);
} else {
server.start();
done();
}
}
);
});
})
.catch(done);
});
after(() => {

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-logs-otlp-http",
"version": "0.52.1",
"version": "0.53.0",
"publishConfig": {
"access": "public"
},
@ -32,7 +32,6 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
@ -44,7 +43,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
@ -73,16 +71,15 @@
"sideEffects": false,
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/resources": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -96,18 +93,18 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/sdk-logs": "0.52.1"
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/sdk-logs": "0.53.0"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-logs-otlp-proto",
"version": "0.52.1",
"version": "0.53.0",
"description": "An OTLP exporter to send logs using protobuf over HTTP",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -27,7 +27,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
@ -65,13 +64,12 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -85,21 +83,21 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-logs": "0.52.1",
"@opentelemetry/sdk-trace-base": "1.25.1"
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-logs": "0.53.0",
"@opentelemetry/sdk-trace-base": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-logs-otlp-proto",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-trace-otlp-grpc",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Collector Exporter allows user to send collected traces to the OpenTelemetry Collector",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -18,7 +18,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js",
"maint:regenerate-test-certs": "cd test/certs && ./regenerate.sh"
},
@ -51,11 +50,10 @@
"devDependencies": {
"@grpc/proto-loader": "^0.7.10",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -65,15 +63,15 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@grpc/grpc-js": "^1.7.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-grpc-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-grpc-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-grpc",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-trace-otlp-http",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Collector Trace Exporter allows user to send collected traces to the OpenTelemetry Collector",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -17,7 +17,6 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
@ -29,7 +28,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
@ -65,15 +63,14 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -87,19 +84,19 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-http",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-trace-otlp-proto",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Collector Exporter allows user to send collected traces to the OpenTelemetry Collector using protobuf over HTTP",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -27,7 +27,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
@ -64,13 +63,12 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -84,19 +82,19 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-proto",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/opentelemetry-browser-detector",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Resource Detector for Browser",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -17,7 +17,6 @@
"test:browser": "karma start --single-run",
"tdd": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"version": "node ../../../scripts/version-update.js",
"watch": "tsc --build --watch tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
@ -55,13 +54,12 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -75,15 +73,15 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/resources": "1.25.1"
"@opentelemetry/resources": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/browser-detector"
}

View File

@ -14,14 +14,13 @@
* limitations under the License.
*/
import { diag } from '@opentelemetry/api';
import { Attributes, diag } from '@opentelemetry/api';
import {
Detector,
IResource,
Resource,
ResourceDetectionConfig,
} from '@opentelemetry/resources';
import { ResourceAttributes } from '@opentelemetry/resources';
import { BROWSER_ATTRIBUTES, UserAgentData } from './types';
/**
@ -33,7 +32,7 @@ class BrowserDetector implements Detector {
if (!isBrowser) {
return Resource.empty();
}
const browserResource: ResourceAttributes = getBrowserAttributes();
const browserResource: Attributes = getBrowserAttributes();
return this._getResourceAttributes(browserResource, config);
}
/**
@ -44,7 +43,7 @@ class BrowserDetector implements Detector {
* @returns The sanitized resource attributes.
*/
private _getResourceAttributes(
browserResource: ResourceAttributes,
browserResource: Attributes,
_config?: ResourceDetectionConfig
) {
if (
@ -62,8 +61,8 @@ class BrowserDetector implements Detector {
}
// Add Browser related attributes to resources
function getBrowserAttributes(): ResourceAttributes {
const browserAttribs: ResourceAttributes = {};
function getBrowserAttributes(): Attributes {
const browserAttribs: Attributes = {};
const userAgentData: UserAgentData | undefined = (navigator as any)
.userAgentData;
if (userAgentData) {

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-metrics-otlp-grpc",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Collector Metrics Exporter allows user to send collected metrics to the OpenTelemetry Collector",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -18,7 +18,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js",
"maint:regenerate-test-certs": "cd test/certs && ./regenerate.sh"
},
@ -54,7 +53,6 @@
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -68,13 +66,13 @@
},
"dependencies": {
"@grpc/grpc-js": "^1.7.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/exporter-metrics-otlp-http": "0.52.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-grpc-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/exporter-metrics-otlp-http": "0.53.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/otlp-grpc-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-metrics-otlp-http",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Collector Metrics Exporter allows user to send collected metrics to the OpenTelemetry Collector",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -17,7 +17,6 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
@ -29,7 +28,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
@ -65,15 +63,14 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -87,7 +84,7 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
@ -95,11 +92,11 @@
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-http",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-metrics-otlp-proto",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Collector Metrics Exporter allows user to send collected metrics to the OpenTelemetry Collector using protobuf over HTTP",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -20,7 +20,6 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
@ -60,7 +59,6 @@
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -73,12 +71,12 @@
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/exporter-metrics-otlp-http": "0.52.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/exporter-metrics-otlp-http": "0.53.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-proto",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-prometheus",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry Exporter Prometheus provides a metrics endpoint for Prometheus",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -11,7 +11,6 @@
"clean": "tsc --build --clean",
"test": "nyc mocha 'test/**/*.test.ts'",
"tdd": "npm run test -- --watch-extensions ts --watch",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"version": "node ../../../scripts/version-update.js",
@ -45,11 +44,10 @@
},
"devDependencies": {
"@opentelemetry/api": "1.9.0",
"@opentelemetry/semantic-conventions": "1.25.1",
"@opentelemetry/semantic-conventions": "1.27.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -61,9 +59,9 @@
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-prometheus",
"sideEffects": false

View File

@ -14,11 +14,7 @@
* limitations under the License.
*/
import {
diag,
MetricAttributes,
MetricAttributeValue,
} from '@opentelemetry/api';
import { diag, Attributes, AttributeValue } from '@opentelemetry/api';
import {
ResourceMetrics,
InstrumentType,
@ -48,7 +44,7 @@ function escapeString(str: string) {
*
* `undefined` is converted to an empty string.
*/
function escapeAttributeValue(str: MetricAttributeValue = '') {
function escapeAttributeValue(str: AttributeValue = '') {
if (typeof str !== 'string') {
str = JSON.stringify(str);
}
@ -136,10 +132,10 @@ function toPrometheusType(metricData: MetricData): PrometheusDataTypeLiteral {
function stringify(
metricName: string,
attributes: MetricAttributes,
attributes: Attributes,
value: number,
timestamp?: number,
additionalAttributes?: MetricAttributes
additionalAttributes?: Attributes
) {
let hasAttribute = false;
let attributesStr = '';

View File

@ -15,7 +15,7 @@
*/
import * as assert from 'assert';
import { MetricAttributes, UpDownCounter } from '@opentelemetry/api';
import { Attributes, UpDownCounter } from '@opentelemetry/api';
import {
Aggregation,
AggregationTemporality,
@ -610,7 +610,7 @@ describe('PrometheusSerializer', () => {
NaN: NaN,
null: null,
undefined: undefined,
} as unknown as MetricAttributes);
} as unknown as Attributes);
});
assert.strictEqual(
@ -649,7 +649,7 @@ describe('PrometheusSerializer', () => {
backslashN: '\u005c\u006e', // \n => \\n (\u005c\u005c\u006e)
backslashDoubleQuote: '\u005c\u0022', // \" => \\\" (\u005c\u005c\u005c\u0022)
backslashLineFeed: '\u005c\u000a', // \↵ => \\\n (\u005c\u005c\u005c\u006e)
} as unknown as MetricAttributes);
} as unknown as Attributes);
});
assert.strictEqual(
@ -674,7 +674,7 @@ describe('PrometheusSerializer', () => {
// error while linting: text format parsing error in line 282: expected '=' after label name, found '-'
counter.add(1, {
'account-id': '123456',
} as unknown as MetricAttributes);
} as unknown as Attributes);
});
assert.strictEqual(result, 'test_total{account_id="123456"} 1\n');

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/instrumentation-fetch",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry instrumentation for fetch http client in web browsers",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -13,7 +13,6 @@
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"version": "node ../../../scripts/version-update.js",
"tdd": "karma start",
"test:browser": "karma start --single-run",
@ -56,18 +55,17 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-zone": "1.25.1",
"@opentelemetry/propagator-b3": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/context-zone": "1.26.0",
"@opentelemetry/propagator-b3": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -81,18 +79,18 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/sdk-trace-web": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/sdk-trace-web": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-fetch",
"sideEffects": false

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/instrumentation-grpc",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry instrumentation for `@grpc/grpc-js` rpc client and server for gRPC framework",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -13,7 +13,6 @@
"tdd": "npm run test -- --watch-extensions ts --watch",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"version": "node ../../../scripts/version-update.js",
"watch": "tsc --build --watch",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
@ -51,10 +50,10 @@
"@grpc/grpc-js": "^1.7.1",
"@grpc/proto-loader": "^0.7.10",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "1.25.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/sdk-trace-node": "1.25.1",
"@opentelemetry/context-async-hooks": "1.26.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@opentelemetry/sdk-trace-node": "1.26.0",
"@protobuf-ts/grpc-transport": "2.9.4",
"@protobuf-ts/runtime": "2.9.4",
"@protobuf-ts/runtime-rpc": "2.9.4",
@ -62,7 +61,6 @@
"@types/node": "18.6.5",
"@types/semver": "7.5.8",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -75,8 +73,8 @@
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-grpc",
"sideEffects": false

View File

@ -76,7 +76,44 @@ The following options are deprecated:
## Semantic Conventions
This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md)
### Client Spans
Prior to version `0.54`, this instrumentation created spans targeting an experimental semantic convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md).
This package is capable of emitting both Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md) and [Version 1.27.0](https://github.com/open-telemetry/semantic-conventions/blob/v1.27.0/docs/http/http-spans.md).
It is controlled using the environment variable `OTEL_SEMCONV_STABILITY_OPT_IN`, which is a comma separated list of values.
The values `http` and `http/dup` control this instrumentation.
See details for the behavior of each of these values below.
If neither `http` or `http/dup` is included in `OTEL_SEMCONV_STABILITY_OPT_IN`, the old experimental semantic conventions will be used by default.
#### Stable Semantic Conventions 1.27
Enabled when `OTEL_SEMCONV_STABILITY_OPT_IN` contains `http` OR `http/dup`.
This is the recommended configuration, and will soon become the default behavior.
Follow all requirements and recommendations of HTTP Client Span Semantic Conventions [Version 1.27.0](https://github.com/open-telemetry/semantic-conventions/blob/v1.27.0/docs/http/http-spans.md), including all required and recommended attributes.
#### Legacy Behavior (default)
Enabled when `OTEL_SEMCONV_STABILITY_OPT_IN` contains `http/dup` or DOES NOT CONTAIN `http`.
This is the current default behavior.
Create HTTP client spans which implement Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md).
#### Upgrading Semantic Conventions
When upgrading to the new semantic conventions, it is recommended to do so in the following order:
1. Upgrade `@opentelemetry/instrumentation-http` to the latest version
2. Set `OTEL_SEMCONV_STABILITY_OPT_IN=http/dup` to emit both old and new semantic conventions
3. Modify alerts, dashboards, metrics, and other processes to expect the new semantic conventions
4. Set `OTEL_SEMCONV_STABILITY_OPT_IN=http` to emit only the new semantic conventions
This will cause both the old and new semantic conventions to be emitted during the transition period.
### Server Spans
This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md).
Attributes collected:

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/instrumentation-http",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry instrumentation for `node:http` and `node:https` http client and server modules",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -15,7 +15,6 @@
"tdd": "npm run test -- --watch-extensions ts --watch",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"version": "node ../../../scripts/version-update.js",
"watch": "tsc --build --watch",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
@ -50,18 +49,17 @@
},
"devDependencies": {
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/sdk-trace-node": "1.25.1",
"@opentelemetry/context-async-hooks": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@opentelemetry/sdk-trace-node": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/request-promise-native": "1.0.21",
"@types/semver": "7.5.8",
"@types/sinon": "17.0.3",
"@types/superagent": "8.1.8",
"axios": "1.6.0",
"codecov": "3.8.3",
"@types/superagent": "8.1.9",
"axios": "1.7.4",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -77,9 +75,9 @@
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/semantic-conventions": "1.25.1",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/semantic-conventions": "1.27.0",
"semver": "^7.5.2"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http",

View File

@ -46,17 +46,39 @@ import {
HttpInstrumentationConfig,
HttpRequestArgs,
Https,
SemconvStability,
} from './types';
import * as utils from './utils';
import { VERSION } from './version';
import {
InstrumentationBase,
InstrumentationNodeModuleDefinition,
safeExecuteInTheMiddle,
} from '@opentelemetry/instrumentation';
import { RPCMetadata, RPCType, setRPCMetadata } from '@opentelemetry/core';
import {
RPCMetadata,
RPCType,
setRPCMetadata,
getEnv,
} from '@opentelemetry/core';
import { errorMonitor } from 'events';
import { SEMATTRS_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';
import {
extractHostnameAndPort,
getIncomingRequestAttributes,
getIncomingRequestAttributesOnResponse,
getIncomingRequestMetricAttributes,
getIncomingRequestMetricAttributesOnResponse,
getOutgoingRequestAttributes,
getOutgoingRequestAttributesOnResponse,
getOutgoingRequestMetricAttributes,
getOutgoingRequestMetricAttributesOnResponse,
getRequestInfo,
headerCapture,
isIgnored,
isValidOptionsType,
parseResponseStatus,
setSpanWithError,
} from './utils';
/**
* Http instrumentation instrumentation for Opentelemetry
@ -68,9 +90,21 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
private _httpServerDurationHistogram!: Histogram;
private _httpClientDurationHistogram!: Histogram;
private _semconvStability = SemconvStability.OLD;
constructor(config: HttpInstrumentationConfig = {}) {
super('@opentelemetry/instrumentation-http', VERSION, config);
this._headerCapture = this._createHeaderCapture();
for (const entry in getEnv().OTEL_SEMCONV_STABILITY_OPT_IN) {
if (entry.toLowerCase() === 'http/dup') {
// http/dup takes highest precedence. If it is found, there is no need to read the rest of the list
this._semconvStability = SemconvStability.DUPLICATE;
break;
} else if (entry.toLowerCase() === 'http') {
this._semconvStability = SemconvStability.STABLE;
}
}
}
protected override _updateMetricInstruments() {
@ -319,12 +353,14 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
if (request.listenerCount('response') <= 1) {
response.resume();
}
const responseAttributes =
utils.getOutgoingRequestAttributesOnResponse(response);
const responseAttributes = getOutgoingRequestAttributesOnResponse(
response,
this._semconvStability
);
span.setAttributes(responseAttributes);
metricAttributes = Object.assign(
metricAttributes,
utils.getOutgoingRequestMetricAttributesOnResponse(responseAttributes)
getOutgoingRequestMetricAttributesOnResponse(responseAttributes)
);
if (this.getConfig().responseHook) {
@ -352,11 +388,9 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
if (response.aborted && !response.complete) {
status = { code: SpanStatusCode.ERROR };
} else {
// behaves same for new and old semconv
status = {
code: utils.parseResponseStatus(
SpanKind.CLIENT,
response.statusCode
),
code: parseResponseStatus(SpanKind.CLIENT, response.statusCode),
};
}
@ -390,7 +424,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
return;
}
responseFinished = true;
utils.setSpanWithError(span, error);
setSpanWithError(span, error, this._semconvStability);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message,
@ -418,7 +452,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
return;
}
responseFinished = true;
utils.setSpanWithError(span, error);
setSpanWithError(span, error, this._semconvStability);
this._closeHttpSpan(span, SpanKind.CLIENT, startTime, metricAttributes);
});
@ -453,7 +487,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
);
if (
utils.isIgnored(
isIgnored(
pathname,
instrumentation.getConfig().ignoreIncomingPaths,
(e: unknown) =>
@ -482,7 +516,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
const headers = request.headers;
const spanAttributes = utils.getIncomingRequestAttributes(request, {
const spanAttributes = getIncomingRequestAttributes(request, {
component: component,
serverName: instrumentation.getConfig().serverName,
hookAttributes: instrumentation._callStartSpanHook(
@ -498,7 +532,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
const startTime = hrTime();
const metricAttributes =
utils.getIncomingRequestMetricAttributes(spanAttributes);
getIncomingRequestMetricAttributes(spanAttributes);
const ctx = propagation.extract(ROOT_CONTEXT, headers);
const span = instrumentation._startHttpSpan(method, spanOptions, ctx);
@ -553,7 +587,11 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
() => original.apply(this, [event, ...args]),
error => {
if (error) {
utils.setSpanWithError(span, error);
setSpanWithError(
span,
error,
instrumentation._semconvStability
);
instrumentation._closeHttpSpan(
span,
SpanKind.SERVER,
@ -579,7 +617,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
options: url.URL | http.RequestOptions | string,
...args: unknown[]
): http.ClientRequest {
if (!utils.isValidOptionsType(options)) {
if (!isValidOptionsType(options)) {
return original.apply(this, [options, ...args]);
}
const extraOptions =
@ -587,13 +625,13 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
(typeof options === 'string' || options instanceof url.URL)
? (args.shift() as http.RequestOptions)
: undefined;
const { origin, pathname, method, optionsParsed } = utils.getRequestInfo(
const { origin, pathname, method, optionsParsed } = getRequestInfo(
options,
extraOptions
);
if (
utils.isIgnored(
isIgnored(
origin + pathname,
instrumentation.getConfig().ignoreOutgoingUrls,
(e: unknown) =>
@ -618,21 +656,25 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
return original.apply(this, [optionsParsed, ...args]);
}
const { hostname, port } = utils.extractHostnameAndPort(optionsParsed);
const { hostname, port } = extractHostnameAndPort(optionsParsed);
const attributes = utils.getOutgoingRequestAttributes(optionsParsed, {
component,
port,
hostname,
hookAttributes: instrumentation._callStartSpanHook(
optionsParsed,
instrumentation.getConfig().startOutgoingSpanHook
),
});
const attributes = getOutgoingRequestAttributes(
optionsParsed,
{
component,
port,
hostname,
hookAttributes: instrumentation._callStartSpanHook(
optionsParsed,
instrumentation.getConfig().startOutgoingSpanHook
),
},
instrumentation._semconvStability
);
const startTime = hrTime();
const metricAttributes: MetricAttributes =
utils.getOutgoingRequestMetricAttributes(attributes);
getOutgoingRequestMetricAttributes(attributes);
const spanOptions: SpanOptions = {
kind: SpanKind.CLIENT,
@ -666,7 +708,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
() => original.apply(this, [optionsParsed, ...args]),
error => {
if (error) {
utils.setSpanWithError(span, error);
setSpanWithError(span, error, instrumentation._semconvStability);
instrumentation._closeHttpSpan(
span,
SpanKind.CLIENT,
@ -699,13 +741,13 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
metricAttributes: MetricAttributes,
startTime: HrTime
) {
const attributes = utils.getIncomingRequestAttributesOnResponse(
const attributes = getIncomingRequestAttributesOnResponse(
request,
response
);
metricAttributes = Object.assign(
metricAttributes,
utils.getIncomingRequestMetricAttributesOnResponse(attributes)
getIncomingRequestMetricAttributesOnResponse(attributes)
);
this._headerCapture.server.captureResponseHeaders(span, header =>
@ -713,7 +755,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
);
span.setAttributes(attributes).setStatus({
code: utils.parseResponseStatus(SpanKind.SERVER, response.statusCode),
code: parseResponseStatus(SpanKind.SERVER, response.statusCode),
});
const route = attributes[SEMATTRS_HTTP_ROUTE];
@ -743,7 +785,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
startTime: HrTime,
error: Err
) {
utils.setSpanWithError(span, error);
setSpanWithError(span, error, this._semconvStability);
this._closeHttpSpan(span, SpanKind.SERVER, startTime, metricAttributes);
}
@ -837,21 +879,21 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
return {
client: {
captureRequestHeaders: utils.headerCapture(
captureRequestHeaders: headerCapture(
'request',
config.headersToSpanAttributes?.client?.requestHeaders ?? []
),
captureResponseHeaders: utils.headerCapture(
captureResponseHeaders: headerCapture(
'response',
config.headersToSpanAttributes?.client?.responseHeaders ?? []
),
},
server: {
captureRequestHeaders: utils.headerCapture(
captureRequestHeaders: headerCapture(
'request',
config.headersToSpanAttributes?.server?.requestHeaders ?? []
),
captureResponseHeaders: utils.headerCapture(
captureResponseHeaders: headerCapture(
'response',
config.headersToSpanAttributes?.server?.responseHeaders ?? []
),

View File

@ -132,3 +132,18 @@ export interface Err extends Error {
syscall?: string;
stack?: string;
}
/**
* Tracks whether this instrumentation emits old experimental,
* new stable, or both semantic conventions.
*
* Enum values chosen such that the enum may be used as a bitmask.
*/
export const enum SemconvStability {
/** Emit only stable semantic conventions */
STABLE = 0x1,
/** Emit only old semantic convetions */
OLD = 0x2,
/** Emit both stable and old semantic convetions */
DUPLICATE = 0x1 | 0x2,
}

View File

@ -20,8 +20,19 @@ import {
Span,
context,
SpanKind,
Attributes,
} from '@opentelemetry/api';
import {
ATTR_ERROR_TYPE,
ATTR_HTTP_REQUEST_METHOD,
ATTR_HTTP_REQUEST_METHOD_ORIGINAL,
ATTR_HTTP_RESPONSE_STATUS_CODE,
ATTR_NETWORK_PEER_ADDRESS,
ATTR_NETWORK_PEER_PORT,
ATTR_NETWORK_PROTOCOL_VERSION,
ATTR_SERVER_ADDRESS,
ATTR_SERVER_PORT,
ATTR_URL_FULL,
NETTRANSPORTVALUES_IP_TCP,
NETTRANSPORTVALUES_IP_UDP,
SEMATTRS_HTTP_CLIENT_IP,
@ -57,7 +68,12 @@ import {
import { getRPCMetadata, RPCType } from '@opentelemetry/core';
import * as url from 'url';
import { AttributeNames } from './enums/AttributeNames';
import { Err, IgnoreMatcher, ParsedRequestOptions } from './types';
import {
Err,
IgnoreMatcher,
ParsedRequestOptions,
SemconvStability,
} from './types';
/**
* Get an absolute url
@ -163,12 +179,27 @@ export const isIgnored = (
* Sets the span with the error passed in params
* @param {Span} span the span that need to be set
* @param {Error} error error that will be set to span
* @param {SemconvStability} semconvStability determines which semconv version to use
*/
export const setSpanWithError = (span: Span, error: Err): void => {
export const setSpanWithError = (
span: Span,
error: Err,
semconvStability: SemconvStability
): void => {
const message = error.message;
span.setAttribute(AttributeNames.HTTP_ERROR_NAME, error.name);
span.setAttribute(AttributeNames.HTTP_ERROR_MESSAGE, message);
if ((semconvStability & SemconvStability.OLD) === SemconvStability.OLD) {
span.setAttribute(AttributeNames.HTTP_ERROR_NAME, error.name);
span.setAttribute(AttributeNames.HTTP_ERROR_MESSAGE, message);
}
if (
(semconvStability & SemconvStability.STABLE) ===
SemconvStability.STABLE
) {
span.setAttribute(ATTR_ERROR_TYPE, error.name);
}
span.setStatus({ code: SpanStatusCode.ERROR, message });
span.recordException(error);
};
@ -196,6 +227,8 @@ export const setRequestContentLengthAttribute = (
* Adds attributes for response content-length and content-encoding HTTP headers
* @param { IncomingMessage } Response object whose headers will be analyzed
* @param { SpanAttributes } SpanAttributes object to be modified
*
* @deprecated this is for an older version of semconv. It is retained for compatibility using OTEL_SEMCONV_STABILITY_OPT_IN
*/
export const setResponseContentLengthAttribute = (
response: IncomingMessage,
@ -343,6 +376,7 @@ export const extractHostnameAndPort = (
* Returns outgoing request attributes scoped to the options passed to the request
* @param {ParsedRequestOptions} requestOptions the same options used to make the request
* @param {{ component: string, hostname: string, hookAttributes?: SpanAttributes }} options used to pass data needed to create attributes
* @param {SemconvStability} semconvStability determines which semconv version to use
*/
export const getOutgoingRequestAttributes = (
requestOptions: ParsedRequestOptions,
@ -351,7 +385,8 @@ export const getOutgoingRequestAttributes = (
hostname: string;
port: string | number;
hookAttributes?: SpanAttributes;
}
},
semconvStability: SemconvStability
): SpanAttributes => {
const hostname = options.hostname;
const port = options.port;
@ -359,22 +394,49 @@ export const getOutgoingRequestAttributes = (
const method = requestMethod ? requestMethod.toUpperCase() : 'GET';
const headers = requestOptions.headers || {};
const userAgent = headers['user-agent'];
const attributes: SpanAttributes = {
[SEMATTRS_HTTP_URL]: getAbsoluteUrl(
requestOptions,
headers,
`${options.component}:`
),
const urlFull = getAbsoluteUrl(
requestOptions,
headers,
`${options.component}:`
);
const oldAttributes: SpanAttributes = {
[SEMATTRS_HTTP_URL]: urlFull,
[SEMATTRS_HTTP_METHOD]: method,
[SEMATTRS_HTTP_TARGET]: requestOptions.path || '/',
[SEMATTRS_NET_PEER_NAME]: hostname,
[SEMATTRS_HTTP_HOST]: headers.host ?? `${hostname}:${port}`,
};
if (userAgent !== undefined) {
attributes[SEMATTRS_HTTP_USER_AGENT] = userAgent;
const newAttributes: Attributes = {
// Required attributes
[ATTR_HTTP_REQUEST_METHOD]: method,
[ATTR_SERVER_ADDRESS]: hostname,
[ATTR_SERVER_PORT]: Number(port),
[ATTR_URL_FULL]: urlFull,
// leaving out protocol version, it is not yet negotiated
// leaving out protocol name, it is only required when protocol version is set
// retries and redirects not supported
// Opt-in attributes left off for now
};
// conditionally required if request method required case normalization
if (requestMethod && method !== requestMethod) {
newAttributes[ATTR_HTTP_REQUEST_METHOD_ORIGINAL] = requestMethod;
}
return Object.assign(attributes, options.hookAttributes);
if (userAgent !== undefined) {
oldAttributes[SEMATTRS_HTTP_USER_AGENT] = userAgent;
}
switch (semconvStability) {
case SemconvStability.STABLE:
return Object.assign(newAttributes, options.hookAttributes);
case SemconvStability.OLD:
return Object.assign(oldAttributes, options.hookAttributes);
}
return Object.assign(oldAttributes, newAttributes, options.hookAttributes);
};
/**
@ -413,29 +475,49 @@ export const setAttributesFromHttpKind = (
/**
* Returns outgoing request attributes scoped to the response data
* @param {IncomingMessage} response the response object
* @param {{ hostname: string }} options used to pass data needed to create attributes
* @param {SemconvStability} semconvStability determines which semconv version to use
*/
export const getOutgoingRequestAttributesOnResponse = (
response: IncomingMessage
response: IncomingMessage,
semconvStability: SemconvStability
): SpanAttributes => {
const { statusCode, statusMessage, httpVersion, socket } = response;
const attributes: SpanAttributes = {};
const oldAttributes: SpanAttributes = {};
const stableAttributes: Attributes = {};
if (statusCode != null) {
stableAttributes[ATTR_HTTP_RESPONSE_STATUS_CODE] = statusCode;
}
if (socket) {
const { remoteAddress, remotePort } = socket;
attributes[SEMATTRS_NET_PEER_IP] = remoteAddress;
attributes[SEMATTRS_NET_PEER_PORT] = remotePort;
oldAttributes[SEMATTRS_NET_PEER_IP] = remoteAddress;
oldAttributes[SEMATTRS_NET_PEER_PORT] = remotePort;
// Recommended
stableAttributes[ATTR_NETWORK_PEER_ADDRESS] = remoteAddress;
stableAttributes[ATTR_NETWORK_PEER_PORT] = remotePort;
stableAttributes[ATTR_NETWORK_PROTOCOL_VERSION] = response.httpVersion;
}
setResponseContentLengthAttribute(response, attributes);
setResponseContentLengthAttribute(response, oldAttributes);
if (statusCode) {
attributes[SEMATTRS_HTTP_STATUS_CODE] = statusCode;
attributes[AttributeNames.HTTP_STATUS_TEXT] = (
oldAttributes[SEMATTRS_HTTP_STATUS_CODE] = statusCode;
oldAttributes[AttributeNames.HTTP_STATUS_TEXT] = (
statusMessage || ''
).toUpperCase();
}
setAttributesFromHttpKind(httpVersion, attributes);
return attributes;
setAttributesFromHttpKind(httpVersion, oldAttributes);
switch (semconvStability) {
case SemconvStability.STABLE:
return stableAttributes;
case SemconvStability.OLD:
return oldAttributes;
}
return Object.assign(oldAttributes, stableAttributes);
};
/**

View File

@ -30,12 +30,28 @@ import {
SimpleSpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import {
ATTR_HTTP_REQUEST_METHOD,
ATTR_HTTP_RESPONSE_STATUS_CODE,
ATTR_NETWORK_PEER_ADDRESS,
ATTR_NETWORK_PEER_PORT,
ATTR_NETWORK_PROTOCOL_VERSION,
ATTR_SERVER_ADDRESS,
ATTR_SERVER_PORT,
ATTR_URL_FULL,
HTTP_REQUEST_METHOD_VALUE_GET,
NETTRANSPORTVALUES_IP_TCP,
SEMATTRS_HTTP_CLIENT_IP,
SEMATTRS_HTTP_FLAVOR,
SEMATTRS_HTTP_HOST,
SEMATTRS_HTTP_METHOD,
SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
SEMATTRS_HTTP_ROUTE,
SEMATTRS_HTTP_STATUS_CODE,
SEMATTRS_HTTP_TARGET,
SEMATTRS_HTTP_URL,
SEMATTRS_NET_HOST_PORT,
SEMATTRS_NET_PEER_IP,
SEMATTRS_NET_PEER_NAME,
SEMATTRS_NET_PEER_PORT,
SEMATTRS_NET_TRANSPORT,
} from '@opentelemetry/semantic-conventions';
@ -43,7 +59,7 @@ import * as assert from 'assert';
import * as nock from 'nock';
import * as path from 'path';
import { HttpInstrumentation } from '../../src/http';
import { HttpInstrumentationConfig } from '../../src/types';
import { HttpInstrumentationConfig, SemconvStability } from '../../src/types';
import { assertSpan } from '../utils/assertSpan';
import { DummyPropagation } from '../utils/DummyPropagation';
import { httpRequest } from '../utils/httpRequest';
@ -63,6 +79,7 @@ instrumentation.enable();
instrumentation.disable();
import * as http from 'http';
import { AttributeNames } from '../../src/enums/AttributeNames';
const applyCustomAttributesOnSpanErrorMessage =
'bad applyCustomAttributesOnSpan function';
@ -156,7 +173,7 @@ describe('HttpInstrumentation', () => {
memoryExporter.reset();
});
before(() => {
before(async () => {
const config: HttpInstrumentationConfig = {
ignoreIncomingPaths: [
(url: string) => {
@ -184,7 +201,7 @@ describe('HttpInstrumentation', () => {
response.end('Test Server Response');
});
server.listen(serverPort);
await new Promise<void>(resolve => server.listen(serverPort, resolve));
});
after(() => {
@ -237,7 +254,7 @@ describe('HttpInstrumentation', () => {
instrumentation.disable();
});
it('allows to disable outgoing request instrumentation', () => {
it('allows to disable outgoing request instrumentation', async () => {
server.close();
instrumentation.disable();
@ -249,14 +266,14 @@ describe('HttpInstrumentation', () => {
response.end('Test Server Response');
});
server.listen(serverPort);
await new Promise<void>(resolve => server.listen(serverPort, resolve));
assert.strictEqual(isWrapped(http.Server.prototype.emit), true);
assert.strictEqual(isWrapped(http.get), false);
assert.strictEqual(isWrapped(http.request), false);
});
it('allows to disable incoming request instrumentation', () => {
it('allows to disable incoming request instrumentation', async () => {
server.close();
instrumentation.disable();
@ -268,7 +285,7 @@ describe('HttpInstrumentation', () => {
response.end('Test Server Response');
});
server.listen(serverPort);
await new Promise<void>(resolve => server.listen(serverPort, resolve));
assert.strictEqual(isWrapped(http.Server.prototype.emit), false);
assert.strictEqual(isWrapped(http.get), true);
@ -281,7 +298,7 @@ describe('HttpInstrumentation', () => {
memoryExporter.reset();
});
before(() => {
before(async () => {
instrumentation.setConfig({
ignoreIncomingPaths: [
'/ignored/string',
@ -347,7 +364,7 @@ describe('HttpInstrumentation', () => {
response.end('Test Server Response');
});
server.listen(serverPort);
await new Promise<void>(resolve => server.listen(serverPort, resolve));
});
after(() => {
@ -1013,6 +1030,137 @@ describe('HttpInstrumentation', () => {
});
});
describe('with semconv stability set to http', () => {
beforeEach(() => {
memoryExporter.reset();
});
before(async () => {
instrumentation.setConfig({});
instrumentation['_semconvStability'] = SemconvStability.STABLE;
instrumentation.enable();
server = http.createServer((request, response) => {
if (request.url?.includes('/premature-close')) {
response.destroy();
return;
}
if (request.url?.includes('/hang')) {
// write response headers.
response.write('');
// hang the request.
return;
}
if (request.url?.includes('/destroy-request')) {
// force flush http response header to trigger client response callback
response.write('');
setTimeout(() => {
request.socket.destroy();
}, 100);
return;
}
if (request.url?.includes('/ignored')) {
provider.getTracer('test').startSpan('some-span').end();
}
if (request.url?.includes('/setroute')) {
const rpcData = getRPCMetadata(context.active());
assert.ok(rpcData != null);
assert.strictEqual(rpcData.type, RPCType.HTTP);
assert.strictEqual(rpcData.route, undefined);
rpcData.route = 'TheRoute';
}
response.end('Test Server Response');
});
await new Promise<void>(resolve => server.listen(serverPort, resolve));
});
after(() => {
server.close();
instrumentation.disable();
});
it('should generate semconv 1.27 spans', async () => {
const response = await httpRequest.get(
`${protocol}://${hostname}:${serverPort}${pathname}`
);
const spans = memoryExporter.getFinishedSpans();
const [_, outgoingSpan] = spans;
assert.strictEqual(spans.length, 2);
// should have only required and recommended attributes for semconv 1.27
assert.deepStrictEqual(outgoingSpan.attributes, {
[ATTR_HTTP_REQUEST_METHOD]: HTTP_REQUEST_METHOD_VALUE_GET,
[ATTR_SERVER_ADDRESS]: hostname,
[ATTR_SERVER_PORT]: serverPort,
[ATTR_URL_FULL]: `${protocol}://${hostname}:${serverPort}${pathname}`,
[ATTR_HTTP_RESPONSE_STATUS_CODE]: 200,
[ATTR_NETWORK_PEER_ADDRESS]: response.address,
[ATTR_NETWORK_PEER_PORT]: serverPort,
[ATTR_NETWORK_PROTOCOL_VERSION]: '1.1',
});
});
});
describe('with semconv stability set to http/dup', () => {
beforeEach(() => {
memoryExporter.reset();
instrumentation.setConfig({});
});
before(async () => {
instrumentation['_semconvStability'] = SemconvStability.DUPLICATE;
instrumentation.enable();
server = http.createServer((_, response) => {
response.end('Test Server Response');
});
await new Promise<void>(resolve => server.listen(serverPort, resolve));
});
after(() => {
server.close();
instrumentation.disable();
});
it('should create client spans with semconv 1.27 and old 1.7', async () => {
const response = await httpRequest.get(
`${protocol}://${hostname}:${serverPort}${pathname}`
);
const spans = memoryExporter.getFinishedSpans();
assert.strictEqual(spans.length, 2);
const outgoingSpan = spans[1];
// should have only required and recommended attributes for semconv 1.27
assert.deepStrictEqual(outgoingSpan.attributes, {
// 1.27 attributes
[ATTR_HTTP_REQUEST_METHOD]: HTTP_REQUEST_METHOD_VALUE_GET,
[ATTR_SERVER_ADDRESS]: hostname,
[ATTR_SERVER_PORT]: serverPort,
[ATTR_URL_FULL]: `http://${hostname}:${serverPort}${pathname}`,
[ATTR_HTTP_RESPONSE_STATUS_CODE]: 200,
[ATTR_NETWORK_PEER_ADDRESS]: response.address,
[ATTR_NETWORK_PEER_PORT]: serverPort,
[ATTR_NETWORK_PROTOCOL_VERSION]: '1.1',
// 1.7 attributes
[SEMATTRS_HTTP_FLAVOR]: '1.1',
[SEMATTRS_HTTP_HOST]: `${hostname}:${serverPort}`,
[SEMATTRS_HTTP_METHOD]: 'GET',
[SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED]: 20,
[SEMATTRS_HTTP_STATUS_CODE]: 200,
[SEMATTRS_HTTP_TARGET]: '/test',
[SEMATTRS_HTTP_URL]: `http://${hostname}:${serverPort}${pathname}`,
[SEMATTRS_NET_PEER_IP]: response.address,
[SEMATTRS_NET_PEER_NAME]: hostname,
[SEMATTRS_NET_PEER_PORT]: serverPort,
[SEMATTRS_NET_TRANSPORT]: 'ip_tcp',
// unspecified old names
[AttributeNames.HTTP_STATUS_TEXT]: 'OK',
});
});
});
describe('with require parent span', () => {
beforeEach(done => {
memoryExporter.reset();
@ -1167,7 +1315,7 @@ describe('HttpInstrumentation', () => {
memoryExporter.reset();
});
before(() => {
before(async () => {
instrumentation.setConfig({
headersToSpanAttributes: {
client: {
@ -1187,7 +1335,7 @@ describe('HttpInstrumentation', () => {
response.end('Test Server Response');
});
server.listen(serverPort);
await new Promise<void>(resolve => server.listen(serverPort, resolve));
});
after(() => {

View File

@ -36,7 +36,11 @@ import { IncomingMessage, ServerResponse } from 'http';
import { Socket } from 'net';
import * as sinon from 'sinon';
import * as url from 'url';
import { IgnoreMatcher, ParsedRequestOptions } from '../../src/types';
import {
IgnoreMatcher,
ParsedRequestOptions,
SemconvStability,
} from '../../src/types';
import * as utils from '../../src/utils';
import { AttributeNames } from '../../src/enums/AttributeNames';
import { RPCType, setRPCMetadata } from '@opentelemetry/core';
@ -261,8 +265,11 @@ describe('Utility', () => {
{ spanId: '', traceId: '', traceFlags: TraceFlags.SAMPLED },
SpanKind.INTERNAL
);
/* tslint:disable-next-line:no-any */
utils.setSpanWithError(span, new Error(errorMessage));
utils.setSpanWithError(
span,
new Error(errorMessage),
SemconvStability.OLD
);
const attributes = span.attributes;
assert.strictEqual(
attributes[AttributeNames.HTTP_ERROR_MESSAGE],

View File

@ -22,6 +22,7 @@ type GetResult = Promise<{
resHeaders: http.IncomingHttpHeaders;
reqHeaders: http.OutgoingHttpHeaders;
method: string | undefined;
address?: string;
}>;
function get(input: string | URL, options?: http.RequestOptions): GetResult;
@ -46,6 +47,7 @@ function get(input: any, options?: any): GetResult {
reqHeaders: req.getHeaders ? req.getHeaders() : (req as any)._headers,
resHeaders: res.headers,
method: res.req.method,
address: req.socket?.remoteAddress,
});
});
resp.on('error', err => {

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/instrumentation-xml-http-request",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry instrumentation for XMLHttpRequest http client in web browsers",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -13,7 +13,6 @@
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"version": "node ../../../scripts/version-update.js",
"tdd": "karma start",
"test:browser": "karma start --single-run",
@ -56,18 +55,17 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-zone": "1.25.1",
"@opentelemetry/propagator-b3": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/context-zone": "1.26.0",
"@opentelemetry/propagator-b3": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -81,18 +79,18 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/sdk-trace-web": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/sdk-trace-web": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-xml-http-request",
"sideEffects": false

View File

@ -7,6 +7,9 @@
## Installation
**Note: Much of OpenTelemetry JS documentation is written assuming the compiled application is run as CommonJS.**
For more details on ECMAScript Modules vs CommonJS, refer to [esm-support](https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md).
```bash
npm install --save @opentelemetry/instrumentation
```
@ -108,7 +111,7 @@ export class MyInstrumentation extends InstrumentationBase {
// Later, but before the module to instrument is required
const myInstrumentationn = new MyInstrumentation();
const myInstrumentation = new MyInstrumentation();
myInstrumentation.setTracerProvider(provider); // this is optional, only if global TracerProvider shouldn't be used
myInstrumentation.setMeterProvider(meterProvider); // this is optional
myInstrumentation.enable();
@ -219,12 +222,17 @@ If nothing is specified the global registered provider is used. Usually this is
There might be use case where someone has the need for more providers within an application. Please note that special care must be takes in such setups
to avoid leaking information from one provider to the other because there are a lot places where e.g. the global `ContextManager` or `Propagator` is used.
## Instrumentation for ES Modules In Node.js (experimental)
## Instrumentation for ECMAScript Modules (ESM) in Node.js (experimental)
As the module loading mechanism for ESM is different than CJS, you need to select a custom loader so instrumentation can load hook on the ESM module it want to patch. To do so, you must provide the `--experimental-loader=@opentelemetry/instrumentation/hook.mjs` flag to the `node` binary. Alternatively you can set the `NODE_OPTIONS` environment variable to `NODE_OPTIONS="--experimental-loader=@opentelemetry/instrumentation/hook.mjs"`.
As the ESM module loader from Node.js is experimental, so is our support for it. Feel free to provide feedback or report issues about it.
Node.js uses a different module loader for ECMAScript Modules (ESM) vs. CommonJS (CJS).
A `require()` call will cause Node.js to use the CommonJS module loader.
An `import ...` statement or `import()` call will cause Node.js to use the ECMAScript module loader.
**Note**: ESM Instrumentation is not yet supported for Node 20.
If your application is written in JavaScript as ESM, or it must compile to ESM from TypeScript, then a loader hook is required to properly patch instrumentation.
The custom hook for ESM instrumentation is `--experimental-loader=@opentelemetry/instrumentation/hook.mjs`.
This flag must be passed to the `node` binary, which is often done as a startup command and/or in the `NODE_OPTIONS` environment variable.
For more details on ECMAScript Modules vs CommonJS, refer to [esm-support](https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md).
## Limitations

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/instrumentation",
"version": "0.52.1",
"version": "0.53.0",
"description": "Base class for node which OpenTelemetry instrumentation modules extend",
"author": "OpenTelemetry Authors",
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation",
@ -41,8 +41,6 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run tdd:node",
@ -72,7 +70,7 @@
"url": "https://github.com/open-telemetry/opentelemetry-js/issues"
},
"dependencies": {
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/api-logs": "0.53.0",
"@types/shimmer": "^1.2.0",
"import-in-the-middle": "^1.8.1",
"require-in-the-middle": "^7.1.1",
@ -84,15 +82,15 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/sdk-metrics": "1.25.1",
"@opentelemetry/sdk-metrics": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/semver": "7.5.8",
"@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cpx2": "2.0.0",
@ -109,7 +107,7 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},

View File

@ -41,7 +41,7 @@ export abstract class InstrumentationAbstract<
ConfigType extends InstrumentationConfig = InstrumentationConfig,
> implements Instrumentation<ConfigType>
{
protected _config: ConfigType;
protected _config: ConfigType = {} as ConfigType;
private _tracer: Tracer;
private _meter: Meter;
@ -53,12 +53,7 @@ export abstract class InstrumentationAbstract<
public readonly instrumentationVersion: string,
config: ConfigType
) {
// copy config first level properties to ensure they are immutable.
// nested properties are not copied, thus are mutable from the outside.
this._config = {
enabled: true,
...config,
};
this.setConfig(config);
this._diag = diag.createComponentLogger({
namespace: instrumentationName,
@ -144,12 +139,15 @@ export abstract class InstrumentationAbstract<
/**
* Sets InstrumentationConfig to this plugin
* @param InstrumentationConfig
* @param config
*/
public setConfig(config: ConfigType): void {
// copy config first level properties to ensure they are immutable.
// nested properties are not copied, thus are mutable from the outside.
this._config = { ...config };
this._config = {
enabled: true,
...config,
};
}
/**

View File

@ -30,9 +30,9 @@ interface TestInstrumentationConfig extends InstrumentationConfig {
isActive?: boolean;
}
class TestInstrumentation extends InstrumentationBase {
constructor(config: TestInstrumentationConfig & InstrumentationConfig = {}) {
super('test', '1.0.0', Object.assign({}, config));
class TestInstrumentation extends InstrumentationBase<TestInstrumentationConfig> {
constructor(config = {}) {
super('test', '1.0.0', config);
}
override enable() {}
override disable() {}
@ -117,7 +117,7 @@ describe('BaseInstrumentation', () => {
});
describe('getConfig', () => {
it('should return instrumentation config', () => {
it('should return instrumentation config, "enabled" should be true by default', () => {
const instrumentation: Instrumentation = new TestInstrumentation({
isActive: false,
});
@ -125,6 +125,7 @@ describe('BaseInstrumentation', () => {
instrumentation.getConfig() as TestInstrumentationConfig;
assert.notStrictEqual(configuration, null);
assert.strictEqual(configuration.isActive, false);
assert.strictEqual(configuration.enabled, true);
});
});
@ -139,6 +140,18 @@ describe('BaseInstrumentation', () => {
instrumentation.getConfig() as TestInstrumentationConfig;
assert.strictEqual(configuration.isActive, true);
});
it('should ensure "enabled" defaults to true', () => {
const instrumentation: Instrumentation = new TestInstrumentation();
const config: TestInstrumentationConfig = {
isActive: true,
};
instrumentation.setConfig(config);
const configuration =
instrumentation.getConfig() as TestInstrumentationConfig;
assert.strictEqual(configuration.enabled, true);
assert.strictEqual(configuration.isActive, true);
});
});
describe('getModuleDefinitions', () => {

View File

@ -9,6 +9,9 @@ This package provides the full OpenTelemetry SDK for Node.js including tracing a
## Quick Start
**Note: Much of OpenTelemetry JS documentation is written assuming the compiled application is run as CommonJS.**
For more details on ECMAScript Modules vs CommonJS, refer to [esm-support](https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md).
To get started you need to install `@opentelemetry/sdk-node`, a metrics and/or tracing exporter, and any appropriate instrumentation for the node modules used by your application.
### Installation
@ -191,19 +194,19 @@ This is an alternative to programmatically configuring an exporter or span proce
### Exporters
| Environment variable | Description |
|----------------------|-------------|
| Environment variable | Description |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OTEL_TRACES_EXPORTER | List of exporters to be used for tracing, separated by commas. Options include `otlp`, `jaeger`, `zipkin`, and `none`. Default is `otlp`. `none` means no autoconfigured exporter. |
| OTEL_LOGS_EXPORTER | List of exporters to be used for logging, separated by commas. Options include `otlp`, `console` and `none`. Default is `otlp`. `none` means no autoconfigured exporter. |
| OTEL_LOGS_EXPORTER | List of exporters to be used for logging, separated by commas. Options include `otlp`, `console` and `none`. Default is `otlp`. `none` means no autoconfigured exporter. |
### OTLP Exporter
| Environment variable | Description |
|----------------------|-------------|
| OTEL_EXPORTER_OTLP_PROTOCOL | The transport protocol to use on OTLP trace, metric, and log requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_EXPORTER_OTLP_TRACES_PROTOCOL | The transport protocol to use on OTLP trace requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_EXPORTER_OTLP_METRICS_PROTOCOL | The transport protocol to use on OTLP metric requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_EXPORTER_OTLP_LOGS_PROTOCOL | The transport protocol to use on OTLP log requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| Environment variable | Description |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| OTEL_EXPORTER_OTLP_PROTOCOL | The transport protocol to use on OTLP trace, metric, and log requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_EXPORTER_OTLP_TRACES_PROTOCOL | The transport protocol to use on OTLP trace requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_EXPORTER_OTLP_METRICS_PROTOCOL | The transport protocol to use on OTLP metric requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_EXPORTER_OTLP_LOGS_PROTOCOL | The transport protocol to use on OTLP log requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
Additionally, you can specify other applicable environment variables that apply to each exporter such as the following:

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/sdk-node",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry SDK for Node.js",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -10,7 +10,6 @@
"compile": "tsc --build",
"clean": "tsc --build --clean",
"test": "nyc mocha test/**/*.test.ts",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"version": "node ../../../scripts/version-update.js",
@ -45,35 +44,34 @@
"access": "public"
},
"dependencies": {
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/exporter-trace-otlp-grpc": "0.52.1",
"@opentelemetry/exporter-trace-otlp-http": "0.52.1",
"@opentelemetry/exporter-trace-otlp-proto": "0.52.1",
"@opentelemetry/exporter-logs-otlp-grpc": "0.52.1",
"@opentelemetry/exporter-logs-otlp-http": "0.52.1",
"@opentelemetry/exporter-logs-otlp-proto": "0.52.1",
"@opentelemetry/exporter-zipkin": "1.25.1",
"@opentelemetry/instrumentation": "0.52.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-logs": "0.52.1",
"@opentelemetry/sdk-metrics": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/sdk-trace-node": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1"
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/exporter-logs-otlp-grpc": "0.53.0",
"@opentelemetry/exporter-logs-otlp-http": "0.53.0",
"@opentelemetry/exporter-logs-otlp-proto": "0.53.0",
"@opentelemetry/exporter-trace-otlp-grpc": "0.53.0",
"@opentelemetry/exporter-trace-otlp-http": "0.53.0",
"@opentelemetry/exporter-trace-otlp-proto": "0.53.0",
"@opentelemetry/exporter-zipkin": "1.26.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-logs": "0.53.0",
"@opentelemetry/sdk-metrics": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@opentelemetry/sdk-trace-node": "1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"peerDependencies": {
"@opentelemetry/api": ">=1.3.0 <1.10.0"
},
"devDependencies": {
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "1.25.1",
"@opentelemetry/exporter-jaeger": "1.25.1",
"@opentelemetry/context-async-hooks": "1.26.0",
"@opentelemetry/exporter-jaeger": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/semver": "7.5.8",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",

View File

@ -66,7 +66,7 @@ import {
serviceInstanceIdDetectorSync,
} from '@opentelemetry/resources';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { logs } from '@opentelemetry/api-logs';
import { logs, ProxyLoggerProvider } from '@opentelemetry/api-logs';
import {
SimpleLogRecordProcessor,
InMemoryLogRecordExporter,
@ -90,6 +90,7 @@ describe('Node SDK', () => {
let ctxManager: any;
let propagator: any;
let delegate: any;
let logsDelegate: any;
beforeEach(() => {
diag.disable();
@ -102,6 +103,9 @@ describe('Node SDK', () => {
ctxManager = context['_getContextManager']();
propagator = propagation['_getGlobalPropagator']();
delegate = (trace.getTracerProvider() as ProxyTracerProvider).getDelegate();
logsDelegate = (
logs.getLoggerProvider() as ProxyLoggerProvider
).getDelegate();
});
afterEach(() => {
@ -113,6 +117,7 @@ describe('Node SDK', () => {
// need to set OTEL_TRACES_EXPORTER to none since default value is otlp
// which sets up an exporter and affects the context manager
env.OTEL_TRACES_EXPORTER = 'none';
env.OTEL_LOGS_EXPORTER = 'none';
const sdk = new NodeSDK({
autoDetectResources: false,
});
@ -135,6 +140,11 @@ describe('Node SDK', () => {
'tracer provider should not have changed'
);
assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));
assert.strictEqual(
(logs.getLoggerProvider() as ProxyLoggerProvider).getDelegate(),
logsDelegate,
'logger provider should not have changed'
);
delete env.OTEL_TRACES_EXPORTER;
await sdk.shutdown();
});
@ -327,7 +337,10 @@ describe('Node SDK', () => {
'tracer provider should not have changed'
);
assert.ok(logs.getLoggerProvider() instanceof LoggerProvider);
assert.ok(
(logs.getLoggerProvider() as ProxyLoggerProvider) instanceof
LoggerProvider
);
await sdk.shutdown();
delete env.OTEL_TRACES_EXPORTER;
});

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/otlp-exporter-base",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry OTLP Exporter base (for internal use only)",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -17,8 +17,6 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
@ -62,18 +60,17 @@
"access": "public"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-transformer": "0.52.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-transformer": "0.53.0"
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -87,12 +84,12 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/otlp-exporter-base",
"sideEffects": false

View File

@ -1,13 +1,12 @@
{
"name": "@opentelemetry/otlp-grpc-exporter-base",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry OTLP-gRPC Exporter base (for internal use only)",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js",
"scripts": {
"prepublishOnly": "npm run compile",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"compile": "tsc --build",
"clean": "tsc --build --clean",
"lint": "eslint . --ext .ts",
@ -48,12 +47,11 @@
},
"devDependencies": {
"@opentelemetry/api": "1.9.0",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -63,13 +61,13 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@grpc/grpc-js": "^1.7.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/otlp-exporter-base": "0.52.1",
"@opentelemetry/otlp-transformer": "0.52.1"
"@opentelemetry/core": "1.26.0",
"@opentelemetry/otlp-exporter-base": "0.53.0",
"@opentelemetry/otlp-transformer": "0.53.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/otlp-grpc-exporter-base",
"sideEffects": false

View File

@ -160,7 +160,8 @@ export function configureCompression(
const envCompression =
getEnv().OTEL_EXPORTER_OTLP_TRACES_COMPRESSION ||
getEnv().OTEL_EXPORTER_OTLP_COMPRESSION;
getEnv().OTEL_EXPORTER_OTLP_COMPRESSION ||
'none';
if (envCompression === 'gzip') {
return CompressionAlgorithm.GZIP;

View File

@ -4,7 +4,7 @@
"publishConfig": {
"access": "public"
},
"version": "0.52.1",
"version": "0.53.0",
"description": "Transform OpenTelemetry SDK data into OTLP",
"module": "build/esm/index.js",
"esnext": "build/esnext/index.js",
@ -28,7 +28,6 @@
"prewatch": "node ../../../scripts/version-update.js",
"watch": "npm run protos && tsc -w tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
@ -66,7 +65,6 @@
"@types/mocha": "10.0.7",
"@types/webpack-env": "1.16.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -77,18 +75,18 @@
"lerna": "6.6.2",
"mocha": "10.7.3",
"nyc": "15.1.0",
"protobufjs-cli": "1.1.2",
"protobufjs-cli": "1.1.3",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0"
"webpack": "5.94.0"
},
"dependencies": {
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-logs": "0.52.1",
"@opentelemetry/sdk-metrics": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-logs": "0.53.0",
"@opentelemetry/sdk-metrics": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"protobufjs": "^7.3.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/otlp-transformer",

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/propagator-aws-xray-lambda",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenTelemetry AWS Xray propagator provides context propagation for systems that are using AWS X-Ray format.",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@ -46,14 +46,13 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": "1.9.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"babel-loader": "8.3.0",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -63,7 +62,7 @@
"typescript": "4.4.4"
},
"dependencies": {
"@opentelemetry/propagator-aws-xray": "1.25.1"
"@opentelemetry/propagator-aws-xray": "1.26.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/propagator-aws-xray-lambda#readme"
}

View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,8 @@
module.exports = {
"env": {
"mocha": true,
"commonjs": true,
"node": true,
},
...require('../../../eslint.base.js')
}

View File

@ -0,0 +1,4 @@
/bin
/coverage
/doc
/test

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,66 @@
# Jaeger Remote Sampler
[![NPM Published Version][npm-img]][npm-url]
[![Apache License][license-image]][license-image]
**Note: This is an experimental package under active development. Minor releases may include breaking changes.**
The Jaeger Remote Sampler package is designed for OpenTelemetry to dynamically fetch and update sampling strategies from a Jaeger agent or collector. This enables applications to adjust their sampling strategies based on the current configuration provided by Jaeger, optimizing for both performance and observability.
## Installation
```bash
npm install --save @opentelemetry/sampler-jaeger-remote
```
## Usage
To integrate the Jaeger Remote Sampler with your application, configure it with the endpoint of your Jaeger agent or collector. The sampler can be set up as follows:
```javascript
const { JaegerRemoteSampler } = require('@opentelemetry/sampler-jaeger-remote');
const { Resource } = require('@opentelemetry/resources');
const { NodeTracerProvider } = require('@opentelemetry/node');
// Jaeger agent endpoint
const sampler = new JaegerRemoteSampler({
endpoint: 'http://your-jaeger-agent:14268/api/sampling',
serviceName: 'your-service-name',
initialSampler: new AlwaysOnSampler(),
poolingInterval: 60000 // 60 seconds
});
const provider = new NodeTracerProvider({
resource: Resource.default().merge(new Resource({
'service.name': 'your-service-name'
})),
sampler
});
provider.register();
```
## Supported Configuration Options
The Jaeger Remote Sampler supports the following sampling strategies based on the configuration received from the remote endpoint:
1. **Per-Operation Sampling**: If the remote configuration includes `operationSampling` with `perOperationStrategies`, it creates a `PerOperationSampler`. This allows for different sampling rates for different operations.
2. **Probabilistic Sampling**: If the remote configuration specifies `StrategyType.PROBABILISTIC`, it creates a `TraceIdRatioBasedSampler`. This samples a percentage of traces based on the trace ID.
3. **Default Sampling**: If none of the above apply, it falls back to the initial sampler provided in the constructor.
## Useful links
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
- For more about OpenTelemetry JavaScript: <https://github.com/open-telemetry/opentelemetry-js>
- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
## License
Apache 2.0 - See [LICENSE][license-url] for more information.
[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/sampler-jaeger-remote
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fsampler-jaeger-remote.svg

View File

@ -0,0 +1,67 @@
{
"name": "@opentelemetry/sampler-jaeger-remote",
"version": "0.53.0",
"description": "Jaeger Remote Sampler",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js",
"scripts": {
"prepublishOnly": "npm run compile",
"compile": "tsc --build",
"clean": "tsc --build --clean",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
"test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
"version": "node ../../../scripts/version-update.js",
"watch": "tsc -w",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
"nodejs",
"metrics",
"stats"
],
"author": "OpenTelemetry Authors",
"license": "Apache-2.0",
"engines": {
"node": ">=14"
},
"files": [
"build/src/**/*.js",
"build/src/**/*.js.map",
"build/src/**/*.d.ts",
"LICENSE",
"README.md"
],
"publishConfig": {
"access": "public"
},
"dependencies": {
"@opentelemetry/sdk-trace-base": "1.26.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
},
"devDependencies": {
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"cross-var": "1.1.0",
"eslint-plugin-header": "^3.1.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.1.3",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
"ts-loader": "8.4.0",
"typescript": "4.4.4"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/sampler-jaeger-remote",
"sideEffects": false
}

View File

@ -0,0 +1,139 @@
/*
* 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 { Link, SpanKind, Attributes, diag, Context } from '@opentelemetry/api';
import {
Sampler,
SamplingResult,
ParentBasedSampler,
TraceIdRatioBasedSampler,
} from '@opentelemetry/sdk-trace-base';
import axios from 'axios';
import { PerOperationSampler } from './PerOperationSampler';
import { SamplingStrategyResponse, StrategyType } from './types';
interface JaegerRemoteSamplerOptions {
/** Address of a service that implements the Remote Sampling API, such as Jaeger Collector or OpenTelemetry Collector */
endpoint: string;
/** Service name for Remote Sampling API */
serviceName?: string;
/** Polling interval for getting configuration from remote */
poolingInterval: number;
/** Initial sampler that is used before the first configuration is fetched */
initialSampler: Sampler;
}
/** JaegerRemoteSampler */
export class JaegerRemoteSampler implements Sampler {
private _endpoint: string;
private _serviceName?: string;
private _poolingInterval: number;
private _sampler: Sampler;
private _syncingConfig: boolean;
constructor(config: JaegerRemoteSamplerOptions) {
this._endpoint = config.endpoint;
this._serviceName = config.serviceName;
this._poolingInterval = config.poolingInterval;
this._sampler = config.initialSampler;
this._syncingConfig = false;
setInterval(async () => {
if (this._syncingConfig) {
return;
}
this._syncingConfig = true;
try {
await this.getAndUpdateSampler();
} catch (err) {
diag.warn('Could not update sampler', err);
} finally {
this._syncingConfig = false;
}
}, this._poolingInterval);
}
shouldSample(
context: Context,
traceId: string,
spanName: string,
spanKind: SpanKind,
attributes: Attributes,
links: Link[]
): SamplingResult {
return this._sampler.shouldSample(
context,
traceId,
spanName,
spanKind,
attributes,
links
);
}
toString(): string {
return `JaegerRemoteSampler{endpoint=${this._endpoint},${
this._serviceName && ` serviceName=${this._serviceName},`
} poolingInterval=${this._poolingInterval}, sampler=${this._sampler}}`;
}
private async getAndUpdateSampler() {
const newConfig = await this.getSamplerConfig(this._serviceName);
this._sampler = await this.convertSamplingResponseToSampler(newConfig);
}
private convertSamplingResponseToSampler(
newConfig: SamplingStrategyResponse
): Sampler {
const perOperationStrategies =
newConfig.operationSampling?.perOperationStrategies;
if (
newConfig.operationSampling &&
perOperationStrategies &&
perOperationStrategies.length > 0
) {
const defaultSampler: Sampler = new TraceIdRatioBasedSampler(
newConfig.operationSampling.defaultSamplingProbability
);
return new ParentBasedSampler({
root: new PerOperationSampler({
defaultSampler,
perOperationStrategies,
}),
});
}
switch (newConfig.strategyType) {
case StrategyType.PROBABILISTIC:
return new ParentBasedSampler({
root: new TraceIdRatioBasedSampler(
newConfig.probabilisticSampling.samplingRate
),
});
default:
diag.warn(`Strategy ${newConfig.strategyType} not supported.`);
return this._sampler;
}
}
private async getSamplerConfig(
serviceName?: string
): Promise<SamplingStrategyResponse> {
const response = await axios.get<SamplingStrategyResponse>(
`${this._endpoint}/sampling?service=${serviceName ?? ''}`
);
return response.data;
}
}

View File

@ -0,0 +1,82 @@
/*
* 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, SpanKind, Link, SpanAttributes } from '@opentelemetry/api';
import {
Sampler,
SamplingResult,
TraceIdRatioBasedSampler,
} from '@opentelemetry/sdk-trace-base';
import { PerOperationStrategy } from './types';
interface PerOperationSamplerOptions {
/** The default sampler to use in case span does not have a custom strategy. */
defaultSampler: Sampler;
/** Stores strategies for every custom span. */
perOperationStrategies: PerOperationStrategy[];
}
/** PerOperationSampler to be used from JaegerRemoteSampler */
export class PerOperationSampler implements Sampler {
private _defaultSampler: Sampler;
private _perOperationSampler: Map<string, Sampler>;
constructor(config: PerOperationSamplerOptions) {
this._defaultSampler = config.defaultSampler;
this._perOperationSampler = new Map<string, Sampler>(
config.perOperationStrategies.map(perOperationStrategy => [
perOperationStrategy.operation,
new TraceIdRatioBasedSampler(
perOperationStrategy.probabilisticSampling.samplingRate
),
])
);
}
private getSamplerForOperation(spanName: string): Sampler {
let resultantSampler = this._perOperationSampler.get(spanName);
if (resultantSampler == null) {
resultantSampler = this._defaultSampler;
}
return resultantSampler;
}
shouldSample(
context: Context,
traceId: string,
spanName: string,
spanKind: SpanKind,
attributes: SpanAttributes,
links: Link[]
): SamplingResult {
return this.getSamplerForOperation(spanName).shouldSample(
context,
traceId,
spanName,
spanKind,
attributes,
links
);
}
toString(): string {
return `PerOperationSampler{default=${
this._defaultSampler
}, perOperationSamplers={${Array.from(this._perOperationSampler).map(
([key, value]) => `${key}=${value}`
)}}}`;
}
}

View File

@ -0,0 +1,18 @@
/*
* 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 { JaegerRemoteSampler } from './JaegerRemoteSampler';
export { StrategyType, ProbabilisticSamplingOptions } from './types';

View File

@ -0,0 +1,67 @@
/*
* 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.
*/
/**
* Enum representing different types of sampling strategies.
*/
export enum StrategyType {
/** Constant sampling strategy */
CONST = 'CONST',
/** Probabilistic sampling strategy */
PROBABILISTIC = 'PROBABILISTIC',
/** Rate-limiting sampling strategy */
RATELIMITING = 'RATELIMITING',
/** Remote sampling strategy */
REMOTE = 'REMOTE',
}
/**
* Interface for probabilistic sampling options.
*/
export interface ProbabilisticSamplingOptions {
/** The sampling rate, typically a number between 0 and 1 */
samplingRate: number;
}
/**
* Interface representing a per-operation sampling strategy.
*/
export interface PerOperationStrategy {
/** The name or identifier of the operation */
operation: string;
/** The probabilistic sampling options for this operation */
probabilisticSampling: ProbabilisticSamplingOptions;
}
/**
* Interface representing the response of a sampling strategy.
*/
export interface SamplingStrategyResponse {
/** The type of sampling strategy being used */
strategyType: StrategyType;
/** The probabilistic sampling options */
probabilisticSampling: ProbabilisticSamplingOptions;
/** Optional operation-specific sampling configuration */
operationSampling?: {
/** The default sampling probability for operations */
defaultSamplingProbability: number;
/** The default lower bound of traces per second */
defaultLowerBoundTracesPerSecond: number;
/** Array of per-operation sampling strategies */
perOperationStrategies: PerOperationStrategy[];
/** The default upper bound of traces per second */
defaultUpperBoundTracesPerSecond: number;
};
}

View File

@ -0,0 +1,526 @@
/*
* 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 {
AlwaysOffSampler,
AlwaysOnSampler,
ParentBasedSampler,
SamplingDecision,
TraceIdRatioBasedSampler,
} from '@opentelemetry/sdk-trace-base';
import * as api from '@opentelemetry/api';
import { JaegerRemoteSampler } from '../src';
import * as sinon from 'sinon';
import * as assert from 'assert';
import { SpanKind } from '@opentelemetry/api';
import { SamplingStrategyResponse, StrategyType } from '../src/types';
import { PerOperationSampler } from '../src/PerOperationSampler';
import { randomSamplingProability } from './utils';
import axios from 'axios';
describe('JaegerRemoteSampler', () => {
const endpoint = 'http://localhost:5778';
const serviceName = 'foo';
const alwaysOnSampler = new AlwaysOnSampler();
const alwaysOffSampler = new AlwaysOffSampler();
const numberOfIterations = Math.floor((Math.random() + 0.01) * 100);
const poolingInterval = Math.floor((Math.random() + 0.01) * 5 * 1000);
let clock: sinon.SinonFakeTimers;
beforeEach(() => {
clock = sinon.useFakeTimers(Date.now());
});
afterEach(() => {
clock.restore();
});
describe('constructor', () => {
let getAndUpdateSamplerStub: sinon.SinonStub;
beforeEach(() => {
getAndUpdateSamplerStub = sinon
.stub(JaegerRemoteSampler.prototype, 'getAndUpdateSampler' as any)
.resolves();
});
afterEach(() => {
getAndUpdateSamplerStub.restore();
});
it('Test Sampler to run at fixed poolingInterval', async () => {
new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval * numberOfIterations);
sinon.assert.callCount(getAndUpdateSamplerStub, numberOfIterations);
});
it('Dont try to sync if already syncing.', async () => {
getAndUpdateSamplerStub.callsFake(
async () =>
new Promise(resolve => setTimeout(resolve, poolingInterval + 1000))
);
new JaegerRemoteSampler({
endpoint,
poolingInterval,
serviceName,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval * 2);
sinon.assert.callCount(getAndUpdateSamplerStub, 1);
});
it('Doesnt throw unhandled promise rejection when failing to get remote config', async () => {
getAndUpdateSamplerStub.rejects();
const unhandledRejectionListener = sinon.fake();
process.once('unhandledRejection', unhandledRejectionListener);
new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval * 2);
sinon.assert.callCount(getAndUpdateSamplerStub, 2);
sinon.assert.callCount(unhandledRejectionListener, 0);
});
});
describe('shouldSample', () => {
let samplerStubInstance: sinon.SinonStubbedInstance<AlwaysOnSampler>;
beforeEach(() => {
samplerStubInstance = sinon.createStubInstance(AlwaysOnSampler);
samplerStubInstance.shouldSample.returns({
decision: SamplingDecision.RECORD,
});
});
it('Should return SamplingDecision.RECORD decision provided by the current sampler set in it.', async () => {
const jaegerRemoteSampler = new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: samplerStubInstance,
});
assert.equal(
jaegerRemoteSampler.shouldSample(
api.ROOT_CONTEXT,
'',
'',
SpanKind.CLIENT,
{},
[]
).decision,
SamplingDecision.RECORD
);
});
});
describe('getAndUpdateSampler', () => {
let getSamplerConfigStub: sinon.SinonStub;
let convertSamplingResponseToSamplerStub: sinon.SinonStub;
const sampleSamplingStrategyResponse: SamplingStrategyResponse = {
strategyType: StrategyType.PROBABILISTIC,
probabilisticSampling: {
samplingRate: 0,
},
operationSampling: {
defaultSamplingProbability: 0,
defaultLowerBoundTracesPerSecond: 0,
perOperationStrategies: [],
defaultUpperBoundTracesPerSecond: 0,
},
};
beforeEach(() => {
getSamplerConfigStub = sinon
.stub(JaegerRemoteSampler.prototype, 'getSamplerConfig' as any)
.resolves(sampleSamplingStrategyResponse);
convertSamplingResponseToSamplerStub = sinon
.stub(
JaegerRemoteSampler.prototype,
'convertSamplingResponseToSampler' as any
)
.resolves(alwaysOffSampler);
});
afterEach(() => {
getSamplerConfigStub.restore();
convertSamplingResponseToSamplerStub.restore();
});
it('getSamplerConfig is called with service name set in the constructor.', async () => {
new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
sinon.assert.calledWithExactly(getSamplerConfigStub, serviceName);
});
it('convertSamplingResponseToSampler is passed config provided by getSamplerConfig.', async () => {
new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
sinon.assert.calledWithExactly(
convertSamplingResponseToSamplerStub,
sampleSamplingStrategyResponse
);
});
it('internal sampler is set to sampler returned by convertSamplingResponseToSampler.', async () => {
const jaegerRemoteSampler = new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
assert.equal(jaegerRemoteSampler['_sampler'], alwaysOffSampler);
});
});
describe('convertSamplingResponseToSampler', () => {
let getSamplerConfigStub: sinon.SinonStub;
beforeEach(() => {
getSamplerConfigStub = sinon.stub(
JaegerRemoteSampler.prototype,
'getSamplerConfig' as any
);
});
afterEach(() => {
getSamplerConfigStub.restore();
});
describe('defaultStrategy', () => {
it('Use root level samplingRate when operationSampling object is null.', async () => {
const samplingRate = randomSamplingProability();
const samplingStrategyResponseWithoutPerOperationStrategies: SamplingStrategyResponse =
{
strategyType: StrategyType.PROBABILISTIC,
probabilisticSampling: {
samplingRate,
},
};
getSamplerConfigStub.resolves(
samplingStrategyResponseWithoutPerOperationStrategies
);
const jaegerRemoteSampler = new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
const jaegerCurrentSampler = jaegerRemoteSampler['_sampler'];
assert.equal(jaegerCurrentSampler instanceof ParentBasedSampler, true);
const parentBasedRootSampler = (
jaegerCurrentSampler as ParentBasedSampler
)['_root'];
assert.equal(
parentBasedRootSampler instanceof TraceIdRatioBasedSampler,
true
);
const internalTraceIdRatioBasedSamplerRatio = (
parentBasedRootSampler as TraceIdRatioBasedSampler
)['_ratio'];
assert.equal(internalTraceIdRatioBasedSamplerRatio, samplingRate);
});
it('Use root level samplingRate perOperation Strategies is a empty array.', async () => {
const samplingRate = randomSamplingProability();
const samplingStrategyResponseWithoutPerOperationStrategies: SamplingStrategyResponse =
{
strategyType: StrategyType.PROBABILISTIC,
probabilisticSampling: {
samplingRate,
},
operationSampling: {
defaultSamplingProbability: 1.5,
defaultLowerBoundTracesPerSecond: 1.6,
perOperationStrategies: [],
defaultUpperBoundTracesPerSecond: 18,
},
};
getSamplerConfigStub.resolves(
samplingStrategyResponseWithoutPerOperationStrategies
);
const jaegerRemoteSampler = new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
const jaegerCurrentSampler = jaegerRemoteSampler['_sampler'];
assert.equal(jaegerCurrentSampler instanceof ParentBasedSampler, true);
const parentBasedRootSampler = (
jaegerCurrentSampler as ParentBasedSampler
)['_root'];
assert.equal(
parentBasedRootSampler instanceof TraceIdRatioBasedSampler,
true
);
const internalTraceIdRatioBasedSamplerRatio = (
parentBasedRootSampler as TraceIdRatioBasedSampler
)['_ratio'];
assert.equal(internalTraceIdRatioBasedSamplerRatio, samplingRate);
});
});
describe('perOperationStrategy', () => {
const defaultSamplingProbability = randomSamplingProability();
const op1SamplingRate = randomSamplingProability();
const op2SamplingRate = randomSamplingProability();
const op1 = 'op1';
const op2 = 'op2';
const samplingStrategyResponseWithPerOperationStrategies: SamplingStrategyResponse =
{
strategyType: StrategyType.PROBABILISTIC,
probabilisticSampling: {
samplingRate: 1.5,
},
operationSampling: {
defaultSamplingProbability,
defaultLowerBoundTracesPerSecond: 1.6,
perOperationStrategies: [
{
operation: op1,
probabilisticSampling: {
samplingRate: op1SamplingRate,
},
},
{
operation: op2,
probabilisticSampling: {
samplingRate: op2SamplingRate,
},
},
],
defaultUpperBoundTracesPerSecond: 1.8,
},
};
beforeEach(() => {
getSamplerConfigStub.resolves(
samplingStrategyResponseWithPerOperationStrategies
);
});
it('Use default probability from inside operationSampling object and perOperationStrategies values for specific operations.', async () => {
const jaegerRemoteSampler = new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
const jaegerCurrentSampler = jaegerRemoteSampler['_sampler'];
assert.equal(jaegerCurrentSampler instanceof ParentBasedSampler, true);
const parentBasedRootSampler = (
jaegerCurrentSampler as ParentBasedSampler
)['_root'];
assert.equal(
parentBasedRootSampler instanceof PerOperationSampler,
true
);
const perOperationSampler =
parentBasedRootSampler as PerOperationSampler;
const defaultSampler =
perOperationSampler['getSamplerForOperation']('');
assert.equal(defaultSampler instanceof TraceIdRatioBasedSampler, true);
const defautRatio = (defaultSampler as TraceIdRatioBasedSampler)[
'_ratio'
];
assert.equal(defaultSamplingProbability, defautRatio);
const op1Sampler = perOperationSampler['getSamplerForOperation'](op1);
assert.equal(op1Sampler instanceof TraceIdRatioBasedSampler, true);
const op1Ratio = (op1Sampler as TraceIdRatioBasedSampler)['_ratio'];
assert.equal(op1SamplingRate, op1Ratio);
const op2Sampler = perOperationSampler['getSamplerForOperation'](op2);
assert.equal(op2Sampler instanceof TraceIdRatioBasedSampler, true);
const op2Ratio = (op2Sampler as TraceIdRatioBasedSampler)['_ratio'];
assert.equal(op2SamplingRate, op2Ratio);
});
});
describe('errorCase', () => {
let diagWarnStub: sinon.SinonStub;
const invalidStrategyType = 'ANY_TEXT';
const errorSamplingStrategyResponse = {
strategyType: invalidStrategyType,
probabilisticSampling: {
samplingRate: 0,
},
operationSampling: {
defaultSamplingProbability: 0,
defaultLowerBoundTracesPerSecond: 0,
perOperationStrategies: [],
defaultUpperBoundTracesPerSecond: 0,
},
};
beforeEach(() => {
getSamplerConfigStub.resolves(errorSamplingStrategyResponse);
diagWarnStub = sinon.stub(api.diag, 'warn');
});
it('Throw error when unsupported strategy type is sent by api.', async () => {
new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
sinon.assert.calledOnceWithExactly(
diagWarnStub,
`Strategy ${invalidStrategyType} not supported.`
);
});
});
});
describe('toString', () => {
let getSamplerConfigStub: sinon.SinonStub;
const defaultSamplingProbability = randomSamplingProability();
const op1SamplingRate = randomSamplingProability();
const op1 = 'op1';
const samplingStrategyResponseWithPerOperationStrategies: SamplingStrategyResponse =
{
strategyType: StrategyType.PROBABILISTIC,
probabilisticSampling: {
samplingRate: 1.5,
},
operationSampling: {
defaultSamplingProbability,
defaultLowerBoundTracesPerSecond: 1.6,
perOperationStrategies: [
{
operation: op1,
probabilisticSampling: {
samplingRate: op1SamplingRate,
},
},
],
defaultUpperBoundTracesPerSecond: 1.8,
},
};
beforeEach(() => {
getSamplerConfigStub = sinon.stub(
JaegerRemoteSampler.prototype,
'getSamplerConfig' as any
);
});
afterEach(() => {
getSamplerConfigStub.restore();
});
beforeEach(() => {
getSamplerConfigStub.resolves(
samplingStrategyResponseWithPerOperationStrategies
);
});
it('Should reflect sampler name with current sampler runninng in it', async () => {
const jaegerRemoteSampler = new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
const jaegerCurrentSampler = jaegerRemoteSampler.toString();
assert.equal(
jaegerCurrentSampler,
`JaegerRemoteSampler{endpoint=${endpoint}, serviceName=${serviceName}, poolingInterval=${poolingInterval}, sampler=ParentBased{root=PerOperationSampler{default=TraceIdRatioBased{${defaultSamplingProbability}}, perOperationSamplers={${op1}=TraceIdRatioBased{${op1SamplingRate}}}}, remoteParentSampled=AlwaysOnSampler, remoteParentNotSampled=AlwaysOffSampler, localParentSampled=AlwaysOnSampler, localParentNotSampled=AlwaysOffSampler}}`
);
});
});
describe('getSamplerConfig', () => {
let axiosGetStub: sinon.SinonStub;
beforeEach(() => {
axiosGetStub = sinon.stub(axios, 'get');
});
afterEach(() => {
axiosGetStub.restore();
});
it('Should pass endpoint and service name.', async () => {
new JaegerRemoteSampler({
endpoint,
serviceName,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
sinon.assert.calledOnceWithExactly(
axiosGetStub,
`${endpoint}/sampling?service=${serviceName}`
);
});
it('Should pass endpoint and blank service name if nothing is provided.', async () => {
new JaegerRemoteSampler({
endpoint,
serviceName: undefined,
poolingInterval,
initialSampler: alwaysOnSampler,
});
await clock.tickAsync(poolingInterval);
sinon.assert.calledOnceWithExactly(
axiosGetStub,
`${endpoint}/sampling?service=`
);
});
});
});

View File

@ -0,0 +1,52 @@
/*
* 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 {
AlwaysOnSampler,
SamplingDecision,
} from '@opentelemetry/sdk-trace-base';
import { PerOperationSampler } from '../src/PerOperationSampler';
import sinon = require('sinon');
import * as api from '@opentelemetry/api';
describe('PerOPerationSampler', () => {
describe('shouldSample', () => {
let samplerStubInstance1: sinon.SinonStubbedInstance<AlwaysOnSampler>;
beforeEach(() => {
samplerStubInstance1 = sinon.createStubInstance(AlwaysOnSampler);
samplerStubInstance1.shouldSample.returns({
decision: SamplingDecision.RECORD,
});
});
it('Should return samplingDecision decision provided by default sampler.', async () => {
const perOperationSampler = new PerOperationSampler({
defaultSampler: samplerStubInstance1,
perOperationStrategies: [],
});
perOperationSampler.shouldSample(
api.ROOT_CONTEXT,
'',
'',
api.SpanKind.CLIENT,
{},
[]
);
sinon.assert.callCount(samplerStubInstance1.shouldSample, 1);
});
});
});

View File

@ -0,0 +1,20 @@
/*
* 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 const randomSamplingProability = () => {
const rand = Math.random() + 0.01;
return rand > 1 ? rand - 0.01 : rand;
};

View File

@ -0,0 +1,19 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "build",
"rootDir": "."
},
"include": [
"src/**/*.ts",
"test/**/*.ts"
],
"references": [
{
"path": "../../../api"
},
{
"path": "../../../packages/opentelemetry-sdk-trace-base"
}
]
}

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/sdk-events",
"version": "0.52.1",
"version": "0.53.0",
"publishConfig": {
"access": "public"
},
@ -24,8 +24,6 @@
},
"scripts": {
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
@ -76,9 +74,8 @@
"@types/node": "18.6.5",
"@types/sinon": "10.0.20",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -92,13 +89,13 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"dependencies": {
"@opentelemetry/api-events": "0.52.1",
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/sdk-logs": "0.52.1"
"@opentelemetry/api-events": "0.53.0",
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/sdk-logs": "0.53.0"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/sdk-logs",
"version": "0.52.1",
"version": "0.53.0",
"publishConfig": {
"access": "public"
},
@ -36,7 +36,6 @@
"test:browser": "karma start --single-run",
"tdd": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"version": "node ../../../scripts/version-update.js",
@ -73,7 +72,7 @@
},
"devDependencies": {
"@babel/core": "7.25.2",
"@babel/preset-env": "7.25.3",
"@babel/preset-env": "7.25.4",
"@opentelemetry/api": ">=1.4.0 <1.10.0",
"@opentelemetry/api-logs": "0.52.0",
"@opentelemetry/resources_1.9.0": "npm:@opentelemetry/resources@1.9.0",
@ -81,7 +80,6 @@
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
@ -95,13 +93,13 @@
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
},
"dependencies": {
"@opentelemetry/api-logs": "0.52.1",
"@opentelemetry/core": "1.25.1",
"@opentelemetry/resources": "1.25.1"
"@opentelemetry/api-logs": "0.53.0",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/resources": "1.26.0"
}
}

View File

@ -23,6 +23,8 @@ import type { LogRecordExporter } from './LogRecordExporter';
/**
* This is implementation of {@link LogRecordExporter} that prints LogRecords to the
* console. This class can be used for diagnostic purposes.
*
* NOTE: This {@link LogRecordExporter} is intended for diagnostics use only, output rendered to the console may change at any time.
*/
/* eslint-disable no-console */

View File

@ -32,7 +32,8 @@ import {
import { BatchLogRecordProcessorBase } from '../../../src/export/BatchLogRecordProcessorBase';
import { reconfigureLimits } from '../../../src/config';
import { LoggerProviderSharedState } from '../../../src/internal/LoggerProviderSharedState';
import { Resource, ResourceAttributes } from '@opentelemetry/resources';
import { Attributes } from '@opentelemetry/api';
import { Resource } from '@opentelemetry/resources';
class BatchLogRecordProcessor extends BatchLogRecordProcessorBase<BufferConfig> {
onInit() {}
@ -316,7 +317,7 @@ describe('BatchLogRecordProcessorBase', () => {
const processor = new BatchLogRecordProcessor(exporter);
const asyncResource = new Resource(
{},
new Promise<ResourceAttributes>(resolve => {
new Promise<Attributes>(resolve => {
setTimeout(() => resolve({ async: 'fromasync' }), 1);
})
);

View File

@ -21,7 +21,8 @@ import {
loggingErrorHandler,
setGlobalErrorHandler,
} from '@opentelemetry/core';
import { Resource, ResourceAttributes } from '@opentelemetry/resources';
import { Attributes } from '@opentelemetry/api';
import { Resource } from '@opentelemetry/resources';
import { Resource as Resource190 } from '@opentelemetry/resources_1.9.0';
import {
@ -121,7 +122,7 @@ describe('SimpleLogRecordProcessor', () => {
const exporter = new InMemoryLogRecordExporter();
const asyncResource = new Resource(
{},
new Promise<ResourceAttributes>(resolve => {
new Promise<Attributes>(resolve => {
setTimeout(() => resolve({ async: 'fromasync' }), 1);
})
);
@ -143,7 +144,7 @@ describe('SimpleLogRecordProcessor', () => {
const testExporterWithDelay = new TestExporterWithDelay();
const asyncResource = new Resource(
{},
new Promise<ResourceAttributes>(resolve => {
new Promise<Attributes>(resolve => {
setTimeout(() => resolve({ async: 'fromasync' }), 1);
})
);

View File

@ -1,6 +1,6 @@
{
"name": "@opentelemetry/shim-opencensus",
"version": "0.52.1",
"version": "0.53.0",
"description": "OpenCensus to OpenTelemetry shim",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@ -15,7 +15,6 @@
"clean": "tsc --build --clean",
"tdd": "npm run test -- --extension ts --watch",
"test": "nyc mocha test/**/*.test.ts",
"codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"version": "node ../../../scripts/version-update.js",
@ -51,12 +50,11 @@
"devDependencies": {
"@opencensus/core": "0.1.0",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "1.25.1",
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/context-async-hooks": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.7.3",
@ -66,12 +64,12 @@
},
"peerDependencies": {
"@opencensus/core": "^0.1.0",
"@opentelemetry/api": "^1.0.0"
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
"@opentelemetry/core": "1.25.1",
"@opentelemetry/resources": "1.25.1",
"@opentelemetry/sdk-metrics": "1.25.1",
"@opentelemetry/core": "1.26.0",
"@opentelemetry/resources": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0",
"require-in-the-middle": "^7.1.1",
"semver": "^7.5.2"
},

View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,7 @@
module.exports = {
env: {
mocha: true,
node: true,
},
...require('../../../eslint.base.js'),
};

View File

@ -0,0 +1,4 @@
/bin
/coverage
/doc
/test

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,30 @@
# OpenTelemetry Web Utils
[![NPM Published Version][npm-img]][npm-url]
[![Apache License][license-image]][license-image]
**Note: This is an experimental package under active development. New releases may include breaking changes.**
This package contains classes and utils that are common for web use cases.
## Installation
```bash
npm install --save @opentelemetry/web-common
```
## Useful links
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
- For more about OpenTelemetry JavaScript: <https://github.com/open-telemetry/opentelemetry-js>
- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
## License
Apache 2.0 - See [LICENSE][license-url] for more information.
[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/sdk-logs
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fsdk%2Dlogs.svg

View File

@ -0,0 +1,26 @@
/*!
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const karmaWebpackConfig = require('../../../karma.webpack');
const karmaBaseConfig = require('../../../karma.base');
module.exports = config => {
config.set(
Object.assign({}, karmaBaseConfig, {
webpack: karmaWebpackConfig,
})
);
};

View File

@ -0,0 +1,101 @@
{
"name": "@opentelemetry/web-common",
"version": "0.53.0",
"publishConfig": {
"access": "public"
},
"description": "Common utilities for web instrumentation",
"author": "OpenTelemetry Authors",
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/web-common",
"license": "Apache-2.0",
"main": "build/src/index.js",
"module": "build/esm/index.js",
"esnext": "build/esnext/index.js",
"types": "build/src/index.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/open-telemetry/opentelemetry-js.git"
},
"bugs": {
"url": "https://github.com/open-telemetry/opentelemetry-js/issues"
},
"engines": {
"node": ">=14"
},
"scripts": {
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
"prepublishOnly": "npm run compile",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "npm run precompile",
"tdd": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
"test": "nyc mocha test/**/*.test.ts",
"test:browser": "karma start --single-run",
"version": "node ../../../scripts/version-update.js",
"watch": "tsc --build --watch tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
"web",
"tracing",
"profiling",
"stats",
"monitoring"
],
"files": [
"build/esm/**/*.js",
"build/esm/**/*.js.map",
"build/esm/**/*.d.ts",
"build/esnext/**/*.js",
"build/esnext/**/*.js.map",
"build/esnext/**/*.d.ts",
"build/src/**/*.js",
"build/src/**/*.js.map",
"build/src/**/*.d.ts",
"doc",
"LICENSE",
"README.md"
],
"sideEffects": false,
"peerDependencies": {
"@opentelemetry/api": ">=1.4.0 <1.10.0"
},
"dependencies": {
"@opentelemetry/sdk-logs": "^0.53.0",
"@opentelemetry/sdk-trace-base": "^1.26.0",
"@opentelemetry/semantic-conventions": "1.27.0"
},
"devDependencies": {
"@babel/core": "7.25.2",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/api-events": "0.53.0",
"@opentelemetry/api-logs": "0.53.0",
"@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/sinon": "10.0.20",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.4.1",
"babel-plugin-istanbul": "7.0.0",
"cross-var": "1.1.0",
"karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
"karma-coverage": "2.2.1",
"karma-mocha": "2.0.1",
"karma-spec-reporter": "0.0.36",
"karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.7.3",
"nyc": "15.1.0",
"sinon": "15.1.2",
"ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.94.0",
"webpack-cli": "5.1.4",
"webpack-merge": "5.10.0"
}
}

View File

@ -0,0 +1,49 @@
/*
* 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 } from '@opentelemetry/api';
import { LogRecord, LogRecordProcessor } from '@opentelemetry/sdk-logs';
import { ATTR_SESSION_ID } from '@opentelemetry/semantic-conventions/incubating';
import { SessionProvider } from './types/SessionProvider';
/**
* SessionLogRecordProcessor is a {@link SpanProcessor} adds the session.id attribute
*/
export class SessionLogRecordProcessor implements LogRecordProcessor {
private _sessionIdProvider: SessionProvider;
constructor(sessionIdProvider: SessionProvider) {
this._sessionIdProvider = sessionIdProvider;
}
onEmit(logRecord: LogRecord, _context?: Context | undefined): void {
const sessionId = this._sessionIdProvider?.getSessionId();
if (sessionId) {
logRecord.setAttribute(ATTR_SESSION_ID, sessionId);
}
}
/**
* Forces to export all finished spans
*/
async forceFlush(): Promise<void> {}
/**
* Shuts down the processor. Called when SDK is shut down. This is an
* opportunity for processor to do any cleanup required.
*/
async shutdown(): Promise<void> {}
}

View File

@ -0,0 +1,67 @@
/*
* 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 } from '@opentelemetry/api';
import {
SpanProcessor,
Span,
ReadableSpan,
} from '@opentelemetry/sdk-trace-base';
import { ATTR_SESSION_ID } from '@opentelemetry/semantic-conventions/incubating';
import { SessionProvider } from './types/SessionProvider';
/**
* SessionSpanProcessor is a {@link SpanProcessor} that adds the session.id attribute
*/
export class SessionSpanProcessor implements SpanProcessor {
private _sessionIdProvider: SessionProvider;
constructor(sessionIdProvider: SessionProvider) {
this._sessionIdProvider = sessionIdProvider;
}
/**
* Forces to export all finished spans
*/
async forceFlush(): Promise<void> {}
/**
* Called when a {@link Span} is started, if the `span.isRecording()`
* returns true.
* @param span the Span that just started.
*/
onStart(span: Span, _parentContext: Context): void {
const sessionId = this._sessionIdProvider?.getSessionId();
if (sessionId) {
span.setAttribute(ATTR_SESSION_ID, sessionId);
}
}
/**
* Called when a {@link ReadableSpan} is ended, if the `span.isRecording()`
* returns true.
* @param span the Span that just ended.
*/
onEnd(_: ReadableSpan): void {
// no-op
}
/**
* Shuts down the processor. Called when SDK is shut down. This is an
* opportunity for processor to do any cleanup required.
*/
async shutdown(): Promise<void> {}
}

View 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 { SessionProvider } from './types/SessionProvider';
export {
createSessionSpanProcessor,
createSessionLogRecordProcessor,
} from './utils';

View File

@ -0,0 +1,19 @@
/*
* 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 interface SessionProvider {
getSessionId(): string | null;
}

View File

@ -0,0 +1,33 @@
/*
* 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 { SessionProvider } from './types/SessionProvider';
import { SpanProcessor } from '@opentelemetry/sdk-trace-base';
import { SessionSpanProcessor } from './SessionSpanProcessor';
import { LogRecordProcessor } from '@opentelemetry/sdk-logs';
import { SessionLogRecordProcessor } from './SessionLogRecordProcessor';
export function createSessionSpanProcessor(
sessionProvider: SessionProvider
): SpanProcessor {
return new SessionSpanProcessor(sessionProvider);
}
export function createSessionLogRecordProcessor(
sessionProvider: SessionProvider
): LogRecordProcessor {
return new SessionLogRecordProcessor(sessionProvider);
}

Some files were not shown because too many files have changed in this diff Show More