diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
index 5cadb10953d..5e195159de6 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -45,14 +45,14 @@ body:
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { ConsoleSpanExporter } = require('@opentelemetry/sdk-trace-base');
const { Resource } = require('@opentelemetry/resources');
- const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
+ const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
// configure the SDK to export telemetry data to the console
// enable all auto-instrumentations from the meta package
const traceExporter = new ConsoleSpanExporter();
const sdk = new opentelemetry.NodeSDK({
resource: new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: 'my-service',
+ [SEMRESATTRS_SERVICE_NAME]: 'my-service',
}),
traceExporter,
instrumentations: [getNodeAutoInstrumentations()]
diff --git a/.github/repository-settings.md b/.github/repository-settings.md
index c5f00a2e3e2..e36ce47e530 100644
--- a/.github/repository-settings.md
+++ b/.github/repository-settings.md
@@ -10,8 +10,8 @@ No changes
## Collaborators and Teams
-* There is currently no `javascript-triagers` role
-* `javascript-maintainers` has `Admin` permission
+- There is currently no `javascript-triagers` role
+- `javascript-maintainers` has `Admin` permission
## Branches
@@ -19,13 +19,13 @@ No changes
### `main`
-* Uncheck "Restrict who can push to matching branches"
-* Check "Require merge queue"
- * Build concurrency: 5
- * Minimum pull requests to merge: 1 or after 5 minutes
- * Maximum pull requests to merge: 5
- * Check "Only merge non-failing pull requests"
- * Status check timeout: 60 minutes
+- Uncheck "Restrict who can push to matching branches"
+- Check "Require merge queue"
+ - Build concurrency: 5
+ - Minimum pull requests to merge: 1 or after 5 minutes
+ - Maximum pull requests to merge: 5
+ - Check "Only merge non-failing pull requests"
+ - Status check timeout: 60 minutes
### `dependabot/**/**`
@@ -36,10 +36,10 @@ Our dependencies are managed by a bot which creates PRs from a fork.
This is a special branch which we use to publish the automatically generated docs.
It is exempt from most protections.
-
-* "Allow force pushes from everyone" (requires write permission)
+
+- "Allow force pushes from everyone" (requires write permission)
## Pages
-* Source: Deploy from a branch
-* Branch: `gh-pages` `/ (root)`
+- Source: Deploy from a branch
+- Branch: `gh-pages` `/ (root)`
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 81608395315..8197a4f89fb 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -21,22 +21,6 @@ jobs:
package-lock.json
node-version: '20'
- - name: Lint changelog file
- uses: avto-dev/markdown-lint@v1
- with:
- # Commenting due to
- # https://github.com/avto-dev/markdown-lint/blob/aab9be9823fcd706f6da3e6ad6c64874c23fbd4c/lint/rules/changelog.js#L51-L71
- # TODO: adhere to, or overwrite above rule and uncomment rules
- # rules: "/lint/rules/changelog.js"
- config: "/lint/config/changelog.yml"
- args: "./CHANGELOG.md"
-
- - name: Lint markdown files
- uses: avto-dev/markdown-lint@v1
- with:
- args: "./**/*.md"
- ignore: './CHANGELOG.md ./experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/protos ./experimental/packages/opentelemetry-exporter-metrics-otlp-proto/protos ./packages/exporter-trace-otlp-grpc/protos ./packages/exporter-trace-otlp-proto/protos'
-
- name: Bootstrap
run: npm ci
@@ -44,6 +28,7 @@ jobs:
run: |
npm run lint
npm run lint:examples
+ npm run lint:markdown
- name: Lint doc files
run: |
diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml
new file mode 100644
index 00000000000..a99ad66a139
--- /dev/null
+++ b/.github/workflows/sbom.yml
@@ -0,0 +1,79 @@
+name: SBOM
+on:
+ release:
+ types: [published]
+
+permissions: read-all
+
+jobs:
+ generate-sboms:
+ runs-on: ubuntu-latest
+ env:
+ NPM_CONFIG_UNSAFE_PERM: true
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - run: npm install -g npm@latest
+
+ - name: Bootstrap
+ run: npm ci
+
+ - name: Generate SBOM for core packages
+ if: ${{ ! startsWith(github.ref, 'refs/tags/experimental') && ! startsWith(github.ref, 'refs/tags/api') }}
+ run: |
+ for dir in $(find packages -mindepth 1 -maxdepth 1 -type d)
+ do
+ dir_name=$(basename "$dir")
+ echo "Generating SBOM for $dir_name"
+ npm sbom --sbom-format=spdx --legacy-peer-deps --workspace ${dir} > "opentelemetry-js_${dir_name}.spdx.json"
+ done
+
+ - name: Generate SBOM for the API package
+ if: startsWith(github.ref, 'refs/tags/api/')
+ run: |
+ npm sbom --sbom-format=spdx --legacy-peer-deps --workspace api > opentelemetry-js_api.spdx.json
+
+ - name: Generate SBOMs for experimental packages
+ if: startsWith(github.ref, 'refs/tags/experimental/')
+ run: |
+ for dir in $(find experimental/packages -mindepth 1 -maxdepth 1 -type d)
+ do
+ dir_name=$(basename "$dir")
+ echo "Generating SBOM for $dir_name"
+ npm sbom --sbom-format=spdx --legacy-peer-deps --workspace ${dir} > "opentelemetry-js_${dir_name}.spdx.json"
+ done
+
+ - name: Zip all SBOM files
+ run: |
+ zip sbom.zip *.spdx.json
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: SBOM.zip
+ path: ./sbom.zip
+
+ add-release-artifact:
+ needs: generate-sboms
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Download artifact from generate-sboms
+ uses: actions/download-artifact@v4
+ with:
+ name: SBOM.zip
+ - name: Upload release asset
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ github.event.release.upload_url }}
+ asset_path: ./sbom.zip
+ asset_name: SBOM.zip
+ asset_content_type: application/zip
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index 430964f594a..46719b405a7 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -14,6 +14,7 @@ jobs:
node_version:
- "18"
- "20"
+ - "22"
runs-on: ubuntu-latest
env:
NPM_CONFIG_UNSAFE_PERM: true
@@ -130,8 +131,6 @@ jobs:
- "8"
- "10"
- "12"
- - "14"
- - "16"
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -148,7 +147,7 @@ jobs:
working-directory: ./api
run: |
npm install --ignore-scripts
- npm install @types/mocha@^7 mocha@^7 ts-loader@^8 ts-mocha@^8
+ npm install @types/mocha@^7 mocha@^7 ts-loader@^8
node ../scripts/version-update.js
npx tsc --build tsconfig.json tsconfig.esm.json
diff --git a/.gitignore b/.gitignore
index 6c3473bdbd0..8bea02a1b00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -91,3 +91,6 @@ package.json.lerna_backup
# non-aggregated benchmark results
.benchmark-results.txt
+
+# release notes for release creation
+.tmp/
diff --git a/.gitmodules b/.gitmodules
index 33a9a7d9b21..78c96d882d2 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "experimental/packages/otlp-grpc-exporter-base/protos"]
- path = experimental/packages/otlp-grpc-exporter-base/protos
- url = https://github.com/open-telemetry/opentelemetry-proto.git
-[submodule "experimental/packages/otlp-proto-exporter-base/protos"]
- path = experimental/packages/otlp-proto-exporter-base/protos
+[submodule "experimental/packages/otlp-transformer/protos"]
+ path = experimental/packages/otlp-transformer/protos
url = https://github.com/open-telemetry/opentelemetry-proto.git
diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc
new file mode 100644
index 00000000000..54ea8e7f3af
--- /dev/null
+++ b/.markdownlint-cli2.jsonc
@@ -0,0 +1,15 @@
+// https://github.com/DavidAnson/markdownlint-cli2#markdownlint-cli2jsonc
+{
+ "config": {
+ // https://github.com/DavidAnson/markdownlint/blob/main/README.md#rules--aliases
+ "MD013": false,
+ "MD024": false,
+ "MD033": false,
+ "MD041": false,
+ "MD026": false,
+ "MD004": { "style": "dash" } // ul-style
+ },
+ "gitignore": true,
+ "noBanner": true,
+ "noProgress": true
+}
diff --git a/.markdownlint.json b/.markdownlint.json
deleted file mode 100644
index 6208ac19f1d..00000000000
--- a/.markdownlint.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "MD013": false,
- "MD024": false,
- "MD033": false,
- "MD041": false,
- "MD026": false
-}
diff --git a/.mocharc.yml b/.mocharc.yml
new file mode 100644
index 00000000000..45bd4bdc15e
--- /dev/null
+++ b/.mocharc.yml
@@ -0,0 +1 @@
+require: 'ts-node/register'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 29b9a3ce9ee..729a8067c4a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,4 @@
+
# CHANGELOG
All notable changes to this project will be documented in this file.
@@ -15,14 +16,90 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/
### :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
+
### :bug: (Bug Fix)
-* fix(sdk-metrics): increase the depth of the output to the console such that objects in the metric are printed fully to the console [#4522](https://github.com/open-telemetry/opentelemetry-js/pull/4522) @JacksonWeber
+* 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
### :books: (Refine Doc)
### :house: (Internal)
+* refactor: Simplify the code for the `getEnv` function [#4799](https://github.com/open-telemetry/opentelemetry-js/pull/4799) @danstarns
+
+## 1.25.1
+
+### :books: (Refine Doc)
+
+* refactor(examples): added usage of @opentelemetry/semantic-conventions and @opentelemetry/resources to the examples in examples/opentelemetry-web for maintaining consistency across all examples. [#4764](https://github.com/open-telemetry/opentelemetry-js/pull/4764) @Zen-cronic
+
+### :house: (Internal)
+
+* refactor(context-zone-peer-dep): use explicit exports [#4785](https://github.com/open-telemetry/opentelemetry-js/pull/4787) @pichlermarc
+* refactor(context-async-hooks): use explicit exports [#4785](https://github.com/open-telemetry/opentelemetry-js/pull/4786) @pichlermarc
+
+## 1.25.0
+
+### :rocket: (Enhancement)
+
+* feat: support node 22 [#4666](https://github.com/open-telemetry/opentelemetry-js/pull/4666) @dyladan
+* feat(context-zone*): support zone.js 0.12.x [#4376](https://github.com/open-telemetry/opentelemetry-js/pull/4736) @maldago
+* refactor(core): Use tree-shakeable string constants for semconv [#4739](https://github.com/open-telemetry/opentelemetry-js/pull/4739) @JohannesHuster
+* refactor(shim-opentracing): Use tree-shakeable string constants for semconv [#4746](https://github.com/open-telemetry/opentelemetry-js/pull/4746) @JohannesHuster
+* refactor(sdk-trace-web): Use tree-shakeable string constants for semconv [#4747](https://github.com/open-telemetry/opentelemetry-js/pull/4747) @JohannesHuster
+* refactor(sdk-trace-node): Use tree-shakeable string constants for semconv [#4748](https://github.com/open-telemetry/opentelemetry-js/pull/4748) @JohannesHuster
+* refactor(sdk-trace-base): Use tree-shakeable string constants for semconv [#4749](https://github.com/open-telemetry/opentelemetry-js/pull/4749) @JohannesHuster
+* refactor(resources): update deprecated semconv to use exported strings [#4755](https://github.com/open-telemetry/opentelemetry-js/pull/#4755) @JamieDanielson
+* refactor(exporters): update deprecated semconv to use exported strings [#4756](https://github.com/open-telemetry/opentelemetry-js/pull/#4756) @JamieDanielson
+
+### :books: (Refine Doc)
+
+* refactor(examples): use new exported string constants for semconv in examples/esm-http-ts [#4758](https://github.com/open-telemetry/opentelemetry-js/pull/4758) @Zen-cronic
+* refactor(examples): use new exported string constants for semconv in examples/basic-tracer-node [#4759](https://github.com/open-telemetry/opentelemetry-js/pull/4759#pull) @Zen-cronic
+* refactor(examples): use new exported string constants for semconv in examples/http [#4750](https://github.com/open-telemetry/opentelemetry-js/pull/4750) @Zen-cronic
+* refactor(examples): use new exported string constants for semconv in examples/grpc-js [#4760](https://github.com/open-telemetry/opentelemetry-js/pull/4760#pull) @Zen-cronic
+* refactor(examples): use new exported string constants for semconv in examples/otlp-exporter-node [#4762](https://github.com/open-telemetry/opentelemetry-js/pull/4762) @Zen-cronic
+* refactor(examples): use new exported string constants for semconv in examples/opentracing-shim [#4761](https://github.com/open-telemetry/opentelemetry-js/pull/4761) @Zen-cronic
+
+## 1.24.1
+
+### :bug: (Bug Fix)
+
+* fix(core): align inconsistent behavior of `getEnv()` and `getEnvWithoutDefaults()` when a `process` polyfill is used [#4648](https://github.com/open-telemetry/opentelemetry-js/pull/4648) @pichlermarc
+ * `getEnvWithoutDefaults()` would use `process.env` if it was defined when running in a browser, while `getEnv()` would always use `_globalThis`. Now both use `_globalThis` when running in a browser.
+* fix(resources): prevent circular import (resource -> detector -> resource -> ...) [#4653](https://github.com/open-telemetry/opentelemetry-js/pull/4653) @pichlermarc
+ * fixes a circular import warning which would appear in rollup when bundling `@opentelemetry/resources`
+* fix(exporter-metrics-otlp-grpc): add explicit otlp-exporter-base dependency to exporter-metrics-otlp-grpc [#4678](https://github.com/open-telemetry/opentelemetry-js/pull/4678) @AkselAllas
+
+## 1.24.0
+
+### :rocket: (Enhancement)
+
+* feat(sdk-trace-base): log resource attributes in ConsoleSpanExporter [#4605](https://github.com/open-telemetry/opentelemetry-js/pull/4605) @pichlermarc
+* feat(propagator-aws-xray): moved AWS Xray propagator from contrib [4603](https://github.com/open-telemetry/opentelemetry-js/pull/4603) @martinkuba
+* feat(resources): new experimental detector ServiceInstanceIdDetectorSync that sets the value for `service.instance.id` as random UUID. [#4608](https://github.com/open-telemetry/opentelemetry-js/pull/4608) @maryliag
+
+### :bug: (Bug Fix)
+
+* fix(sdk-trace-web): fix invalid timings in span events [#4486](https://github.com/open-telemetry/opentelemetry-js/pull/4486) @Abinet18
+* fix(resources): ensure BrowserDetector does not think Node.js v21 is a browser [#4561](https://github.com/open-telemetry/opentelemetry-js/issues/4561) @trentm
+* fix(core): align inconsistent behavior of `getEnv()` and `getEnvWithoutDefaults()` when a `process` polyfill is used [#4648](https://github.com/open-telemetry/opentelemetry-js/pull/4648) @pichlermarc
+ * `getEnvWithoutDefaults()` would use `process.env` if it was defined when running in a browser, while `getEnv()` would always use `_globalThis`. Now both use `_globalThis` when running in a browser.
+
+## 1.23.0
+
+### :rocket: (Enhancement)
+
+* perf(sdk-trace-base): do not allocate arrays if resource has no pending async attributes [#4576](https://github.com/open-telemetry/opentelemetry-js/pull/4576) @Samuron
+* feat(sdk-metrics): added experimental synchronous gauge to SDK [#4565](https://github.com/open-telemetry/opentelemetry-js/pull/4565) @clintonb
+ * this change will become user-facing in an upcoming release
+
+### :bug: (Bug Fix)
+
+* fix(sdk-metrics): increase the depth of the output to the console such that objects in the metric are printed fully to the console [#4522](https://github.com/open-telemetry/opentelemetry-js/pull/4522) @JacksonWeber
+
## 1.22.0
### :rocket: (Enhancement)
@@ -31,6 +108,7 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/
* feat(instrumentation): Make `init()` method public [#4418](https://github.com/open-telemetry/opentelemetry-js/pull/4418)
* feat(context-zone-peer-dep, context-zone): support zone.js 0.13.x, 0.14.x [#4469](https://github.com/open-telemetry/opentelemetry-js/pull/4469) @pichlermarc
* chore: Semantic Conventions export individual strings [4185](https://github.com/open-telemetry/opentelemetry-js/issues/4185)
+* feat(sdk-trace-base): allow adding span links after span creation [#4536](https://github.com/open-telemetry/opentelemetry-js/pull/4536) @seemk
### :bug: (Bug Fix)
@@ -1882,7 +1960,7 @@ No changes
* `opentelemetry-api`, `opentelemetry-exporter-prometheus`, `opentelemetry-metrics`
* [#1137](https://github.com/open-telemetry/opentelemetry-js/pull/1137) Batch observer ([@obecny](https://github.com/obecny))
* `opentelemetry-exporter-collector`
- * [#1256](https://github.com/open-telemetry/opentelemetry-js/pull/1256) feat: [Collector Metric Exporter][1/x] Rename CollectorExporter to CollectorTraceExporter ([@davidwitten](https://github.com/davidwitten))
+ * [#1256](https://github.com/open-telemetry/opentelemetry-js/pull/1256) feat: Collector Metric Exporter [1/x] Rename CollectorExporter to CollectorTraceExporter ([@davidwitten](https://github.com/davidwitten))
### :rocket: (Enhancement)
diff --git a/CHANGELOG_NEXT.md b/CHANGELOG_NEXT.md
index d8949608e11..a41332c0fc8 100644
--- a/CHANGELOG_NEXT.md
+++ b/CHANGELOG_NEXT.md
@@ -1,3 +1,5 @@
+
+
## 2.0
### :boom: Breaking Change
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5fb78e3ba3b..516e67d5242 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -104,7 +104,7 @@ An entry into `CHANGELOG.md` or `experimental/CHANGELOG.md` is required for the
- Changes to default settings
- New components being added
-It is reasonable to omit an entry to the changelog under these circuimstances:
+It is reasonable to omit an entry to the changelog under these circumstances:
- Updating test to remove flakiness or improve coverage
- Updates to the CI/CD process
@@ -247,6 +247,13 @@ cd packages/opentelemetry-module-name
npm run lint:fix
```
+Similarly, Markdown files (such as README.md files) can be linted:
+
+```sh
+npm run lint:markdown
+npm run lint:markdown:fix # can automatically fix some Markdown rules
+```
+
### Generating docs
We use [typedoc](https://www.npmjs.com/package/typedoc) to generate the api documentation.
diff --git a/README.md b/README.md
index 34c05bbfa17..24942a07aa4 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# OpenTelemetry JavaScript SDK 2.0
-> [!WARNING]
+> [!WARNING]
> You have found the working branch for the work in progress 2.0 SDK.
> If you are a user, you are probably looking for the 1.x SDK on the main branch.
diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md
index f33bcbaddf4..860f839c371 100644
--- a/api/CHANGELOG.md
+++ b/api/CHANGELOG.md
@@ -1,3 +1,4 @@
+
# CHANGELOG
All notable changes to this project will be documented in this file.
@@ -14,6 +15,15 @@ All notable changes to this project will be documented in this file.
### :house: (Internal)
+## 1.9.0
+
+### :rocket: (Enhancement)
+
+* feat(metrics): added synchronous gauge [#4528](https://github.com/open-telemetry/opentelemetry-js/pull/4528) @clintonb
+* feat(api): allow adding span links after span creation [#4536](https://github.com/open-telemetry/opentelemetry-js/pull/4536) @seemk
+ * This change is non-breaking for end-users, but breaking for Trace SDK implmentations in accordance with the [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/a03382ada8afa9415266a84dafac0510ec8c160f/specification/upgrading.md?plain=1#L97-L122) as new features need to be implemented.
+* feat: support node 22 [#4666](https://github.com/open-telemetry/opentelemetry-js/pull/4666) @dyladan
+
## 1.8.0
### :rocket: (Enhancement)
@@ -93,13 +103,13 @@ All notable changes to this project will be documented in this file.
* export tracer options ([#154](https://www.github.com/open-telemetry/opentelemetry-js-api/issues/154)) ([b125324](https://www.github.com/open-telemetry/opentelemetry-js-api/commit/b125324438fb2f24eb80c7c6673afc8cfc99575e))
-### [1.0.4](https://www.github.com/open-telemetry/opentelemetry-js-api/compare/v1.0.3...v1.0.4) (2021-12-18)
+## [1.0.4](https://www.github.com/open-telemetry/opentelemetry-js-api/compare/v1.0.3...v1.0.4) (2021-12-18)
### Bug Fixes
* align globalThis fallbacks with otel-core ([#126](https://www.github.com/open-telemetry/opentelemetry-js-api/issues/126)) ([3507de7](https://www.github.com/open-telemetry/opentelemetry-js-api/commit/3507de7c3b95396696657c021953b0b24a63a029))
-### [1.0.3](https://www.github.com/open-telemetry/opentelemetry-js-api/compare/v1.0.2...v1.0.3) (2021-08-30)
+## [1.0.3](https://www.github.com/open-telemetry/opentelemetry-js-api/compare/v1.0.2...v1.0.3) (2021-08-30)
### Bug Fixes
diff --git a/api/README.md b/api/README.md
index 56dd23d177d..59d4cd7a08d 100644
--- a/api/README.md
+++ b/api/README.md
@@ -36,7 +36,7 @@ npm install @opentelemetry/api @opentelemetry/sdk-trace-base
### Trace Your Application
-In order to get started with tracing, you will need to first register an SDK. The SDK you are using may provide a convenience method which calls the registration methods for you, but if you would like to call them directly they are documented here: [sdk registration methods][docs-sdk-registration].
+In order to get started with tracing, you will need to first register an SDK. The SDK you are using may provide a convenience method which calls the registration methods for you, but if you would like to call them directly they are documented here: [SDK registration methods][docs-sdk-registration].
Once you have registered an SDK, you can start and end spans. A simple example of basic SDK registration and tracing a simple operation is below. The example should export spans to the console once per second. For more information, see the [tracing documentation][docs-tracing].
@@ -112,6 +112,5 @@ 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/api/LICENSE
-[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[docs-tracing]: https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/tracing.md
[docs-sdk-registration]: https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/sdk-registration.md
diff --git a/api/package.json b/api/package.json
index 39ee9b075c1..9f88c16fcd3 100644
--- a/api/package.json
+++ b/api/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/api",
- "version": "1.8.0",
+ "version": "1.9.0",
"description": "Public API for OpenTelemetry",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@@ -40,8 +40,8 @@
"lint:fix": "eslint . --ext .ts --fix",
"lint": "eslint . --ext .ts",
"test:browser": "karma start --single-run",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'",
- "test:eol": "ts-mocha -p tsconfig.json 'test/**/*.test.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts'",
+ "test:eol": "mocha 'test/**/*.test.ts'",
"test:webworker": "karma start karma.worker.js --single-run",
"cycle-check": "dpdm --exit-code circular:1 src/index.ts",
"version": "node ../scripts/version-update.js",
@@ -80,31 +80,30 @@
"access": "public"
},
"devDependencies": {
- "@types/mocha": "10.0.6",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"@types/webpack": "5.28.5",
"@types/webpack-env": "1.16.3",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"dpdm": "3.13.1",
- "karma": "6.4.2",
+ "karma": "6.4.4",
"karma-chrome-launcher": "3.1.0",
"karma-coverage": "2.2.1",
"karma-mocha": "2.0.1",
"karma-mocha-webworker": "1.3.0",
"karma-spec-reporter": "0.0.36",
- "karma-webpack": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"memfs": "3.5.3",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
- "unionfs": "4.5.1",
+ "unionfs": "4.5.4",
"webpack": "5.89.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/api",
diff --git a/api/src/index.ts b/api/src/index.ts
index c5dbe1685bf..af483a9a416 100644
--- a/api/src/index.ts
+++ b/api/src/index.ts
@@ -43,6 +43,7 @@ export { MeterProvider } from './metrics/MeterProvider';
export {
ValueType,
Counter,
+ Gauge,
Histogram,
MetricOptions,
Observable,
diff --git a/api/src/metrics/Meter.ts b/api/src/metrics/Meter.ts
index 1405ae74730..2cc0c2acd5f 100644
--- a/api/src/metrics/Meter.ts
+++ b/api/src/metrics/Meter.ts
@@ -17,6 +17,7 @@
import {
BatchObservableCallback,
Counter,
+ Gauge,
Histogram,
MetricAttributes,
MetricOptions,
@@ -45,6 +46,16 @@ export interface MeterOptions {
* for the exported metric are deferred.
*/
export interface Meter {
+ /**
+ * Creates and returns a new `Gauge`.
+ * @param name the name of the metric.
+ * @param [options] the metric options.
+ */
+ createGauge(
+ name: string,
+ options?: MetricOptions
+ ): Gauge;
+
/**
* Creates and returns a new `Histogram`.
* @param name the name of the metric.
diff --git a/api/src/metrics/Metric.ts b/api/src/metrics/Metric.ts
index e8abca3b1d7..b2a1b7326b8 100644
--- a/api/src/metrics/Metric.ts
+++ b/api/src/metrics/Metric.ts
@@ -98,6 +98,15 @@ export interface UpDownCounter<
add(value: number, attributes?: AttributesTypes, context?: Context): void;
}
+export interface Gauge<
+ AttributesTypes extends MetricAttributes = MetricAttributes,
+> {
+ /**
+ * Records a measurement.
+ */
+ record(value: number, attributes?: AttributesTypes, context?: Context): void;
+}
+
export interface Histogram<
AttributesTypes extends MetricAttributes = MetricAttributes,
> {
diff --git a/api/src/metrics/NoopMeter.ts b/api/src/metrics/NoopMeter.ts
index 81143c0dddb..7adea12f46a 100644
--- a/api/src/metrics/NoopMeter.ts
+++ b/api/src/metrics/NoopMeter.ts
@@ -18,15 +18,16 @@ import { Meter } from './Meter';
import {
BatchObservableCallback,
Counter,
+ Gauge,
Histogram,
+ MetricAttributes,
MetricOptions,
+ Observable,
ObservableCallback,
ObservableCounter,
ObservableGauge,
ObservableUpDownCounter,
UpDownCounter,
- MetricAttributes,
- Observable,
} from './Metric';
/**
@@ -36,6 +37,13 @@ import {
export class NoopMeter implements Meter {
constructor() {}
+ /**
+ * @see {@link Meter.createGauge}
+ */
+ createGauge(_name: string, _options?: MetricOptions): Gauge {
+ return NOOP_GAUGE_METRIC;
+ }
+
/**
* @see {@link Meter.createHistogram}
*/
@@ -114,6 +122,10 @@ export class NoopUpDownCounterMetric
add(_value: number, _attributes: MetricAttributes): void {}
}
+export class NoopGaugeMetric extends NoopMetric implements Gauge {
+ record(_value: number, _attributes: MetricAttributes): void {}
+}
+
export class NoopHistogramMetric extends NoopMetric implements Histogram {
record(_value: number, _attributes: MetricAttributes): void {}
}
@@ -140,6 +152,7 @@ export const NOOP_METER = new NoopMeter();
// Synchronous instruments
export const NOOP_COUNTER_METRIC = new NoopCounterMetric();
+export const NOOP_GAUGE_METRIC = new NoopGaugeMetric();
export const NOOP_HISTOGRAM_METRIC = new NoopHistogramMetric();
export const NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric();
diff --git a/api/src/trace/NonRecordingSpan.ts b/api/src/trace/NonRecordingSpan.ts
index a9e5bcaf9be..9ee3d28837a 100644
--- a/api/src/trace/NonRecordingSpan.ts
+++ b/api/src/trace/NonRecordingSpan.ts
@@ -21,6 +21,7 @@ import { INVALID_SPAN_CONTEXT } from './invalid-span-constants';
import { Span } from './span';
import { SpanContext } from './span_context';
import { SpanStatus } from './status';
+import { Link } from './link';
/**
* The NonRecordingSpan is the default {@link Span} that is used when no Span
@@ -52,6 +53,14 @@ export class NonRecordingSpan implements Span {
return this;
}
+ addLink(_link: Link): this {
+ return this;
+ }
+
+ addLinks(_links: Link[]): this {
+ return this;
+ }
+
// By default does nothing
setStatus(_status: SpanStatus): this {
return this;
diff --git a/api/src/trace/span.ts b/api/src/trace/span.ts
index d80b8c2626d..e3b563f103a 100644
--- a/api/src/trace/span.ts
+++ b/api/src/trace/span.ts
@@ -19,6 +19,7 @@ import { TimeInput } from '../common/Time';
import { SpanAttributes, SpanAttributeValue } from './attributes';
import { SpanContext } from './span_context';
import { SpanStatus } from './status';
+import { Link } from './link';
/**
* An interface that represents a span. A span represents a single operation
@@ -76,6 +77,26 @@ export interface Span {
startTime?: TimeInput
): this;
+ /**
+ * Adds a single link to the span.
+ *
+ * Links added after the creation will not affect the sampling decision.
+ * It is preferred span links be added at span creation.
+ *
+ * @param link the link to add.
+ */
+ addLink(link: Link): this;
+
+ /**
+ * Adds multiple links to the span.
+ *
+ * Links added after the creation will not affect the sampling decision.
+ * It is preferred span links be added at span creation.
+ *
+ * @param links the links to add.
+ */
+ addLinks(links: Link[]): this;
+
/**
* Sets a status to the span. If used, this will override the default Span
* status. Default is {@link SpanStatusCode.UNSET}. SetStatus overrides the value
diff --git a/api/test/common/internal/version.test.ts b/api/test/common/internal/version.test.ts
index cfffeb20fa5..b3bf94d45d6 100644
--- a/api/test/common/internal/version.test.ts
+++ b/api/test/common/internal/version.test.ts
@@ -17,13 +17,18 @@
import * as assert from 'assert';
import { VERSION } from '../../../src/version';
-describe('version', () => {
- it('should have generated VERSION.ts', () => {
+describe('version', function () {
+ it('should have generated VERSION.ts', function () {
+ // Skip in case we're not running in Node.js
+ if (global.process?.versions?.node === undefined) {
+ this.skip();
+ }
+
const pjson = require('../../../package.json');
assert.strictEqual(pjson.version, VERSION);
});
- it('prerelease tag versions are banned', () => {
+ it('prerelease tag versions are banned', function () {
// see https://github.com/open-telemetry/opentelemetry-js-api/issues/74
assert.ok(VERSION.match(/^\d+\.\d+\.\d+$/));
});
diff --git a/api/test/common/metrics/Metric.test.ts b/api/test/common/metrics/Metric.test.ts
index 95422d4cc2f..cfb12e476a9 100644
--- a/api/test/common/metrics/Metric.test.ts
+++ b/api/test/common/metrics/Metric.test.ts
@@ -42,7 +42,7 @@ describe('Metric', () => {
const counter: Counter = {
add(_value: number, _attribute: Attributes) {},
};
- // @ts-expect-error Expacting the type of Attributes
+ // @ts-expect-error Expecting the type of Attributes
counter.add(1, { 'another-attribute': 'value' });
});
});
@@ -72,7 +72,7 @@ describe('Metric', () => {
const counter: UpDownCounter = {
add(_value: number, _attribute: Attributes) {},
};
- // @ts-expect-error Expacting the type of Attributes
+ // @ts-expect-error Expecting the type of Attributes
counter.add(1, { 'another-attribute': 'value' });
});
});
@@ -102,7 +102,7 @@ describe('Metric', () => {
const counter: Histogram = {
record(_value: number, _attribute: Attributes) {},
};
- // @ts-expect-error Expacting the type of Attributes
+ // @ts-expect-error Expecting the type of Attributes
counter.record(1, { 'another-attribute': 'value' });
});
});
diff --git a/api/test/common/noop-implementations/noop-meter.test.ts b/api/test/common/noop-implementations/noop-meter.test.ts
index cde2b094de1..107e4f275a2 100644
--- a/api/test/common/noop-implementations/noop-meter.test.ts
+++ b/api/test/common/noop-implementations/noop-meter.test.ts
@@ -24,6 +24,7 @@ import {
NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC,
NOOP_UP_DOWN_COUNTER_METRIC,
createNoopMeter,
+ NOOP_GAUGE_METRIC,
} from '../../../src/metrics/NoopMeter';
import { NoopMeterProvider } from '../../../src/metrics/NoopMeterProvider';
@@ -116,6 +117,17 @@ describe('NoopMeter', () => {
);
});
+ it('gauge should not crash', () => {
+ const meter = new NoopMeterProvider().getMeter('test-noop');
+ const observableGauge = meter.createGauge('some-name');
+
+ // ensure the correct noop const is returned
+ assert.strictEqual(observableGauge, NOOP_GAUGE_METRIC);
+
+ const gaugeWithOptions = meter.createGauge('some-name', options);
+ assert.strictEqual(gaugeWithOptions, NOOP_GAUGE_METRIC);
+ });
+
it('observable up down counter should not crash', () => {
const meter = new NoopMeterProvider().getMeter('test-noop');
const observableUpDownCounter =
diff --git a/api/test/common/noop-implementations/noop-span.test.ts b/api/test/common/noop-implementations/noop-span.test.ts
index 5bc341f31a2..05020716de1 100644
--- a/api/test/common/noop-implementations/noop-span.test.ts
+++ b/api/test/common/noop-implementations/noop-span.test.ts
@@ -36,6 +36,14 @@ describe('NonRecordingSpan', () => {
my_number_attribute: 123,
});
+ const linkContext = {
+ traceId: 'e4cda95b652f4a1592b449d5929fda1b',
+ spanId: '7e0c63257de34c92',
+ traceFlags: TraceFlags.SAMPLED,
+ };
+ span.addLink({ context: linkContext });
+ span.addLinks([{ context: linkContext }]);
+
span.addEvent('sent');
span.addEvent('sent', { id: '42', key: 'value' });
diff --git a/doc/contributing/dependencies.md b/doc/contributing/dependencies.md
index 4e12902e8f5..6675f25231f 100644
--- a/doc/contributing/dependencies.md
+++ b/doc/contributing/dependencies.md
@@ -25,7 +25,7 @@ An exception is granted for dependencies on `@opentelemetry/api`, which, if used
Packages categorized as third-party and listed under the `"dependencies"` section (e.g., @grpc/grpc-js, @grpc/proto-loader, shimmer, etc.) should remain unpinned and utilize the caret (`^`) symbol. This approach offers several advantages:
-* Our users could get bug fixes of those 3rd-party packages easily, without waiting for us to update our library.
-* In cases where multiple packages have dependencies on different versions of the same package, npm will opt for the most recent version, saving space and preventing potential disruptions.
+- Our users could get bug fixes of those 3rd-party packages easily, without waiting for us to update our library.
+- In cases where multiple packages have dependencies on different versions of the same package, npm will opt for the most recent version, saving space and preventing potential disruptions.
It's important to acknowledge that this approach does expose users to potential breaking changes arising from either human error or libraries that do not strictly follow to semver conventions. This trade-off is an inherent aspect of this approach.
diff --git a/doc/sdk-registration.md b/doc/sdk-registration.md
index a7a3bc72b73..919f9a23681 100644
--- a/doc/sdk-registration.md
+++ b/doc/sdk-registration.md
@@ -23,6 +23,7 @@ api.propagation.setGlobalPropagator(httpTraceContextPropagator);
api.context.setGlobalContextManager(asyncHooksContextManager);
```
+[opentelemetry-js]: https://github.com/open-telemetry/opentelemetry-js
[trace-api-docs]: https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_api.TraceAPI.html
[propagation-api-docs]: https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_api.PropagationAPI.html
[context-api-docs]: https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_api.ContextAPI.html
diff --git a/doc/upgrade-guide.md b/doc/upgrade-guide.md
index 7c8ea16f7cd..b650112681e 100644
--- a/doc/upgrade-guide.md
+++ b/doc/upgrade-guide.md
@@ -107,7 +107,7 @@ Collector exporter packages and types are renamed:
- All plugins have been removed in favor of instrumentations.
-- The `@opentelemetry/propagator-b3` package previously exported three propagators: `B3Propagator`,`B3SinglePropagator`, and `B3MultiPropagator`, but now only exports the `B3Propagator`. It extracts b3 context in single and multi-header encodings, and injects context using the single-header encoding by default, but can be configured to inject context using the multi-header endcoding during construction: `new B3Propagator({ injectEncoding: B3InjectEncoding.MULTI_HEADER })`. If you were previously using the `B3SinglePropagator` or `B3MultiPropagator` directly, you should update your code to use the `B3Propagator` with the appropriate configuration. See the [readme][otel-propagator-b3] for full details and usage.
+- The `@opentelemetry/propagator-b3` package previously exported three propagators: `B3Propagator`,`B3SinglePropagator`, and `B3MultiPropagator`, but now only exports the `B3Propagator`. It extracts b3 context in single and multi-header encodings, and injects context using the single-header encoding by default, but can be configured to inject context using the multi-header encoding during construction: `new B3Propagator({ injectEncoding: B3InjectEncoding.MULTI_HEADER })`. If you were previously using the `B3SinglePropagator` or `B3MultiPropagator` directly, you should update your code to use the `B3Propagator` with the appropriate configuration. See the [README](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-propagator-b3/README.md) for full details and usage.
- Sampling configuration via environment variable has changed. If you were using `OTEL_SAMPLING_PROBABILITY` then you should replace it with `OTEL_TRACES_SAMPLER=parentbased_traceidratio` and `OTEL_TRACES_SAMPLER_ARG=` where `` is a number in the [0..1] range, e.g. "0.25". Default is 1.0 if unset.
@@ -232,7 +232,7 @@ Some types exported from `"@opentelemetry/api"` have been changed to be more spe
## 0.15.0 to 0.16.0
-[PR-1863](https://github.com/open-telemetry/opentelemetry-js/pull/1863) removed public attributes `keepAlive` and `httpAgentOptions` from nodejs `CollectorTraceExporter` and `CollectorMetricExporter`
+[PR-1863](https://github.com/open-telemetry/opentelemetry-js/pull/1863) removed public attributes `keepAlive` and `httpAgentOptions` from Node.js `CollectorTraceExporter` and `CollectorMetricExporter`
## 0.14.0 to 0.15.0
diff --git a/examples/basic-tracer-node/README.md b/examples/basic-tracer-node/README.md
index d7da08813f0..9b574ae5fc0 100644
--- a/examples/basic-tracer-node/README.md
+++ b/examples/basic-tracer-node/README.md
@@ -24,13 +24,13 @@ npm start
Open the Jaeger UI in your browser [http://localhost:16686](http://localhost:16686)
-
+
Select `basic-service` under *Service Name* and click on *Find Traces*.
Click on the trace to view its details.
-
+
## Useful links
diff --git a/examples/basic-tracer-node/index.js b/examples/basic-tracer-node/index.js
index 3c85a54c6ec..889d4ba31e4 100644
--- a/examples/basic-tracer-node/index.js
+++ b/examples/basic-tracer-node/index.js
@@ -2,13 +2,13 @@
const opentelemetry = require('@opentelemetry/api');
const { Resource } = require('@opentelemetry/resources');
-const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
const { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const provider = new BasicTracerProvider({
resource: new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: 'basic-service',
+ [SEMRESATTRS_SERVICE_NAME]: 'basic-service',
}),
});
diff --git a/examples/basic-tracer-node/package.json b/examples/basic-tracer-node/package.json
index 2012f1f3b16..044e378b7dd 100644
--- a/examples/basic-tracer-node/package.json
+++ b/examples/basic-tracer-node/package.json
@@ -27,7 +27,7 @@
"@opentelemetry/api": "^1.0.2",
"@opentelemetry/exporter-jaeger": "0.25.0",
"@opentelemetry/resources": "0.25.0",
- "@opentelemetry/semantic-conventions": "0.25.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0",
"@opentelemetry/sdk-trace-base": "0.25.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/basic-tracer-node"
diff --git a/examples/esm-http-ts/index.ts b/examples/esm-http-ts/index.ts
index b4719a8bc76..38ea5680471 100644
--- a/examples/esm-http-ts/index.ts
+++ b/examples/esm-http-ts/index.ts
@@ -7,13 +7,13 @@ import {
SimpleSpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import { Resource } from '@opentelemetry/resources';
-import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
+import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import http from 'http';
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
const tracerProvider = new NodeTracerProvider({
resource: new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: 'esm-http-ts-example',
+ [SEMRESATTRS_SERVICE_NAME]: 'esm-http-ts-example',
}),
});
const exporter = new ConsoleSpanExporter();
diff --git a/examples/esm-http-ts/package.json b/examples/esm-http-ts/package.json
index 39263c093e4..3f5df1fa63b 100644
--- a/examples/esm-http-ts/package.json
+++ b/examples/esm-http-ts/package.json
@@ -1,13 +1,14 @@
{
"name": "esm-http-ts",
"private": true,
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "Example of HTTP integration with OpenTelemetry using ESM and TypeScript",
"main": "build/index.js",
"type": "module",
"scripts": {
"build": "tsc --build",
- "start": "node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ./build/index.js"
+ "start": "node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ./build/index.js",
+ "align-api-deps": "node ../../scripts/align-api-deps.js"
},
"repository": {
"type": "git",
@@ -30,13 +31,13 @@
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/",
"dependencies": {
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/exporter-trace-otlp-proto": "0.49.1",
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/instrumentation-http": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@opentelemetry/sdk-trace-node": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.0"
+ "@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"
}
}
diff --git a/examples/grpc-js/README.md b/examples/grpc-js/README.md
index 1ec7a42a0e5..fcc0de41dc5 100644
--- a/examples/grpc-js/README.md
+++ b/examples/grpc-js/README.md
@@ -36,7 +36,7 @@ Setup [Jaeger Tracing](https://www.jaegertracing.io/docs/latest/getting-started/
`zipkin:server` script should output the `traceid` in the terminal (e.g `traceid: 4815c3d576d930189725f1f1d1bdfcc6`).
Go to Zipkin with your browser (e.g
-
+
### Jaeger
@@ -59,7 +59,7 @@ Go to Zipkin with your browser (e.g
-
+
## Useful links
diff --git a/examples/grpc-js/package.json b/examples/grpc-js/package.json
index 6cbd02c0146..f7ae1e51262 100644
--- a/examples/grpc-js/package.json
+++ b/examples/grpc-js/package.json
@@ -35,7 +35,7 @@
"@opentelemetry/instrumentation": "^0.27.0",
"@opentelemetry/instrumentation-grpc": "^0.27.0",
"@opentelemetry/resources": "^1.0.1",
- "@opentelemetry/semantic-conventions": "^1.0.1",
+ "@opentelemetry/semantic-conventions": "^1.22.0",
"@opentelemetry/sdk-trace-base": "^1.0.1",
"@opentelemetry/sdk-trace-node": "^1.0.1",
"google-protobuf": "^3.9.2"
diff --git a/examples/grpc-js/tracer.js b/examples/grpc-js/tracer.js
index 5c5a9edb860..77d30dbd1c2 100644
--- a/examples/grpc-js/tracer.js
+++ b/examples/grpc-js/tracer.js
@@ -4,7 +4,7 @@ const opentelemetry = require('@opentelemetry/api');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { Resource } = require('@opentelemetry/resources');
-const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
@@ -15,7 +15,7 @@ const EXPORTER = process.env.EXPORTER || '';
module.exports = (serviceName) => {
const provider = new NodeTracerProvider({
resource: new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
+ [SEMRESATTRS_SERVICE_NAME]: serviceName,
}),
});
diff --git a/examples/http/README.md b/examples/http/README.md
index 95bad89e5a7..f42c3770477 100644
--- a/examples/http/README.md
+++ b/examples/http/README.md
@@ -46,7 +46,7 @@ Setup [Jaeger Tracing](https://www.jaegertracing.io/docs/latest/getting-started/
`zipkin:server` script should output the `traceid` in the terminal (e.g `traceid: 4815c3d576d930189725f1f1d1bdfcc6`).
Go to Zipkin with your browser (e.g )
-
+
### Jaeger
@@ -69,7 +69,7 @@ Go to Zipkin with your browser (e.g )
-
+
## Useful links
diff --git a/examples/http/package.json b/examples/http/package.json
index 83985ffe0cf..67950f24820 100644
--- a/examples/http/package.json
+++ b/examples/http/package.json
@@ -1,14 +1,15 @@
{
"name": "http-example",
"private": true,
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "Example of HTTP integration with OpenTelemetry",
"main": "index.js",
"scripts": {
"zipkin:server": "cross-env EXPORTER=zipkin node ./server.js",
"zipkin:client": "cross-env EXPORTER=zipkin node ./client.js",
"jaeger:server": "cross-env EXPORTER=jaeger node ./server.js",
- "jaeger:client": "cross-env EXPORTER=jaeger node ./client.js"
+ "jaeger:client": "cross-env EXPORTER=jaeger node ./client.js",
+ "align-api-deps": "node ../../scripts/align-api-deps.js"
},
"repository": {
"type": "git",
@@ -29,14 +30,14 @@
},
"dependencies": {
"@opentelemetry/api": "^1.3.0",
- "@opentelemetry/exporter-jaeger": "1.22.0",
- "@opentelemetry/exporter-zipkin": "1.22.0",
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/instrumentation-http": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@opentelemetry/sdk-trace-node": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/http",
"devDependencies": {
diff --git a/examples/http/tracer.js b/examples/http/tracer.js
index 82dbca2f70a..b2351221bde 100644
--- a/examples/http/tracer.js
+++ b/examples/http/tracer.js
@@ -4,7 +4,7 @@ const opentelemetry = require('@opentelemetry/api');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { Resource } = require('@opentelemetry/resources');
-const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
@@ -15,7 +15,7 @@ const EXPORTER = process.env.EXPORTER || '';
module.exports = (serviceName) => {
const provider = new NodeTracerProvider({
resource: new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
+ [SEMRESATTRS_SERVICE_NAME]: serviceName,
}),
});
diff --git a/examples/https/README.md b/examples/https/README.md
index 2f930945646..65032eb7803 100644
--- a/examples/https/README.md
+++ b/examples/https/README.md
@@ -56,7 +56,7 @@ npm run docker:start
Go to Zipkin with your browser (
e.g
-
+
### Jaeger
@@ -80,7 +80,7 @@ e.g
Go to Jaeger with your browser (
e.g
-
+
## Useful links
diff --git a/examples/https/package.json b/examples/https/package.json
index 054b1185698..3d79af832e8 100644
--- a/examples/https/package.json
+++ b/examples/https/package.json
@@ -1,7 +1,7 @@
{
"name": "https-example",
"private": true,
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "Example of HTTPs integration with OpenTelemetry",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@@ -12,7 +12,8 @@
"jaeger:client": "cross-env EXPORTER=jaeger node ./client.js",
"docker:start": "cd ./docker && docker-compose down && docker-compose up",
"docker:startd": "cd ./docker && docker-compose down && docker-compose up -d",
- "docker:stop": "cd ./docker && docker-compose down"
+ "docker:stop": "cd ./docker && docker-compose down",
+ "align-api-deps": "node ../../scripts/align-api-deps.js"
},
"repository": {
"type": "git",
@@ -33,14 +34,14 @@
},
"dependencies": {
"@opentelemetry/api": "^1.0.0",
- "@opentelemetry/exporter-jaeger": "1.22.0",
- "@opentelemetry/exporter-zipkin": "1.22.0",
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/instrumentation-http": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@opentelemetry/sdk-trace-node": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/https",
"devDependencies": {
diff --git a/examples/https/server-cert.pem b/examples/https/server-cert.pem
index 4dd904f0882..5e957ab5b25 100644
--- a/examples/https/server-cert.pem
+++ b/examples/https/server-cert.pem
@@ -1,22 +1,22 @@
-----BEGIN CERTIFICATE-----
-MIIDozCCAougAwIBAgIUZdBdHwmbcYbMUvOesYRyYlg11JMwDQYJKoZIhvcNAQEL
+MIIDozCCAougAwIBAgIUNmVva8tI/hqzZAB7FZzPmNr/Q0owDQYJKoZIhvcNAQEL
BQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQHDBFPcGVuVGVs
ZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9vdDENMAsGA1UECwwEVGVzdDELMAkGA1UE
-AwwCY2EwHhcNMjEwNjA4MDgxNTE2WhcNMzEwNjA2MDgxNTE2WjBhMQswCQYDVQQG
+AwwCY2EwHhcNMjQwNjA4MTkxODUyWhcNMzQwNjA2MTkxODUyWjBhMQswCQYDVQQG
EwJDTDELMAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0w
CwYDVQQKDARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBALw9Shaqp1O1zgYK8z5pnvuHK3o9cUNT
-+EJz5KLADn11HSgfj5S96s6lDP9mUy8oDXdk9zSH8QsPp/maVh0AM1WrPDDTBJT5
-vdPyUezzn4wvBrJSG/mmy/p4QU1srmE0ueuhgot97GZa9qu+gOqGei3YTjrbx14H
-jyvexx+QhqrpUg46qAm67pJHC5jN6LmufoIvepyvQCEbKN+n2B2tAn9on1wo7UmB
-igTEiWxk1Gn70IJuyTEbpHoLFviQ5kvTYXM/2KHMOXjZM9fQxtbseNUmj8VK3+tS
-5jBdIROZxKxh3r9rV7SBHrblTWB3CZ/NsJblZuzMazLWkYS1/JZud9ECAwEAAaNT
-MFEwHQYDVR0OBBYEFP6+DMoQBCg7tOYrSUpWKQrbfJ5yMB8GA1UdIwQYMBaAFP6+
-DMoQBCg7tOYrSUpWKQrbfJ5yMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
-BQADggEBAGbkwraWuKnhcE8GrLCO0qLq5GaF+WvxqVzgPvG3G6bQJuEnS6LT65nR
-ICU82vCQBikW6lDfpsiwcVqOmgefUmjI99Aw5S1dkYy2J+WZrU/EgX445JLGJMpB
-Bh0QajFT6gdQiuURqTmxAhNj4VrUqtrNapP8vFKerR7nTrORG0ELEcvzVYCLNvDm
-OYWvLEMZifNWKY6hRdhZXho5hfu7/YPUhZUpcSxkTUsDnG3gzkTyX1TzeWe7wlJr
-dtNIk50lUCR6TlSpTaVB+6uhVjaLZpZwBAT5H0dWQXm0Ww5AYsEAT9Uzh9fZYu4m
-iMhztKH3PWjDB+jSzcOv9FXeYWgprWk=
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAM80Psz6Kc4/x1Qx4OmYuacrCDL4JNY+
+SWzEm1kb25/E1+TrxYC8XluJtXwi9JRC7ovR8UIbZNVgWwPHlSXrTQsVe2sISr4K
+oRg87vmcRYzsOval+ZViFelUo9t5sYeiX0xBuMP1ENfEL+gtu2QrkmgDhy/XdRpm
+qpcrtJxXaIXedy82y7Av5da7jJyJ+9oaTq0Am0qyZjpzTs3jKEh1roWoc3pd6T4d
+asNHLeKrsq3bTasEH/Lo9k4t+2n1j5C+L5gWhPcCv8yzhGsrSiqxn+P9m/USXY/w
+HH9AyV7Dk4Jh8BjUOlYaqOLIEow7hwdxVBk1BO6Jmpxv8KI3qQjtLWsCAwEAAaNT
+MFEwHQYDVR0OBBYEFOueTx80MsHFiBvP0RO99CpVdj0ZMB8GA1UdIwQYMBaAFOue
+Tx80MsHFiBvP0RO99CpVdj0ZMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAJYqqU3wCDX+YZDZ4zd8k725MSfKk1omCxDzDzjuNAjqD/vuSE0YfdFB
+bTWMiBGsCqa6FgWwyT2oMPnJKShScZReFEZcM2s+/odfwUTwF4lD/UvZf6PdDhJ5
+kxqhoej2ZT8NY+m+rddmg5MaurIcIfOhOxRjarmhs2lrg5qmGKznauettsmA1ZpR
+d2ZZA10WstCKN7jHOUqUmSB/2oC/NZno09yXqgbNwIEwBgsUDNaYkGzIzsKD+mOy
+NTxLo/PJ5venVgboomDkWJqOOm+HtqfD64rczWyTS/ZdQhuFlk+aCYAwOhYZZH9Z
+IEkKcW8xN5+q8Bi9nsst5F1cuw84LD4=
-----END CERTIFICATE-----
diff --git a/examples/https/server-key.pem b/examples/https/server-key.pem
index 267ed0464e2..81c27246449 100644
--- a/examples/https/server-key.pem
+++ b/examples/https/server-key.pem
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8PUoWqqdTtc4G
-CvM+aZ77hyt6PXFDU/hCc+SiwA59dR0oH4+UverOpQz/ZlMvKA13ZPc0h/ELD6f5
-mlYdADNVqzww0wSU+b3T8lHs85+MLwayUhv5psv6eEFNbK5hNLnroYKLfexmWvar
-voDqhnot2E4628deB48r3scfkIaq6VIOOqgJuu6SRwuYzei5rn6CL3qcr0AhGyjf
-p9gdrQJ/aJ9cKO1JgYoExIlsZNRp+9CCbskxG6R6Cxb4kOZL02FzP9ihzDl42TPX
-0MbW7HjVJo/FSt/rUuYwXSETmcSsYd6/a1e0gR625U1gdwmfzbCW5WbszGsy1pGE
-tfyWbnfRAgMBAAECggEAP1YT7qp+4ICkkI3wqEhbkOA7Ncckq/W964YZINWkSnw0
-UkLESdTZA6yvQeQJCy3b0hdrwgYXiZQ7/ZT7coiVvTZ/ayIlQYcCYyT+gc67GSzd
-gPR1qzt/GIiL2GRADD70a58NUKgO+aWTp9fSgpa612AXemBmpXG/r5Amya0UUr7Y
-KdSpBuOgomZMqEm2mYDdI4LRw2xbWoWTVvCndhypbXTJ2D8/QhbNfliWTG9MBy90
-UAQpaQGNwHzmCgwBJ03QJuE+OXjX80XcOOIYh6l68wkDeSfqaYx95OQZ3oOr6QT8
-TLYv08M9Grrrj5rPttpycBoxVbtLxkhE0Rt0q9K4HQKBgQD0EuR35CNTIIx/gikO
-CxdbSroPW9r92+IXCWcbbtRbVruHBpXzsMeHse4uqhtYmFNbgfgh12dC6OX7NzJx
-3Ds4NW8DvcZ3mVq8iEiOZnX5ydeeYMetlDWhXx2/0be5vqmrUkkWdfXsFUCyS8Lw
-vGRc9BiNqFePg2HsoVd2tezrwwKBgQDFb/eef/nOM1Eq5h+u+0Pyyg07iRuxxNup
-YXY9hwNJyF+NUoIWx2Jfyh+dQfMC18g/4hN4Hwfm/nC85SkPheKJnXYgMWMXp2Y7
-PBgdZGCX/546xiS5VGAoRuLd8oO2AlDfgU4tw6U0WZguJ6hMXlePlKz/uAJ237FB
-gcPyGNeY2wKBgQDOD4038zInolk75YYHxzFm78X55ZETtipBTLzyGjXLD4SvUM4U
-uXEbjQsL9q2ztJbbsPTujU8u3DYeS9GY81hD8kjRnc0LeDt05JJtNu/vfYs+uXKb
-h39nyEfzhHlapi/U5lmyTtDbCm5emTvxxvvsxmBcaH3UOhXYk7amEJ3/xQKBgA+s
-svj3agqv0krYmD1ZH2zgE6rdWMCFQ3cwEKYT2PP7n3Jl0YQjcjDuqBHhEXzxSqmf
-tjH8LLFvE947R0Y/N9v7D0zA/v/6v0gGnld/B5gpqBM8dd/szfGEpzA9t600g90q
-s904Qh5k2osXhOoDN2pjwFRQ9Ikhez4bIkZPKJavAoGAV2YPXyw5rrAZtCtybqsO
-B+15Lh+KC+vs0rBBhb0MUpXQPgQ6SX8ozpLHtqlsUpNfHwOk5K958jMrM9Rx4dhS
-Z6WuTa+9QpmXzYTnCDBbEU06+YB1QR2QfU4BlAAu1RtUbbt84/7OAoNh2IqOO4XJ
-THlhj8odimsk4R1B0RipBis=
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDPND7M+inOP8dU
+MeDpmLmnKwgy+CTWPklsxJtZG9ufxNfk68WAvF5bibV8IvSUQu6L0fFCG2TVYFsD
+x5Ul600LFXtrCEq+CqEYPO75nEWM7Dr2pfmVYhXpVKPbebGHol9MQbjD9RDXxC/o
+LbtkK5JoA4cv13UaZqqXK7ScV2iF3ncvNsuwL+XWu4ycifvaGk6tAJtKsmY6c07N
+4yhIda6FqHN6Xek+HWrDRy3iq7Kt202rBB/y6PZOLftp9Y+Qvi+YFoT3Ar/Ms4Rr
+K0oqsZ/j/Zv1El2P8Bx/QMlew5OCYfAY1DpWGqjiyBKMO4cHcVQZNQTuiZqcb/Ci
+N6kI7S1rAgMBAAECggEAA4u31WckhwCFZzXxTN4Ns0QjwEeJzdbEB+X3aJd28y15
+qlO0jgbrMHLTVbv9ZnocvezKTaDNYW9kL1TfgwYbS+jCs2qxaL4i0pjcWA4qDIbQ
+XX8qnblPea42nZ9f/9ux+MqZIFVVw/N6BGWf8s9iEoCY9CMiQGDoY2zeitxeEAhe
+KGZHozaTUVAClrwMqKYlablWjX8zcoi6bKffUwz/MwecI2iVW72y9/xIGTlwhdZW
+8kDlkBOea3QV5yafcJQ1VsHrvUX3rf4C5uknCenwKbC3Au4+kBdQjv+bUk6aMR38
+OdnMCaUcnuT/UzbbtOSgJ+sVcGW9Jqo0DfS5CNPhuQKBgQD2EtOhjkUErc8KUhPW
+Pt8FNBAuoKsk4mRHpFsY2OjGYA50oiCtiphqfTzkQLbNhVtq83AHNUNWUKBjnMUd
+nAOIIvhpiEI7O+RuOafBtcFBIrUo2Ey5dwfvLJrpb7pEnYj8DNFVPQ/aBxP+mD4b
+RrHRY8DZdVHU9TDMDK7ObpKScwKBgQDXkASnc7O/D0iFxev004sqdTrGo3cBCJUH
+h/c68BrUvPw5u6fFulq5Wt6OOaFoWQmUSVyrhZD3vfrZ1Jocid3wn9uuu9vOazcz
+M3EOF1rz5bgjwb/vk6CyGh1MfmeVCRnuQ3mBIXQ0xwS4QY71Vvw3099fhbtbMHez
+5gyQv1ojKQKBgHkXBqGHmxsUVL/lZ/GT+rdayWPImK+L4IEItfNiOhn0huiKJ75+
+Z0Zv3pkL52j3aOcWaFiDs2E0R9j8+lr5vRsu6kM0VDNF48ECCjVetXzSEYfJ+OeD
+VZoyvwCEhIrjYtd1j0V8yOInfYVZcaaGgVZi2jGoc95x0dN3okXfT61VAoGAVrCA
+bqdFPizzSXkTL15ztRt4C7JphWziIik37+fnom5uMPmauxX6rlgw8JmUo9ZK1+u4
+7PHGHxuz6i5p29hF/SMMwfSirRzJEjo52STjWvqjVx3wBnUkRvvhlIWxOmpylzNj
+hd7iUOdIqqES0O+udvUp+8xYUI/pU9vMadnKciECgYB3cJ+7EPNgJgdpQ9Pslex8
+6iHdQH9DIyIb/KqQVe7em5NZXwANCAOQ6KqzhszM/eH7NoSeN7C9Z9uHHIHDfz4m
+QO896l7rM1k1R/USaUK4By/O/t/V/aIGjOnPsXxEGrEPDXXBtzUAEs5yAa+Ne1m7
+BiP9MuDgBTVkV1iJx37eqg==
-----END PRIVATE KEY-----
diff --git a/examples/https/tracer.js b/examples/https/tracer.js
index a223e218044..9d76f30355b 100644
--- a/examples/https/tracer.js
+++ b/examples/https/tracer.js
@@ -4,7 +4,7 @@ const opentelemetry = require('@opentelemetry/api');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { Resource } = require('@opentelemetry/resources');
-const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
@@ -17,7 +17,7 @@ module.exports = (serviceName) => {
let exporter;
const provider = new NodeTracerProvider({
resource: new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
+ [SEMRESATTRS_SERVICE_NAME]: serviceName,
}),
});
diff --git a/examples/opentelemetry-web/examples/fetch-proto/index.js b/examples/opentelemetry-web/examples/fetch-proto/index.js
index 9a9e85184cd..0faaa0149aa 100644
--- a/examples/opentelemetry-web/examples/fetch-proto/index.js
+++ b/examples/opentelemetry-web/examples/fetch-proto/index.js
@@ -6,8 +6,14 @@ const { ZoneContextManager } = require("@opentelemetry/context-zone");
const { B3Propagator } = require("@opentelemetry/propagator-b3");
const { registerInstrumentations } = require("@opentelemetry/instrumentation");
const { OTLPTraceExporter: OTLPTraceExporterProto } = require("@opentelemetry/exporter-trace-otlp-proto");
+const { Resource } = require("@opentelemetry/resources");
+const { SEMRESATTRS_SERVICE_NAME } = require("@opentelemetry/semantic-conventions");
-const provider = new WebTracerProvider();
+const provider = new WebTracerProvider({
+ resource: new Resource({
+ [SEMRESATTRS_SERVICE_NAME]: 'fetch-proto-web-service'
+ })
+});
// Note: For production consider using the "BatchSpanProcessor" to reduce the number of requests
// to your exporter. Using the SimpleSpanProcessor here as it sends the spans immediately to the
diff --git a/examples/opentelemetry-web/examples/fetch/index.js b/examples/opentelemetry-web/examples/fetch/index.js
index f2632b2e4c3..3326beb19b6 100644
--- a/examples/opentelemetry-web/examples/fetch/index.js
+++ b/examples/opentelemetry-web/examples/fetch/index.js
@@ -6,8 +6,14 @@ const { FetchInstrumentation } = require( '@opentelemetry/instrumentation-fetch'
const { ZoneContextManager } = require( '@opentelemetry/context-zone');
const { B3Propagator } = require( '@opentelemetry/propagator-b3');
const { registerInstrumentations } = require( '@opentelemetry/instrumentation');
+const { Resource } = require('@opentelemetry/resources');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
-const provider = new WebTracerProvider();
+const provider = new WebTracerProvider({
+ resource: new Resource({
+ [SEMRESATTRS_SERVICE_NAME]: 'fetch-web-service'
+ })
+});
// Note: For production consider using the "BatchSpanProcessor" to reduce the number of requests
// to your exporter. Using the SimpleSpanProcessor here as it sends the spans immediately to the
diff --git a/examples/opentelemetry-web/examples/fetchXhr/index.js b/examples/opentelemetry-web/examples/fetchXhr/index.js
index 8e266f78a7b..1d93af4c49d 100644
--- a/examples/opentelemetry-web/examples/fetchXhr/index.js
+++ b/examples/opentelemetry-web/examples/fetchXhr/index.js
@@ -6,8 +6,14 @@ const { FetchInstrumentation } = require('@opentelemetry/instrumentation-fetch')
const { XMLHttpRequestInstrumentation } = require('@opentelemetry/instrumentation-xml-http-request');
const { ZoneContextManager } = require('@opentelemetry/context-zone');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
+const { Resource } = require('@opentelemetry/resources');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
-const provider = new WebTracerProvider();
+const provider = new WebTracerProvider({
+ resource: new Resource({
+ [SEMRESATTRS_SERVICE_NAME]: 'fetch-xhr-web-service'
+ })
+});
// Note: For production consider using the "BatchSpanProcessor" to reduce the number of requests
// to your exporter. Using the SimpleSpanProcessor here as it sends the spans immediately to the
diff --git a/examples/opentelemetry-web/examples/fetchXhrB3/index.js b/examples/opentelemetry-web/examples/fetchXhrB3/index.js
index 64afe58d48a..2923cccc6b7 100644
--- a/examples/opentelemetry-web/examples/fetchXhrB3/index.js
+++ b/examples/opentelemetry-web/examples/fetchXhrB3/index.js
@@ -7,8 +7,14 @@ const { XMLHttpRequestInstrumentation } = require( '@opentelemetry/instrumentati
const { ZoneContextManager } = require( '@opentelemetry/context-zone');
const { B3Propagator } = require( '@opentelemetry/propagator-b3');
const { registerInstrumentations } = require( '@opentelemetry/instrumentation');
+const { Resource } = require('@opentelemetry/resources');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
-const provider = new WebTracerProvider();
+const provider = new WebTracerProvider({
+ resource: new Resource({
+ [SEMRESATTRS_SERVICE_NAME]: 'fetch-xhr-b3-web-service'
+ })
+});
// Note: For production consider using the "BatchSpanProcessor" to reduce the number of requests
// to your exporter. Using the SimpleSpanProcessor here as it sends the spans immediately to the
diff --git a/examples/opentelemetry-web/examples/xml-http-request/index.js b/examples/opentelemetry-web/examples/xml-http-request/index.js
index ff2b173bcfc..7530528ed87 100644
--- a/examples/opentelemetry-web/examples/xml-http-request/index.js
+++ b/examples/opentelemetry-web/examples/xml-http-request/index.js
@@ -6,8 +6,14 @@ const { ZoneContextManager } = require( '@opentelemetry/context-zone');
const { OTLPTraceExporter } = require( '@opentelemetry/exporter-trace-otlp-http');
const { B3Propagator } = require( '@opentelemetry/propagator-b3');
const { registerInstrumentations } = require( '@opentelemetry/instrumentation');
+const { Resource } = require('@opentelemetry/resources');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
-const providerWithZone = new WebTracerProvider();
+const providerWithZone = new WebTracerProvider({
+ resource: new Resource({
+ [SEMRESATTRS_SERVICE_NAME]: 'xml-http-web-service'
+ })
+});
// Note: For production consider using the "BatchSpanProcessor" to reduce the number of requests
// to your exporter. Using the SimpleSpanProcessor here as it sends the spans immediately to the
diff --git a/examples/opentelemetry-web/examples/zipkin/index.js b/examples/opentelemetry-web/examples/zipkin/index.js
index aa01c595c9d..d76de7e563b 100644
--- a/examples/opentelemetry-web/examples/zipkin/index.js
+++ b/examples/opentelemetry-web/examples/zipkin/index.js
@@ -1,8 +1,15 @@
const { ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { WebTracerProvider } = require('@opentelemetry/sdk-trace-web');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
+const { Resource } = require('@opentelemetry/resources');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
+
+const provider = new WebTracerProvider({
+ resource: new Resource({
+ [SEMRESATTRS_SERVICE_NAME]: 'zipkin-web-service'
+ })
+});
-const provider = new WebTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.addSpanProcessor(new SimpleSpanProcessor(new ZipkinExporter({
// testing interceptor
diff --git a/examples/opentelemetry-web/package.json b/examples/opentelemetry-web/package.json
index ba92043e87e..1236e6ec00a 100644
--- a/examples/opentelemetry-web/package.json
+++ b/examples/opentelemetry-web/package.json
@@ -1,7 +1,7 @@
{
"name": "web-opentelemetry-example",
"private": true,
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "Example of using @opentelemetry/sdk-trace-web and @opentelemetry/sdk-metrics in browser",
"main": "index.js",
"scripts": {
@@ -11,7 +11,8 @@
"start-prodnc": "webpack serve --progress --color --port 8090 --config webpack.prod.config.js --hot --host 0.0.0.0 --no-compress",
"docker:start": "cd ./docker && docker-compose down && docker-compose up",
"docker:startd": "cd ./docker && docker-compose down && docker-compose up -d",
- "docker:stop": "cd ./docker && docker-compose down"
+ "docker:stop": "cd ./docker && docker-compose down",
+ "align-api-deps": "node ../../scripts/align-api-deps.js"
},
"repository": {
"type": "git",
@@ -44,20 +45,20 @@
},
"dependencies": {
"@opentelemetry/api": "^1.3.0",
- "@opentelemetry/context-zone": "1.22.0",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/exporter-metrics-otlp-http": "0.49.1",
- "@opentelemetry/exporter-trace-otlp-http": "0.49.1",
- "@opentelemetry/exporter-trace-otlp-proto": "0.49.1",
- "@opentelemetry/exporter-zipkin": "1.22.0",
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/instrumentation-fetch": "0.49.1",
- "@opentelemetry/instrumentation-xml-http-request": "0.49.1",
- "@opentelemetry/propagator-b3": "1.22.0",
- "@opentelemetry/sdk-metrics": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@opentelemetry/sdk-trace-web": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/tracer-web"
}
diff --git a/examples/opentracing-shim/README.md b/examples/opentracing-shim/README.md
index 3be4c09d76f..d4f4459b32c 100644
--- a/examples/opentracing-shim/README.md
+++ b/examples/opentracing-shim/README.md
@@ -45,7 +45,7 @@ $ npm run zipkin:client
Go to Zipkin with your browser (e.g
-
+
### Jaeger
@@ -71,7 +71,7 @@ $ npm run jaeger:client
Go to Jaeger with your browser (e.g
-
+
## Useful links
diff --git a/examples/opentracing-shim/package.json b/examples/opentracing-shim/package.json
index 9895029b431..aacfe56df51 100644
--- a/examples/opentracing-shim/package.json
+++ b/examples/opentracing-shim/package.json
@@ -8,7 +8,8 @@
"zipkin:client": "cross-env EXPORTER=zipkin node ./client.js",
"zipkin:server": "cross-env EXPORTER=zipkin node ./server.js",
"jaeger:client": "cross-env EXPORTER=jaeger node ./client.js",
- "jaeger:server": "cross-env EXPORTER=jaeger node ./server.js"
+ "jaeger:server": "cross-env EXPORTER=jaeger node ./server.js",
+ "align-api-deps": "node ../../scripts/align-api-deps.js"
},
"repository": {
"type": "git",
@@ -35,7 +36,7 @@
"@opentelemetry/instrumentation": "0.25.0",
"@opentelemetry/sdk-trace-node": "0.25.0",
"@opentelemetry/resources": "0.25.0",
- "@opentelemetry/semantic-conventions": "0.25.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0",
"@opentelemetry/shim-opentracing": "0.25.0",
"@opentelemetry/sdk-trace-base": "0.25.0",
"opentracing": "^0.14.4"
diff --git a/examples/opentracing-shim/shim.js b/examples/opentracing-shim/shim.js
index fe6771ced4a..0f791071ee4 100644
--- a/examples/opentracing-shim/shim.js
+++ b/examples/opentracing-shim/shim.js
@@ -1,6 +1,6 @@
'use strict';
-const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
const { Resource } = require('@opentelemetry/resources');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
@@ -10,7 +10,7 @@ const { TracerShim } = require('@opentelemetry/shim-opentracing');
function shim(serviceName) {
const provider = new NodeTracerProvider({
- resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: serviceName }),
+ resource: new Resource({ [SEMRESATTRS_SERVICE_NAME]: serviceName }),
});
provider.addSpanProcessor(new SimpleSpanProcessor(getExporter(serviceName)));
diff --git a/examples/otlp-exporter-node/README.md b/examples/otlp-exporter-node/README.md
index 43b902b2a63..a478baa8b30 100644
--- a/examples/otlp-exporter-node/README.md
+++ b/examples/otlp-exporter-node/README.md
@@ -44,8 +44,8 @@ The prometheus client will be available at .
Note: It may take some time for the application metrics to appear on the Prometheus dashboard.
-
-
+
+
## Useful links
diff --git a/examples/otlp-exporter-node/metrics.js b/examples/otlp-exporter-node/metrics.js
index 0594ba42e3f..22507ef528b 100644
--- a/examples/otlp-exporter-node/metrics.js
+++ b/examples/otlp-exporter-node/metrics.js
@@ -13,7 +13,7 @@ const {
} = require('@opentelemetry/sdk-metrics');
const { Resource } = require('@opentelemetry/resources');
const {
- SemanticResourceAttributes,
+ SEMRESATTRS_SERVICE_NAME,
} = require('@opentelemetry/semantic-conventions');
// Optional and only needed to see the internal diagnostic logging (during development)
@@ -36,7 +36,7 @@ const expHistogramView = new View({
// Create an instance of the metric provider
const meterProvider = new MeterProvider({
resource: new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: 'basic-metric-service',
+ [SEMRESATTRS_SERVICE_NAME]: 'basic-metric-service',
}),
views: [expHistogramView],
});
diff --git a/examples/otlp-exporter-node/package.json b/examples/otlp-exporter-node/package.json
index 4e634c42372..0def81bdea1 100644
--- a/examples/otlp-exporter-node/package.json
+++ b/examples/otlp-exporter-node/package.json
@@ -1,7 +1,7 @@
{
"name": "example-otlp-exporter-node",
"private": true,
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "Example of using @opentelemetry/collector-exporter in Node.js",
"main": "index.js",
"scripts": {
@@ -9,7 +9,8 @@
"start:metrics": "node metrics.js",
"docker:start": "cd ./docker && docker-compose down && docker-compose up",
"docker:startd": "cd ./docker && docker-compose down && docker-compose up -d",
- "docker:stop": "cd ./docker && docker-compose down"
+ "docker:stop": "cd ./docker && docker-compose down",
+ "align-api-deps": "node ../../scripts/align-api-deps.js"
},
"repository": {
"type": "git",
@@ -29,17 +30,17 @@
},
"dependencies": {
"@opentelemetry/api": "^1.3.0",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/exporter-metrics-otlp-grpc": "0.49.1",
- "@opentelemetry/exporter-metrics-otlp-http": "0.49.1",
- "@opentelemetry/exporter-metrics-otlp-proto": "0.49.1",
- "@opentelemetry/exporter-trace-otlp-grpc": "0.49.1",
- "@opentelemetry/exporter-trace-otlp-http": "0.49.1",
- "@opentelemetry/exporter-trace-otlp-proto": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-metrics": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/otlp-exporter-node"
}
diff --git a/examples/otlp-exporter-node/tracing.js b/examples/otlp-exporter-node/tracing.js
index d2a64144422..475665f23cd 100644
--- a/examples/otlp-exporter-node/tracing.js
+++ b/examples/otlp-exporter-node/tracing.js
@@ -2,7 +2,7 @@
const { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { Resource } = require('@opentelemetry/resources');
-const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
+const { SEMRESATTRS_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
const {
diag,
trace,
@@ -24,7 +24,7 @@ const exporter = new OTLPTraceExporter({
const provider = new BasicTracerProvider({
resource: new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: 'basic-service',
+ [SEMRESATTRS_SERVICE_NAME]: 'basic-service',
}),
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md
index c437d9eec67..84dc4c0b83e 100644
--- a/experimental/CHANGELOG.md
+++ b/experimental/CHANGELOG.md
@@ -1,3 +1,4 @@
+
# CHANGELOG
All notable changes to experimental packages in this project will be documented in this file.
@@ -6,14 +7,172 @@ All notable changes to experimental packages in this project will be documented
### :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
+ * (user-facing) `compression` was intended for internal use and has been removed from all exporters
+ * (user-facing) `hostname` was intended for use in tests and is not used by any exporters, it will be removed in a future release
+* fix(exporter-*-otlp-*)!: ensure `User-Agent` header cannot be overwritten by the user [#4743](https://github.com/open-telemetry/opentelemetry-js/pull/4743) @pichlermarc
+ * allowing overrides of the `User-Agent` header was not specification compliant.
+
### :rocket: (Enhancement)
+* 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
+
### :bug: (Bug Fix)
+* 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
+
### :books: (Refine Doc)
### :house: (Internal)
+* refactor: Simplify the code for the `getEnv` function [#4799](https://github.com/open-telemetry/opentelemetry-js/pull/4799) @danstarns
+
+## 0.52.1
+
+### :rocket: (Enhancement)
+
+* refactor(instrumentation-fetch): move fetch to use SEMATRR [#4632](https://github.com/open-telemetry/opentelemetry-js/pull/4632)
+* refactor(otlp-transformer): use explicit exports [#4785](https://github.com/open-telemetry/opentelemetry-js/pull/4785) @pichlermarc
+
+### :bug: (Bug Fix)
+
+* fix(sdk-node): register context manager if no tracer options are provided [#4781](https://github.com/open-telemetry/opentelemetry-js/pull/4781) @pichlermarc
+* fix(instrumentation): Update `import-in-the-middle` to fix [numerous bugs](https://github.com/DataDog/import-in-the-middle/releases/tag/v1.8.1) [#4806](https://github.com/open-telemetry/opentelemetry-js/pull/4806) @timfish
+* chore(instrumentation): Use a caret version for `import-in-the-middle` dependency [#4810](https://github.com/open-telemetry/opentelemetry-js/pull/4810) @timfish
+
+### :house: (Internal)
+
+* test: add `npm run maint:regenerate-test-certs` maintenance script and regenerate recently expired test certs [#4777](https://github.com/open-telemetry/opentelemetry-js/pull/4777)
+
+## 0.52.0
+
+### :boom: Breaking Change
+
+* feat(exporter-*-otlp-*)!: move serialization for Node.js exporters to `@opentelemetry/otlp-transformer` [#4542](https://github.com/open-telemetry/opentelemetry-js/pull/4542) @pichlermarc
+ * Breaking changes:
+ * (user-facing) `convert()` now returns an empty object and will be removed in a follow-up
+ * (internal) OTLPExporterNodeBase now has additional constructor parameters that are required
+ * (internal) OTLPExporterNodeBase now has an additional `ResponseType` type parameter
+* feat(exporter-*-otlp-*)!: move serialization for Node.js exporters to `@opentelemetry/otlp-transformer` [#4581](https://github.com/open-telemetry/opentelemetry-js/pull/4581) @pichlermarc
+ * Breaking changes:
+ * (user-facing) `convert()` has been removed from all exporters
+ * (internal) OTLPExporterBrowserBase: `RequestType` has been replaced by a `ResponseType` type-argument
+ * (internal) OTLPExporterNodeBase: `ServiceRequest` has been replaced by a `ServiceResponse` type-argument
+ * (internal) the `@opentelemetry/otlp-exporter-proto-base` package has been removed, and will from now on be deprecated in `npm`
+* feat(instrumentation): remove default value for config in base instrumentation constructor [#4695](https://github.com/open-telemetry/opentelemetry-js/pull/4695): @blumamir
+* fix(instrumentation)!: remove unused supportedVersions from Instrumentation interface [#4694](https://github.com/open-telemetry/opentelemetry-js/pull/4694) @blumamir
+* feat(instrumentation)!: simplify `registerInstrumentations()` API
+ * Breaking changes:
+ * removes `InstrumentationOptions` type
+ * occurrences of `InstrumentationOptions` are now replaced by `(Instrumentation | Instrumentation[])[]`
+ * migrate usages of `registerInstrumentations({instrumentations: fooInstrumentation})` to `registerInstrumentations({instrumentations: [fooInstrumentation]})`
+ * passing Instrumentation classes to `registerInstrumentations()` is now not possible anymore.
+* feat(sdk-node)!: simplify type of `instrumentations` option
+ * Breaking changes:
+ * replaces `InstrumentationOptions` with `(Instrumentation | Instrumentation[])[]`
+
+### :rocket: (Enhancement)
+
+* feat(instrumentation): apply unwrap before wrap in base class [#4692](https://github.com/open-telemetry/opentelemetry-js/pull/4692)
+* feat(instrumentation): add util to execute span customization hook in base class [#4663](https://github.com/open-telemetry/opentelemetry-js/pull/4663) @blumamir
+* feat(instrumentation): generic config type in instrumentation base [#4659](https://github.com/open-telemetry/opentelemetry-js/pull/4659) @blumamir
+* feat: support node 22 [#4666](https://github.com/open-telemetry/opentelemetry-js/pull/4666) @dyladan
+* feat(propagator-aws-xray-lambda): add AWS Xray Lambda propagator [4554](https://github.com/open-telemetry/opentelemetry-js/pull/4554)
+* refactor(instrumentation-xml-http-request): use exported strings for semantic attributes. [#4681](https://github.com/open-telemetry/opentelemetry-js/pull/4681/files)
+* refactor(sdk-node): Use tree-shakeable string constants for semconv [#4767](https://github.com/open-telemetry/opentelemetry-js/pull/4767) @JohannesHuster
+
+### :bug: (Bug Fix)
+
+* fix(instrumentation): Update `import-in-the-middle` to fix [numerous bugs](https://github.com/DataDog/import-in-the-middle/pull/91) [#4745](https://github.com/open-telemetry/opentelemetry-js/pull/4745) @timfish
+
+### :books: (Refine Doc)
+
+* docs(instrumentation): better docs for supportedVersions option [#4693](https://github.com/open-telemetry/opentelemetry-js/pull/4693) @blumamir
+* docs: align all supported versions to a common format [#4696](https://github.com/open-telemetry/opentelemetry-js/pull/4696) @blumamir
+* refactor(examples): use new exported string constants for semconv in experimental/examples/opencensus-shim [#4763](https://github.com/open-telemetry/opentelemetry-js/pull/4763#pull) @Zen-cronic
+
+## 0.51.1
+
+### :bug: (Bug Fix)
+
+* fix(instrumentation): update import-in-the-middle to 1.7.4
+
+## 0.51.0
+
+### :boom: Breaking Change
+
+* feat(sdk-node)!: remove long deprecated methods in favor of constructor options [#4606](https://github.com/open-telemetry/opentelemetry-js/pull/4606) @pichlermarc
+ * `NodeSDK.configureTracerProvider()`, please use constructor options instead
+ * `NodeSDK.configureMeterProvider()`, please use constructor options instead
+ * `NodeSDK.configureLoggerProvider()`, please use constructor options instead
+ * `NodeSDK.addResource()`, please use constructor options instead
+ * `NodeSDK.detectResources()`, this is not necessary anymore, resources are now auto-detected on `NodeSDK.start()` if the constructor option `autoDetectResources` is unset, `undefined` or `true`.
+* feat(instrumentation): add patch and unpatch diag log messages [#4641](https://github.com/open-telemetry/opentelemetry-js/pull/4641)
+ * Instrumentations should not log patch and unpatch messages to diag channel.
+* feat!(instrumentation): remove moduleExports generic type from instrumentation registration [#4598](https://github.com/open-telemetry/opentelemetry-js/pull/4598) @blumamir
+ * breaking for instrumentation authors that depend on
+ * `InstrumentationBase`
+ * `InstrumentationNodeModuleDefinition`
+ * `InstrumentationNodeModuleFile`
+* feat(api-events): removed traceId and spanId from Event interface, added context and severityNumber [#4629](https://github.com/open-telemetry/opentelemetry-js/pull/4629)
+
+### :rocket: (Enhancement)
+
+* feat(sdk-logs): log resource attributes in ConsoleLogRecordExporter [#4646](https://github.com/open-telemetry/opentelemetry-js/pull/4646) @harelmo-lumigo
+* refactor(instrumentation-grpc): move to use SEMATTRS [#4633](https://github.com/open-telemetry/opentelemetry-js/pull/4633)
+* feat(otlp-transformer): consolidate scope/resource creation in transformer [#4600](https://github.com/open-telemetry/opentelemetry-js/pull/4600)
+* feat(sdk-logs): print message when attributes are dropped due to attribute count limit [#4614](https://github.com/open-telemetry/opentelemetry-js/pull/4614) @HyunnoH
+* feat(sdk-node): add usage for the detector ServiceInstanceIdDetectorSync. [#4626](https://github.com/open-telemetry/opentelemetry-js/pull/4626) @maryliag
+ * The resource detector can be added to default resource detector list by adding the value `serviceinstance` to the list of resource detectors on the environment variable `OTEL_NODE_RESOURCE_DETECTORS`, e.g `OTEL_NODE_RESOURCE_DETECTORS=env,host,os,serviceinstance`
+ * The value can be overwritten by
+ * merging a resource containing the `service.instance.id` attribute
+ * using another resource detector which writes `service.instance.id`
+* feat(sdk-events): add Events SDK [#4629](https://github.com/open-telemetry/opentelemetry-js/pull/4629)
+
+### :bug: (Bug Fix)
+
+* fix(otlp-grpc-exporter-base): avoid TypeError on exporter shutdown [#4612](https://github.com/open-telemetry/opentelemetry-js/pull/4612) @pichlermarc
+* fix(instrumentation): Don't use `require` to load `package.json` files [#4593](https://github.com/open-telemetry/opentelemetry-js/pull/4593) @timfish
+
+## 0.50.0
+
+### :boom: Breaking Change
+
+* fix(exporter-*-otlp-grpc)!: lazy load gRPC to improve compatibility with `@opentelemetry/instrumenation-grpc` [#4432](https://github.com/open-telemetry/opentelemetry-js/pull/4432) @pichlermarc
+ * Fixes a bug where requiring up the gRPC exporter before enabling the instrumentation from `@opentelemetry/instrumentation-grpc` would lead to missing telemetry
+ * Breaking changes, removes several functions and properties that were used internally and were not intended for end-users
+ * `getServiceClientType()`
+ * this returned a static enum value that would denote the export type (`SPAN`, `METRICS`, `LOGS`)
+ * `getServiceProtoPath()`
+ * this returned a static enum value that would correspond to the gRPC service path
+ * `metadata`
+ * was used internally to access metadata, but as a side effect allowed end-users to modify metadata on runtime.
+ * `serviceClient`
+ * was used internally to keep track of the service client used by the exporter, as a side effect it allowed end-users to modify the gRPC service client that was used
+ * `compression`
+ * was used internally to keep track of the compression to use but was unintentionally exposed to the users. It allowed to read and write the value, writing, however, would have no effect.
+
+### :rocket: (Enhancement)
+
+* feat(instrumentation-xhr): optionally ignore network events [#4571](https://github.com/open-telemetry/opentelemetry-js/pull/4571/) @mustafahaddara
+* refactor(instrumentation-http): use exported strings for semconv [#4573](https://github.com/open-telemetry/opentelemetry-js/pull/4573/) @JamieDanielson
+* perf(instrumentation-http): remove obvious temp allocations [#4576](https://github.com/open-telemetry/opentelemetry-js/pull/4576) @Samuron
+* feat(sdk-node): add `HostDetector` as default resource detector [#4566](https://github.com/open-telemetry/opentelemetry-js/pull/4566) @maryliag
+* feat(api-events): added data field to the Event interface [#4575](https://github.com/open-telemetry/opentelemetry-js/pull/4575) @martinkuba
+
+### :bug: (Bug Fix)
+
+* fix(exporter-*-otlp-*): use parseHeaders() to ensure header-values are not 'undefined' #4540
+ * Fixes a bug where passing `undefined` as a header value would crash the end-user app after the export timeout elapsed.
+* fix(sdk-logs): ensure default resource attributes are used as fallbacks when a resource is passed to LoggerProvider.
+
+### :books: (Refine Doc)
+
+* docs(instrumentation-http): document semantic conventions and attributes in use. [#4587](https://github.com/open-telemetry/opentelemetry-js/pull/4587/) @JamieDanielson
+
## 0.49.1
### :bug: (Bug Fix)
@@ -59,19 +218,6 @@ All notable changes to experimental packages in this project will be documented
* This breaking change only affects users that are using the *experimental* `@opentelemetry/instrumentation/hook.mjs` loader hook AND Node.js 18.19 or later:
* This reverts back to an older version of `import-in-the-middle` due to
* This version does not support Node.js 18.19 or later
-* fix(exporter-*-otlp-grpc)!: lazy load gRPC to improve compatibility with `@opentelemetry/instrumenation-grpc` [#4432](https://github.com/open-telemetry/opentelemetry-js/pull/4432) @pichlermarc
- * Fixes a bug where requiring up the gRPC exporter before enabling the instrumentation from `@opentelemetry/instrumentation-grpc` would lead to missing telemetry
- * Breaking changes, removes several functions and properties that were used internally and were not intended for end-users
- * `getServiceClientType()`
- * this returned a static enum value that would denote the export type (`SPAN`, `METRICS`, `LOGS`)
- * `getServiceProtoPath()`
- * this returned a static enum value that would correspond to the gRPC service path
- * `metadata`
- * was used internally to access metadata, but as a side effect allowed end-users to modify metadata on runtime.
- * `serviceClient`
- * was used internally to keep track of the service client used by the exporter, as a side effect it allowed end-users to modify the gRPC service client that was used
- * `compression`
- * was used internally to keep track of the compression to use but was unintentionally exposed to the users. It allowed to read and write the value, writing, however, would have no effect.
### :bug: (Bug Fix)
diff --git a/experimental/backwards-compatibility/node14/package.json b/experimental/backwards-compatibility/node14/package.json
index 1adf3aa82ee..8bb203bbd84 100644
--- a/experimental/backwards-compatibility/node14/package.json
+++ b/experimental/backwards-compatibility/node14/package.json
@@ -1,16 +1,17 @@
{
"name": "backcompat-node14",
- "version": "0.49.1",
+ "version": "0.52.1",
"private": true,
"description": "Backwards compatibility app for node 14 types and the OpenTelemetry Node.js SDK",
"main": "index.js",
"scripts": {
"test:backcompat": "tsc --noEmit index.ts && tsc --noEmit --esModuleInterop index.ts",
- "peer-api-check": "node ../../../scripts/peer-api-check.js"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"dependencies": {
- "@opentelemetry/sdk-node": "0.49.1",
- "@opentelemetry/sdk-trace-base": "1.22.0"
+ "@opentelemetry/sdk-node": "0.52.1",
+ "@opentelemetry/sdk-trace-base": "1.25.1"
},
"devDependencies": {
"@types/node": "14.18.25",
diff --git a/experimental/backwards-compatibility/node16/package.json b/experimental/backwards-compatibility/node16/package.json
index dfcf93dc702..39daa2730a6 100644
--- a/experimental/backwards-compatibility/node16/package.json
+++ b/experimental/backwards-compatibility/node16/package.json
@@ -1,16 +1,17 @@
{
"name": "backcompat-node16",
- "version": "0.49.1",
+ "version": "0.52.1",
"private": true,
"description": "Backwards compatibility app for node 16 types and the OpenTelemetry Node.js SDK",
"main": "index.js",
"scripts": {
"test:backcompat": "tsc --noEmit index.ts && tsc --noEmit --esModuleInterop index.ts",
- "peer-api-check": "node ../../../scripts/peer-api-check.js"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"dependencies": {
- "@opentelemetry/sdk-node": "0.49.1",
- "@opentelemetry/sdk-trace-base": "1.22.0"
+ "@opentelemetry/sdk-node": "0.52.1",
+ "@opentelemetry/sdk-trace-base": "1.25.1"
},
"devDependencies": {
"@types/node": "16.11.52",
diff --git a/experimental/examples/README.md b/experimental/examples/README.md
index 8bfe7496c7e..427f0559b80 100644
--- a/experimental/examples/README.md
+++ b/experimental/examples/README.md
@@ -7,7 +7,7 @@ This directory contains examples of how to run real applications with OpenTeleme
These examples are using work in progress metrics packages.
|Name | Description | Complexity Level |
-------------- | ------------- | ------------ |
+|------------- | ------------- | ------------ |
|[prometheus](prometheus/) | Basic Metric use with Prometheus (`@opentelemetry/exporter-prometheus`) Exporter | Beginner |
## Contributing
diff --git a/experimental/examples/events/README.md b/experimental/examples/events/README.md
new file mode 100644
index 00000000000..4d46172626d
--- /dev/null
+++ b/experimental/examples/events/README.md
@@ -0,0 +1,21 @@
+## Installation
+
+```sh
+# from this directory
+npm install
+```
+
+## Run the Application
+
+```sh
+npm start
+```
+
+## Useful links
+
+- For more information on OpenTelemetry, visit:
+- For more information on OpenTelemetry logs, visit:
+
+## LICENSE
+
+Apache License 2.0
diff --git a/experimental/examples/events/index.ts b/experimental/examples/events/index.ts
new file mode 100644
index 00000000000..3a5eef4da28
--- /dev/null
+++ b/experimental/examples/events/index.ts
@@ -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 { DiagConsoleLogger, DiagLogLevel, diag } from '@opentelemetry/api';
+import {
+ LoggerProvider,
+ ConsoleLogRecordExporter,
+ SimpleLogRecordProcessor,
+} from '@opentelemetry/sdk-logs';
+import { events } from '@opentelemetry/api-events';
+import { EventLoggerProvider } from '@opentelemetry/sdk-events';
+
+// Optional and only needed to see the internal diagnostic logging (during development)
+diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
+
+// configure global LoggerProvider
+const loggerProvider = new LoggerProvider();
+loggerProvider.addLogRecordProcessor(
+ new SimpleLogRecordProcessor(new ConsoleLogRecordExporter())
+);
+
+// uncomment to use OTLP exporter
+// import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
+// const logExporter = new OTLPLogExporter();
+// loggerProvider.addLogRecordProcessor(new SimpleLogRecordProcessor(logExporter));
+
+// configure global EventLoggerProvider
+const eventLoggerProvider = new EventLoggerProvider(loggerProvider);
+events.setGlobalEventLoggerProvider(eventLoggerProvider);
+
+// emit a log record
+const eventLogger = events.getEventLogger('example');
+eventLogger.emit({
+ name: 'my-domain.my-event',
+ data: {
+ a: 1,
+ b: 'hello',
+ c: {
+ d: 123
+ }
+ }
+});
diff --git a/experimental/examples/events/package.json b/experimental/examples/events/package.json
new file mode 100644
index 00000000000..cec31205dcb
--- /dev/null
+++ b/experimental/examples/events/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "events-example",
+ "version": "0.52.1",
+ "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"
+ },
+ "devDependencies": {
+ "@types/node": "18.6.5",
+ "ts-node": "^10.9.1"
+ }
+}
diff --git a/experimental/examples/events/tsconfig.json b/experimental/examples/events/tsconfig.json
new file mode 100644
index 00000000000..62cb24e0552
--- /dev/null
+++ b/experimental/examples/events/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "build",
+ "rootDir": "."
+ },
+ "include": ["./index.ts"],
+ "references": [
+ {
+ "path": "../../../api"
+ },
+ {
+ "path": "../../../experimental/packages/api-events"
+ },
+ {
+ "path": "../../../experimental/packages/api-logs"
+ },
+ {
+ "path": "../../../experimental/packages/sdk-events"
+ },
+ {
+ "path": "../../../experimental/packages/sdk-logs"
+ },
+ {
+ "path": "../../../experimental/packages/exporter-logs-otlp-http"
+ }
+ ]
+}
diff --git a/experimental/examples/logs/README.md b/experimental/examples/logs/README.md
index 591d1eb5da4..2b9c691a170 100644
--- a/experimental/examples/logs/README.md
+++ b/experimental/examples/logs/README.md
@@ -7,8 +7,6 @@ npm install
## Run the Application
-LogRecord
-
```sh
npm start
```
diff --git a/experimental/examples/logs/package.json b/experimental/examples/logs/package.json
index af5423cb589..83d17e025b5 100644
--- a/experimental/examples/logs/package.json
+++ b/experimental/examples/logs/package.json
@@ -1,14 +1,15 @@
{
"name": "logs-example",
- "version": "0.49.1",
+ "version": "0.52.1",
"private": true,
"scripts": {
- "start": "ts-node index.ts"
+ "start": "ts-node index.ts",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"dependencies": {
"@opentelemetry/api": "^1.7.0",
- "@opentelemetry/api-logs": "0.49.1",
- "@opentelemetry/sdk-logs": "0.49.1"
+ "@opentelemetry/api-logs": "0.52.1",
+ "@opentelemetry/sdk-logs": "0.52.1"
},
"devDependencies": {
"@types/node": "18.6.5",
diff --git a/experimental/examples/opencensus-shim/README.md b/experimental/examples/opencensus-shim/README.md
index 6d95a91356e..ce38fd14d05 100644
--- a/experimental/examples/opencensus-shim/README.md
+++ b/experimental/examples/opencensus-shim/README.md
@@ -64,7 +64,7 @@ Go to Jaeger with your browser and click on the "Servi
- A child for the sleep operation. This was manually instrumented with OpenTelemetry.
Notice this span is correctly recorded as a child of the OpenCensus instrumentation.
-
+
## Check the Prometheus metrics
@@ -72,7 +72,7 @@ Load the Prometheus metrics endpoint of the server at
+
## Useful links
diff --git a/experimental/examples/opencensus-shim/package.json b/experimental/examples/opencensus-shim/package.json
index d0ea8c85b30..4fd8ae2bcd8 100644
--- a/experimental/examples/opencensus-shim/package.json
+++ b/experimental/examples/opencensus-shim/package.json
@@ -1,12 +1,13 @@
{
"name": "opencensus-shim",
"private": true,
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "Example of using @opentelemetry/shim-opencensus in Node.js",
"main": "index.js",
"scripts": {
"client": "node -r @opentelemetry/shim-opencensus/register ./client.js",
- "server": "node -r @opentelemetry/shim-opencensus/register ./server.js"
+ "server": "node -r @opentelemetry/shim-opencensus/register ./server.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"repository": {
"type": "git",
@@ -30,14 +31,14 @@
"@opencensus/core": "0.1.0",
"@opencensus/instrumentation-http": "0.1.0",
"@opencensus/nodejs-base": "0.1.0",
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/exporter-prometheus": "0.49.1",
- "@opentelemetry/exporter-trace-otlp-grpc": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-metrics": "1.22.0",
- "@opentelemetry/sdk-trace-node": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.0",
- "@opentelemetry/shim-opencensus": "0.49.1"
+ "@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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/examples/opencensus-shim"
}
diff --git a/experimental/examples/opencensus-shim/setup.js b/experimental/examples/opencensus-shim/setup.js
index 99bf8bf8b44..1bb277eddb4 100644
--- a/experimental/examples/opencensus-shim/setup.js
+++ b/experimental/examples/opencensus-shim/setup.js
@@ -27,7 +27,7 @@ const {
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
const { Resource } = require('@opentelemetry/resources');
const {
- SemanticResourceAttributes,
+ SEMRESATTRS_SERVICE_NAME,
} = require('@opentelemetry/semantic-conventions');
const { OpenCensusMetricProducer } = require('@opentelemetry/shim-opencensus');
const instrumentationHttp = require('@opencensus/instrumentation-http');
@@ -46,7 +46,7 @@ module.exports = function setup(serviceName) {
tracing.tracer = new oc.CoreTracer();
const resource = new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
+ [SEMRESATTRS_SERVICE_NAME]: serviceName,
});
const tracerProvider = new NodeTracerProvider({ resource });
tracerProvider.addSpanProcessor(
diff --git a/experimental/examples/prometheus/README.md b/experimental/examples/prometheus/README.md
index f82f2fc4843..9f2203a8be8 100644
--- a/experimental/examples/prometheus/README.md
+++ b/experimental/examples/prometheus/README.md
@@ -58,9 +58,9 @@ prometheus --config.file=prometheus.yml
If you are using the default configurations, the prometheus client will be available at
-
-
-
+
+
+
## Useful links
diff --git a/experimental/examples/prometheus/package.json b/experimental/examples/prometheus/package.json
index 10c8a48e8e1..c7f98d34bea 100644
--- a/experimental/examples/prometheus/package.json
+++ b/experimental/examples/prometheus/package.json
@@ -1,17 +1,18 @@
{
"name": "prometheus-example",
- "version": "0.49.1",
+ "version": "0.52.1",
"private": true,
"description": "Example of using @opentelemetry/sdk-metrics and @opentelemetry/exporter-prometheus",
"main": "index.js",
"scripts": {
- "start": "node index.js"
+ "start": "node index.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"author": "OpenTelemetry Authors",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/api": "^1.3.0",
- "@opentelemetry/exporter-prometheus": "0.49.1",
- "@opentelemetry/sdk-metrics": "1.22.0"
+ "@opentelemetry/exporter-prometheus": "0.52.1",
+ "@opentelemetry/sdk-metrics": "1.25.1"
}
}
diff --git a/experimental/packages/api-events/README.md b/experimental/packages/api-events/README.md
index 3aff88eff62..66af35291c7 100644
--- a/experimental/packages/api-events/README.md
+++ b/experimental/packages/api-events/README.md
@@ -28,18 +28,18 @@ If you are writing an instrumentation library, or prefer to call the API methods
```javascript
const api = require("@opentelemetry/api-events");
-/* A specific implementation of EventEmitterProvider comes from an SDK */
-const eventEmitterProvider = createEventEmitterProvider();
+/* A specific implementation of EventLoggerProvider comes from an SDK */
+const eventLoggerProvider = createEventLoggerProvider();
-/* Initialize EventEmitterProvider */
-api.events.setGlobalEventEmitterProvider(eventEmitterProvider);
-/* returns eventEmitterProvider (no-op if a working provider has not been initialized) */
-api.events.getEventEmitterProvider();
-/* returns an event emitter from the registered global event emitter provider (no-op if a working provider has not been initialized) */
-const eventEmitter = api.events.getEventEmitter(name, version);
+/* Initialize EventLoggerProvider */
+api.events.setGlobalEventLoggerProvider(eventLoggerProvider);
+/* returns eventLoggerProvider (no-op if a working provider has not been initialized) */
+api.events.getEventLoggerProvider();
+/* returns an event logger from the registered global event logger provider (no-op if a working provider has not been initialized) */
+const eventLogger = api.events.getEventLogger(name, version);
// logging an event in an instrumentation library
-eventEmitter.emit({ name: 'event-name', domain: 'event-domain' });
+eventLogger.emit({ name: 'event-name' });
```
## Useful links
@@ -57,4 +57,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/api-logs
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fapi-logs.svg
-[logs-api-docs]: https://open-telemetry.github.io/opentelemetry-js/modules/_opentelemetry_api_logs.html
+[events-api-docs]: https://open-telemetry.github.io/opentelemetry-js/modules/_opentelemetry_api_events.html
diff --git a/experimental/packages/api-events/package.json b/experimental/packages/api-events/package.json
index 643d95c82c7..b3513ed0db9 100644
--- a/experimental/packages/api-events/package.json
+++ b/experimental/packages/api-events/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/api-events",
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "Public events API for OpenTelemetry",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@@ -14,20 +14,21 @@
},
"repository": "open-telemetry/opentelemetry-js",
"scripts": {
- "prepublishOnly": "npm run compile",
- "compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
+ "build": "npm run compile",
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
- "test": "nyc ts-mocha -p tsconfig.json 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",
+ "compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
+ "prepublishOnly": "npm run compile",
+ "precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
+ "prewatch": "node ../../../scripts/version-update.js",
+ "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",
- "precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
- "prewatch": "node ../../../scripts/version-update.js"
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -61,26 +62,26 @@
"access": "public"
},
"dependencies": {
- "@opentelemetry/api": "^1.0.0"
+ "@opentelemetry/api": "^1.0.0",
+ "@opentelemetry/api-logs": "0.52.1"
},
"devDependencies": {
- "@types/mocha": "10.0.6",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/webpack-env": "1.16.3",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0"
},
diff --git a/experimental/packages/api-events/src/NoopEventEmitter.ts b/experimental/packages/api-events/src/NoopEventLogger.ts
similarity index 86%
rename from experimental/packages/api-events/src/NoopEventEmitter.ts
rename to experimental/packages/api-events/src/NoopEventLogger.ts
index b576e02bcf0..4ee4d7e23a7 100644
--- a/experimental/packages/api-events/src/NoopEventEmitter.ts
+++ b/experimental/packages/api-events/src/NoopEventLogger.ts
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-import { EventEmitter } from './types/EventEmitter';
+import { EventLogger } from './types/EventLogger';
import { Event } from './types/Event';
-export class NoopEventEmitter implements EventEmitter {
+export class NoopEventLogger implements EventLogger {
emit(_event: Event): void {}
}
diff --git a/experimental/packages/api-events/src/NoopEventEmitterProvider.ts b/experimental/packages/api-events/src/NoopEventLoggerProvider.ts
similarity index 55%
rename from experimental/packages/api-events/src/NoopEventEmitterProvider.ts
rename to experimental/packages/api-events/src/NoopEventLoggerProvider.ts
index 95731b0a8d9..4fa5630b67d 100644
--- a/experimental/packages/api-events/src/NoopEventEmitterProvider.ts
+++ b/experimental/packages/api-events/src/NoopEventLoggerProvider.ts
@@ -14,20 +14,19 @@
* limitations under the License.
*/
-import { EventEmitterProvider } from './types/EventEmitterProvider';
-import { EventEmitter } from './types/EventEmitter';
-import { EventEmitterOptions } from './types/EventEmitterOptions';
-import { NoopEventEmitter } from './NoopEventEmitter';
+import { EventLoggerProvider } from './types/EventLoggerProvider';
+import { EventLogger } from './types/EventLogger';
+import { EventLoggerOptions } from './types/EventLoggerOptions';
+import { NoopEventLogger } from './NoopEventLogger';
-export class NoopEventEmitterProvider implements EventEmitterProvider {
- getEventEmitter(
+export class NoopEventLoggerProvider implements EventLoggerProvider {
+ getEventLogger(
_name: string,
- _domain: string,
_version?: string | undefined,
- _options?: EventEmitterOptions | undefined
- ): EventEmitter {
- return new NoopEventEmitter();
+ _options?: EventLoggerOptions | undefined
+ ): EventLogger {
+ return new NoopEventLogger();
}
}
-export const NOOP_EVENT_EMITTER_PROVIDER = new NoopEventEmitterProvider();
+export const NOOP_EVENT_LOGGER_PROVIDER = new NoopEventLoggerProvider();
diff --git a/experimental/packages/api-events/src/api/events.ts b/experimental/packages/api-events/src/api/events.ts
index f17c93a2d34..c5a631c8fd4 100644
--- a/experimental/packages/api-events/src/api/events.ts
+++ b/experimental/packages/api-events/src/api/events.ts
@@ -20,10 +20,10 @@ import {
_global,
makeGetter,
} from '../internal/global-utils';
-import { EventEmitterProvider } from '../types/EventEmitterProvider';
-import { NOOP_EVENT_EMITTER_PROVIDER } from '../NoopEventEmitterProvider';
-import { EventEmitter } from '../types/EventEmitter';
-import { EventEmitterOptions } from '../types/EventEmitterOptions';
+import { EventLoggerProvider } from '../types/EventLoggerProvider';
+import { NOOP_EVENT_LOGGER_PROVIDER } from '../NoopEventLoggerProvider';
+import { EventLogger } from '../types/EventLogger';
+import { EventLoggerOptions } from '../types/EventLoggerOptions';
export class EventsAPI {
private static _instance?: EventsAPI;
@@ -38,54 +38,48 @@ export class EventsAPI {
return this._instance;
}
- public setGlobalEventEmitterProvider(
- provider: EventEmitterProvider
- ): EventEmitterProvider {
+ public setGlobalEventLoggerProvider(
+ provider: EventLoggerProvider
+ ): EventLoggerProvider {
if (_global[GLOBAL_EVENTS_API_KEY]) {
- return this.getEventEmitterProvider();
+ return this.getEventLoggerProvider();
}
- _global[GLOBAL_EVENTS_API_KEY] = makeGetter(
+ _global[GLOBAL_EVENTS_API_KEY] = makeGetter(
API_BACKWARDS_COMPATIBILITY_VERSION,
provider,
- NOOP_EVENT_EMITTER_PROVIDER
+ NOOP_EVENT_LOGGER_PROVIDER
);
return provider;
}
/**
- * Returns the global event emitter provider.
+ * Returns the global event logger provider.
*
- * @returns EventEmitterProvider
+ * @returns EventLoggerProvider
*/
- public getEventEmitterProvider(): EventEmitterProvider {
+ public getEventLoggerProvider(): EventLoggerProvider {
return (
_global[GLOBAL_EVENTS_API_KEY]?.(API_BACKWARDS_COMPATIBILITY_VERSION) ??
- NOOP_EVENT_EMITTER_PROVIDER
+ NOOP_EVENT_LOGGER_PROVIDER
);
}
/**
- * Returns a event emitter from the global event emitter provider.
+ * Returns a event logger from the global event logger provider.
*
- * @returns EventEmitter
+ * @returns EventLogger
*/
- public getEventEmitter(
+ public getEventLogger(
name: string,
- domain: string,
version?: string,
- options?: EventEmitterOptions
- ): EventEmitter {
- return this.getEventEmitterProvider().getEventEmitter(
- name,
- domain,
- version,
- options
- );
+ options?: EventLoggerOptions
+ ): EventLogger {
+ return this.getEventLoggerProvider().getEventLogger(name, version, options);
}
- /** Remove the global event emitter provider */
+ /** Remove the global event logger provider */
public disable(): void {
delete _global[GLOBAL_EVENTS_API_KEY];
}
diff --git a/experimental/packages/api-events/src/index.ts b/experimental/packages/api-events/src/index.ts
index 63fadffd48b..dbd464027ea 100644
--- a/experimental/packages/api-events/src/index.ts
+++ b/experimental/packages/api-events/src/index.ts
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-export * from './types/EventEmitter';
-export * from './types/EventEmitterProvider';
+export * from './types/EventLogger';
+export * from './types/EventLoggerProvider';
export * from './types/Event';
-export * from './types/EventEmitterOptions';
+export * from './types/EventLoggerOptions';
import { EventsAPI } from './api/events';
export const events = EventsAPI.getInstance();
diff --git a/experimental/packages/api-events/src/internal/global-utils.ts b/experimental/packages/api-events/src/internal/global-utils.ts
index d58b8901279..171cb0e1c7d 100644
--- a/experimental/packages/api-events/src/internal/global-utils.ts
+++ b/experimental/packages/api-events/src/internal/global-utils.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { EventEmitterProvider } from '../types/EventEmitterProvider';
+import { EventLoggerProvider } from '../types/EventLoggerProvider';
import { _globalThis } from '../platform';
export const GLOBAL_EVENTS_API_KEY = Symbol.for(
@@ -23,7 +23,7 @@ export const GLOBAL_EVENTS_API_KEY = Symbol.for(
type Get = (version: number) => T;
type OtelGlobal = Partial<{
- [GLOBAL_EVENTS_API_KEY]: Get;
+ [GLOBAL_EVENTS_API_KEY]: Get;
}>;
export const _global = _globalThis as OtelGlobal;
diff --git a/experimental/packages/api-events/src/types/Event.ts b/experimental/packages/api-events/src/types/Event.ts
index 03e4ef89dbd..572dd3b08c0 100644
--- a/experimental/packages/api-events/src/types/Event.ts
+++ b/experimental/packages/api-events/src/types/Event.ts
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-import { Attributes } from '@opentelemetry/api';
+import { Attributes, Context, TimeInput } from '@opentelemetry/api';
+import { AnyValue, SeverityNumber } from '@opentelemetry/api-logs';
export interface Event {
/**
* The time when the event occurred as UNIX Epoch time in nanoseconds.
*/
- timestamp?: number;
+ timestamp?: TimeInput;
/**
* The name of the event.
@@ -28,22 +29,23 @@ export interface Event {
name: string;
/**
- * Additional attributes that describe the event.
+ * Data that describes the event.
+ * Intended to be used by instrumentation libraries.
*/
- attributes?: Attributes;
+ data?: AnyValue;
/**
- * 8 least significant bits are the trace flags as defined in W3C Trace Context specification.
+ * Additional attributes that describe the event.
*/
- traceFlags?: number;
+ attributes?: Attributes;
/**
- * A unique identifier for a trace.
+ * Numerical value of the severity.
*/
- traceId?: string;
+ severityNumber?: SeverityNumber;
/**
- * A unique identifier for a span within a trace.
+ * The Context associated with the Event.
*/
- spanId?: string;
+ context?: Context;
}
diff --git a/experimental/packages/api-events/src/types/EventEmitterProvider.ts b/experimental/packages/api-events/src/types/EventEmitterProvider.ts
deleted file mode 100644
index 276b2e627dc..00000000000
--- a/experimental/packages/api-events/src/types/EventEmitterProvider.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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 { EventEmitter } from './EventEmitter';
-import { EventEmitterOptions } from './EventEmitterOptions';
-
-/**
- * A registry for creating named {@link EventEmitter}s.
- */
-export interface EventEmitterProvider {
- /**
- * Returns an EventEmitter, creating one if one with the given name, version, and
- * schemaUrl pair is not already created.
- *
- * @param name The name of the event emitter or instrumentation library.
- * @param domain The domain for events created by the event emitter.
- * @param version The version of the event emitter or instrumentation library.
- * @param options The options of the event emitter or instrumentation library.
- * @returns EventEmitter An event emitter with the given name and version.
- */
- getEventEmitter(
- name: string,
- domain: string,
- version?: string,
- options?: EventEmitterOptions
- ): EventEmitter;
-}
diff --git a/experimental/packages/api-events/src/types/EventEmitter.ts b/experimental/packages/api-events/src/types/EventLogger.ts
similarity index 96%
rename from experimental/packages/api-events/src/types/EventEmitter.ts
rename to experimental/packages/api-events/src/types/EventLogger.ts
index 1222339516a..9a465b9c481 100644
--- a/experimental/packages/api-events/src/types/EventEmitter.ts
+++ b/experimental/packages/api-events/src/types/EventLogger.ts
@@ -16,7 +16,7 @@
import { Event } from './Event';
-export interface EventEmitter {
+export interface EventLogger {
/**
* Emit an event. This method should only be used by instrumentations emitting events.
*
diff --git a/experimental/packages/api-events/src/types/EventEmitterOptions.ts b/experimental/packages/api-events/src/types/EventLoggerOptions.ts
similarity index 95%
rename from experimental/packages/api-events/src/types/EventEmitterOptions.ts
rename to experimental/packages/api-events/src/types/EventLoggerOptions.ts
index f5b983884eb..93aa29780a4 100644
--- a/experimental/packages/api-events/src/types/EventEmitterOptions.ts
+++ b/experimental/packages/api-events/src/types/EventLoggerOptions.ts
@@ -16,7 +16,7 @@
import { Attributes } from '@opentelemetry/api';
-export interface EventEmitterOptions {
+export interface EventLoggerOptions {
/**
* The schemaUrl of the tracer or instrumentation library
* @default ''
diff --git a/experimental/packages/api-events/src/types/EventLoggerProvider.ts b/experimental/packages/api-events/src/types/EventLoggerProvider.ts
new file mode 100644
index 00000000000..69eebe9202e
--- /dev/null
+++ b/experimental/packages/api-events/src/types/EventLoggerProvider.ts
@@ -0,0 +1,38 @@
+/*
+ * 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 { EventLogger } from './EventLogger';
+import { EventLoggerOptions } from './EventLoggerOptions';
+
+/**
+ * A registry for creating named {@link EventLogger}s.
+ */
+export interface EventLoggerProvider {
+ /**
+ * Returns an EventLogger, creating one if one with the given name, version, and
+ * schemaUrl pair is not already created.
+ *
+ * @param name The name of the event logger or instrumentation library.
+ * @param version The version of the event logger or instrumentation library.
+ * @param options The options of the event logger or instrumentation library.
+ * @returns EventLogger An event logger with the given name and version.
+ */
+ getEventLogger(
+ name: string,
+ version?: string,
+ options?: EventLoggerOptions
+ ): EventLogger;
+}
diff --git a/experimental/packages/api-events/test/api/api.test.ts b/experimental/packages/api-events/test/api/api.test.ts
index e091688ff87..4fb0509397c 100644
--- a/experimental/packages/api-events/test/api/api.test.ts
+++ b/experimental/packages/api-events/test/api/api.test.ts
@@ -15,57 +15,57 @@
*/
import * as assert from 'assert';
-import { EventEmitter, events } from '../../src';
-import { NoopEventEmitter } from '../../src/NoopEventEmitter';
-import { NoopEventEmitterProvider } from '../../src/NoopEventEmitterProvider';
+import { EventLogger, events } from '../../src';
+import { NoopEventLogger } from '../../src/NoopEventLogger';
+import { NoopEventLoggerProvider } from '../../src/NoopEventLoggerProvider';
describe('API', () => {
- const dummyEventEmitter = new NoopEventEmitter();
+ const dummyEventLogger = new NoopEventLogger();
- it('should expose a event emitter provider via getEventEmitterProvider', () => {
- const provider = events.getEventEmitterProvider();
+ it('should expose a event logger provider via getEventLoggerProvider', () => {
+ const provider = events.getEventLoggerProvider();
assert.ok(provider);
assert.strictEqual(typeof provider, 'object');
});
- describe('GlobalEventEmitterProvider', () => {
+ describe('GlobalEventLoggerProvider', () => {
beforeEach(() => {
events.disable();
});
- it('should use the global event emitter provider', () => {
- events.setGlobalEventEmitterProvider(new TestEventEmitterProvider());
- const eventEmitter = events
- .getEventEmitterProvider()
- .getEventEmitter('name', 'domain');
- assert.deepStrictEqual(eventEmitter, dummyEventEmitter);
+ it('should use the global event logger provider', () => {
+ events.setGlobalEventLoggerProvider(new TestEventLoggerProvider());
+ const eventLogger = events
+ .getEventLoggerProvider()
+ .getEventLogger('name');
+ assert.deepStrictEqual(eventLogger, dummyEventLogger);
});
it('should not allow overriding global provider if already set', () => {
- const provider1 = new TestEventEmitterProvider();
- const provider2 = new TestEventEmitterProvider();
- events.setGlobalEventEmitterProvider(provider1);
- assert.equal(events.getEventEmitterProvider(), provider1);
- events.setGlobalEventEmitterProvider(provider2);
- assert.equal(events.getEventEmitterProvider(), provider1);
+ const provider1 = new TestEventLoggerProvider();
+ const provider2 = new TestEventLoggerProvider();
+ events.setGlobalEventLoggerProvider(provider1);
+ assert.equal(events.getEventLoggerProvider(), provider1);
+ events.setGlobalEventLoggerProvider(provider2);
+ assert.equal(events.getEventLoggerProvider(), provider1);
});
});
- describe('getEventEmitter', () => {
+ describe('getEventLogger', () => {
beforeEach(() => {
events.disable();
});
- it('should return a event emitter instance from global provider', () => {
- events.setGlobalEventEmitterProvider(new TestEventEmitterProvider());
- const eventEmitter = events.getEventEmitter('myEventEmitter', 'domain');
- assert.deepStrictEqual(eventEmitter, dummyEventEmitter);
+ it('should return a event logger instance from global provider', () => {
+ events.setGlobalEventLoggerProvider(new TestEventLoggerProvider());
+ const eventLogger = events.getEventLogger('myEventLogger');
+ assert.deepStrictEqual(eventLogger, dummyEventLogger);
});
});
- class TestEventEmitterProvider extends NoopEventEmitterProvider {
- override getEventEmitter(): EventEmitter {
- return dummyEventEmitter;
+ class TestEventLoggerProvider extends NoopEventLoggerProvider {
+ override getEventLogger(): EventLogger {
+ return dummyEventLogger;
}
}
});
diff --git a/experimental/packages/api-events/test/internal/global.test.ts b/experimental/packages/api-events/test/internal/global.test.ts
index 0a4eb04f579..cdf71b556cb 100644
--- a/experimental/packages/api-events/test/internal/global.test.ts
+++ b/experimental/packages/api-events/test/internal/global.test.ts
@@ -19,7 +19,7 @@ import {
_global,
GLOBAL_EVENTS_API_KEY,
} from '../../src/internal/global-utils';
-import { NoopEventEmitterProvider } from '../../src/NoopEventEmitterProvider';
+import { NoopEventLoggerProvider } from '../../src/NoopEventLoggerProvider';
const api1 = require('../../src') as typeof import('../../src');
@@ -34,8 +34,8 @@ describe('Global Utils', () => {
assert.notStrictEqual(api1, api2);
// that return separate noop instances to start
assert.notStrictEqual(
- api1.events.getEventEmitterProvider(),
- api2.events.getEventEmitterProvider()
+ api1.events.getEventLoggerProvider(),
+ api2.events.getEventLoggerProvider()
);
beforeEach(() => {
@@ -43,38 +43,38 @@ describe('Global Utils', () => {
api2.events.disable();
});
- it('should change the global event emitter provider', () => {
- const original = api1.events.getEventEmitterProvider();
- const newEventEmitterProvider = new NoopEventEmitterProvider();
- api1.events.setGlobalEventEmitterProvider(newEventEmitterProvider);
- assert.notStrictEqual(api1.events.getEventEmitterProvider(), original);
+ it('should change the global event logger provider', () => {
+ const original = api1.events.getEventLoggerProvider();
+ const newEventLoggerProvider = new NoopEventLoggerProvider();
+ api1.events.setGlobalEventLoggerProvider(newEventLoggerProvider);
+ assert.notStrictEqual(api1.events.getEventLoggerProvider(), original);
assert.strictEqual(
- api1.events.getEventEmitterProvider(),
- newEventEmitterProvider
+ api1.events.getEventLoggerProvider(),
+ newEventLoggerProvider
);
});
it('should load an instance from one which was set in the other', () => {
- api1.events.setGlobalEventEmitterProvider(new NoopEventEmitterProvider());
+ api1.events.setGlobalEventLoggerProvider(new NoopEventLoggerProvider());
assert.strictEqual(
- api1.events.getEventEmitterProvider(),
- api2.events.getEventEmitterProvider()
+ api1.events.getEventLoggerProvider(),
+ api2.events.getEventLoggerProvider()
);
});
it('should disable both if one is disabled', () => {
- const original = api1.events.getEventEmitterProvider();
+ const original = api1.events.getEventLoggerProvider();
- api1.events.setGlobalEventEmitterProvider(new NoopEventEmitterProvider());
+ api1.events.setGlobalEventLoggerProvider(new NoopEventLoggerProvider());
- assert.notStrictEqual(original, api1.events.getEventEmitterProvider());
+ assert.notStrictEqual(original, api1.events.getEventLoggerProvider());
api2.events.disable();
- assert.strictEqual(original, api1.events.getEventEmitterProvider());
+ assert.strictEqual(original, api1.events.getEventLoggerProvider());
});
it('should return the module NoOp implementation if the version is a mismatch', () => {
- const original = api1.events.getEventEmitterProvider();
- api1.events.setGlobalEventEmitterProvider(new NoopEventEmitterProvider());
+ const original = api1.events.getEventLoggerProvider();
+ api1.events.setGlobalEventLoggerProvider(new NoopEventLoggerProvider());
const afterSet = _global[GLOBAL_EVENTS_API_KEY]!(-1);
assert.strictEqual(original, afterSet);
diff --git a/experimental/packages/api-events/test/noop-implementations/noop-event-emitter-provider.test.ts b/experimental/packages/api-events/test/noop-implementations/noop-event-logger-provider.test.ts
similarity index 60%
rename from experimental/packages/api-events/test/noop-implementations/noop-event-emitter-provider.test.ts
rename to experimental/packages/api-events/test/noop-implementations/noop-event-logger-provider.test.ts
index ad88d370585..995eb473a34 100644
--- a/experimental/packages/api-events/test/noop-implementations/noop-event-emitter-provider.test.ts
+++ b/experimental/packages/api-events/test/noop-implementations/noop-event-logger-provider.test.ts
@@ -15,28 +15,25 @@
*/
import * as assert from 'assert';
-import { NoopEventEmitter } from '../../src/NoopEventEmitter';
-import { NoopEventEmitterProvider } from '../../src/NoopEventEmitterProvider';
+import { NoopEventLogger } from '../../src/NoopEventLogger';
+import { NoopEventLoggerProvider } from '../../src/NoopEventLoggerProvider';
describe('NoopLoggerProvider', () => {
it('should not crash', () => {
- const eventEmitterProvider = new NoopEventEmitterProvider();
+ const eventLoggerProvider = new NoopEventLoggerProvider();
assert.ok(
- eventEmitterProvider.getEventEmitter('emitter-name', 'domain') instanceof
- NoopEventEmitter
+ eventLoggerProvider.getEventLogger('logger-name') instanceof
+ NoopEventLogger
);
assert.ok(
- eventEmitterProvider.getEventEmitter(
- 'emitter-name',
- 'domain',
- 'v1'
- ) instanceof NoopEventEmitter
+ eventLoggerProvider.getEventLogger('logger-name', 'v1') instanceof
+ NoopEventLogger
);
assert.ok(
- eventEmitterProvider.getEventEmitter('emitter-name', 'domain', 'v1', {
+ eventLoggerProvider.getEventLogger('logger-name', 'v1', {
schemaUrl: 'https://opentelemetry.io/schemas/1.7.0',
- }) instanceof NoopEventEmitter
+ }) instanceof NoopEventLogger
);
});
});
diff --git a/experimental/packages/api-events/test/noop-implementations/noop-event-emitter.test.ts b/experimental/packages/api-events/test/noop-implementations/noop-event-logger.test.ts
similarity index 62%
rename from experimental/packages/api-events/test/noop-implementations/noop-event-emitter.test.ts
rename to experimental/packages/api-events/test/noop-implementations/noop-event-logger.test.ts
index 933a3e6e885..b29a6271bf8 100644
--- a/experimental/packages/api-events/test/noop-implementations/noop-event-emitter.test.ts
+++ b/experimental/packages/api-events/test/noop-implementations/noop-event-logger.test.ts
@@ -15,24 +15,18 @@
*/
import * as assert from 'assert';
-import { NoopEventEmitter } from '../../src/NoopEventEmitter';
-import { NoopEventEmitterProvider } from '../../src/NoopEventEmitterProvider';
+import { NoopEventLogger } from '../../src/NoopEventLogger';
+import { NoopEventLoggerProvider } from '../../src/NoopEventLoggerProvider';
-describe('NoopEventEmitter', () => {
+describe('NoopEventLogger', () => {
it('constructor should not crash', () => {
- const logger = new NoopEventEmitterProvider().getEventEmitter(
- 'test-noop',
- 'test-domain'
- );
- assert(logger instanceof NoopEventEmitter);
+ const logger = new NoopEventLoggerProvider().getEventLogger('test-noop');
+ assert(logger instanceof NoopEventLogger);
});
it('calling emit should not crash', () => {
- const emitter = new NoopEventEmitterProvider().getEventEmitter(
- 'test-noop',
- 'test-domain'
- );
- emitter.emit({
+ const logger = new NoopEventLoggerProvider().getEventLogger('test-noop');
+ logger.emit({
name: 'event name',
});
});
diff --git a/experimental/packages/api-events/tsconfig.esm.json b/experimental/packages/api-events/tsconfig.esm.json
index f0383c00422..91cc36db7ae 100644
--- a/experimental/packages/api-events/tsconfig.esm.json
+++ b/experimental/packages/api-events/tsconfig.esm.json
@@ -11,6 +11,9 @@
"references": [
{
"path": "../../../api"
+ },
+ {
+ "path": "../api-logs"
}
]
}
diff --git a/experimental/packages/api-events/tsconfig.esnext.json b/experimental/packages/api-events/tsconfig.esnext.json
index 218899ff2da..80e34599a90 100644
--- a/experimental/packages/api-events/tsconfig.esnext.json
+++ b/experimental/packages/api-events/tsconfig.esnext.json
@@ -11,6 +11,9 @@
"references": [
{
"path": "../../../api"
+ },
+ {
+ "path": "../api-logs"
}
]
}
diff --git a/experimental/packages/api-events/tsconfig.json b/experimental/packages/api-events/tsconfig.json
index 5849e79c034..40ca71c181e 100644
--- a/experimental/packages/api-events/tsconfig.json
+++ b/experimental/packages/api-events/tsconfig.json
@@ -12,6 +12,9 @@
"references": [
{
"path": "../../../api"
+ },
+ {
+ "path": "../api-logs"
}
]
}
diff --git a/experimental/packages/api-logs/package.json b/experimental/packages/api-logs/package.json
index 4dfa4fd579f..d3eca36f3bb 100644
--- a/experimental/packages/api-logs/package.json
+++ b/experimental/packages/api-logs/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/api-logs",
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "Public logs API for OpenTelemetry",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@@ -17,7 +17,7 @@
"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",
- "test": "nyc ts-mocha -p tsconfig.json test/**/*.test.ts",
+ "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 ../../../",
@@ -27,7 +27,8 @@
"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",
- "prewatch": "node ../../../scripts/version-update.js"
+ "prewatch": "node ../../../scripts/version-update.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -64,23 +65,22 @@
"@opentelemetry/api": "^1.0.0"
},
"devDependencies": {
- "@types/mocha": "10.0.6",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/webpack-env": "1.16.3",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0"
},
diff --git a/experimental/packages/api-logs/src/index.ts b/experimental/packages/api-logs/src/index.ts
index 34b4d8e20ee..3ea2ae39c8b 100644
--- a/experimental/packages/api-logs/src/index.ts
+++ b/experimental/packages/api-logs/src/index.ts
@@ -18,6 +18,7 @@ export * from './types/Logger';
export * from './types/LoggerProvider';
export * from './types/LogRecord';
export * from './types/LoggerOptions';
+export * from './types/AnyValue';
export * from './NoopLogger';
export * from './NoopLoggerProvider';
diff --git a/experimental/packages/api-logs/src/types/AnyValue.ts b/experimental/packages/api-logs/src/types/AnyValue.ts
new file mode 100644
index 00000000000..7a97de7ed60
--- /dev/null
+++ b/experimental/packages/api-logs/src/types/AnyValue.ts
@@ -0,0 +1,29 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { AttributeValue } from '@opentelemetry/api';
+
+/**
+ * AnyValueMap is a map from string to AnyValue (attribute value or a nested map)
+ */
+export interface AnyValueMap {
+ [attributeKey: string]: AnyValue | undefined;
+}
+
+/**
+ * AnyValue is a either an attribute value or a map of AnyValue(s)
+ */
+export type AnyValue = AttributeValue | AnyValueMap;
diff --git a/experimental/packages/api-logs/src/types/LogRecord.ts b/experimental/packages/api-logs/src/types/LogRecord.ts
index 69dd14f7cba..85d5e4ff4dd 100644
--- a/experimental/packages/api-logs/src/types/LogRecord.ts
+++ b/experimental/packages/api-logs/src/types/LogRecord.ts
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-import { AttributeValue, Context, TimeInput } from '@opentelemetry/api';
+import { Context, TimeInput } from '@opentelemetry/api';
+import { AnyValue, AnyValueMap } from './AnyValue';
-export type LogAttributeValue = AttributeValue | LogAttributes;
-export interface LogAttributes {
- [attributeKey: string]: LogAttributeValue | undefined;
-}
+export type LogBody = AnyValue;
+export type LogAttributes = AnyValueMap;
export enum SeverityNumber {
UNSPECIFIED = 0,
@@ -73,7 +72,7 @@ export interface LogRecord {
/**
* A value containing the body of the log record.
*/
- body?: string;
+ body?: LogBody;
/**
* Attributes that define the log record.
diff --git a/experimental/packages/exporter-logs-otlp-grpc/README.md b/experimental/packages/exporter-logs-otlp-grpc/README.md
index b2ba24bf9ab..f052ff6d8b3 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/README.md
+++ b/experimental/packages/exporter-logs-otlp-grpc/README.md
@@ -84,7 +84,6 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-logs-otlp-grpc
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-logs-otlp-grpc.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/exporter-trace-otlp-grpc
[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc
diff --git a/experimental/packages/exporter-logs-otlp-grpc/package.json b/experimental/packages/exporter-logs-otlp-grpc/package.json
index 38cd36b6241..9d88af8296e 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/package.json
+++ b/experimental/packages/exporter-logs-otlp-grpc/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-logs-otlp-grpc",
- "version": "0.49.1",
+ "version": "0.52.1",
"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",
@@ -12,13 +12,15 @@
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts'",
"version": "node ../../../scripts/version-update.js",
"watch": "tsc --watch --build",
"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 ../../../"
+ "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"
},
"keywords": [
"opentelemetry",
@@ -49,22 +51,20 @@
},
"devDependencies": {
"@grpc/proto-loader": "^0.7.10",
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/api-logs": "0.49.1",
- "@opentelemetry/otlp-exporter-base": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@types/mocha": "10.0.6",
+ "@opentelemetry/api": "1.9.0",
+ "@opentelemetry/api-logs": "0.52.1",
+ "@opentelemetry/otlp-exporter-base": "0.52.1",
+ "@opentelemetry/resources": "1.25.1",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4"
},
"peerDependencies": {
@@ -72,10 +72,10 @@
},
"dependencies": {
"@grpc/grpc-js": "^1.7.1",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/otlp-grpc-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/sdk-logs": "0.49.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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-logs-otlp-grpc",
"sideEffects": false
diff --git a/experimental/packages/exporter-logs-otlp-grpc/src/OTLPLogExporter.ts b/experimental/packages/exporter-logs-otlp-grpc/src/OTLPLogExporter.ts
index b59a177b22e..1172126cbd4 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/src/OTLPLogExporter.ts
+++ b/experimental/packages/exporter-logs-otlp-grpc/src/OTLPLogExporter.ts
@@ -21,12 +21,10 @@ import {
OTLPGRPCExporterNodeBase,
validateAndNormalizeUrl,
DEFAULT_COLLECTOR_URL,
- LogsSerializer,
} from '@opentelemetry/otlp-grpc-exporter-base';
import {
- createExportLogsServiceRequest,
- IExportLogsServiceRequest,
IExportLogsServiceResponse,
+ ProtobufLogsSerializer,
} from '@opentelemetry/otlp-transformer';
import { VERSION } from './version';
@@ -40,7 +38,6 @@ const USER_AGENT = {
export class OTLPLogExporter
extends OTLPGRPCExporterNodeBase<
ReadableLogRecord,
- IExportLogsServiceRequest,
IExportLogsServiceResponse
>
implements LogRecordExporter
@@ -57,14 +54,10 @@ export class OTLPLogExporter
signalSpecificMetadata,
'LogsExportService',
'/opentelemetry.proto.collector.logs.v1.LogsService/Export',
- LogsSerializer
+ ProtobufLogsSerializer
);
}
- convert(logRecords: ReadableLogRecord[]): IExportLogsServiceRequest {
- return createExportLogsServiceRequest(logRecords);
- }
-
getDefaultUrl(config: OTLPGRPCExporterConfigNode) {
return validateAndNormalizeUrl(this.getUrlFromConfig(config));
}
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/OTLPLogExporter.test.ts b/experimental/packages/exporter-logs-otlp-grpc/test/OTLPLogExporter.test.ts
index e48a1cef684..35cc083ccc1 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/OTLPLogExporter.test.ts
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/OTLPLogExporter.test.ts
@@ -18,6 +18,7 @@ import * as protoLoader from '@grpc/proto-loader';
import { diag } from '@opentelemetry/api';
import * as assert from 'assert';
+import * as crypto from 'crypto';
import * as fs from 'fs';
import * as grpc from '@grpc/grpc-js';
import * as path from 'path';
@@ -40,9 +41,7 @@ import { VERSION } from '../src/version';
const logsServiceProtoPath =
'opentelemetry/proto/collector/logs/v1/logs_service.proto';
-const includeDirs = [
- path.resolve(__dirname, '../../otlp-grpc-exporter-base/protos'),
-];
+const includeDirs = [path.resolve(__dirname, '../../otlp-transformer/protos')];
const httpAddr = 'https://localhost:1503';
const udsAddr = 'unix:///tmp/otlp-logs.sock';
@@ -144,6 +143,24 @@ const testCollectorExporter = (params: TestParams) => {
sinon.restore();
});
+ if (useTLS && crypto.X509Certificate) {
+ it('test certs are valid', () => {
+ const certPaths = [
+ './test/certs/ca.crt',
+ './test/certs/client.crt',
+ './test/certs/server.crt',
+ ];
+ certPaths.forEach(certPath => {
+ const cert = new crypto.X509Certificate(fs.readFileSync(certPath));
+ const now = new Date();
+ assert.ok(
+ new Date(cert.validTo) > now,
+ `TLS cert "${certPath}" is still valid: cert.validTo="${cert.validTo}" (if this fails use 'npm run maint:regenerate-test-certs')`
+ );
+ });
+ });
+ }
+
describe('instance', () => {
it('should warn about headers when using grpc', () => {
// Need to stub/spy on the underlying logger as the 'diag' instance is global
@@ -224,9 +241,9 @@ const testCollectorExporter = (params: TestParams) => {
setTimeout(() => {
const result = responseSpy.args[0][0] as core.ExportResult;
assert.strictEqual(result.code, core.ExportResultCode.FAILED);
- assert.strictEqual(
+ assert.match(
responseSpy.args[0][0].error.details,
- 'Deadline exceeded'
+ /Deadline exceeded.*/
);
done();
}, 300);
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/ca.crt b/experimental/packages/exporter-logs-otlp-grpc/test/certs/ca.crt
index c194f049542..62270748a6e 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/ca.crt
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/ca.crt
@@ -1,33 +1,33 @@
-----BEGIN CERTIFICATE-----
-MIIFozCCA4ugAwIBAgIUFA6cfBQ2t0ZOpLTRUIE6VN+kGBkwDQYJKoZIhvcNAQEL
+MIIFozCCA4ugAwIBAgIUAlsD9Gz58PTwA00z7LcmYLcREgswDQYJKoZIhvcNAQEL
BQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQHDBFPcGVuVGVs
ZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9vdDENMAsGA1UECwwEVGVzdDELMAkGA1UE
-AwwCY2EwHhcNMjMwNjA4MTY0NDIzWhcNMjQwNjA3MTY0NDIzWjBhMQswCQYDVQQG
+AwwCY2EwHhcNMjQwNjA4MTkxODQ4WhcNMjUwNjA4MTkxODQ4WjBhMQswCQYDVQQG
EwJDTDELMAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0w
CwYDVQQKDARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTCCAiIwDQYJ
-KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMm3OXVbMd0t2r4x+Pg4fecPeFhRzsg6
-sp7AM4UYlhb0Xkx8ij3q0E47uQM/OSari6qi7p1Un6nzgaXmhosaNkVXaKV4dQ4g
-zKqrvC2+nTYU4lwss4Rx32CQxOKXEvN5FPwLTNo903PP3wqJyVt8syN0CDW953m/
-hUdkNaOe/lXmDJ9TmTTGyuPZFSlNlufbaNsBUM5chVFgBYDQIVy0jls8MiYLfao5
-tfprj+yS+lnTDl54dDTVVyAgV22SY65cnUgvO4bu3nzhS/h2Xg4/6/yAuYaRI7GQ
-xvlA4pzx+aLaRDTJKiszRrHbQFv4PY+MmkVxvg2Oka4Vc2XMgDM87H0bd+beO8NH
-Tf7UHU5AmIr2j2R27LWeELOqanm1HYn2VK182lD7OwQ5u5yqZZuke8bMMPJQEPUm
-EwhIgXMVIlGps2+rDUEalPYkQ/BmAcs2g7fywW3RhIWCacggKoee1x9a6oiUM5yi
-oDJ6T/C4WUQzIVebdMC25zBBlxcy8fK4Yus/DFTqM/eXPl4NVzbH/yB5tlU2GU0Q
-V4tpGL1jsUy4b7r1bzuYVNfnKrarUGFF5TIHuvDo3voJNGb4hWBH/JdttG/9NaWA
-HomZ8CUWR+gNEzyPkwq7upkiblKxJV7HKo79Eex+dlWa+Ru1F3kwYE200Y+a/wOF
-Rj4+PfMu7WvpAgMBAAGjUzBRMB0GA1UdDgQWBBSwH/Wk2wTc+MEPAEornj1eGKra
-0zAfBgNVHSMEGDAWgBSwH/Wk2wTc+MEPAEornj1eGKra0zAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCNkzOjjqH3qeQ0wT/Has5PSoWwRwq+B1JT
-gg29bgEMD6dVkLdzgEuRVVkMtc/tCZAkA02pc0VN8+lNLW7ckNU/QhMTQYn+FgMR
-cG86vR9loTnwUrxR4dS6Nbx1sQ7hpe2GZkWpTNmjh1duHBNHv9nS2JmMkRypqRne
-oAI3/th1Qlrtl/zDn02/+P5/av0YJcMOcnRkULHnI62cbXHa2iPd/nENgH2xC6CA
-EuYN/bnmOEUPeKljU1IZS6asjGMLdWLmpLs7oOcHGLD3pax+om69Pmn7rps8Z071
-WsJDHFCftItCUrg4KWwpXr77Vq4WAN2tOBdDHEZsbES6a54+7sc1QKOVSWwPuGEd
-ShFHhTzoaB0dpwm6kLdYsEkC8JLIjV+Ikg5X3VTDITjUlHoJf2mxCGOzBiCnUr75
-Am0eBqlVcc/2aVk1tcVS9N7reY/KcMaAJvI314O9I94pYdIIm5jw3UmA9Y6HmpN0
-vYtQUF2sS5W82XoFD8bpOq/bx1o2ib2x32dfPQkVgd4sbmpsyN62Fy1HpHwXtXno
-xGVaDzGSWj/7RyYyKhNmp3nfQsU0Tt6iVkM+N30vl2heZqEUgXxCG9qHVzWv9z6x
-AJzuafjM8tviROpiHkvzsmq7uDhksGooKCi+m+eoEBJrd0J4gjngAi1NYjTsB2GT
-4mvPz05UkA==
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMv6RFj5bgfSnj27LJMUwceaVI8Rz6Ks
+BKRyJlM/cE3MQg+58BjoelLxfRsCxHFLvwuo/S6l0leRYAvzCexsnFnqd5Ie0tMi
+1pB6YMPcmzUwbJCywLUGBin85TDFpEd1L1cSxKvi4DoC6EDYdBge0yp3T1my3mlu
+8LaMVYr22RQvofwaTqFwmOQSqxK3wR9LRWTMDoUioMdolkIv7y1lpQ59ORWlASfP
+SMUhh4KAYmDCtH9M40iY7kwCMv8ZwB2DIiw1qZxkk3MFJoyI5HZuvb586Pp5GfHI
+Wry2KaTZskGCDB/8mURhMyFQnsO+kN9moYLm+NVk+8jzTTus4DUI6sEnpSgF05hU
+O9lIL+HAFl/6N5d/W5wbSfOulPwJCd+c49ylIAUu38ZmNmRpmGPalBlluDYu8Exw
+d/uoXBmt5vyeE9d14uTYYt+xef942s66Qnoq9wLFJymSsMb1v41Pv/zjeV53NIRE
+xJ1sSH+5xcRaAdvjdmN2q5zuKddkD/2FyIl0NkWwNYefKaFdLEy9MfdbBgKBHOkh
+neTWIZwI8Kkff6v5MTW022MK7v3nis1wUjrvEn0CyI8USCh/wcNBmiJsrEPltN+S
+CsriZLwT1x4mce+43+bibxinL+RZogWxZ/Q+TkeUsluBNjn8hwWy5n/750HKgRAa
+D+KxGkn92B9tAgMBAAGjUzBRMB0GA1UdDgQWBBQjlis82orRLmms4w1dbJFf9NDO
+6zAfBgNVHSMEGDAWgBQjlis82orRLmms4w1dbJFf9NDO6zAPBgNVHRMBAf8EBTAD
+AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQARxfWyzqU9aUrSt50daVayVezg3gJQh4XI
+V0p+LGEF6rlGVlX3lnhyf1g/nd1jdiBxMGnROXTFotdw4h1yQjlNrPp5Gh7ZJets
+NPvo0xYfCckEmwUFX1+ikwteSciOmBKypAsEYlPjUuGxhMm7WT18WyogjUZOz8k9
+Q3DSAsf3KR516uYeK+U/RTOiYc6HzCPxBy5fG80aI4rxcdJkA60RxHEM2ZqdhlYY
++DkE6843xEbrF4TjmoDeOq471D4Zl3DqLg9v7YbOARV2G8MYUsBkeSTcSz+DWEXA
+MSoQMgv2Z6G7ToUeYhRXOLHHILHmu5Hc2ldVvLmbhkfDICjYnNqsiuSnKkZ2WqBn
+1GXTjTEPl+FNt0Gwy/+ygiG4Z2S5Cc2ULPLMs9E9N2Iiq+LNjmgw3dUy8pwOTfDo
+heluT4NeGmHxh4sFQpg96z0K1JCZZpzJCsSAJRXxLdSl7VVFXTGbmRjD8BrBWn4k
+9euT4UHgWj+xSYkJWpIkuTMJ6M4+B/JQQNVwKok/xqTHadOJ2f4V6j4cy517hMu6
+oFo/XF6zG3N0sGfkFTlcE7xsruRbir7utAEQwuUGQsy1SeGRrLCwBcvhetq1jVR8
+mjXEADzaP1a9+nMG+LFD+PeHcpYbuxaOwAinFbA1SwwGmAwWFhXudSiFpIM2btrE
+f9n1KYObAw==
-----END CERTIFICATE-----
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/ca.key b/experimental/packages/exporter-logs-otlp-grpc/test/certs/ca.key
index 00ccb046224..6d444ffdab8 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/ca.key
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/ca.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+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
+Z4y6eNlrPgWPTUHp+YTgMmZ/c1kwHGo=
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.crt b/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.crt
index fd05c9c40be..ff9555042c9 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.crt
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.crt
@@ -1,31 +1,32 @@
-----BEGIN CERTIFICATE-----
-MIIFPzCCAycCAQEwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNV
-BAgMAlJNMRowGAYDVQQHDBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9v
-dDENMAsGA1UECwwEVGVzdDELMAkGA1UEAwwCY2EwHhcNMjMwNjA4MTY0NDI2WhcN
-MjQwNjA3MTY0NDI2WjBqMQswCQYDVQQGEwJDTDELMAkGA1UECAwCUk0xGjAYBgNV
-BAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQKDARUZXN0MQ8wDQYDVQQLDAZD
-bGllbnQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBANewSXGnuCUsPcOnXPq7SUFTLaSM62x2FnJrzb6rne8KYQ615l6D
-d2Nm7MrttHWJUBQS6iDCsEGlF/AWYO5adVuZ+Xf+S+NoWMXPTUuJYq+5VEeAS8PM
-IriksA8Npn0hAMNTDrd/eNXQ5W4zLQOqUWnKcuE0P1M7gI3/rfX9/JXkZfUmkQGK
-OSva3qJHOcG7Bc7vqbJnkFebIw87e2iHxNnUf5IoJmrUaOMdFiQyHBBoJyTVJ3wp
-Ufr6Q2+d0sIyes9PV33DbB8DyKGdOfbLg4YmKsnAvnypC0p2Xw9yAnHlQX27Ngcq
-tfzcOXx3QlNPxQDF3oNHzi8GD7ysex1z7PRIsZlLVQLshAdOfA+naktPezj52R8V
-BtWaxgVFI7IA5X21reS25t01k/GXNcyIJxW5KSz00b1h8+mpz0n0R3Mz3HuZybAX
-g5bnZ+91jOeQmTt08eMXjwAGClxcOqfrssfDvOnUSZjDpzEGDaVuFGVPA9hR/eKN
-Bfo659rv45pYhtxoHLz1LJWoZ1uegmKrGF1w16K05k5mpzwH6fzqDzzbF1xyynGX
-yfbIqsvsBniuWGmhMjlfT5+l0VG2GgsD7Yijv6SV0YZrVf85iA5q6XdKTBuKYmin
-ZEbneEjw9kc9myMeC5ik7wHuksA/BQcja1TPwB4ZRbPEcfi2iFxbtsSzAgMBAAEw
-DQYJKoZIhvcNAQELBQADggIBAGdcqEI2l/dKxu9vPuRC2/VRgjgDBN4UJJCY111T
-2A7GsGzd7lRhtxB5ZzClF77UiRJG+cvFai00c9+L3wp8qy4sZWY4MaJIWoKRh72Q
-sRiH8AskeIl3uvvvaH86bbmpDo7M48Cs/zXZo9VhLzD8ZuHcS1mdjkOcnQzkbSzR
-YeM9ActeuJRmsdQ+gSzCTvFqmGutL6xvM8b9a6PwyY5nPxS+eh0/7KNp+EXBvp0U
-MWp6mMfq22nAwAQRLbvh5f+a/4GSwg73By6hwnsgb7tpBBJ6ppnKAIALRf7l5JwS
-V0LM5Vnpp4J4JjdYyQzk2xkxi+UGIP1IRigbeWc4K3qgg6BUUkfSf4W9oJD4JCa2
-cOsqnKqFxTwXT4b9j9qsPpg7mUQ2+UtU4Lv3h/7sXpbpx0ldb2Hnaq+JqUz0l/7c
-54y3+nzke7I4CWKtLJUSamQiyOC3CBVkRX0YEYUBhMXim6dKAfiOEV6K3bwiU+YZ
-aDe0lEeLbzAp87DKRTAvDYhRMIFtD3g2qmYrWpQ4gj8vSEorNAfg3kVHMFRGlk9o
-jaFduAz0hKk+QG5SgePXMph5ZRXGRq0FnDbF2gZ7WV+jZiIhsYGJ43+RBWHh4HO4
-P4h9eOWQG8AxpDRmOo2KmyPbV0V/eltC4N0oOAmWz+i0qqulnpG4dOzQKpinRBBr
-jPt5
+MIIFiDCCA3CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJDTDEL
+MAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQK
+DARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTAeFw0yNDA2MDgxOTE4
+NDlaFw0yNTA2MDgxOTE4NDlaMGoxCzAJBgNVBAYTAkNMMQswCQYDVQQIDAJSTTEa
+MBgGA1UEBwwRT3BlblRlbGVtZXRyeVRlc3QxDTALBgNVBAoMBFRlc3QxDzANBgNV
+BAsMBkNsaWVudDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAwmlAXHz7CE3EQ7XEMNwYymj193+C3Mo6V210X2BKjCuZ
+SRdq0c/VpAWeFy5f1SHzFEkvpmfXKjePrnQL9fT5bFwUusx1pepI1c+9eHMxiSxc
+rpO5SPfEPfZPHOhZBUYEYI2MRektn0UaE/a9qiQpBh5fFtyMedLkyNkfJ2OAbwCJ
+XRwmUpt5pWAFORXDecVLWtTSVMQsWsOI/2gae6dgbTbJdXaLUV/UFsBOlp6m1mwb
+PsHiQDawxM5aks2AjRA79aBSF1IxwO9Duqv3ZjqFd8C1nXr7oqVyEujQFtjIAvNJ
+I1aP9Mu5Pybcp928VkQT8PdRcaLDt8iuOyggI86CITxVFOur8GxASHF1EF4ymkfG
+jS5jCLh8BLqAGqNERQpoNyD879yTlq8ho/k/F0in9WyaEjbuEKo6wPhJUgZ1JV0q
+CpqxmTlGgcWBg1Mnl8RdmHkq68zsmTpLbPzpuXlv51KmJCahc31jWHJjN1ORPGPg
+hLrKkbcylW/6HTpI5i2kkn+k5owUAkst7K0njRH5TF4p7iYuC4zwSnTgxlvio9E5
+Ci6BinMgkDOjwNovXy60mR+RnKP9yxlpuJ/jbZvR9a2SYpMbu1CrBFyZ4JkTLCEC
+A6rh6arjXVW6rTwEjKpMoqhZXg7CNux7gxq/czo9S6Ja0xVOnomTRCHLTgCoAOcC
+AwEAAaNCMEAwHQYDVR0OBBYEFMI7y2a70iF6O+SLnWA2FXbjIlhkMB8GA1UdIwQY
+MBaAFCOWKzzaitEuaazjDV1skV/00M7rMA0GCSqGSIb3DQEBCwUAA4ICAQADNVle
+3YVLZs/MULoWXTwVWgriM/o5/j0iYQ4xAWlTkaT38gLov16EmwOZJbXSfDVyom1p
+M818j1IwqUKdMNJyCAiXE3IriBLLSjtk6tpi4sQ2Es/QnyINGoMcAugfoymjJPhA
+Pr0fJK06fs/8BDcPhlbZl3DfMF4heXh/6wlgGfjwRoXmRwtzw1Iavw9ThbolhJTm
+RiE4WE2Grh0AGtqe4EJHVDslhq2oe0UHU55BbwBPWvpUYb7VWR5dd3B04TgnOnR2
+ESzUgb4suQmNEIQsO/k2O7aIQj9jJzPCULzkmcUppAP9ig9lipmi/Fa0+1nFVJrT
+lAnlDm8EW5g/S+XdFTEd22mSaWM5hjTQqDlGi2Ni6R4jDcPE7uyFS0FwTk6e72YE
+CP+wLIDd8s8Q8Bp5jP5JgJm3f1MCXGDtoGVR4fgMF+N36eKVGFIeFN/jQaLAE4pO
+3qaVCEpQCPC4NoCW+lIOLtYQ+nTg6RVCHf26uZqkuHKqh/gGP9MCSEkg9b78iC8D
+ciKxp4gz7CUUV+cmDMcDJxqAaBZnA+V0brVqDcYtul1UyanPN4WsJbBRG5s705vy
+m7Fk4k2GWdfyEiOjrRd2EuezmemeSD4S9aIgtAGhggcIMtkJaSdS6zfjo/nuu2kO
+A0+Bw3OOUbvnnJ0MlmLHeCSMPBCu4xVaKda8Lw==
-----END CERTIFICATE-----
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.csr b/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.csr
index b7838967259..1fe2d47932e 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.csr
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.csr
@@ -2,27 +2,27 @@
MIIErzCCApcCAQAwajELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQH
DBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEVGVzdDEPMA0GA1UECwwGQ2xp
ZW50MRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
-ggIKAoICAQDXsElxp7glLD3Dp1z6u0lBUy2kjOtsdhZya82+q53vCmEOteZeg3dj
-ZuzK7bR1iVAUEuogwrBBpRfwFmDuWnVbmfl3/kvjaFjFz01LiWKvuVRHgEvDzCK4
-pLAPDaZ9IQDDUw63f3jV0OVuMy0DqlFpynLhND9TO4CN/631/fyV5GX1JpEBijkr
-2t6iRznBuwXO76myZ5BXmyMPO3toh8TZ1H+SKCZq1GjjHRYkMhwQaCck1Sd8KVH6
-+kNvndLCMnrPT1d9w2wfA8ihnTn2y4OGJirJwL58qQtKdl8PcgJx5UF9uzYHKrX8
-3Dl8d0JTT8UAxd6DR84vBg+8rHsdc+z0SLGZS1UC7IQHTnwPp2pLT3s4+dkfFQbV
-msYFRSOyAOV9ta3ktubdNZPxlzXMiCcVuSks9NG9YfPpqc9J9EdzM9x7mcmwF4OW
-52fvdYznkJk7dPHjF48ABgpcXDqn67LHw7zp1EmYw6cxBg2lbhRlTwPYUf3ijQX6
-Oufa7+OaWIbcaBy89SyVqGdbnoJiqxhdcNeitOZOZqc8B+n86g882xdccspxl8n2
-yKrL7AZ4rlhpoTI5X0+fpdFRthoLA+2Io7+kldGGa1X/OYgOaul3SkwbimJop2RG
-53hI8PZHPZsjHguYpO8B7pLAPwUHI2tUz8AeGUWzxHH4tohcW7bEswIDAQABoAAw
-DQYJKoZIhvcNAQELBQADggIBACboOarzimaArw3lDm6ET5yiU7NxTWtnWwFUOoSh
-qS2cvumnCokUlrDyMSSKoHl2i2biUd9uiHuEqlh0yufNgnTsyAXLg0UiBHAv5Tos
-Esc5A+JTV5ehy+Zrjpl3Ayh8difS8hJEBjMhH+7rCN3rhpvwkTSaXDCQTBzWPhQ1
-R0EIho/SNOh5mXQKAUWwhtleI0sEJC/PqezGfN+w+URHnzE7YMwg02bvoMxBEror
-YVddG4o0nIyd6CPg++K7TBzYGGOf1CUCrI9S1bBn3jcv2mq5YgZMdLEa0HkA9XzU
-J/dTSGz5pJbkoaX9IHv8a3uoc+V1jdNWZRmTUYG/cNoAFISoG+uuJLgesF5l+vxx
-GUwkE6wj4bNYR/Pqy5963oDmA3ndBzR1wtCZqIsLX3t3A9fLLtIEgeN/XDSvNDBs
-YdwBrx2HTatK7QCJ5e+4ACs6Wc2c1nnDviPddpxUgl0pHKcMbT+xNk7bY5fjl5Qr
-wzuBNgvQcsZxNNvI8bs13k/eBmKrKOV2WUP1mHRzSoxPX3gzGRSWCe/7QR51oWlB
-Qkb6OGVGLCKPnhIKFeZ6G1Qv8q7/hOOlmWGO4bN7s5fjAKEsm3JV1xrsqSKRofRG
-JfdPjQD88jewIAk6xGSMKmc4usQN+y/IfU8yZ57MHSHULccA1Wl/VXfgKCAxS5fK
-uXtm
+ggIKAoICAQDCaUBcfPsITcRDtcQw3BjKaPX3f4LcyjpXbXRfYEqMK5lJF2rRz9Wk
+BZ4XLl/VIfMUSS+mZ9cqN4+udAv19PlsXBS6zHWl6kjVz714czGJLFyuk7lI98Q9
+9k8c6FkFRgRgjYxF6S2fRRoT9r2qJCkGHl8W3Ix50uTI2R8nY4BvAIldHCZSm3ml
+YAU5FcN5xUta1NJUxCxaw4j/aBp7p2BtNsl1dotRX9QWwE6WnqbWbBs+weJANrDE
+zlqSzYCNEDv1oFIXUjHA70O6q/dmOoV3wLWdevuipXIS6NAW2MgC80kjVo/0y7k/
+Jtyn3bxWRBPw91FxosO3yK47KCAjzoIhPFUU66vwbEBIcXUQXjKaR8aNLmMIuHwE
+uoAao0RFCmg3IPzv3JOWryGj+T8XSKf1bJoSNu4QqjrA+ElSBnUlXSoKmrGZOUaB
+xYGDUyeXxF2YeSrrzOyZOkts/Om5eW/nUqYkJqFzfWNYcmM3U5E8Y+CEusqRtzKV
+b/odOkjmLaSSf6TmjBQCSy3srSeNEflMXinuJi4LjPBKdODGW+Kj0TkKLoGKcyCQ
+M6PA2i9fLrSZH5Gco/3LGWm4n+Ntm9H1rZJikxu7UKsEXJngmRMsIQIDquHpquNd
+VbqtPASMqkyiqFleDsI27HuDGr9zOj1LolrTFU6eiZNEIctOAKgA5wIDAQABoAAw
+DQYJKoZIhvcNAQELBQADggIBAHfjpZwmJgizjCW89+pYI0vhYH9LH22YhN7qzV6y
+smS9JNRe/N3jCOadpKgsmx7W52+RZHkdst69dvg775cMJjQ6qNouXALydUHTloXj
+2k562BeUCfDBFlBR06dRGdGNkAuntAEdn/uV7+wU2SyptPGpXW8HP5xHyYoqdIlA
+tEqcb/Ue9WqG7oiP4X6FI56/4HjVt9PiFtCWZS1uU06eJSRufMDSzKzS12jNfm6C
+TGHD0vnzzJdW2YkaGwAUa2Iluzm7lo3eD0QJOaa9RvquxPCjbIKnzJQuzOpcI6Lm
+m/fd3fGxyAl6T8kCMnItzjFTgux7NuPps3oF/FKaiNqeL/HZXWLRRI74agzlvUP7
+10HqmUvw+diVka4+ve/8zmStn7pUb5IHd8C0OGbU/N2Y+UX++jYlI5W6vXGpjo76
+R2FMaG+crPAlOKZ9/7t9+NeoqYM5iW8zLiGTXX1Zx0UKMV2om3b8CXVsGrB3y7WG
+j3ZYs/4apg9sNqsIs8+udOPkfx8a3a+ZvBlrCl3XavYCaUHoNH5+dThQWvMpaFAQ
+Z2wKwuSkD9kTQqeTJUj684ztf2kDopM+nt9j54ZhrkfsDiGMUtz8Xk4SPYTdN/Yc
+KKVBOnm/4Hr1bASAukkQmF7AEUyUG6eJVGrEP/5MWuWc6ddONFj+eiwyAd2OzVq7
+3tvv
-----END CERTIFICATE REQUEST-----
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.key b/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.key
index 58414d8d59a..4cfd6bcdb31 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.key
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/client.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+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
+GCjn3ccqyYWia5VCpKUwdjE0k/SMU8/D
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/regenerate.sh b/experimental/packages/exporter-logs-otlp-grpc/test/certs/regenerate.sh
index 84637be753d..cc052a4effe 100755
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/regenerate.sh
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/regenerate.sh
@@ -1,10 +1,9 @@
#!/usr/bin/env sh
#
-# Usage: regenerate.sh
+# Regenerate certificates that are used for tests using TLS.
+# Certs are generated with a one year expiry, so periodic regen is required.
#
-# regenerate.sh regenerates certificates that are used to test gRPC with TLS
-# Make sure you run it in test/certs directory.
-# It also serves as a documentation on how existing certificates were generated.
+# Usage: npm run maint:regenerate-test-certs
rm ca.crt ca.key client.crt client.csr client.key server.crt server.csr server.key
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.crt b/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.crt
index ace156a29ee..99877d77596 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.crt
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.crt
@@ -1,31 +1,32 @@
-----BEGIN CERTIFICATE-----
-MIIFPzCCAycCAQEwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNV
-BAgMAlJNMRowGAYDVQQHDBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9v
-dDENMAsGA1UECwwEVGVzdDELMAkGA1UEAwwCY2EwHhcNMjMwNjA4MTY0NDI0WhcN
-MjQwNjA3MTY0NDI0WjBqMQswCQYDVQQGEwJDTDELMAkGA1UECAwCUk0xGjAYBgNV
-BAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQKDARUZXN0MQ8wDQYDVQQLDAZT
-ZXJ2ZXIxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBAKtVnxPqCZheCuqePfLknxc+6MeyYkf494U8WWeZo+yirYV3zY70
-1KhKZ+M+XDqhrBXc7IQHZd2KKxYBGnrv9yvbllmtZRdnk3hnn8B4eNh3w5gCRKPo
-GSTeiNN7WEIRwYZNkr8AWgeoYT1jN8SAMn5+qSqKSd62Z1BPJNi0eQmTVxgLZqzx
-92AWBZQl9rOme+1zV6ohKcR22Of3yUl6476L1rYYcX0DXp0QFkhK0TFKNt3cHxqq
-WTRuMTnyCj7woWRtwclWTdO2buAkJe8cIde6rcbaUAX9jTdkbAgYAB9MctEKqasO
-MqFyMzweS3sG9oUnmd0/GRL9as314xTZuz8fFnfj5l0BN6thVMmvEEYU3rTLQRKf
-AKWzI2VrU+5wIxN8O/4ZbriQ5ae13p6TDYilSZ6kMxSzfOM/A00hlA+DKMS0o8g8
-V9Y3wcl3aSSjoZbH7XS/uDEueodudz9V3HxCk7Wc41SpunQPFprmPDWtjiW0jcMD
-3kHV819r2F8aidKN94Q+3KI+N/mwn1QdDVsquiCq0wbR54i3CoAkQbi5YeUdEZD6
-/mNLs/BABgzSbANw7Fn1Pd9gY/JIsRhMskcFRqXe9tOqKk8/GxMv/r9MgJn6HHlk
-iDa3OZsoOtFbjjOPFoy/Xq9YMi4ODnJkEhe7BSsVl/wkDAUdg7Zfu8XVAgMBAAEw
-DQYJKoZIhvcNAQELBQADggIBAEft+R+qGyKffiiJpYWLPn0C9SmpjZiWPK331n57
-Nk3GA8u9gRgD1gyqqLr19r86nLArF8jcB/nChPB1A9ysW3xyTNvpOlAwYvEjxWR2
-tJr8wiDucAd+SnQud6e+5PI5e8LnyxYoeoZ+i6hMbhNV70NthoINHMAQx+5NeSpa
-Q0GJ4d0XA3W/8Pu6oK7O0QkVovVut73Koz5DqsF91zFJp7SjVKaCnnjRKyU8wbg5
-uTO0TRheEtx3AeEXNps5Yhq0daLTnmnuFeyaJHm2F1QuBmma1TTwIF3HDclv2wLn
-Jp+MWG9yoN9oEJLqS/AvDu1BltPSuvnYgLZr7cl0os+TEqpzxroa4ziE98dEiy0D
-K4YQ59UTz6C8Ps0uX0hcs3jsvZOkBWptusvJBfZN59xLJAVmF2igkgIBKoiXvXmv
-fXDx0hsOBg2IPe2O8lLHlFKlJZlMc+prH1iD0Xv6HefSP4L1eZHU37zjrRf/GiNX
-r6GoEhJR2pKEoZQT81xpYp/w+qjzWcTl/mLD6FEePRzV92h3ubjRWBB36UhLtnEG
-LJgp7yq3aGu7rg9rnuz8J6DG8DStE9rNuRjkV1O2C/PvR97XmVoIqbrMlxX9MUQJ
-XxLm5dqBz7EVuhDJSyp4zCkDYsOj1y/SLL2O3cTyQQeZg6jlqripNqWnviAdTWe5
-JIPp
+MIIFiDCCA3CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJDTDEL
+MAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQK
+DARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTAeFw0yNDA2MDgxOTE4
+NDhaFw0yNTA2MDgxOTE4NDhaMGoxCzAJBgNVBAYTAkNMMQswCQYDVQQIDAJSTTEa
+MBgGA1UEBwwRT3BlblRlbGVtZXRyeVRlc3QxDTALBgNVBAoMBFRlc3QxDzANBgNV
+BAsMBlNlcnZlcjESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAs4sfkgZBkGLNdsv1i2tcfrMOfqm/7xfGHTC05mBDatv3
+3k0RL+9KhR7xblAR3VadAN8HhdtmzlB+kdVYsSZHeZDJFjOnwXoxMRFxoNWxc4t/
+RTyj7JfWtYVL+2AXqOvXeMBCY5N3otS6i/6evoeBf4rEKs4h2bBoRTzEhBKlF7zR
+HkqnhBrTR/vjOJYvasUte8KRFbsJeoxAsn5oCLQHA5+DBggBfFX8pO/JIGRYbdpr
+oZ7AU0l9hdTMP7iakL1pZIuddROwk6kF5mc22T2Jey/sQp5OqxqT9mtbyZqDdQsF
+V/jmuMs6H/fBfOkeJaAPyNeJ+Pa23WsuODzefWzCMDTCEwGsHddi5vWCbJaFWqu1
+9C9uy6iSP5aAnmW+RTi/bVv/KZavl+NGF8RFMaOr8hCtkvh8JqW19D9SmtU8Ky45
+qHSqz2q7awfbWLy8xMM8IYM6L5jCB27g2XeA/SjCb2ryab0OP6a8LSezXMBzQuml
+f1C3kNnm2pSFFfLNimPs7A01zqo6eowGm3yneRBlTTyHgTFOFzuP7sEtY6p/GI6F
++jKBtSXUiKqAAwpObcMXS9a5td8wpAs87IEKKAb58BcSkzslU1fuY28At9kEUIWR
+z1dyQRBPxiu4NaSxcIpI9cEBvHYSAf454noTuehlZvL6tCaAobZZMqsXSfvnVvkC
+AwEAAaNCMEAwHQYDVR0OBBYEFFRmQkQkZmb8ER1Cx/6FOWmKXKlXMB8GA1UdIwQY
+MBaAFCOWKzzaitEuaazjDV1skV/00M7rMA0GCSqGSIb3DQEBCwUAA4ICAQAYQHvf
+s1hrdDUDzn6LQiAMbDh3VwEVOg3O/8uomn6+J/TCBkTAD6avMO3hZH28Kc5H4c8P
+9db7rBkmqyOzOo7JG8xJz7vg90oh0sqo5+G73h9PQb7G8f6wCGJTD9IbRDcgCspW
+Z8zIBZGxpeHHitdB2Jik1DxUkqViwxlBzBkiNpqixDde5U5EqxbecTBIuMqJkkxG
+7JV61Mbb6r8xCNPqd1qYDQ6fggV1MFb6yf9TEuLmV2mKn1ypo/MzMBoTMGgKoHS8
+RgiN0bztRayaEqnmMZ5TQOYkmuGbW1oBwXeA7lorOu7/Yi4/IP0/H0rt/mSUhh5K
+ubtZkWrsZV3xPeERYL9UiuOdEJ58tI3u3yDFvnULczH8bzapZisxQIfaMasq9aHg
+LO8lqMk4+Kyb09vz+DPuMGdDkl4hchHlySUCrhmMmrCJTgQHmEmQMF+1TBP1cFXe
+B9grn4zr+sVsqKNMArnQoUff42cFi1E5pZq7Z4DfGltcv81ay51OgTVxMJYOUB9Q
+1PJcO0hkLrV66kSbTd5//6uyYuAOy5ZVXOFHOO/tDBlKlgOqYXe5tj90uZQh0AnJ
+NeH73pwS3x9dF0JZBcviaH/yTK2ggi9lmzJ0EkwqUXyfYfJZGBgnLVDnNpXSUUha
+v1h7xzhfZgYbWEgwV+AWiXlHTrZCXSmY3sM2QA==
-----END CERTIFICATE-----
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.csr b/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.csr
index b421a7a60c9..b459ff45ffd 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.csr
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.csr
@@ -2,27 +2,27 @@
MIIErzCCApcCAQAwajELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQH
DBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEVGVzdDEPMA0GA1UECwwGU2Vy
dmVyMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
-ggIKAoICAQCrVZ8T6gmYXgrqnj3y5J8XPujHsmJH+PeFPFlnmaPsoq2Fd82O9NSo
-SmfjPlw6oawV3OyEB2XdiisWARp67/cr25ZZrWUXZ5N4Z5/AeHjYd8OYAkSj6Bkk
-3ojTe1hCEcGGTZK/AFoHqGE9YzfEgDJ+fqkqiknetmdQTyTYtHkJk1cYC2as8fdg
-FgWUJfazpnvtc1eqISnEdtjn98lJeuO+i9a2GHF9A16dEBZIStExSjbd3B8aqlk0
-bjE58go+8KFkbcHJVk3Ttm7gJCXvHCHXuq3G2lAF/Y03ZGwIGAAfTHLRCqmrDjKh
-cjM8Hkt7BvaFJ5ndPxkS/WrN9eMU2bs/HxZ34+ZdATerYVTJrxBGFN60y0ESnwCl
-syNla1PucCMTfDv+GW64kOWntd6ekw2IpUmepDMUs3zjPwNNIZQPgyjEtKPIPFfW
-N8HJd2kko6GWx+10v7gxLnqHbnc/Vdx8QpO1nONUqbp0Dxaa5jw1rY4ltI3DA95B
-1fNfa9hfGonSjfeEPtyiPjf5sJ9UHQ1bKrogqtMG0eeItwqAJEG4uWHlHRGQ+v5j
-S7PwQAYM0mwDcOxZ9T3fYGPySLEYTLJHBUal3vbTqipPPxsTL/6/TICZ+hx5ZIg2
-tzmbKDrRW44zjxaMv16vWDIuDg5yZBIXuwUrFZf8JAwFHYO2X7vF1QIDAQABoAAw
-DQYJKoZIhvcNAQELBQADggIBAJCMEdjKyklN2izvOhd7+JMXm/ClW3hjowbu+csO
-JNz8NqUNLrKJjFyV3yAUGWuyp3z982S+XGfcm3nU7n9AJOjT4DLJId6opOtA6CSp
-KTRgVZmeViL6O6UqBLTacz5DDjwMQXxszc+QpU53cMT6Y7VMvIOhQ6AmIvz1v71u
-5gaYmlbfXVlmiPHEKRsQG9/DNIPe1mHP0p+S9qYKmCx7Jlpee7IstW/hNjt7alDn
-uFaxFjxmCCSdWaMRyMW/qNRks9q3VdhJPan+amFeXceoEG7SOKiFiOc8A7DribSm
-iKc2YlOw14xqc+cJutiKBvoBMri2eh1JgCbPT4ufVGFpbDkfYwAJxWx44Eg0X90j
-gJUw8IRuHQZkEYss6jwFMFcOqjpe+AqrssOl4GZmu5gcaiUnj8PkSVZLTOrLilPg
-sSDjzmoHdv4QcBppTrjj6PyR5Xd6DeGasWkMPvIPjiPN3mOhfxJ3C87atMqOhTLx
-em7vFOBegAW6g40J9JD1XMoI/zFnTU8NevZQgCyx/Tq1XNRmUeMA6y/qpfTNKi/f
-F7v/7nDWoxBgpOw3J0E9R+6rxD7Cjb2RWZEf20ZGdNBlPE+UG9c9b3HC3IHiwRHb
-L9Fi0251w+fkaPX8dojQKErCEknqJ1SCP5S5F5g1QCQby22Y7LQsggMMf94s/wQX
-4uMh
+ggIKAoICAQCzix+SBkGQYs12y/WLa1x+sw5+qb/vF8YdMLTmYENq2/feTREv70qF
+HvFuUBHdVp0A3weF22bOUH6R1VixJkd5kMkWM6fBejExEXGg1bFzi39FPKPsl9a1
+hUv7YBeo69d4wEJjk3ei1LqL/p6+h4F/isQqziHZsGhFPMSEEqUXvNEeSqeEGtNH
+++M4li9qxS17wpEVuwl6jECyfmgItAcDn4MGCAF8Vfyk78kgZFht2muhnsBTSX2F
+1Mw/uJqQvWlki511E7CTqQXmZzbZPYl7L+xCnk6rGpP2a1vJmoN1CwVX+Oa4yzof
+98F86R4loA/I14n49rbday44PN59bMIwNMITAawd12Lm9YJsloVaq7X0L27LqJI/
+loCeZb5FOL9tW/8plq+X40YXxEUxo6vyEK2S+HwmpbX0P1Ka1TwrLjmodKrPartr
+B9tYvLzEwzwhgzovmMIHbuDZd4D9KMJvavJpvQ4/prwtJ7NcwHNC6aV/ULeQ2eba
+lIUV8s2KY+zsDTXOqjp6jAabfKd5EGVNPIeBMU4XO4/uwS1jqn8YjoX6MoG1JdSI
+qoADCk5twxdL1rm13zCkCzzsgQooBvnwFxKTOyVTV+5jbwC32QRQhZHPV3JBEE/G
+K7g1pLFwikj1wQG8dhIB/jniehO56GVm8vq0JoChtlkyqxdJ++dW+QIDAQABoAAw
+DQYJKoZIhvcNAQELBQADggIBAB5lc1i6TI58ZkV8dxlqw2OJaTuj2064GzQvwekc
+iRSg8QaeVaGhA+jnet/UvBCDBqFAh4nMY/THKWB7721agRbSJS3RtyiZbBFNBDQt
+dLPXO6HY6HGM1Z2ov71HNeDBQnqYSmOld3RkO9Co9nGhjOLkBtvoiAWmMHS3pnpq
+o2ssCd2GmbMmiAdSJspgWJnCJUQneV0hW+l7b79oW8E0j4aZLQ7g0B3y2iTg2Ngk
+0R301hh3Fs9B5PYa/TlOJsd4icgxvMjCvsIxHaihKjvNLDu3GhYRyHlxyAnZVvaG
+GAqHn2WyvLeg2bMswy7FV9J6qI5PQVaApLb2g5TPbG6y52XgLMCl06fM25UbTaym
+GCAEeylvXwIClPNlmnvLnytABHA5tLkfHt+E7UPJmPv8BuOeRTYtlp3UB/aI6rKG
+HOMZnhUNZTVCnxid6gLEI7xMxdAKP6N1sWdcDD8bkcVEk8IjOJrpQzuYUchQwzZ+
+hZIact21gTuN5xhxq1f1gvEN0th1vUSjfZ0K67M9mgqNdza8fXOaUNc3XwRUxhfB
+1kpXxDuH2dzjsy3CGeobry8nHmUB/P2KEy8u7ue7Ra3J4stFCPDRJqroRM3V8xNK
+1+I2KBM8UeybFzYya9xqT9q0FNe/ukS2ohV5C1YjnxrMQ2Mx+CqJOVqpA/nP55ZE
+cuZ8
-----END CERTIFICATE REQUEST-----
diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.key b/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.key
index 80b9cea7bf3..8af97da4a70 100644
--- a/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.key
+++ b/experimental/packages/exporter-logs-otlp-grpc/test/certs/server.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+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
+LPnexONaL/II1DilmyNT5mZMXCXP
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/exporter-logs-otlp-http/README.md b/experimental/packages/exporter-logs-otlp-http/README.md
index 24f0d7f4a03..72cd8fec781 100644
--- a/experimental/packages/exporter-logs-otlp-http/README.md
+++ b/experimental/packages/exporter-logs-otlp-http/README.md
@@ -58,7 +58,7 @@ import {
LoggerProvider,
BatchLogRecordProcessor,
} from '@opentelemetry/sdk-logs';
-import { OTLPLogsExporter } from '@opentelemetry/exporter-logs-otlp-http';
+import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
// exporter options. see all options in OTLPExporterNodeConfigBase
const collectorOptions = {
@@ -108,7 +108,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-logs-otlp-http
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-logs-otlp-http.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
-[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/exporter-trace-otlp-http
[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-http
diff --git a/experimental/packages/exporter-logs-otlp-http/package.json b/experimental/packages/exporter-logs-otlp-http/package.json
index 5525ef51ca4..801fb83518e 100644
--- a/experimental/packages/exporter-logs-otlp-http/package.json
+++ b/experimental/packages/exporter-logs-otlp-http/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-logs-otlp-http",
- "version": "0.49.1",
+ "version": "0.52.1",
"publishConfig": {
"access": "public"
},
@@ -37,14 +37,15 @@
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.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",
"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 ../../../"
+ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -71,31 +72,29 @@
],
"sideEffects": false,
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/resources": "1.22.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@opentelemetry/resources": "1.25.1",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
@@ -105,10 +104,10 @@
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
- "@opentelemetry/api-logs": "0.49.1",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/otlp-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/sdk-logs": "0.49.1"
+ "@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"
}
}
diff --git a/experimental/packages/exporter-logs-otlp-http/src/platform/browser/OTLPLogExporter.ts b/experimental/packages/exporter-logs-otlp-http/src/platform/browser/OTLPLogExporter.ts
index d65ff9aeb81..a4f5f2ddd55 100644
--- a/experimental/packages/exporter-logs-otlp-http/src/platform/browser/OTLPLogExporter.ts
+++ b/experimental/packages/exporter-logs-otlp-http/src/platform/browser/OTLPLogExporter.ts
@@ -19,10 +19,10 @@ import type {
LogRecordExporter,
} from '@opentelemetry/sdk-logs';
import type { OTLPExporterConfigBase } from '@opentelemetry/otlp-exporter-base';
-import type { IExportLogsServiceRequest } from '@opentelemetry/otlp-transformer';
+import type { IExportLogsServiceResponse } from '@opentelemetry/otlp-transformer';
import { OTLPExporterBrowserBase } from '@opentelemetry/otlp-exporter-base';
import { baggageUtils, getEnv } from '@opentelemetry/core';
-import { createExportLogsServiceRequest } from '@opentelemetry/otlp-transformer';
+import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer';
import { getDefaultUrl } from '../config';
@@ -30,15 +30,19 @@ import { getDefaultUrl } from '../config';
* Collector Logs Exporter for Web
*/
export class OTLPLogExporter
- extends OTLPExporterBrowserBase
+ extends OTLPExporterBrowserBase
implements LogRecordExporter
{
constructor(config: OTLPExporterConfigBase = {}) {
// load OTEL_EXPORTER_OTLP_LOGS_TIMEOUT env var
- super({
- timeoutMillis: getEnv().OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
- ...config,
- });
+ super(
+ {
+ timeoutMillis: getEnv().OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
+ ...config,
+ },
+ JsonLogsSerializer,
+ 'application/json'
+ );
this._headers = {
...this._headers,
...baggageUtils.parseKeyPairsIntoRecord(
@@ -47,13 +51,6 @@ export class OTLPLogExporter
};
}
- convert(logRecords: ReadableLogRecord[]): IExportLogsServiceRequest {
- return createExportLogsServiceRequest(logRecords, {
- useHex: true,
- useLongBits: false,
- });
- }
-
getDefaultUrl(config: OTLPExporterConfigBase): string {
return getDefaultUrl(config);
}
diff --git a/experimental/packages/exporter-logs-otlp-http/src/platform/config.ts b/experimental/packages/exporter-logs-otlp-http/src/platform/config.ts
index a41ee964682..5ce6eb75f77 100644
--- a/experimental/packages/exporter-logs-otlp-http/src/platform/config.ts
+++ b/experimental/packages/exporter-logs-otlp-http/src/platform/config.ts
@@ -30,14 +30,21 @@ export const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_
* @returns url string
*/
export function getDefaultUrl(config: OTLPExporterConfigBase): string {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_LOGS_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_LOGS_ENDPOINT)
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT);
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
+
+ return DEFAULT_COLLECTOR_URL;
}
diff --git a/experimental/packages/exporter-logs-otlp-http/src/platform/node/OTLPLogExporter.ts b/experimental/packages/exporter-logs-otlp-http/src/platform/node/OTLPLogExporter.ts
index 9181b082cf9..1837993e911 100644
--- a/experimental/packages/exporter-logs-otlp-http/src/platform/node/OTLPLogExporter.ts
+++ b/experimental/packages/exporter-logs-otlp-http/src/platform/node/OTLPLogExporter.ts
@@ -19,10 +19,13 @@ import type {
LogRecordExporter,
} from '@opentelemetry/sdk-logs';
import type { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base';
-import type { IExportLogsServiceRequest } from '@opentelemetry/otlp-transformer';
+import type { IExportLogsServiceResponse } from '@opentelemetry/otlp-transformer';
import { getEnv, baggageUtils } from '@opentelemetry/core';
-import { OTLPExporterNodeBase } from '@opentelemetry/otlp-exporter-base';
-import { createExportLogsServiceRequest } from '@opentelemetry/otlp-transformer';
+import {
+ OTLPExporterNodeBase,
+ parseHeaders,
+} from '@opentelemetry/otlp-exporter-base';
+import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer';
import { getDefaultUrl } from '../config';
import { VERSION } from '../../version';
@@ -35,30 +38,26 @@ const USER_AGENT = {
* Collector Logs Exporter for Node
*/
export class OTLPLogExporter
- extends OTLPExporterNodeBase
+ extends OTLPExporterNodeBase
implements LogRecordExporter
{
constructor(config: OTLPExporterNodeConfigBase = {}) {
// load OTEL_EXPORTER_OTLP_LOGS_TIMEOUT env
- super({
- timeoutMillis: getEnv().OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
- ...config,
- });
- this.headers = {
- ...this.headers,
- ...USER_AGENT,
- ...baggageUtils.parseKeyPairsIntoRecord(
- getEnv().OTEL_EXPORTER_OTLP_LOGS_HEADERS
- ),
- ...config.headers,
- };
- }
-
- convert(logRecords: ReadableLogRecord[]): IExportLogsServiceRequest {
- return createExportLogsServiceRequest(logRecords, {
- useHex: true,
- useLongBits: false,
- });
+ super(
+ {
+ timeoutMillis: getEnv().OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
+ ...config,
+ },
+ JsonLogsSerializer,
+ {
+ ...baggageUtils.parseKeyPairsIntoRecord(
+ getEnv().OTEL_EXPORTER_OTLP_LOGS_HEADERS
+ ),
+ ...parseHeaders(config?.headers),
+ ...USER_AGENT,
+ 'Content-Type': 'application/json',
+ }
+ );
}
getDefaultUrl(config: OTLPExporterNodeConfigBase): string {
diff --git a/experimental/packages/exporter-logs-otlp-http/test/browser/OTLPLogExporter.test.ts b/experimental/packages/exporter-logs-otlp-http/test/browser/OTLPLogExporter.test.ts
index 2443c97ef48..d8fbcfff4a2 100644
--- a/experimental/packages/exporter-logs-otlp-http/test/browser/OTLPLogExporter.test.ts
+++ b/experimental/packages/exporter-logs-otlp-http/test/browser/OTLPLogExporter.test.ts
@@ -32,7 +32,7 @@ describe('OTLPLogExporter', () => {
sinon.restore();
});
- if (typeof process === 'undefined') {
+ if (global.process?.versions?.node === undefined) {
envSource = globalThis as unknown as Record;
} else {
envSource = process.env as Record;
diff --git a/experimental/packages/exporter-logs-otlp-http/test/config.test.ts b/experimental/packages/exporter-logs-otlp-http/test/config.test.ts
index 77656de5612..2f5e8dd1d24 100644
--- a/experimental/packages/exporter-logs-otlp-http/test/config.test.ts
+++ b/experimental/packages/exporter-logs-otlp-http/test/config.test.ts
@@ -21,7 +21,7 @@ import { getDefaultUrl } from '../src/platform/config';
describe('getDefaultUrl', () => {
let envSource: Record;
- if (typeof process === 'undefined') {
+ if (global.process?.versions?.node === undefined) {
envSource = globalThis as unknown as Record;
} else {
envSource = process.env as Record;
diff --git a/experimental/packages/exporter-logs-otlp-http/test/node/OTLPLogExporter.test.ts b/experimental/packages/exporter-logs-otlp-http/test/node/OTLPLogExporter.test.ts
index 5920657b5b6..8e6b076ed60 100644
--- a/experimental/packages/exporter-logs-otlp-http/test/node/OTLPLogExporter.test.ts
+++ b/experimental/packages/exporter-logs-otlp-http/test/node/OTLPLogExporter.test.ts
@@ -43,7 +43,7 @@ class MockedResponse extends Stream {
super();
}
- send(data: string) {
+ send(data: Uint8Array) {
this.emit('data', data);
this.emit('end');
}
@@ -65,10 +65,13 @@ describe('OTLPLogExporter', () => {
afterEach(() => {
fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.restore();
});
- if (typeof process === 'undefined') {
+ if (global.process?.versions?.node === undefined) {
envSource = globalThis as unknown as Record;
} else {
envSource = process.env as Record;
@@ -83,7 +86,9 @@ describe('OTLPLogExporter', () => {
it('should include user-agent header by default', () => {
const exporter = new OTLPLogExporter();
assert.strictEqual(
- exporter.headers['User-Agent'],
+ exporter['_transport']['_transport']['_parameters']['headers'][
+ 'User-Agent'
+ ],
`OTel-OTLP-Exporter-JavaScript/${VERSION}`
);
});
@@ -91,7 +96,10 @@ describe('OTLPLogExporter', () => {
it('should use headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_LOGS_HEADERS = 'foo=bar';
const exporter = new OTLPLogExporter();
- assert.strictEqual(exporter.headers.foo, 'bar');
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'bar'
+ );
delete envSource.OTEL_EXPORTER_OTLP_LOGS_HEADERS;
});
@@ -106,13 +114,19 @@ describe('OTLPLogExporter', () => {
it('should override headers defined via env with headers defined in constructor', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
- const collectorExporter = new OTLPLogExporter({
+ const exporter = new OTLPLogExporter({
headers: {
foo: 'constructor',
},
});
- assert.strictEqual(collectorExporter.headers.foo, 'constructor');
- assert.strictEqual(collectorExporter.headers.bar, 'foo');
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'constructor'
+ );
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
});
@@ -152,10 +166,12 @@ describe('OTLPLogExporter', () => {
assert.strictEqual(options.method, 'POST');
assert.strictEqual(options.path, '/');
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
collectorExporter.export(logs, () => {});
@@ -165,10 +181,12 @@ describe('OTLPLogExporter', () => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
assert.strictEqual(options.headers['foo'], 'bar');
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
@@ -180,10 +198,12 @@ describe('OTLPLogExporter', () => {
assert.strictEqual(options.agent.keepAlive, true);
assert.strictEqual(options.agent.options.keepAliveMsecs, 2000);
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
@@ -192,10 +212,13 @@ describe('OTLPLogExporter', () => {
it('should successfully send the logs', done => {
const fakeRequest = new Stream.PassThrough();
- sinon.stub(http, 'request').returns(fakeRequest as any);
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
+ sinon.stub(http, 'request').returns(fakeRequest as any);
let buff = Buffer.from('');
- fakeRequest.on('end', () => {
+ fakeRequest.on('finish', () => {
const responseBody = buff.toString();
const json = JSON.parse(responseBody) as IExportLogsServiceRequest;
const log1 = json.resourceLogs?.[0].scopeLogs?.[0].logRecords?.[0];
@@ -222,9 +245,11 @@ describe('OTLPLogExporter', () => {
const spyLoggerError = sinon.stub(diag, 'error');
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
return fakeRequest as any;
});
@@ -237,9 +262,11 @@ describe('OTLPLogExporter', () => {
it('should log the error message', done => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- const mockResError = new MockedResponse(400);
- cb(mockResError);
- mockResError.send('failed');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(400);
+ cb(mockRes);
+ mockRes.send(Buffer.from('failure'));
+ });
return fakeRequest as any;
});
diff --git a/experimental/packages/exporter-logs-otlp-proto/README.md b/experimental/packages/exporter-logs-otlp-proto/README.md
index 30f1e8bb341..cb76bc1fcd5 100644
--- a/experimental/packages/exporter-logs-otlp-proto/README.md
+++ b/experimental/packages/exporter-logs-otlp-proto/README.md
@@ -48,7 +48,7 @@ The OTLPLogExporter has a timeout configuration option which is the maximum time
To override the default timeout duration, use the following options:
-+ Set with environment variables:
+- Set with environment variables:
| Environment variable | Description |
------------------------------|----------------------|-------------|
@@ -57,7 +57,7 @@ To override the default timeout duration, use the following options:
> `OTEL_EXPORTER_OTLP_LOGS_TIMEOUT` takes precedence and overrides `OTEL_EXPORTER_OTLP_TIMEOUT`.
-+ Provide `timeoutMillis` to OTLPLogExporter with `collectorOptions`:
+- Provide `timeoutMillis` to OTLPLogExporter with `collectorOptions`:
```js
const collectorOptions = {
@@ -79,20 +79,20 @@ OTLP requires that transient errors be handled with a [retry strategy](https://g
This retry policy has the following configuration, which there is currently no way to customize.
-+ `DEFAULT_EXPORT_MAX_ATTEMPTS`: The maximum number of attempts, including the original request. Defaults to 5.
-+ `DEFAULT_EXPORT_INITIAL_BACKOFF`: The initial backoff duration. Defaults to 1 second.
-+ `DEFAULT_EXPORT_MAX_BACKOFF`: The maximum backoff duration. Defaults to 5 seconds.
-+ `DEFAULT_EXPORT_BACKOFF_MULTIPLIER`: The backoff multiplier. Defaults to 1.5.
+- `DEFAULT_EXPORT_MAX_ATTEMPTS`: The maximum number of attempts, including the original request. Defaults to 5.
+- `DEFAULT_EXPORT_INITIAL_BACKOFF`: The initial backoff duration. Defaults to 1 second.
+- `DEFAULT_EXPORT_MAX_BACKOFF`: The maximum backoff duration. Defaults to 5 seconds.
+- `DEFAULT_EXPORT_BACKOFF_MULTIPLIER`: The backoff multiplier. Defaults to 1.5.
This retry policy first checks if the response has a `'Retry-After'` header. If there is a `'Retry-After'` header, the exporter will wait the amount specified in the `'Retry-After'` header before retrying. If there is no `'Retry-After'` header, the exporter will use an exponential backoff with jitter retry strategy.
- > The exporter will retry exporting within the [exporter timeout configuration](#Exporter-Timeout-Configuration) time.
+ > The exporter will retry exporting within the [exporter timeout configuration](#exporter-timeout-configuration) time.
## Useful links
-+ For more information on OpenTelemetry, visit:
-+ For more about OpenTelemetry JavaScript:
-+ For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
+- For more information on OpenTelemetry, visit:
+- For more about OpenTelemetry JavaScript:
+- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
## License
@@ -103,8 +103,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-logs-otlp-proto
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-logs-otlp-proto.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
-[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
-[logs-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-logs-otlp-proto
[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/exporter-trace-otlp-proto
[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-proto
diff --git a/experimental/packages/exporter-logs-otlp-proto/package.json b/experimental/packages/exporter-logs-otlp-proto/package.json
index cf7af6ed81e..d07790ee1f8 100644
--- a/experimental/packages/exporter-logs-otlp-proto/package.json
+++ b/experimental/packages/exporter-logs-otlp-proto/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-logs-otlp-proto",
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "An OTLP exporter to send logs using protobuf over HTTP",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@@ -20,14 +20,15 @@
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.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",
"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 ../../../"
+ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -63,28 +64,26 @@
"access": "public"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
- "babel-plugin-istanbul": "6.1.1",
+ "@types/sinon": "17.0.3",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
@@ -94,14 +93,13 @@
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
- "@opentelemetry/api-logs": "0.49.1",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/otlp-exporter-base": "0.49.1",
- "@opentelemetry/otlp-proto-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-logs": "0.49.1",
- "@opentelemetry/sdk-trace-base": "1.22.0"
+ "@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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-logs-otlp-proto",
"sideEffects": false
diff --git a/experimental/packages/exporter-logs-otlp-proto/src/platform/browser/OTLPLogExporter.ts b/experimental/packages/exporter-logs-otlp-proto/src/platform/browser/OTLPLogExporter.ts
index fff28d4e77a..259ce6a0801 100644
--- a/experimental/packages/exporter-logs-otlp-proto/src/platform/browser/OTLPLogExporter.ts
+++ b/experimental/packages/exporter-logs-otlp-proto/src/platform/browser/OTLPLogExporter.ts
@@ -19,14 +19,11 @@ import {
OTLPExporterConfigBase,
appendResourcePathToUrl,
appendRootPathToUrlIfNeeded,
+ OTLPExporterBrowserBase,
} from '@opentelemetry/otlp-exporter-base';
import {
- OTLPProtoExporterBrowserBase,
- ServiceClientType,
-} from '@opentelemetry/otlp-proto-exporter-base';
-import {
- createExportLogsServiceRequest,
- IExportLogsServiceRequest,
+ IExportLogsServiceResponse,
+ ProtobufLogsSerializer,
} from '@opentelemetry/otlp-transformer';
import { ReadableLogRecord, LogRecordExporter } from '@opentelemetry/sdk-logs';
@@ -38,39 +35,35 @@ const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURC
* Collector Trace Exporter for Web
*/
export class OTLPLogExporter
- extends OTLPProtoExporterBrowserBase<
- ReadableLogRecord,
- IExportLogsServiceRequest
- >
+ extends OTLPExporterBrowserBase
implements LogRecordExporter
{
constructor(config: OTLPExporterConfigBase = {}) {
- super(config);
+ super(config, ProtobufLogsSerializer, 'application/x-protobuf');
+ const env = getEnv();
this._headers = Object.assign(
this._headers,
- baggageUtils.parseKeyPairsIntoRecord(
- getEnv().OTEL_EXPORTER_OTLP_LOGS_HEADERS
- )
+ baggageUtils.parseKeyPairsIntoRecord(env.OTEL_EXPORTER_OTLP_LOGS_HEADERS)
);
}
- convert(logs: ReadableLogRecord[]): IExportLogsServiceRequest {
- return createExportLogsServiceRequest(logs);
- }
getDefaultUrl(config: OTLPExporterConfigBase): string {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_LOGS_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_LOGS_ENDPOINT)
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
- }
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT);
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
- getServiceClientType() {
- return ServiceClientType.LOGS;
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/exporter-logs-otlp-proto/src/platform/node/OTLPLogExporter.ts b/experimental/packages/exporter-logs-otlp-proto/src/platform/node/OTLPLogExporter.ts
index caec7352fff..893a06b4ab1 100644
--- a/experimental/packages/exporter-logs-otlp-proto/src/platform/node/OTLPLogExporter.ts
+++ b/experimental/packages/exporter-logs-otlp-proto/src/platform/node/OTLPLogExporter.ts
@@ -19,14 +19,12 @@ import {
OTLPExporterConfigBase,
appendResourcePathToUrl,
appendRootPathToUrlIfNeeded,
+ OTLPExporterNodeBase,
+ parseHeaders,
} from '@opentelemetry/otlp-exporter-base';
import {
- OTLPProtoExporterNodeBase,
- ServiceClientType,
-} from '@opentelemetry/otlp-proto-exporter-base';
-import {
- createExportLogsServiceRequest,
- IExportLogsServiceRequest,
+ IExportLogsServiceResponse,
+ ProtobufLogsSerializer,
} from '@opentelemetry/otlp-transformer';
import { ReadableLogRecord, LogRecordExporter } from '@opentelemetry/sdk-logs';
@@ -43,41 +41,37 @@ const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURC
* Collector Trace Exporter for Node
*/
export class OTLPLogExporter
- extends OTLPProtoExporterNodeBase<
- ReadableLogRecord,
- IExportLogsServiceRequest
- >
+ extends OTLPExporterNodeBase
implements LogRecordExporter
{
constructor(config: OTLPExporterConfigBase = {}) {
- super(config);
- this.headers = {
- ...this.headers,
- ...USER_AGENT,
+ super(config, ProtobufLogsSerializer, {
...baggageUtils.parseKeyPairsIntoRecord(
getEnv().OTEL_EXPORTER_OTLP_LOGS_HEADERS
),
- ...config.headers,
- };
- }
- convert(logs: ReadableLogRecord[]): IExportLogsServiceRequest {
- return createExportLogsServiceRequest(logs);
+ ...parseHeaders(config?.headers),
+ ...USER_AGENT,
+ 'Content-Type': 'application/x-protobuf',
+ });
}
getDefaultUrl(config: OTLPExporterConfigBase): string {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_LOGS_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_LOGS_ENDPOINT)
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
- }
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT);
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
- getServiceClientType() {
- return ServiceClientType.LOGS;
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts b/experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts
index ab2f0885033..c5a110ca1ac 100644
--- a/experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts
+++ b/experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts
@@ -175,7 +175,7 @@ export class MockedResponse extends Stream {
super();
}
- send(data: string) {
+ send(data: Uint8Array) {
this.emit('data', data);
this.emit('end');
}
diff --git a/experimental/packages/exporter-logs-otlp-proto/test/node/OTLPLogExporter.test.ts b/experimental/packages/exporter-logs-otlp-proto/test/node/OTLPLogExporter.test.ts
index 9778c950464..9cf3961fe5d 100644
--- a/experimental/packages/exporter-logs-otlp-proto/test/node/OTLPLogExporter.test.ts
+++ b/experimental/packages/exporter-logs-otlp-proto/test/node/OTLPLogExporter.test.ts
@@ -33,16 +33,27 @@ import {
OTLPExporterNodeConfigBase,
OTLPExporterError,
} from '@opentelemetry/otlp-exporter-base';
-import {
- getExportRequestProto,
- ServiceClientType,
-} from '@opentelemetry/otlp-proto-exporter-base';
import { IExportLogsServiceRequest } from '@opentelemetry/otlp-transformer';
import { ReadableLogRecord } from '@opentelemetry/sdk-logs';
import { VERSION } from '../../src/version';
+import { Root } from 'protobufjs';
+import * as path from 'path';
let fakeRequest: PassThrough;
+const dir = path.resolve(__dirname, '../../../otlp-transformer/protos');
+const root = new Root();
+root.resolvePath = function (origin, target) {
+ return `${dir}/${target}`;
+};
+const proto = root.loadSync([
+ 'opentelemetry/proto/common/v1/common.proto',
+ 'opentelemetry/proto/resource/v1/resource.proto',
+ 'opentelemetry/proto/logs/v1/logs.proto',
+ 'opentelemetry/proto/collector/logs/v1/logs_service.proto',
+]);
+const exportRequestServiceProto = proto?.lookupType('ExportLogsServiceRequest');
+
describe('OTLPLogExporter - node with proto over http', () => {
let collectorExporter: OTLPLogExporter;
let collectorExporterConfig: OTLPExporterNodeConfigBase;
@@ -50,6 +61,9 @@ describe('OTLPLogExporter - node with proto over http', () => {
afterEach(() => {
fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.restore();
});
@@ -141,34 +155,51 @@ describe('OTLPLogExporter - node with proto over http', () => {
it('should include user-agent header by default', () => {
const exporter = new OTLPLogExporter();
assert.strictEqual(
- exporter.headers['User-Agent'],
+ exporter['_transport']['_transport']['_parameters']['headers'][
+ 'User-Agent'
+ ],
`OTel-OTLP-Exporter-JavaScript/${VERSION}`
);
});
it('should use headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_LOGS_HEADERS = 'foo=bar';
- const collectorExporter = new OTLPLogExporter();
- assert.strictEqual(collectorExporter.headers.foo, 'bar');
+ const exporter = new OTLPLogExporter();
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'bar'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should override global headers config with signal headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
envSource.OTEL_EXPORTER_OTLP_LOGS_HEADERS = 'foo=boo';
- const collectorExporter = new OTLPLogExporter();
- assert.strictEqual(collectorExporter.headers.foo, 'boo');
- assert.strictEqual(collectorExporter.headers.bar, 'foo');
+ const exporter = new OTLPLogExporter();
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'boo'
+ );
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_LOGS_HEADERS = '';
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should override headers defined via env with headers defined in constructor', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
- const collectorExporter = new OTLPLogExporter({
+ const exporter = new OTLPLogExporter({
headers: {
foo: 'constructor',
},
});
- assert.strictEqual(collectorExporter.headers.foo, 'constructor');
- assert.strictEqual(collectorExporter.headers.bar, 'foo');
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'constructor'
+ );
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
});
@@ -193,60 +224,63 @@ describe('OTLPLogExporter - node with proto over http', () => {
});
it('should open the connection', done => {
- collectorExporter.export(logs, () => {});
-
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
assert.strictEqual(options.hostname, 'foo.bar.com');
assert.strictEqual(options.method, 'POST');
assert.strictEqual(options.path, '/');
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
+ collectorExporter.export(logs, () => {});
});
it('should set custom headers', done => {
- collectorExporter.export(logs, () => {});
-
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
assert.strictEqual(options.headers['foo'], 'bar');
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
+ collectorExporter.export(logs, () => {});
});
it('should have keep alive and keepAliveMsecs option set', done => {
- collectorExporter.export(logs, () => {});
-
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
assert.strictEqual(options.agent.keepAlive, true);
assert.strictEqual(options.agent.options.keepAliveMsecs, 2000);
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
+ collectorExporter.export(logs, () => {});
});
it('should successfully send the logs', done => {
const fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.stub(http, 'request').returns(fakeRequest as any);
let buff = Buffer.from('');
fakeRequest.on('end', () => {
- const ExportLogsServiceRequestProto = getExportRequestProto(
- ServiceClientType.LOGS
- );
- const data = ExportLogsServiceRequestProto.decode(buff);
+ const data = exportRequestServiceProto.decode(buff);
const json = data?.toJSON() as IExportLogsServiceRequest;
const log1 = json.resourceLogs?.[0].scopeLogs?.[0].logRecords?.[0];
assert.ok(typeof log1 !== 'undefined', "log doesn't exist");
@@ -271,35 +305,39 @@ describe('OTLPLogExporter - node with proto over http', () => {
// Need to stub/spy on the underlying logger as the "diag" instance is global
const spyLoggerError = sinon.stub(diag, 'error');
+ sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
+ return fakeRequest as any;
+ });
+
collectorExporter.export(logs, result => {
assert.strictEqual(result.code, ExportResultCode.SUCCESS);
assert.strictEqual(spyLoggerError.args.length, 0);
done();
});
+ });
+ it('should log the error message', done => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(400);
+ cb(mockRes);
+ mockRes.send(Buffer.from('failure'));
+ });
+
return fakeRequest as any;
});
- });
- it('should log the error message', done => {
collectorExporter.export(logs, result => {
assert.strictEqual(result.code, ExportResultCode.FAILED);
// @ts-expect-error verify error code
assert.strictEqual(result.error.code, 400);
done();
});
-
- sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- const mockResError = new MockedResponse(400);
- cb(mockResError);
- mockResError.send('failed');
-
- return fakeRequest as any;
- });
});
});
describe('export - with compression', () => {
@@ -324,6 +362,9 @@ describe('OTLPLogExporter - node with proto over http', () => {
it('should successfully send the logs', done => {
const fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.stub(http, 'request').returns(fakeRequest as any);
const spySetHeader = sinon.spy();
(fakeRequest as any).setHeader = spySetHeader;
@@ -331,10 +372,7 @@ describe('OTLPLogExporter - node with proto over http', () => {
let buff = Buffer.from('');
fakeRequest.on('end', () => {
const unzippedBuff = zlib.gunzipSync(buff);
- const ExportLogsServiceRequestProto = getExportRequestProto(
- ServiceClientType.LOGS
- );
- const data = ExportLogsServiceRequestProto.decode(unzippedBuff);
+ const data = exportRequestServiceProto.decode(unzippedBuff);
const json = data?.toJSON() as IExportLogsServiceRequest;
const log1 = json.resourceLogs?.[0].scopeLogs?.[0].logRecords?.[0];
assert.ok(typeof log1 !== 'undefined', "log doesn't exist");
@@ -366,7 +404,7 @@ describe('export - real http request destroyed before response received', () =>
setTimeout(() => {
res.statusCode = 200;
res.end();
- }, 200);
+ }, 1000);
});
before(done => {
server.listen(8082, done);
@@ -384,11 +422,15 @@ describe('export - real http request destroyed before response received', () =>
logs.push(Object.assign({}, mockedReadableLogRecord));
collectorExporter.export(logs, result => {
- assert.strictEqual(result.code, ExportResultCode.FAILED);
- const error = result.error as OTLPExporterError;
- assert.ok(error !== undefined);
- assert.strictEqual(error.message, 'Request Timeout');
- done();
+ try {
+ assert.strictEqual(result.code, ExportResultCode.FAILED);
+ const error = result.error as OTLPExporterError;
+ assert.ok(error !== undefined);
+ assert.strictEqual(error.message, 'Request Timeout');
+ done();
+ } catch (e) {
+ done(e);
+ }
});
});
it('should log the timeout request error message when timeout is 100', done => {
diff --git a/experimental/packages/exporter-logs-otlp-proto/tsconfig.esm.json b/experimental/packages/exporter-logs-otlp-proto/tsconfig.esm.json
index 5eba4694be3..051fcfd62cf 100644
--- a/experimental/packages/exporter-logs-otlp-proto/tsconfig.esm.json
+++ b/experimental/packages/exporter-logs-otlp-proto/tsconfig.esm.json
@@ -27,9 +27,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
},
diff --git a/experimental/packages/exporter-logs-otlp-proto/tsconfig.esnext.json b/experimental/packages/exporter-logs-otlp-proto/tsconfig.esnext.json
index b37520a70f3..2bf55f532b2 100644
--- a/experimental/packages/exporter-logs-otlp-proto/tsconfig.esnext.json
+++ b/experimental/packages/exporter-logs-otlp-proto/tsconfig.esnext.json
@@ -27,9 +27,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
},
diff --git a/experimental/packages/exporter-logs-otlp-proto/tsconfig.json b/experimental/packages/exporter-logs-otlp-proto/tsconfig.json
index 2349f8706c7..00f0fe83cb9 100644
--- a/experimental/packages/exporter-logs-otlp-proto/tsconfig.json
+++ b/experimental/packages/exporter-logs-otlp-proto/tsconfig.json
@@ -27,9 +27,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
},
diff --git a/experimental/packages/exporter-trace-otlp-grpc/README.md b/experimental/packages/exporter-trace-otlp-grpc/README.md
index 32d42318702..09bb155c657 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/README.md
+++ b/experimental/packages/exporter-trace-otlp-grpc/README.md
@@ -116,7 +116,7 @@ Note, that this will only work if TLS is also configured on the server.
The OTLPTraceExporter has a timeout configuration option which is the maximum time, in milliseconds, the OTLP exporter will wait for each batch export. The default value is 10000ms.
-+ To override the default timeout duration, provide `timeoutMillis` to OTLPTraceExporter with `collectorOptions`:
+- To override the default timeout duration, provide `timeoutMillis` to OTLPTraceExporter with `collectorOptions`:
```js
const collectorOptions = {
@@ -177,9 +177,9 @@ const exporter = new OTLPTraceExporter(collectorOptions);
## Useful links
-+ For more information on OpenTelemetry, visit:
-+ For more about OpenTelemetry JavaScript:
-+ For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
+- For more information on OpenTelemetry, visit:
+- For more about OpenTelemetry JavaScript:
+- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
## License
@@ -190,6 +190,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-grpc
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-trace-otlp-grpc.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc
diff --git a/experimental/packages/exporter-trace-otlp-grpc/package.json b/experimental/packages/exporter-trace-otlp-grpc/package.json
index 929bfa2ba16..550169bf995 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/package.json
+++ b/experimental/packages/exporter-trace-otlp-grpc/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-trace-otlp-grpc",
- "version": "0.49.1",
+ "version": "0.52.1",
"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",
@@ -12,13 +12,15 @@
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts'",
"version": "node ../../../scripts/version-update.js",
"watch": "tsc --watch --build",
"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 ../../../"
+ "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"
},
"keywords": [
"opentelemetry",
@@ -47,22 +49,19 @@
"access": "public"
},
"devDependencies": {
- "@babel/core": "7.23.6",
"@grpc/proto-loader": "^0.7.10",
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/otlp-exporter-base": "0.49.1",
- "@types/mocha": "10.0.6",
+ "@opentelemetry/api": "1.9.0",
+ "@opentelemetry/otlp-exporter-base": "0.52.1",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4"
},
"peerDependencies": {
@@ -70,11 +69,11 @@
},
"dependencies": {
"@grpc/grpc-js": "^1.7.1",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/otlp-grpc-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0"
+ "@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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-grpc",
"sideEffects": false
diff --git a/experimental/packages/exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts
index 88e55734e6e..cffa9b07498 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts
+++ b/experimental/packages/exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts
@@ -21,12 +21,10 @@ import {
OTLPGRPCExporterNodeBase,
validateAndNormalizeUrl,
DEFAULT_COLLECTOR_URL,
- TraceSerializer,
} from '@opentelemetry/otlp-grpc-exporter-base';
import {
- createExportTraceServiceRequest,
- IExportTraceServiceRequest,
IExportTraceServiceResponse,
+ ProtobufTraceSerializer,
} from '@opentelemetry/otlp-transformer';
import { VERSION } from './version';
@@ -38,11 +36,7 @@ const USER_AGENT = {
* OTLP Trace Exporter for Node
*/
export class OTLPTraceExporter
- extends OTLPGRPCExporterNodeBase<
- ReadableSpan,
- IExportTraceServiceRequest,
- IExportTraceServiceResponse
- >
+ extends OTLPGRPCExporterNodeBase
implements SpanExporter
{
constructor(config: OTLPGRPCExporterConfigNode = {}) {
@@ -57,14 +51,10 @@ export class OTLPTraceExporter
signalSpecificMetadata,
'TraceExportService',
'/opentelemetry.proto.collector.trace.v1.TraceService/Export',
- TraceSerializer
+ ProtobufTraceSerializer
);
}
- convert(spans: ReadableSpan[]): IExportTraceServiceRequest {
- return createExportTraceServiceRequest(spans);
- }
-
getDefaultUrl(config: OTLPGRPCExporterConfigNode) {
return validateAndNormalizeUrl(this.getUrlFromConfig(config));
}
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/OTLPTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-grpc/test/OTLPTraceExporter.test.ts
index 9a3a13ce322..60f250d7f60 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/OTLPTraceExporter.test.ts
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/OTLPTraceExporter.test.ts
@@ -22,6 +22,7 @@ import {
} from '@opentelemetry/sdk-trace-base';
import * as assert from 'assert';
+import * as crypto from 'crypto';
import * as fs from 'fs';
import * as grpc from '@grpc/grpc-js';
import * as path from 'path';
@@ -44,9 +45,7 @@ import {
const traceServiceProtoPath =
'opentelemetry/proto/collector/trace/v1/trace_service.proto';
-const includeDirs = [
- path.resolve(__dirname, '../../otlp-grpc-exporter-base/protos'),
-];
+const includeDirs = [path.resolve(__dirname, '../../otlp-transformer/protos')];
const httpAddr = 'https://localhost:1501';
const udsAddr = 'unix:///tmp/otlp-traces.sock';
@@ -151,6 +150,24 @@ const testCollectorExporter = (params: TestParams) => {
sinon.restore();
});
+ if (useTLS && crypto.X509Certificate) {
+ it('test certs are valid', () => {
+ const certPaths = [
+ './test/certs/ca.crt',
+ './test/certs/client.crt',
+ './test/certs/server.crt',
+ ];
+ certPaths.forEach(certPath => {
+ const cert = new crypto.X509Certificate(fs.readFileSync(certPath));
+ const now = new Date();
+ assert.ok(
+ new Date(cert.validTo) > now,
+ `TLS cert "${certPath}" is still valid: cert.validTo="${cert.validTo}" (if this fails use 'npm run maint:regenerate-test-certs')`
+ );
+ });
+ });
+ }
+
describe('instance', () => {
it('should warn about headers when using grpc', () => {
// Need to stub/spy on the underlying logger as the 'diag' instance is global
@@ -231,9 +248,9 @@ const testCollectorExporter = (params: TestParams) => {
setTimeout(() => {
const result = responseSpy.args[0][0] as core.ExportResult;
assert.strictEqual(result.code, core.ExportResultCode.FAILED);
- assert.strictEqual(
+ assert.match(
responseSpy.args[0][0].error.details,
- 'Deadline exceeded'
+ /Deadline exceeded.*/
);
done();
}, 300);
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/ca.crt b/experimental/packages/exporter-trace-otlp-grpc/test/certs/ca.crt
index c194f049542..08075df43be 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/ca.crt
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/ca.crt
@@ -1,33 +1,33 @@
-----BEGIN CERTIFICATE-----
-MIIFozCCA4ugAwIBAgIUFA6cfBQ2t0ZOpLTRUIE6VN+kGBkwDQYJKoZIhvcNAQEL
+MIIFozCCA4ugAwIBAgIUFk1cYj0iRoo2KlsL519xVhA3k/gwDQYJKoZIhvcNAQEL
BQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQHDBFPcGVuVGVs
ZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9vdDENMAsGA1UECwwEVGVzdDELMAkGA1UE
-AwwCY2EwHhcNMjMwNjA4MTY0NDIzWhcNMjQwNjA3MTY0NDIzWjBhMQswCQYDVQQG
+AwwCY2EwHhcNMjQwNjA4MTkxODUwWhcNMjUwNjA4MTkxODUwWjBhMQswCQYDVQQG
EwJDTDELMAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0w
CwYDVQQKDARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTCCAiIwDQYJ
-KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMm3OXVbMd0t2r4x+Pg4fecPeFhRzsg6
-sp7AM4UYlhb0Xkx8ij3q0E47uQM/OSari6qi7p1Un6nzgaXmhosaNkVXaKV4dQ4g
-zKqrvC2+nTYU4lwss4Rx32CQxOKXEvN5FPwLTNo903PP3wqJyVt8syN0CDW953m/
-hUdkNaOe/lXmDJ9TmTTGyuPZFSlNlufbaNsBUM5chVFgBYDQIVy0jls8MiYLfao5
-tfprj+yS+lnTDl54dDTVVyAgV22SY65cnUgvO4bu3nzhS/h2Xg4/6/yAuYaRI7GQ
-xvlA4pzx+aLaRDTJKiszRrHbQFv4PY+MmkVxvg2Oka4Vc2XMgDM87H0bd+beO8NH
-Tf7UHU5AmIr2j2R27LWeELOqanm1HYn2VK182lD7OwQ5u5yqZZuke8bMMPJQEPUm
-EwhIgXMVIlGps2+rDUEalPYkQ/BmAcs2g7fywW3RhIWCacggKoee1x9a6oiUM5yi
-oDJ6T/C4WUQzIVebdMC25zBBlxcy8fK4Yus/DFTqM/eXPl4NVzbH/yB5tlU2GU0Q
-V4tpGL1jsUy4b7r1bzuYVNfnKrarUGFF5TIHuvDo3voJNGb4hWBH/JdttG/9NaWA
-HomZ8CUWR+gNEzyPkwq7upkiblKxJV7HKo79Eex+dlWa+Ru1F3kwYE200Y+a/wOF
-Rj4+PfMu7WvpAgMBAAGjUzBRMB0GA1UdDgQWBBSwH/Wk2wTc+MEPAEornj1eGKra
-0zAfBgNVHSMEGDAWgBSwH/Wk2wTc+MEPAEornj1eGKra0zAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCNkzOjjqH3qeQ0wT/Has5PSoWwRwq+B1JT
-gg29bgEMD6dVkLdzgEuRVVkMtc/tCZAkA02pc0VN8+lNLW7ckNU/QhMTQYn+FgMR
-cG86vR9loTnwUrxR4dS6Nbx1sQ7hpe2GZkWpTNmjh1duHBNHv9nS2JmMkRypqRne
-oAI3/th1Qlrtl/zDn02/+P5/av0YJcMOcnRkULHnI62cbXHa2iPd/nENgH2xC6CA
-EuYN/bnmOEUPeKljU1IZS6asjGMLdWLmpLs7oOcHGLD3pax+om69Pmn7rps8Z071
-WsJDHFCftItCUrg4KWwpXr77Vq4WAN2tOBdDHEZsbES6a54+7sc1QKOVSWwPuGEd
-ShFHhTzoaB0dpwm6kLdYsEkC8JLIjV+Ikg5X3VTDITjUlHoJf2mxCGOzBiCnUr75
-Am0eBqlVcc/2aVk1tcVS9N7reY/KcMaAJvI314O9I94pYdIIm5jw3UmA9Y6HmpN0
-vYtQUF2sS5W82XoFD8bpOq/bx1o2ib2x32dfPQkVgd4sbmpsyN62Fy1HpHwXtXno
-xGVaDzGSWj/7RyYyKhNmp3nfQsU0Tt6iVkM+N30vl2heZqEUgXxCG9qHVzWv9z6x
-AJzuafjM8tviROpiHkvzsmq7uDhksGooKCi+m+eoEBJrd0J4gjngAi1NYjTsB2GT
-4mvPz05UkA==
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL0NqK2IeL6fBwdEyHewWEdpBjCf1QxH
+S8ejgJTXcI8mUCijn/Q4Wox3ZNiVAad/y2ETYNRWExo4Z0LUq/KFRrdz4oBcxU0L
+lifw5Kbpw4HZk6WzvGw1FhOaOOuCbaBRYJLnVy42AprYfmknvJ1b/iAoOLmYrlJU
+JOhtSiOc3rZDq/A301TwLJ96vOVnoJohGf9aqYoP6EVEYSILpaPvRN5dN8HfPbrE
+WFElLw1heMEivXajxQ4wEdH3j50lU50NcmUC81629Ca+Dia9yLN+leYjZWhelhv2
+le4k/pqC14CfZ91Xbbb/WfVTnzgSmXdjCDpXKzV6YdGKa3t3uYAcvx2RylMdeco3
+JK9y86dFb2pH/5rAjnKxyE7Hgvs2m9+kD8qP2GT2idcwb7/6jbQm7ivxY8LvGvN6
+G5MhhoSecLFcyLatDhGcsNFAV81GQVZQzj+8riz681zEl7zNmCQEQcyyFaHfYMBm
+eD5lzeDUsKXJTwg/toT9ZTSQadjMy4KMFZqsoVpFdf/rpYM8HGuRRJiZwsLAGnNf
+Azlua4ctFMJftS4TJrBzEEf6W9nGRdfslLKI56dssULfC5wwtDgYOg1PrQdYrw7m
+xa8uBGBDpI5czZfnn8Z3MdMng7yP43f/SyplTk87VuZImGO9nDE9OKdcLj7W2UHH
+pD6PfHMR3D4DAgMBAAGjUzBRMB0GA1UdDgQWBBQWSFyaQ5G8Zr9jvMcByugHxZ27
+BjAfBgNVHSMEGDAWgBQWSFyaQ5G8Zr9jvMcByugHxZ27BjAPBgNVHRMBAf8EBTAD
+AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQBQxq6vBqs+Hoie4syroOc11JeFZYqKpWsA
+BxTmjFSVs3RCVk1sf4VW6znX2G5CeBeQHhjnC9j7L45hjeWjbTtx6MT5lPUhRz6D
+OU1e+mTl2uAiH+bFV9QGU6UtQmSMmWfSL11wtnGVJnkQyzGc0kTLiDLZpVTYs9eO
+9upTexE+C8DsCd7uJ37zp9Od6Oh0MthfB98ab7Hkdts9cc7edZuYdWfWaqwkP6Vp
+Icx4asgi8rdG4bdRU1EL87J1ReXheXf+jRLu/bWbNBWC/o6C21abK7DZHrpKv8xf
+WeCNw3wczbdQrAQ96FgJwxloIvCjOZKWNI3vAAcB9aEYMTxcCO2iV0Q+ihIIAg7M
+kTbkjoKbVWAFDbtdwSDvOVv+G/tfb8E7k5rZrBDvsKCbdaR238LIZITgZ8mtLvS7
+DeWlDL9GlFKxNkz64dgSSxpYTOdZKO2/Dty/0LydmlsSz85GeSYXIPlzAp5Zcg+x
+Rs1/zkrWGlnaos9uQj7xKj8B0ltrDLkI0mrX5TFuc9/lbGaJMT3n5jMlcfMUOwgV
+3jCo3i2plrxhLE22tK9M26a0NywkCrygRGiu2fgrunQgLTAbC4EyK1crZYoFXyhI
+Tq//oOEjNgGF8yvDUDh2R2CndsH+w3+P+Z0IrM3xRCqSWFOEvyOJ7pBfiesUwSbI
+nkERQqdGug==
-----END CERTIFICATE-----
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/ca.key b/experimental/packages/exporter-trace-otlp-grpc/test/certs/ca.key
index 00ccb046224..fa1f66e65fc 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/ca.key
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/ca.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+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
+MKrxFkhV1ynkDphHDFz5xXbumyvCNw==
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.crt b/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.crt
index fd05c9c40be..80f6c147e74 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.crt
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.crt
@@ -1,31 +1,32 @@
-----BEGIN CERTIFICATE-----
-MIIFPzCCAycCAQEwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNV
-BAgMAlJNMRowGAYDVQQHDBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9v
-dDENMAsGA1UECwwEVGVzdDELMAkGA1UEAwwCY2EwHhcNMjMwNjA4MTY0NDI2WhcN
-MjQwNjA3MTY0NDI2WjBqMQswCQYDVQQGEwJDTDELMAkGA1UECAwCUk0xGjAYBgNV
-BAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQKDARUZXN0MQ8wDQYDVQQLDAZD
-bGllbnQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBANewSXGnuCUsPcOnXPq7SUFTLaSM62x2FnJrzb6rne8KYQ615l6D
-d2Nm7MrttHWJUBQS6iDCsEGlF/AWYO5adVuZ+Xf+S+NoWMXPTUuJYq+5VEeAS8PM
-IriksA8Npn0hAMNTDrd/eNXQ5W4zLQOqUWnKcuE0P1M7gI3/rfX9/JXkZfUmkQGK
-OSva3qJHOcG7Bc7vqbJnkFebIw87e2iHxNnUf5IoJmrUaOMdFiQyHBBoJyTVJ3wp
-Ufr6Q2+d0sIyes9PV33DbB8DyKGdOfbLg4YmKsnAvnypC0p2Xw9yAnHlQX27Ngcq
-tfzcOXx3QlNPxQDF3oNHzi8GD7ysex1z7PRIsZlLVQLshAdOfA+naktPezj52R8V
-BtWaxgVFI7IA5X21reS25t01k/GXNcyIJxW5KSz00b1h8+mpz0n0R3Mz3HuZybAX
-g5bnZ+91jOeQmTt08eMXjwAGClxcOqfrssfDvOnUSZjDpzEGDaVuFGVPA9hR/eKN
-Bfo659rv45pYhtxoHLz1LJWoZ1uegmKrGF1w16K05k5mpzwH6fzqDzzbF1xyynGX
-yfbIqsvsBniuWGmhMjlfT5+l0VG2GgsD7Yijv6SV0YZrVf85iA5q6XdKTBuKYmin
-ZEbneEjw9kc9myMeC5ik7wHuksA/BQcja1TPwB4ZRbPEcfi2iFxbtsSzAgMBAAEw
-DQYJKoZIhvcNAQELBQADggIBAGdcqEI2l/dKxu9vPuRC2/VRgjgDBN4UJJCY111T
-2A7GsGzd7lRhtxB5ZzClF77UiRJG+cvFai00c9+L3wp8qy4sZWY4MaJIWoKRh72Q
-sRiH8AskeIl3uvvvaH86bbmpDo7M48Cs/zXZo9VhLzD8ZuHcS1mdjkOcnQzkbSzR
-YeM9ActeuJRmsdQ+gSzCTvFqmGutL6xvM8b9a6PwyY5nPxS+eh0/7KNp+EXBvp0U
-MWp6mMfq22nAwAQRLbvh5f+a/4GSwg73By6hwnsgb7tpBBJ6ppnKAIALRf7l5JwS
-V0LM5Vnpp4J4JjdYyQzk2xkxi+UGIP1IRigbeWc4K3qgg6BUUkfSf4W9oJD4JCa2
-cOsqnKqFxTwXT4b9j9qsPpg7mUQ2+UtU4Lv3h/7sXpbpx0ldb2Hnaq+JqUz0l/7c
-54y3+nzke7I4CWKtLJUSamQiyOC3CBVkRX0YEYUBhMXim6dKAfiOEV6K3bwiU+YZ
-aDe0lEeLbzAp87DKRTAvDYhRMIFtD3g2qmYrWpQ4gj8vSEorNAfg3kVHMFRGlk9o
-jaFduAz0hKk+QG5SgePXMph5ZRXGRq0FnDbF2gZ7WV+jZiIhsYGJ43+RBWHh4HO4
-P4h9eOWQG8AxpDRmOo2KmyPbV0V/eltC4N0oOAmWz+i0qqulnpG4dOzQKpinRBBr
-jPt5
+MIIFiDCCA3CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJDTDEL
+MAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQK
+DARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTAeFw0yNDA2MDgxOTE4
+NTBaFw0yNTA2MDgxOTE4NTBaMGoxCzAJBgNVBAYTAkNMMQswCQYDVQQIDAJSTTEa
+MBgGA1UEBwwRT3BlblRlbGVtZXRyeVRlc3QxDTALBgNVBAoMBFRlc3QxDzANBgNV
+BAsMBkNsaWVudDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAp8Llrbwz9XLaS2vrbo8vQB/Ks/kYE7Efh4x3hZFD1IVj
+/7scNhBJJTsO3KGmfuKHcJqhCp7zgGeEaF/ciB2V3JmF1+PcmjOGZyWm8etioS3u
+qfTkS376b6aZ0Vyl4J10gCYEaiacmYPxXbKTz3T1/iD9cNmATNyiJFiVRHP2ERTW
+ROCUnVVguyrHCJVoXEACa7c7lVGfvjMJa56w3X+Ot/JtG1oobhynG33UO9/3S/mJ
+qierFt7Q7bvxvn5paBktUO59qTEvDsTmL28Buj4EHjBEpEJvrr5IDGp7Z30/PXxW
+Y62l6nifMEa/QX/ExxYtzHl6xLk4Ob38oA8i/rz4N6gJFnVq2dY/lip6L4aKfg9+
+inUkqydrG0188EJbQ8/vd0K4wfdeOITNGSL3IGBNABvJsX0sOx9qJxSTFdNz+PZs
+p0reZVcT7AN1yYzYSamvtoI9Sg23ZCVnXTYiUUaLOAoqLxghKLE8sTu3AcNNAuZv
+TDoQdMcvyYvvoyYpJNxeY9nPqDrGE5vMGMS3jYzvCtTGtFR0g23/LLC+2B5STjxx
+ixMdmGERUz9c5uJjGWw/6oooK85KaQg2ly5QW36xnz84oAiw6ZI9Pw9AnnbC+Uix
++WKjxDn0ZcUtlutxQpn663gkaHnEbS9wfR7sTkMOO94Wb0cLnNdXvbkbgnQQ5oEC
+AwEAAaNCMEAwHQYDVR0OBBYEFAJfQgFDvpBqDPTL1enA7y9DQv/UMB8GA1UdIwQY
+MBaAFBZIXJpDkbxmv2O8xwHK6AfFnbsGMA0GCSqGSIb3DQEBCwUAA4ICAQA/e4xK
+wNft7yqDiY3CXjnyaL2n4m6J736UoM0ijmkJlBYiv1CGmn+CE97CWSoIz3gxPWJs
+fe8crVlQXflOm3fvWFzLXqK2026v/Ql1s6GcoG2YCBJLvJYtSrMRUecP48K1qkAA
+m0b7nxM5nKx2pvMYMN+TqBEhjOCCAKgRqCZbhO+oN36n1LcGUpjWy2aCg9N3QBq/
+jlZrOC019eiB97HZOmM27hGKmLflIqLklDBG28ANBSk18Nh7AvH9PZ4QWAZBcAmB
+RJ5/DncdFooHeQVJYyH28lkdvAruFA8YONWgP4rmwBLGBmaKKw3ZxkghV1XKDfCj
+tAlxSLj+WutnKo1E5EML7PAVLhhTfHKx+C7JLjjonyJhr+vozdNSWaYWcaTHMN2l
+s+Hadsi1AmLaYbL/9lVVV1+v+IiPlisMAm+T5PBxnxuiuwARBh3UCeFEkSWmpmA4
+EE9RQ3/JKhqGZRMyRg2tlodgOvSyAlXe+h6MbUF8IRgdvXfgrlGEDYVbLOqW6D8K
+KNO+1hqNdXKC7am7nDH41JlU5CUxSQISOgRV92IJ3jeGMUF35lfYERlR4E9K2TrT
+NXsvLp3Vf7nqfQNhSji3r/hsEEs/ni7fo1SbuaZjX1bGyAGZnMSQMJWyBCeucxsd
+WRHY+ANKPbPWedOdaMn3uGBXndUHFMPu6cyk6w==
-----END CERTIFICATE-----
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.csr b/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.csr
index b7838967259..cee04b8bd64 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.csr
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.csr
@@ -2,27 +2,27 @@
MIIErzCCApcCAQAwajELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQH
DBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEVGVzdDEPMA0GA1UECwwGQ2xp
ZW50MRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
-ggIKAoICAQDXsElxp7glLD3Dp1z6u0lBUy2kjOtsdhZya82+q53vCmEOteZeg3dj
-ZuzK7bR1iVAUEuogwrBBpRfwFmDuWnVbmfl3/kvjaFjFz01LiWKvuVRHgEvDzCK4
-pLAPDaZ9IQDDUw63f3jV0OVuMy0DqlFpynLhND9TO4CN/631/fyV5GX1JpEBijkr
-2t6iRznBuwXO76myZ5BXmyMPO3toh8TZ1H+SKCZq1GjjHRYkMhwQaCck1Sd8KVH6
-+kNvndLCMnrPT1d9w2wfA8ihnTn2y4OGJirJwL58qQtKdl8PcgJx5UF9uzYHKrX8
-3Dl8d0JTT8UAxd6DR84vBg+8rHsdc+z0SLGZS1UC7IQHTnwPp2pLT3s4+dkfFQbV
-msYFRSOyAOV9ta3ktubdNZPxlzXMiCcVuSks9NG9YfPpqc9J9EdzM9x7mcmwF4OW
-52fvdYznkJk7dPHjF48ABgpcXDqn67LHw7zp1EmYw6cxBg2lbhRlTwPYUf3ijQX6
-Oufa7+OaWIbcaBy89SyVqGdbnoJiqxhdcNeitOZOZqc8B+n86g882xdccspxl8n2
-yKrL7AZ4rlhpoTI5X0+fpdFRthoLA+2Io7+kldGGa1X/OYgOaul3SkwbimJop2RG
-53hI8PZHPZsjHguYpO8B7pLAPwUHI2tUz8AeGUWzxHH4tohcW7bEswIDAQABoAAw
-DQYJKoZIhvcNAQELBQADggIBACboOarzimaArw3lDm6ET5yiU7NxTWtnWwFUOoSh
-qS2cvumnCokUlrDyMSSKoHl2i2biUd9uiHuEqlh0yufNgnTsyAXLg0UiBHAv5Tos
-Esc5A+JTV5ehy+Zrjpl3Ayh8difS8hJEBjMhH+7rCN3rhpvwkTSaXDCQTBzWPhQ1
-R0EIho/SNOh5mXQKAUWwhtleI0sEJC/PqezGfN+w+URHnzE7YMwg02bvoMxBEror
-YVddG4o0nIyd6CPg++K7TBzYGGOf1CUCrI9S1bBn3jcv2mq5YgZMdLEa0HkA9XzU
-J/dTSGz5pJbkoaX9IHv8a3uoc+V1jdNWZRmTUYG/cNoAFISoG+uuJLgesF5l+vxx
-GUwkE6wj4bNYR/Pqy5963oDmA3ndBzR1wtCZqIsLX3t3A9fLLtIEgeN/XDSvNDBs
-YdwBrx2HTatK7QCJ5e+4ACs6Wc2c1nnDviPddpxUgl0pHKcMbT+xNk7bY5fjl5Qr
-wzuBNgvQcsZxNNvI8bs13k/eBmKrKOV2WUP1mHRzSoxPX3gzGRSWCe/7QR51oWlB
-Qkb6OGVGLCKPnhIKFeZ6G1Qv8q7/hOOlmWGO4bN7s5fjAKEsm3JV1xrsqSKRofRG
-JfdPjQD88jewIAk6xGSMKmc4usQN+y/IfU8yZ57MHSHULccA1Wl/VXfgKCAxS5fK
-uXtm
+ggIKAoICAQCnwuWtvDP1ctpLa+tujy9AH8qz+RgTsR+HjHeFkUPUhWP/uxw2EEkl
+Ow7coaZ+4odwmqEKnvOAZ4RoX9yIHZXcmYXX49yaM4ZnJabx62KhLe6p9ORLfvpv
+ppnRXKXgnXSAJgRqJpyZg/FdspPPdPX+IP1w2YBM3KIkWJVEc/YRFNZE4JSdVWC7
+KscIlWhcQAJrtzuVUZ++MwlrnrDdf4638m0bWihuHKcbfdQ73/dL+YmqJ6sW3tDt
+u/G+fmloGS1Q7n2pMS8OxOYvbwG6PgQeMESkQm+uvkgMantnfT89fFZjraXqeJ8w
+Rr9Bf8THFi3MeXrEuTg5vfygDyL+vPg3qAkWdWrZ1j+WKnovhop+D36KdSSrJ2sb
+TXzwQltDz+93QrjB9144hM0ZIvcgYE0AG8mxfSw7H2onFJMV03P49mynSt5lVxPs
+A3XJjNhJqa+2gj1KDbdkJWddNiJRRos4CiovGCEosTyxO7cBw00C5m9MOhB0xy/J
+i++jJikk3F5j2c+oOsYTm8wYxLeNjO8K1Ma0VHSDbf8ssL7YHlJOPHGLEx2YYRFT
+P1zm4mMZbD/qiigrzkppCDaXLlBbfrGfPzigCLDpkj0/D0CedsL5SLH5YqPEOfRl
+xS2W63FCmfrreCRoecRtL3B9HuxOQw473hZvRwuc11e9uRuCdBDmgQIDAQABoAAw
+DQYJKoZIhvcNAQELBQADggIBAIfdI8Jw6v7jkdfyelY4NCq00cSryok0m4AqRcOx
+9oYclU7+vYsqiUU7IWGaU4POfPTJEj4iRK76fR2uoTSxrggRuXlKw7BWHZAL2O2r
+14/e6M4dZuGTGoEJX6K+N4OBA0BhB8NreQZ90uGXmD/tp0wutSHVizpiP+JStUhY
+UzMt7jv/iRiCeOMBXecU7KgymCyfIcTxdYo2yXZUnnveBGIobFTWHB1N27rO5iao
+69RJWIM16btOISmIRdy6kpTNuYRentmas+6oFZnrIN7EOjhZL1NnUsUkv+6URADS
+Z+z+8Xac2M10GLNXJaqoOHXN/zks0LPX2ewEEUaeTVajs93urMGw+w9waeIU5YpE
+Smp3KGehthb7Mpu7/CeaowVSekeOTR4xcAvCeLJ1pf+UJscXnCYSPkajzCxAXMzR
+76Aruzoigk4DGVAYfPQuTdD+Ap397LUI8MbhoZQ6UEfvslubblOAoHzTqLxJ3WWt
+/QhuDBQVWoHtIArkPP9kI6PFstwUw+HW5nctO7HQeCBQ7FKHlFEgCUSFedbZNy9A
+daGXHM53IqDA2jpnkujLoGOxLQV3IsymoKGTyFOxP2AJMeAiKYG+xTUxHYCp4Z99
+cM/bPRQJKCYECb+ZQ13dLT9uBJdjIH2lve1UYXdyUC9Y8dNwV5Bvht5P87rDZChX
+8IR+
-----END CERTIFICATE REQUEST-----
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.key b/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.key
index 58414d8d59a..7681e0a5e7e 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.key
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/client.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCnwuWtvDP1ctpL
+a+tujy9AH8qz+RgTsR+HjHeFkUPUhWP/uxw2EEklOw7coaZ+4odwmqEKnvOAZ4Ro
+X9yIHZXcmYXX49yaM4ZnJabx62KhLe6p9ORLfvpvppnRXKXgnXSAJgRqJpyZg/Fd
+spPPdPX+IP1w2YBM3KIkWJVEc/YRFNZE4JSdVWC7KscIlWhcQAJrtzuVUZ++Mwlr
+nrDdf4638m0bWihuHKcbfdQ73/dL+YmqJ6sW3tDtu/G+fmloGS1Q7n2pMS8OxOYv
+bwG6PgQeMESkQm+uvkgMantnfT89fFZjraXqeJ8wRr9Bf8THFi3MeXrEuTg5vfyg
+DyL+vPg3qAkWdWrZ1j+WKnovhop+D36KdSSrJ2sbTXzwQltDz+93QrjB9144hM0Z
+IvcgYE0AG8mxfSw7H2onFJMV03P49mynSt5lVxPsA3XJjNhJqa+2gj1KDbdkJWdd
+NiJRRos4CiovGCEosTyxO7cBw00C5m9MOhB0xy/Ji++jJikk3F5j2c+oOsYTm8wY
+xLeNjO8K1Ma0VHSDbf8ssL7YHlJOPHGLEx2YYRFTP1zm4mMZbD/qiigrzkppCDaX
+LlBbfrGfPzigCLDpkj0/D0CedsL5SLH5YqPEOfRlxS2W63FCmfrreCRoecRtL3B9
+HuxOQw473hZvRwuc11e9uRuCdBDmgQIDAQABAoICAAC8DJiDFicRhRSECYXgprLh
+ZP3rywOhPGTz4T8RkljWak3oEgxEHRAdOOc1i8l2V3rvfGVfLbskYz+Z1p6jhJV2
+Vk4++67WfhS0BvOStqg0pj7Qk4rUs92gc3SS9PLlLdbgIduJdKvdNLTU0QsmoVid
+gyTvZ+5+Oggk3z3NXa88ENm8m4G/LgJNcWvEPNRihOzmc3FvPMKsEY1hhKDuIWam
+wBMCSOJuuNFzNjGRIQZKpY2DncLKlsD6NHTJGZPVx9uRYnluSrlNkwOZWQwYkQ2m
+/g6KKH2qMGkeJ3L8GAkzGYWmdlxlZ0VVSweUmtcgpj3DIjRUTFJ0srVbcfaVgxRl
+i2OBx13bGJ4ZrP3NJBx1uOrldrlRFjANIvBIo5zGF+tUbLkB7wMn5oBfgmdE50+o
+yOVKj2Io7SW5Wmc1tSU9fcEFvs40A79UgAO/BBo8/n8GFxmtOq/WPo/aGy9btj2H
+vP1fWzLRs6zXwpnFvz13+frihsj/7WNcrK75j/EGk7BmCVLzVandTqP9ReiTLSTv
+aipJF/5qVqEF9ytyr1cw4BJNNyl9JfM0BpqxLMYo33JtFc8mg1zlJKPooihuToaK
+3aPCMMOT5ACRDpyr5gumLHTDKRKjFdX7esAroUUAs+nbfH/dVm8nJIQJtoz9IRpc
+oWIpig38if+LaWpKzgQpAoIBAQDjaxBUNKW3zE4VppR9L2BT152rLSu5IM/9DDy4
+1MojD9MlZtfUx7MEt7zib//1c6q5PMByB1GY8MWcsBywRCANYuJg9ffRn3QdrmRc
+6KiBRyah9Zu0Ytg+4GfHQuvFq8YhzBkvDDR/EgQ0Lekwaf1waE/oh/q0UKzrXt1U
+KgajMp6DMfL/Vag00hVYlgnGfwpW8o9oMOJpHMF/nj7ayQWNLKgQvkDgw3M9anwy
+ibmr/BxNCvIql0LUCzvN1WRsgtEcqDOLwYnxIYXrTSU88IWeL19Oj2fSsuZeJx9J
+vnKd5qR2pmyAW6wQoTl8DujThmr68V08w1L0jvf3hqAmJ0a5AoIBAQC82G/WqeEi
+Y9ykm+wZeNvnzWOphwbMhwfclnNazxUBeHf4WyAobzqEYkh3Hn7vjlJDJ0J1/pXT
+DUhiVHaK7/o9+6xyd66daJ2yME/wkWXJTVfxv7nB2PAqasWHjlvNTwe24KPg80PT
+elq5q+XunG6EF0JKQfvtcBG90DimMbtcYaCFj5+Ce33XT6cgrqDiCOrTPIgVGPbK
+bOcmHmZSHCiG/tSLlb3a8j7u07a+yFrxaZCQMpODWWrnPXYDh+pUwVy+t02KaHC1
+0wJdSUkA7XsFRdUHuwr+8z9So+M+JtMUSVssi60GPfmMn6a3sOgDf3roAMpz1Doc
+oIOVu+bnNboJAoIBAQC6RSQ/xEuECuxeIW34R0jAA5gZ78qjPLP/EPnfbjMOmtSY
+Cu93UgZYM+KbGZ9tvMq2JIOAImx8N6G0YC9vVK1oKXlAb9cGtHMYKJH943a5RLzo
+5VIeYuO6RHXcKP0SkEqdvh1Wgsmw1uHolz4rsHSskFP7Iv1+maG4u5/PYwjCvSBG
+VzAwYUl/0h83ytTA56dhZhV+AqQ/8hSvYb8b1pEce9pAtIRRVOVcBY8qmdIhg0Lu
++6s0pWZQZc8bHdC+bDu5HC/0JZbFkW6uNybsDhlzYlvO7fjdBDlaHvMqpLoeiR5m
+LJQsYmnByTxbV57uOmf/mJiEv3t/4mZKMNOVzI/JAoIBACYZbIbcgyVTDGLRalLB
+RWyAzYiYS1DcNUPVvrQlb1F6oomiqNw/hIjM413U8zsVdZdCxm/TyxpnZaEg9UGW
+pN/4dJQrfTkYsCgRAy+/xc9VIVcOnUV0pQ+JtwxgNjk3ppDIxYdOzPJPjxpCigMX
+4FwZ7S/aHB+NKqcm6SbuhaRftej8TuweSgc0dL1tPdwcfHPdlH7dKH0yd3gDThVm
+xO5nXy5CKamQkg3Q/N+EwIRQDfBpo8UuNxksFzEjLK2ozTNU+/nelE66oZF8hZQA
+VX981TvYCqHhJXdgxSn230MKgbB9BY1q13v9gb8xm72I7Jz9+9peiNLZt3JwFGe1
+OTECggEBAI2p9rMyLqiWz0WuUtFtTwAeNbGeapijieqKe2TCqsYeNXGRd2usXg94
+DyR0EfyBquHazH3pmfHE4yMFr/S2vnszWdQ4ZBluqOQk3E4GXxP/ucHdCrI/3pdk
+6EE6Pgj/esQKrzB150UVsNWozYKD/MSog76FkdGcLc6Z+JjiIGUEJYhonuhrV+S3
+U82giIeb7chjCd73CU8P/xr6Dcu13odQLRASMZyeh9mBUZf/Bc6tXbkGZmJpFb1h
+NFBm7idC907JEWv4tXP9LM5zO5PmsExQu8J26S0LxZSQSvW4mOmhNpQ1CBOQrvPE
+oZy6rwoqrtLFacr41Jy5fq4MvMmkxwo=
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/regenerate.sh b/experimental/packages/exporter-trace-otlp-grpc/test/certs/regenerate.sh
index 84637be753d..cc052a4effe 100755
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/regenerate.sh
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/regenerate.sh
@@ -1,10 +1,9 @@
#!/usr/bin/env sh
#
-# Usage: regenerate.sh
+# Regenerate certificates that are used for tests using TLS.
+# Certs are generated with a one year expiry, so periodic regen is required.
#
-# regenerate.sh regenerates certificates that are used to test gRPC with TLS
-# Make sure you run it in test/certs directory.
-# It also serves as a documentation on how existing certificates were generated.
+# Usage: npm run maint:regenerate-test-certs
rm ca.crt ca.key client.crt client.csr client.key server.crt server.csr server.key
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.crt b/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.crt
index ace156a29ee..db941affc40 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.crt
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.crt
@@ -1,31 +1,32 @@
-----BEGIN CERTIFICATE-----
-MIIFPzCCAycCAQEwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNV
-BAgMAlJNMRowGAYDVQQHDBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9v
-dDENMAsGA1UECwwEVGVzdDELMAkGA1UEAwwCY2EwHhcNMjMwNjA4MTY0NDI0WhcN
-MjQwNjA3MTY0NDI0WjBqMQswCQYDVQQGEwJDTDELMAkGA1UECAwCUk0xGjAYBgNV
-BAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQKDARUZXN0MQ8wDQYDVQQLDAZT
-ZXJ2ZXIxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBAKtVnxPqCZheCuqePfLknxc+6MeyYkf494U8WWeZo+yirYV3zY70
-1KhKZ+M+XDqhrBXc7IQHZd2KKxYBGnrv9yvbllmtZRdnk3hnn8B4eNh3w5gCRKPo
-GSTeiNN7WEIRwYZNkr8AWgeoYT1jN8SAMn5+qSqKSd62Z1BPJNi0eQmTVxgLZqzx
-92AWBZQl9rOme+1zV6ohKcR22Of3yUl6476L1rYYcX0DXp0QFkhK0TFKNt3cHxqq
-WTRuMTnyCj7woWRtwclWTdO2buAkJe8cIde6rcbaUAX9jTdkbAgYAB9MctEKqasO
-MqFyMzweS3sG9oUnmd0/GRL9as314xTZuz8fFnfj5l0BN6thVMmvEEYU3rTLQRKf
-AKWzI2VrU+5wIxN8O/4ZbriQ5ae13p6TDYilSZ6kMxSzfOM/A00hlA+DKMS0o8g8
-V9Y3wcl3aSSjoZbH7XS/uDEueodudz9V3HxCk7Wc41SpunQPFprmPDWtjiW0jcMD
-3kHV819r2F8aidKN94Q+3KI+N/mwn1QdDVsquiCq0wbR54i3CoAkQbi5YeUdEZD6
-/mNLs/BABgzSbANw7Fn1Pd9gY/JIsRhMskcFRqXe9tOqKk8/GxMv/r9MgJn6HHlk
-iDa3OZsoOtFbjjOPFoy/Xq9YMi4ODnJkEhe7BSsVl/wkDAUdg7Zfu8XVAgMBAAEw
-DQYJKoZIhvcNAQELBQADggIBAEft+R+qGyKffiiJpYWLPn0C9SmpjZiWPK331n57
-Nk3GA8u9gRgD1gyqqLr19r86nLArF8jcB/nChPB1A9ysW3xyTNvpOlAwYvEjxWR2
-tJr8wiDucAd+SnQud6e+5PI5e8LnyxYoeoZ+i6hMbhNV70NthoINHMAQx+5NeSpa
-Q0GJ4d0XA3W/8Pu6oK7O0QkVovVut73Koz5DqsF91zFJp7SjVKaCnnjRKyU8wbg5
-uTO0TRheEtx3AeEXNps5Yhq0daLTnmnuFeyaJHm2F1QuBmma1TTwIF3HDclv2wLn
-Jp+MWG9yoN9oEJLqS/AvDu1BltPSuvnYgLZr7cl0os+TEqpzxroa4ziE98dEiy0D
-K4YQ59UTz6C8Ps0uX0hcs3jsvZOkBWptusvJBfZN59xLJAVmF2igkgIBKoiXvXmv
-fXDx0hsOBg2IPe2O8lLHlFKlJZlMc+prH1iD0Xv6HefSP4L1eZHU37zjrRf/GiNX
-r6GoEhJR2pKEoZQT81xpYp/w+qjzWcTl/mLD6FEePRzV92h3ubjRWBB36UhLtnEG
-LJgp7yq3aGu7rg9rnuz8J6DG8DStE9rNuRjkV1O2C/PvR97XmVoIqbrMlxX9MUQJ
-XxLm5dqBz7EVuhDJSyp4zCkDYsOj1y/SLL2O3cTyQQeZg6jlqripNqWnviAdTWe5
-JIPp
+MIIFiDCCA3CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJDTDEL
+MAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQK
+DARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTAeFw0yNDA2MDgxOTE4
+NTBaFw0yNTA2MDgxOTE4NTBaMGoxCzAJBgNVBAYTAkNMMQswCQYDVQQIDAJSTTEa
+MBgGA1UEBwwRT3BlblRlbGVtZXRyeVRlc3QxDTALBgNVBAoMBFRlc3QxDzANBgNV
+BAsMBlNlcnZlcjESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAho9Odc3xj0yN5rlGePl4NG5FAhLeoG4zsPm8Wq/F8tYV
+RGNuBv4FbfIwscWc21vN5vxIazlNe+wR9gs+JPXQqetJNBzoKyCnY5JWbUxhD69o
+5CqYUifWBML2+9fJlfPDRyLjZ63PaXw1lM+25F46qLC5VYaXcR8+OUf7SIOJnS6n
+1ZT1s5038tJdHw3pkep/hwaFuMAXEkAgemL/OOYJw4RSGAIGjXdsbDhTzIHovIwu
+LmyAAOivF/FPdTFoMdy08au7t21GMQKSa/eoJ6luMfy67DsqJ5FRFc570ZTjejOq
+VeLrxjjEGOHndZy550nIB50+ukmjGwdgEyQZ4Gie2nLckQMfgAPG6LsxixBoAg1B
+fm2nRDeEA87+5VWPCBxAJ4WrD24HjxTS0P7gXnAnYC8CxBolw6eGhYE4zrAoC0GQ
+tyU5iLdb3J9jbvV/OjHmNcMAbQrOtF+LC+O0YR6TScFyMUQy1DzCPNSjB6LA+bor
+Qwu+ixyFlSAWTbd0CbBep1kzBKGbw4WP7oqU06FAibg5TDizZIey6peq3ia+0gaJ
+08Y9BiJs0IClDP1zhTtXanjRsIfios9ucYzZiB2yfEKZhblBq8eq/z77ssL/4qDf
+czbFm9wcq22Pvsn/sY60UqNkxgfZvUDzhDdXd5EBouUd67KEEW3v6AOy2AG/YYkC
+AwEAAaNCMEAwHQYDVR0OBBYEFLqPQPHvLHjqNkPF9ol0NmzXvNqjMB8GA1UdIwQY
+MBaAFBZIXJpDkbxmv2O8xwHK6AfFnbsGMA0GCSqGSIb3DQEBCwUAA4ICAQB/E9UK
+vxQ6QSjjvwevEAwXcxkGbWNuFhOZGBey+IA9HrZvsvJJa65MMAcuarFbAu9NRVHK
+B+xQcEoZaumTv1ehtp/wRcaPQeixnr9ikwrreHho9bWbcLNc1r9zGAV94Mswq8XY
+Vu3ZNPYGrrI/m7GBu0piMtgK/PiVcn6CnzfQXrBJmP5zgrJNQjiMVbTXYrD3d521
+Pn0ptnvThWEFJhNlFHZ6arYZslU/rLAiWUiWkEiuTKAPiBNSNrQjqnljVBQA7Q/+
+CguQvSWt174tdMgeesvIHnDSvoC6Esk6P97uFi5fEafTE8fhhkOZeoRfKubj6Pwa
+WqU4iRQMEU8NR8BMdHsTweCKL2Rs2mwJFP9fXBW2pKQpfortAIPwO7mW9WUSm92g
+KoYG0rh/zkgYpH9KnnZa6yyauD1V2+lx/7y937puiMkUIqHeXVvTv0brDYmg21j/
+oRwO0BIVqwVItL1E9Ir+uas38bq6ij3Nylkn1cqUfuof+FXTj8BIHpvWwA3RRfzC
+YZQQu3yd3p2GvSmjHtkP3cDdci8OyxXMcCedYWB0Xnw63XaG2li6RRzGfY0kfxrH
+yRGbvxLgpTD3rgFTR2mTDz2Q6UODWriQ7cgmQ8OV+t61v92Di0OnXWVRUCNI+/P9
+xmNKrMU+gfM7amKc4N3oMKZgVtQexHNm7+Geng==
-----END CERTIFICATE-----
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.csr b/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.csr
index b421a7a60c9..6ac87e971b2 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.csr
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.csr
@@ -2,27 +2,27 @@
MIIErzCCApcCAQAwajELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQH
DBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEVGVzdDEPMA0GA1UECwwGU2Vy
dmVyMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
-ggIKAoICAQCrVZ8T6gmYXgrqnj3y5J8XPujHsmJH+PeFPFlnmaPsoq2Fd82O9NSo
-SmfjPlw6oawV3OyEB2XdiisWARp67/cr25ZZrWUXZ5N4Z5/AeHjYd8OYAkSj6Bkk
-3ojTe1hCEcGGTZK/AFoHqGE9YzfEgDJ+fqkqiknetmdQTyTYtHkJk1cYC2as8fdg
-FgWUJfazpnvtc1eqISnEdtjn98lJeuO+i9a2GHF9A16dEBZIStExSjbd3B8aqlk0
-bjE58go+8KFkbcHJVk3Ttm7gJCXvHCHXuq3G2lAF/Y03ZGwIGAAfTHLRCqmrDjKh
-cjM8Hkt7BvaFJ5ndPxkS/WrN9eMU2bs/HxZ34+ZdATerYVTJrxBGFN60y0ESnwCl
-syNla1PucCMTfDv+GW64kOWntd6ekw2IpUmepDMUs3zjPwNNIZQPgyjEtKPIPFfW
-N8HJd2kko6GWx+10v7gxLnqHbnc/Vdx8QpO1nONUqbp0Dxaa5jw1rY4ltI3DA95B
-1fNfa9hfGonSjfeEPtyiPjf5sJ9UHQ1bKrogqtMG0eeItwqAJEG4uWHlHRGQ+v5j
-S7PwQAYM0mwDcOxZ9T3fYGPySLEYTLJHBUal3vbTqipPPxsTL/6/TICZ+hx5ZIg2
-tzmbKDrRW44zjxaMv16vWDIuDg5yZBIXuwUrFZf8JAwFHYO2X7vF1QIDAQABoAAw
-DQYJKoZIhvcNAQELBQADggIBAJCMEdjKyklN2izvOhd7+JMXm/ClW3hjowbu+csO
-JNz8NqUNLrKJjFyV3yAUGWuyp3z982S+XGfcm3nU7n9AJOjT4DLJId6opOtA6CSp
-KTRgVZmeViL6O6UqBLTacz5DDjwMQXxszc+QpU53cMT6Y7VMvIOhQ6AmIvz1v71u
-5gaYmlbfXVlmiPHEKRsQG9/DNIPe1mHP0p+S9qYKmCx7Jlpee7IstW/hNjt7alDn
-uFaxFjxmCCSdWaMRyMW/qNRks9q3VdhJPan+amFeXceoEG7SOKiFiOc8A7DribSm
-iKc2YlOw14xqc+cJutiKBvoBMri2eh1JgCbPT4ufVGFpbDkfYwAJxWx44Eg0X90j
-gJUw8IRuHQZkEYss6jwFMFcOqjpe+AqrssOl4GZmu5gcaiUnj8PkSVZLTOrLilPg
-sSDjzmoHdv4QcBppTrjj6PyR5Xd6DeGasWkMPvIPjiPN3mOhfxJ3C87atMqOhTLx
-em7vFOBegAW6g40J9JD1XMoI/zFnTU8NevZQgCyx/Tq1XNRmUeMA6y/qpfTNKi/f
-F7v/7nDWoxBgpOw3J0E9R+6rxD7Cjb2RWZEf20ZGdNBlPE+UG9c9b3HC3IHiwRHb
-L9Fi0251w+fkaPX8dojQKErCEknqJ1SCP5S5F5g1QCQby22Y7LQsggMMf94s/wQX
-4uMh
+ggIKAoICAQCGj051zfGPTI3muUZ4+Xg0bkUCEt6gbjOw+bxar8Xy1hVEY24G/gVt
+8jCxxZzbW83m/EhrOU177BH2Cz4k9dCp60k0HOgrIKdjklZtTGEPr2jkKphSJ9YE
+wvb718mV88NHIuNnrc9pfDWUz7bkXjqosLlVhpdxHz45R/tIg4mdLqfVlPWznTfy
+0l0fDemR6n+HBoW4wBcSQCB6Yv845gnDhFIYAgaNd2xsOFPMgei8jC4ubIAA6K8X
+8U91MWgx3LTxq7u3bUYxApJr96gnqW4x/LrsOyonkVEVznvRlON6M6pV4uvGOMQY
+4ed1nLnnScgHnT66SaMbB2ATJBngaJ7actyRAx+AA8bouzGLEGgCDUF+badEN4QD
+zv7lVY8IHEAnhasPbgePFNLQ/uBecCdgLwLEGiXDp4aFgTjOsCgLQZC3JTmIt1vc
+n2Nu9X86MeY1wwBtCs60X4sL47RhHpNJwXIxRDLUPMI81KMHosD5uitDC76LHIWV
+IBZNt3QJsF6nWTMEoZvDhY/uipTToUCJuDlMOLNkh7Lql6reJr7SBonTxj0GImzQ
+gKUM/XOFO1dqeNGwh+Kiz25xjNmIHbJ8QpmFuUGrx6r/Pvuywv/ioN9zNsWb3Byr
+bY++yf+xjrRSo2TGB9m9QPOEN1d3kQGi5R3rsoQRbe/oA7LYAb9hiQIDAQABoAAw
+DQYJKoZIhvcNAQELBQADggIBAA6azFPc6LFR3wm8VkPXwQuAEMk8MwTWdSL/7NGf
+tW1AwlXaTVfzD+Q+lDqFCIBeDz783jC8CUzlLwToncQFIKJINE4Df16uX/UDe4Ez
+yyKeuyBKGiPPktmgtYKGnzQNXoJmJ4QjWUyZNxR1qojyj/niVc11WJbKjF1xOl9H
+RAf0W6HGLwjov68ZcHeaShE7utMPLTxa13LQh66bUGkIW9mtu20y9YRjRf9j3Y3n
+56qfRk0f8e/qqnG8EZr+KITm8W3abfDG2onozVYFTWZQ8dJhlYrKmBBoMjnpmG/7
+1DP59Ar+59ikpAtvtbdohhunlcMAcYKfZ/AIb4YcUdjbdMxPgfTEwMso4NL2p1at
+B/B26xqjolUz92oqByYn6G+t6MH9O5jDFvgazg1vVRIDXScxWj26VS37JE5qs7o6
+L5mWCc9XJpMocEX3goeFPERvFs6Ar6RH+j+wQQrHB7mIMBoLbxMQz+ZM6xbkwkv9
+JpRTCbbDUNZSC7FzNRDhlj22x4FnDhNOIwsUu8jH+Hm6c4Nudj+uxowdPvjFkF32
+0o4INWpBLY01SNKhkHuzsbbPvSzx3wx7fB2zHZFvQ558bRBc8j8SrxGegOtEiBkF
+tMTNObLaMHUAQ0y7izjcqFe2DBq8knc/kY9/QCkD5/0Zb/hYz8VnSvdmY2VrXcOn
+bdO+
-----END CERTIFICATE REQUEST-----
diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.key b/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.key
index 80b9cea7bf3..66969c7f7ca 100644
--- a/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.key
+++ b/experimental/packages/exporter-trace-otlp-grpc/test/certs/server.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+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
+nwltH7Jc/hdFyg6QG3p7/28gMdP+oxE=
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/exporter-trace-otlp-http/README.md b/experimental/packages/exporter-trace-otlp-http/README.md
index 141a4a27659..770c8dc22dc 100644
--- a/experimental/packages/exporter-trace-otlp-http/README.md
+++ b/experimental/packages/exporter-trace-otlp-http/README.md
@@ -116,7 +116,7 @@ The OTLPTraceExporter has a timeout configuration option which is the maximum ti
To override the default timeout duration, use the following options:
-+ Set with environment variables:
+- Set with environment variables:
| Environment variable | Description |
|----------------------|-------------|
@@ -125,7 +125,7 @@ To override the default timeout duration, use the following options:
> `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` takes precedence and overrides `OTEL_EXPORTER_OTLP_TIMEOUT`.
-+ Provide `timeoutMillis` to OTLPTraceExporter with `collectorOptions`:
+- Provide `timeoutMillis` to OTLPTraceExporter with `collectorOptions`:
```js
const collectorOptions = {
@@ -148,14 +148,14 @@ OTLP requires that transient errors be handled with a [retry strategy](https://g
This retry policy has the following configuration, which there is currently no way to customize.
-+ `DEFAULT_EXPORT_MAX_ATTEMPTS`: The maximum number of attempts, including the original request. Defaults to 5.
-+ `DEFAULT_EXPORT_INITIAL_BACKOFF`: The initial backoff duration. Defaults to 1 second.
-+ `DEFAULT_EXPORT_MAX_BACKOFF`: The maximum backoff duration. Defaults to 5 seconds.
-+ `DEFAULT_EXPORT_BACKOFF_MULTIPLIER`: The backoff multiplier. Defaults to 1.5.
+- `DEFAULT_EXPORT_MAX_ATTEMPTS`: The maximum number of attempts, including the original request. Defaults to 5.
+- `DEFAULT_EXPORT_INITIAL_BACKOFF`: The initial backoff duration. Defaults to 1 second.
+- `DEFAULT_EXPORT_MAX_BACKOFF`: The maximum backoff duration. Defaults to 5 seconds.
+- `DEFAULT_EXPORT_BACKOFF_MULTIPLIER`: The backoff multiplier. Defaults to 1.5.
This retry policy first checks if the response has a `'Retry-After'` header. If there is a `'Retry-After'` header, the exporter will wait the amount specified in the `'Retry-After'` header before retrying. If there is no `'Retry-After'` header, the exporter will use an exponential backoff with jitter retry strategy.
- > The exporter will retry exporting within the [exporter timeout configuration](#Exporter-Timeout-Configuration) time.
+ > The exporter will retry exporting within the [exporter timeout configuration](#exporter-timeout-configuration) time.
## Running opentelemetry-collector locally to see the traces
@@ -164,9 +164,9 @@ This retry policy first checks if the response has a `'Retry-After'` header. If
## Useful links
-+ For more information on OpenTelemetry, visit:
-+ For more about OpenTelemetry JavaScript:
-+ For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
+- For more information on OpenTelemetry, visit:
+- For more about OpenTelemetry JavaScript:
+- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
## License
@@ -179,7 +179,6 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[npm-url-grpc]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-grpc
[npm-url-proto]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-trace-otlp-http.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
[opentelemetry-spec-protocol-exporter]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options
[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-http
diff --git a/experimental/packages/exporter-trace-otlp-http/package.json b/experimental/packages/exporter-trace-otlp-http/package.json
index b68489a4441..2ea471b7f3e 100644
--- a/experimental/packages/exporter-trace-otlp-http/package.json
+++ b/experimental/packages/exporter-trace-otlp-http/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-trace-otlp-http",
- "version": "0.49.1",
+ "version": "0.52.1",
"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",
@@ -22,14 +22,15 @@
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.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",
"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 ../../../"
+ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -63,30 +64,28 @@
"access": "public"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
@@ -96,11 +95,11 @@
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/otlp-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0"
+ "@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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-http",
"sideEffects": false
diff --git a/experimental/packages/exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts
index fa164f65cf8..b19ce672fd8 100644
--- a/experimental/packages/exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts
+++ b/experimental/packages/exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts
@@ -23,8 +23,8 @@ import {
OTLPExporterBrowserBase,
} from '@opentelemetry/otlp-exporter-base';
import {
- createExportTraceServiceRequest,
- IExportTraceServiceRequest,
+ IExportTraceServiceResponse,
+ JsonTraceSerializer,
} from '@opentelemetry/otlp-transformer';
const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/traces';
@@ -34,35 +34,39 @@ const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURC
* Collector Trace Exporter for Web
*/
export class OTLPTraceExporter
- extends OTLPExporterBrowserBase
+ extends OTLPExporterBrowserBase
implements SpanExporter
{
constructor(config: OTLPExporterConfigBase = {}) {
- super(config);
+ super(config, JsonTraceSerializer, 'application/json');
+ const env = getEnv();
this._headers = Object.assign(
this._headers,
baggageUtils.parseKeyPairsIntoRecord(
- getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS
+ env.OTEL_EXPORTER_OTLP_TRACES_HEADERS
)
);
}
- convert(spans: ReadableSpan[]): IExportTraceServiceRequest {
- return createExportTraceServiceRequest(spans, {
- useHex: true,
- useLongBits: false,
- });
- }
getDefaultUrl(config: OTLPExporterConfigBase): string {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(
+ env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
+ );
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
+
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts
index aeb3b94ca72..aa91b8c237a 100644
--- a/experimental/packages/exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts
+++ b/experimental/packages/exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts
@@ -16,17 +16,18 @@
import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
import { getEnv, baggageUtils } from '@opentelemetry/core';
-import { OTLPExporterNodeBase } from '@opentelemetry/otlp-exporter-base';
+import {
+ OTLPExporterNodeBase,
+ parseHeaders,
+} from '@opentelemetry/otlp-exporter-base';
import {
OTLPExporterNodeConfigBase,
appendResourcePathToUrl,
appendRootPathToUrlIfNeeded,
} from '@opentelemetry/otlp-exporter-base';
-import {
- createExportTraceServiceRequest,
- IExportTraceServiceRequest,
-} from '@opentelemetry/otlp-transformer';
+import { IExportTraceServiceResponse } from '@opentelemetry/otlp-transformer';
import { VERSION } from '../../version';
+import { JsonTraceSerializer } from '@opentelemetry/otlp-transformer';
const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/traces';
const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURCE_PATH}`;
@@ -38,38 +39,39 @@ const USER_AGENT = {
* Collector Trace Exporter for Node
*/
export class OTLPTraceExporter
- extends OTLPExporterNodeBase
+ extends OTLPExporterNodeBase
implements SpanExporter
{
constructor(config: OTLPExporterNodeConfigBase = {}) {
- super(config);
- this.headers = {
- ...this.headers,
- ...USER_AGENT,
+ super(config, JsonTraceSerializer, {
...baggageUtils.parseKeyPairsIntoRecord(
getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS
),
- ...config.headers,
- };
- }
-
- convert(spans: ReadableSpan[]): IExportTraceServiceRequest {
- return createExportTraceServiceRequest(spans, {
- useHex: true,
- useLongBits: false,
+ ...parseHeaders(config?.headers),
+ ...USER_AGENT,
+ 'Content-Type': 'application/json',
});
}
getDefaultUrl(config: OTLPExporterNodeConfigBase): string {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(
+ env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
+ );
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
+
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts
index 4e8bc1d6e17..56efeb8092b 100644
--- a/experimental/packages/exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts
+++ b/experimental/packages/exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts
@@ -195,7 +195,10 @@ describe('OTLPTraceExporter - web', () => {
assert.strictEqual(request.url, 'http://foo.bar.com');
const body = request.requestBody;
- const json = JSON.parse(body) as IExportTraceServiceRequest;
+ const decoder = new TextDecoder();
+ const json = JSON.parse(
+ decoder.decode(body)
+ ) as IExportTraceServiceRequest;
const span1 = json.resourceSpans?.[0].scopeSpans?.[0].spans?.[0];
assert.ok(typeof span1 !== 'undefined', "span doesn't exist");
diff --git a/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts
index e9af4ec37b4..171a8dcf14b 100644
--- a/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts
+++ b/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts
@@ -33,7 +33,6 @@ import {
ensureSpanIsCorrect,
mockedReadableSpan,
} from '../traceHelper';
-import { nextTick } from 'process';
import { MockedResponse } from './nodeHelpers';
import { IExportTraceServiceRequest } from '@opentelemetry/otlp-transformer';
import { VERSION } from '../../src/version';
@@ -51,6 +50,9 @@ describe('OTLPTraceExporter - node with json over http', () => {
afterEach(() => {
fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.restore();
});
@@ -166,51 +168,54 @@ describe('OTLPTraceExporter - node with json over http', () => {
});
it('should use headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar';
- const collectorExporter = new OTLPTraceExporter();
- assert.strictEqual(collectorExporter.headers.foo, 'bar');
+ const exporter = new OTLPTraceExporter();
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'bar'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should include user agent in header', () => {
- const collectorExporter = new OTLPTraceExporter();
+ const exporter = new OTLPTraceExporter();
assert.strictEqual(
- collectorExporter.headers['User-Agent'],
+ exporter['_transport']['_transport']['_parameters']['headers'][
+ 'User-Agent'
+ ],
`OTel-OTLP-Exporter-JavaScript/${VERSION}`
);
});
it('should override global headers config with signal headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'foo=boo';
- const collectorExporter = new OTLPTraceExporter();
- assert.strictEqual(collectorExporter.headers.foo, 'boo');
- assert.strictEqual(collectorExporter.headers.bar, 'foo');
+ const exporter = new OTLPTraceExporter();
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'boo'
+ );
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = '';
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should override headers defined via env with headers defined in constructor', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
- const collectorExporter = new OTLPTraceExporter({
+ const exporter = new OTLPTraceExporter({
headers: {
foo: 'constructor',
},
});
- assert.strictEqual(collectorExporter.headers.foo, 'constructor');
- assert.strictEqual(collectorExporter.headers.bar, 'foo');
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'constructor'
+ );
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
- it('should use compression defined via env', () => {
- envSource.OTEL_EXPORTER_OTLP_COMPRESSION = 'gzip';
- const collectorExporter = new OTLPTraceExporter();
- assert.strictEqual(collectorExporter.compression, 'gzip');
- envSource.OTEL_EXPORTER_OTLP_COMPRESSION = '';
- });
- it('should override global compression config with signal compression defined via env', () => {
- envSource.OTEL_EXPORTER_OTLP_COMPRESSION = 'foo';
- envSource.OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = 'gzip';
- const collectorExporter = new OTLPTraceExporter();
- assert.strictEqual(collectorExporter.compression, 'gzip');
- envSource.OTEL_EXPORTER_OTLP_COMPRESSION = '';
- envSource.OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = '';
- });
});
describe('export', () => {
@@ -234,11 +239,13 @@ describe('OTLPTraceExporter - node with json over http', () => {
collectorExporter.export(spans, () => {});
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
const options = args[0];
assert.strictEqual(options.hostname, 'foo.bar.com');
@@ -252,11 +259,13 @@ describe('OTLPTraceExporter - node with json over http', () => {
collectorExporter.export(spans, () => {});
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
const options = args[0];
assert.strictEqual(options.headers['foo'], 'bar');
@@ -268,11 +277,13 @@ describe('OTLPTraceExporter - node with json over http', () => {
collectorExporter.export(spans, () => {});
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
const options = args[0];
assert.strictEqual(options.headers['Content-Encoding'], undefined);
@@ -284,11 +295,14 @@ describe('OTLPTraceExporter - node with json over http', () => {
collectorExporter.export(spans, () => {});
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
const options = args[0];
const agent = options.agent;
@@ -302,15 +316,18 @@ describe('OTLPTraceExporter - node with json over http', () => {
const clock = sinon.useFakeTimers();
collectorExporter.export(spans, () => {});
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
+ const mockRes = new MockedResponse(200);
+
+ queueMicrotask(() => {
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
- callback(mockRes);
- mockRes.send('success');
clock.restore();
- nextTick(() => {
+ queueMicrotask(() => {
const clock = sinon.useFakeTimers();
collectorExporter.export(spans, () => {});
@@ -319,7 +336,7 @@ describe('OTLPTraceExporter - node with json over http', () => {
const callback2 = args2[1];
callback2(mockRes);
- mockRes2.send('success');
+ mockRes2.send(Buffer.from('success'));
const [firstExportAgent, secondExportAgent] = stubRequest.args.map(
a => a[0].agent
@@ -334,7 +351,7 @@ describe('OTLPTraceExporter - node with json over http', () => {
it('should successfully send the spans', done => {
let buff = Buffer.from('');
- fakeRequest.on('end', () => {
+ fakeRequest.on('finish', () => {
const responseBody = buff.toString();
const json = JSON.parse(responseBody) as IExportTraceServiceRequest;
const span1 = json.resourceSpans?.[0].scopeSpans?.[0].spans?.[0];
@@ -357,7 +374,7 @@ describe('OTLPTraceExporter - node with json over http', () => {
const callback = args[1];
callback(mockRes);
- mockRes.send('success');
+ mockRes.send(Buffer.from('success'));
});
it('should log the successful message', done => {
@@ -367,12 +384,15 @@ describe('OTLPTraceExporter - node with json over http', () => {
collectorExporter.export(spans, responseSpy);
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
+
setTimeout(() => {
assert.strictEqual(stubLoggerError.args.length, 0);
assert.strictEqual(
@@ -389,11 +409,14 @@ describe('OTLPTraceExporter - node with json over http', () => {
collectorExporter.export(spans, responseSpy);
setTimeout(() => {
- const mockResError = new MockedResponse(400);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockResError);
- mockResError.send('failed');
+
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(400);
+ callback(mockRes);
+ mockRes.send(Buffer.from('failure'));
+ });
setTimeout(() => {
const result = responseSpy.args[0][0] as core.ExportResult;
@@ -401,7 +424,6 @@ describe('OTLPTraceExporter - node with json over http', () => {
const error = result.error as OTLPExporterError;
assert.ok(error !== undefined);
assert.strictEqual(error.code, 400);
- assert.strictEqual(error.data, 'failed');
done();
});
});
@@ -431,7 +453,7 @@ describe('OTLPTraceExporter - node with json over http', () => {
it('should successfully send the spans', done => {
let buff = Buffer.from('');
- fakeRequest.on('end', () => {
+ fakeRequest.on('finish', () => {
const responseBody = zlib.gunzipSync(buff).toString();
const json = JSON.parse(responseBody) as IExportTraceServiceRequest;
@@ -455,7 +477,7 @@ describe('OTLPTraceExporter - node with json over http', () => {
const callback = args[1];
callback(mockRes);
- mockRes.send('success');
+ mockRes.send(Buffer.from('success'));
});
});
@@ -483,6 +505,9 @@ describe('OTLPTraceExporter - node with json over http', () => {
describe('export - with timeout', () => {
beforeEach(() => {
fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
stubRequest = sinon.stub(http, 'request').returns(fakeRequest as any);
spySetHeader = sinon.spy();
(fakeRequest as any).setHeader = spySetHeader;
@@ -501,6 +526,7 @@ describe('OTLPTraceExporter - node with json over http', () => {
spans = [];
spans.push(Object.assign({}, mockedReadableSpan));
});
+
it('should log the timeout request error message', done => {
const responseSpy = sinon.spy();
collectorExporter.export(spans, responseSpy);
@@ -513,7 +539,7 @@ describe('OTLPTraceExporter - node with json over http', () => {
assert.strictEqual(result.code, core.ExportResultCode.FAILED);
const error = result.error as OTLPExporterError;
assert.ok(error !== undefined);
- assert.strictEqual(error.message, 'Request Timeout');
+ assert.deepEqual(error, { code: 'ECONNRESET' });
done();
});
diff --git a/experimental/packages/exporter-trace-otlp-http/test/node/nodeHelpers.ts b/experimental/packages/exporter-trace-otlp-http/test/node/nodeHelpers.ts
index d2dce6517b2..e63d21b17c9 100644
--- a/experimental/packages/exporter-trace-otlp-http/test/node/nodeHelpers.ts
+++ b/experimental/packages/exporter-trace-otlp-http/test/node/nodeHelpers.ts
@@ -24,7 +24,7 @@ export class MockedResponse extends Stream {
super();
}
- send(data: string) {
+ send(data: Uint8Array) {
this.emit('data', data);
this.emit('end');
}
diff --git a/experimental/packages/exporter-trace-otlp-proto/README.md b/experimental/packages/exporter-trace-otlp-proto/README.md
index 0be283bebe3..9b6141b873f 100644
--- a/experimental/packages/exporter-trace-otlp-proto/README.md
+++ b/experimental/packages/exporter-trace-otlp-proto/README.md
@@ -46,7 +46,7 @@ The OTLPTraceExporter has a timeout configuration option which is the maximum ti
To override the default timeout duration, use the following options:
-+ Set with environment variables:
+- Set with environment variables:
| Environment variable | Description |
|----------------------|-------------|
@@ -55,7 +55,7 @@ To override the default timeout duration, use the following options:
> `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` takes precedence and overrides `OTEL_EXPORTER_OTLP_TIMEOUT`.
-+ Provide `timeoutMillis` to OTLPTraceExporter with `collectorOptions`:
+- Provide `timeoutMillis` to OTLPTraceExporter with `collectorOptions`:
```js
const collectorOptions = {
@@ -77,14 +77,14 @@ OTLP requires that transient errors be handled with a [retry strategy](https://g
This retry policy has the following configuration, which there is currently no way to customize.
-+ `DEFAULT_EXPORT_MAX_ATTEMPTS`: The maximum number of attempts, including the original request. Defaults to 5.
-+ `DEFAULT_EXPORT_INITIAL_BACKOFF`: The initial backoff duration. Defaults to 1 second.
-+ `DEFAULT_EXPORT_MAX_BACKOFF`: The maximum backoff duration. Defaults to 5 seconds.
-+ `DEFAULT_EXPORT_BACKOFF_MULTIPLIER`: The backoff multiplier. Defaults to 1.5.
+- `DEFAULT_EXPORT_MAX_ATTEMPTS`: The maximum number of attempts, including the original request. Defaults to 5.
+- `DEFAULT_EXPORT_INITIAL_BACKOFF`: The initial backoff duration. Defaults to 1 second.
+- `DEFAULT_EXPORT_MAX_BACKOFF`: The maximum backoff duration. Defaults to 5 seconds.
+- `DEFAULT_EXPORT_BACKOFF_MULTIPLIER`: The backoff multiplier. Defaults to 1.5.
This retry policy first checks if the response has a `'Retry-After'` header. If there is a `'Retry-After'` header, the exporter will wait the amount specified in the `'Retry-After'` header before retrying. If there is no `'Retry-After'` header, the exporter will use an exponential backoff with jitter retry strategy.
- > The exporter will retry exporting within the [exporter timeout configuration](#Exporter-Timeout-Configuration) time.
+ > The exporter will retry exporting within the [exporter timeout configuration](#exporter-timeout-configuration) time.
## Running opentelemetry-collector locally to see the traces
@@ -94,9 +94,9 @@ This retry policy first checks if the response has a `'Retry-After'` header. If
## Useful links
-+ For more information on OpenTelemetry, visit:
-+ For more about OpenTelemetry JavaScript:
-+ For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
+- For more information on OpenTelemetry, visit:
+- For more about OpenTelemetry JavaScript:
+- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
## License
@@ -107,6 +107,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-trace-otlp-proto.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-proto
diff --git a/experimental/packages/exporter-trace-otlp-proto/package.json b/experimental/packages/exporter-trace-otlp-proto/package.json
index 6039d4e1ec0..d72ca465287 100644
--- a/experimental/packages/exporter-trace-otlp-proto/package.json
+++ b/experimental/packages/exporter-trace-otlp-proto/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-trace-otlp-proto",
- "version": "0.49.1",
+ "version": "0.52.1",
"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",
@@ -20,14 +20,15 @@
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.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",
"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 ../../../"
+ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -62,43 +63,40 @@
"access": "public"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
- "babel-plugin-istanbul": "6.1.1",
+ "@types/sinon": "17.0.3",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
- "webpack-cli": "4.10.0",
- "webpack-merge": "5.9.0"
+ "webpack-cli": "5.1.4",
+ "webpack-merge": "5.10.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/otlp-exporter-base": "0.49.1",
- "@opentelemetry/otlp-proto-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0"
+ "@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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-proto",
"sideEffects": false
diff --git a/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/OTLPTraceExporter.ts
index 890268333fa..f474e957888 100644
--- a/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/OTLPTraceExporter.ts
+++ b/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/OTLPTraceExporter.ts
@@ -20,14 +20,11 @@ import {
OTLPExporterConfigBase,
appendResourcePathToUrl,
appendRootPathToUrlIfNeeded,
+ OTLPExporterBrowserBase,
} from '@opentelemetry/otlp-exporter-base';
import {
- OTLPProtoExporterBrowserBase,
- ServiceClientType,
-} from '@opentelemetry/otlp-proto-exporter-base';
-import {
- createExportTraceServiceRequest,
- IExportTraceServiceRequest,
+ IExportTraceServiceResponse,
+ ProtobufTraceSerializer,
} from '@opentelemetry/otlp-transformer';
const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/traces';
@@ -37,36 +34,39 @@ const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURC
* Collector Trace Exporter for Web
*/
export class OTLPTraceExporter
- extends OTLPProtoExporterBrowserBase
+ extends OTLPExporterBrowserBase
implements SpanExporter
{
constructor(config: OTLPExporterConfigBase = {}) {
- super(config);
+ super(config, ProtobufTraceSerializer, 'application/x-protobuf');
+ const env = getEnv();
this._headers = Object.assign(
this._headers,
baggageUtils.parseKeyPairsIntoRecord(
- getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS
+ env.OTEL_EXPORTER_OTLP_TRACES_HEADERS
)
);
}
- convert(spans: ReadableSpan[]): IExportTraceServiceRequest {
- return createExportTraceServiceRequest(spans);
- }
getDefaultUrl(config: OTLPExporterConfigBase): string {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
- }
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(
+ env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
+ );
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
- getServiceClientType() {
- return ServiceClientType.SPANS;
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/exporter-trace-otlp-proto/src/platform/node/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-proto/src/platform/node/OTLPTraceExporter.ts
index be115583cd6..79da4ddc28b 100644
--- a/experimental/packages/exporter-trace-otlp-proto/src/platform/node/OTLPTraceExporter.ts
+++ b/experimental/packages/exporter-trace-otlp-proto/src/platform/node/OTLPTraceExporter.ts
@@ -20,14 +20,12 @@ import {
OTLPExporterNodeConfigBase,
appendResourcePathToUrl,
appendRootPathToUrlIfNeeded,
+ OTLPExporterNodeBase,
+ parseHeaders,
} from '@opentelemetry/otlp-exporter-base';
import {
- OTLPProtoExporterNodeBase,
- ServiceClientType,
-} from '@opentelemetry/otlp-proto-exporter-base';
-import {
- createExportTraceServiceRequest,
- IExportTraceServiceRequest,
+ IExportTraceServiceResponse,
+ ProtobufTraceSerializer,
} from '@opentelemetry/otlp-transformer';
import { VERSION } from '../../version';
@@ -41,39 +39,39 @@ const USER_AGENT = {
* Collector Trace Exporter for Node with protobuf
*/
export class OTLPTraceExporter
- extends OTLPProtoExporterNodeBase
+ extends OTLPExporterNodeBase
implements SpanExporter
{
constructor(config: OTLPExporterNodeConfigBase = {}) {
- super(config);
- this.headers = {
- ...this.headers,
- ...USER_AGENT,
+ super(config, ProtobufTraceSerializer, {
...baggageUtils.parseKeyPairsIntoRecord(
getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS
),
- ...config.headers,
- };
- }
-
- convert(spans: ReadableSpan[]): IExportTraceServiceRequest {
- return createExportTraceServiceRequest(spans);
+ ...parseHeaders(config?.headers),
+ ...USER_AGENT,
+ 'Content-Type': 'application/x-protobuf',
+ });
}
getDefaultUrl(config: OTLPExporterNodeConfigBase) {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
- }
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(
+ env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
+ );
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
- getServiceClientType() {
- return ServiceClientType.SPANS;
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/exporter-trace-otlp-proto/test/node/OTLPTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-proto/test/node/OTLPTraceExporter.test.ts
index b18c5a39deb..6adf335c1a2 100644
--- a/experimental/packages/exporter-trace-otlp-proto/test/node/OTLPTraceExporter.test.ts
+++ b/experimental/packages/exporter-trace-otlp-proto/test/node/OTLPTraceExporter.test.ts
@@ -34,12 +34,25 @@ import {
OTLPExporterNodeConfigBase,
OTLPExporterError,
} from '@opentelemetry/otlp-exporter-base';
-import {
- getExportRequestProto,
- ServiceClientType,
-} from '@opentelemetry/otlp-proto-exporter-base';
import { IExportTraceServiceRequest } from '@opentelemetry/otlp-transformer';
+import { Root } from 'protobufjs';
import { VERSION } from '../../src/version';
+import * as path from 'path';
+
+const dir = path.resolve(__dirname, '../../../otlp-transformer/protos');
+const root = new Root();
+root.resolvePath = function (origin, target) {
+ return `${dir}/${target}`;
+};
+const proto = root.loadSync([
+ 'opentelemetry/proto/common/v1/common.proto',
+ 'opentelemetry/proto/resource/v1/resource.proto',
+ 'opentelemetry/proto/trace/v1/trace.proto',
+ 'opentelemetry/proto/collector/trace/v1/trace_service.proto',
+]);
+const exportRequestServiceProto = proto?.lookupType(
+ 'ExportTraceServiceRequest'
+);
let fakeRequest: PassThrough;
@@ -50,14 +63,19 @@ describe('OTLPTraceExporter - node with proto over http', () => {
afterEach(() => {
fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.restore();
});
describe('default behavior for headers', () => {
- const collectorExporter = new OTLPTraceExporter();
+ const exporter = new OTLPTraceExporter();
it('should include user agent in header', () => {
assert.strictEqual(
- collectorExporter.headers['User-Agent'],
+ exporter['_transport']['_transport']['_parameters']['headers'][
+ 'User-Agent'
+ ],
`OTel-OTLP-Exporter-JavaScript/${VERSION}`
);
});
@@ -151,28 +169,43 @@ describe('OTLPTraceExporter - node with proto over http', () => {
});
it('should use headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar';
- const collectorExporter = new OTLPTraceExporter();
- assert.strictEqual(collectorExporter.headers.foo, 'bar');
+ const exporter = new OTLPTraceExporter();
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'bar'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should override global headers config with signal headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'foo=boo';
- const collectorExporter = new OTLPTraceExporter();
- assert.strictEqual(collectorExporter.headers.foo, 'boo');
- assert.strictEqual(collectorExporter.headers.bar, 'foo');
+ const exporter = new OTLPTraceExporter();
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'boo'
+ );
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = '';
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should override headers defined via env with headers defined in constructor', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
- const collectorExporter = new OTLPTraceExporter({
+ const exporter = new OTLPTraceExporter({
headers: {
foo: 'constructor',
},
});
- assert.strictEqual(collectorExporter.headers.foo, 'constructor');
- assert.strictEqual(collectorExporter.headers.bar, 'foo');
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['foo'],
+ 'constructor'
+ );
+ assert.strictEqual(
+ exporter['_transport']['_transport']['_parameters']['headers']['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
});
@@ -197,60 +230,72 @@ describe('OTLPTraceExporter - node with proto over http', () => {
});
it('should open the connection', done => {
- collectorExporter.export(spans, () => {});
-
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- assert.strictEqual(options.hostname, 'foo.bar.com');
- assert.strictEqual(options.method, 'POST');
- assert.strictEqual(options.path, '/');
-
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ try {
+ assert.strictEqual(options.hostname, 'foo.bar.com');
+ assert.strictEqual(options.method, 'POST');
+ assert.strictEqual(options.path, '/');
+ } catch (e) {
+ done(e);
+ }
+
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
- });
- it('should set custom headers', done => {
collectorExporter.export(spans, () => {});
+ });
+ it('should set custom headers', done => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
assert.strictEqual(options.headers['foo'], 'bar');
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
+
return fakeRequest as any;
});
- });
- it('should have keep alive and keepAliveMsecs option set', done => {
collectorExporter.export(spans, () => {});
+ });
+ it('should have keep alive and keepAliveMsecs option set', done => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
assert.strictEqual(options.agent.keepAlive, true);
assert.strictEqual(options.agent.options.keepAliveMsecs, 2000);
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
+
return fakeRequest as any;
});
+
+ collectorExporter.export(spans, () => {});
});
it('should successfully send the spans', done => {
const fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.stub(http, 'request').returns(fakeRequest as any);
let buff = Buffer.from('');
- fakeRequest.on('end', () => {
- const ExportTraceServiceRequestProto = getExportRequestProto(
- ServiceClientType.SPANS
- );
- const data = ExportTraceServiceRequestProto.decode(buff);
+ fakeRequest.on('finish', () => {
+ const data = exportRequestServiceProto.decode(buff);
const json = data?.toJSON() as IExportTraceServiceRequest;
const span1 = json.resourceSpans?.[0].scopeSpans?.[0].spans?.[0];
assert.ok(typeof span1 !== 'undefined', "span doesn't exist");
@@ -275,35 +320,44 @@ describe('OTLPTraceExporter - node with proto over http', () => {
// Need to stub/spy on the underlying logger as the "diag" instance is global
const spyLoggerError = sinon.stub(diag, 'error');
+ sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
+
+ return fakeRequest as any;
+ });
+
collectorExporter.export(spans, result => {
- assert.strictEqual(result.code, ExportResultCode.SUCCESS);
- assert.strictEqual(spyLoggerError.args.length, 0);
- done();
+ try {
+ assert.strictEqual(result.code, ExportResultCode.SUCCESS);
+ assert.strictEqual(spyLoggerError.args.length, 0);
+ done();
+ } catch (e) {
+ done(e);
+ }
});
+ });
+ it('should log the error message', done => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(400);
+ cb(mockRes);
+ mockRes.send(Buffer.from('failure'));
+ });
+
return fakeRequest as any;
});
- });
- it('should log the error message', done => {
collectorExporter.export(spans, result => {
assert.strictEqual(result.code, ExportResultCode.FAILED);
// @ts-expect-error verify error code
assert.strictEqual(result.error.code, 400);
done();
});
-
- sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- const mockResError = new MockedResponse(400);
- cb(mockResError);
- mockResError.send('failed');
-
- return fakeRequest as any;
- });
});
});
describe('export - with compression', () => {
@@ -328,17 +382,17 @@ describe('OTLPTraceExporter - node with proto over http', () => {
it('should successfully send the spans', done => {
const fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.stub(http, 'request').returns(fakeRequest as any);
const spySetHeader = sinon.spy();
(fakeRequest as any).setHeader = spySetHeader;
let buff = Buffer.from('');
- fakeRequest.on('end', () => {
+ fakeRequest.on('finish', () => {
const unzippedBuff = zlib.gunzipSync(buff);
- const ExportTraceServiceRequestProto = getExportRequestProto(
- ServiceClientType.SPANS
- );
- const data = ExportTraceServiceRequestProto.decode(unzippedBuff);
+ const data = exportRequestServiceProto.decode(unzippedBuff);
const json = data?.toJSON() as IExportTraceServiceRequest;
const span1 = json.resourceSpans?.[0].scopeSpans?.[0].spans?.[0];
assert.ok(typeof span1 !== 'undefined', "span doesn't exist");
@@ -370,7 +424,7 @@ describe('export - real http request destroyed before response received', () =>
setTimeout(() => {
res.statusCode = 200;
res.end();
- }, 200);
+ }, 1000);
});
before(done => {
server.listen(8080, done);
@@ -378,23 +432,6 @@ describe('export - real http request destroyed before response received', () =>
after(done => {
server.close(done);
});
- it('should log the timeout request error message when timeout is 1', done => {
- collectorExporterConfig = {
- url: 'http://localhost:8080',
- timeoutMillis: 1,
- };
- collectorExporter = new OTLPTraceExporter(collectorExporterConfig);
- spans = [];
- spans.push(Object.assign({}, mockedReadableSpan));
-
- collectorExporter.export(spans, result => {
- assert.strictEqual(result.code, ExportResultCode.FAILED);
- const error = result.error as OTLPExporterError;
- assert.ok(error !== undefined);
- assert.strictEqual(error.message, 'Request Timeout');
- done();
- });
- });
it('should log the timeout request error message when timeout is 100', done => {
collectorExporterConfig = {
url: 'http://localhost:8080',
diff --git a/experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts b/experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts
index 3a21d9b79d9..efbdc032830 100644
--- a/experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts
+++ b/experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts
@@ -268,7 +268,7 @@ export class MockedResponse extends Stream {
super();
}
- send(data: string) {
+ send(data: Uint8Array) {
this.emit('data', data);
this.emit('end');
}
diff --git a/experimental/packages/exporter-trace-otlp-proto/tsconfig.esm.json b/experimental/packages/exporter-trace-otlp-proto/tsconfig.esm.json
index 22887f7b0a0..8647f6ec567 100644
--- a/experimental/packages/exporter-trace-otlp-proto/tsconfig.esm.json
+++ b/experimental/packages/exporter-trace-otlp-proto/tsconfig.esm.json
@@ -24,9 +24,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
}
diff --git a/experimental/packages/exporter-trace-otlp-proto/tsconfig.esnext.json b/experimental/packages/exporter-trace-otlp-proto/tsconfig.esnext.json
index 199ea3b3251..b85acc27dfc 100644
--- a/experimental/packages/exporter-trace-otlp-proto/tsconfig.esnext.json
+++ b/experimental/packages/exporter-trace-otlp-proto/tsconfig.esnext.json
@@ -24,9 +24,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
}
diff --git a/experimental/packages/exporter-trace-otlp-proto/tsconfig.json b/experimental/packages/exporter-trace-otlp-proto/tsconfig.json
index cf9d8d1ec7e..417e1ad4684 100644
--- a/experimental/packages/exporter-trace-otlp-proto/tsconfig.json
+++ b/experimental/packages/exporter-trace-otlp-proto/tsconfig.json
@@ -24,9 +24,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
}
diff --git a/experimental/packages/opentelemetry-browser-detector/README.md b/experimental/packages/opentelemetry-browser-detector/README.md
index a1e9002ea98..b1cbe45e574 100644
--- a/experimental/packages/opentelemetry-browser-detector/README.md
+++ b/experimental/packages/opentelemetry-browser-detector/README.md
@@ -14,12 +14,12 @@ npm install --save @opentelemetry/opentelemetry-browser-detector
```js
import { Resource, detectResources } from '@opentelemetry/resources';
-import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
+import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { browserDetector } from '@opentelemetry/opentelemetry-browser-detector';
async function start(){
let resource= new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: 'Test App Name',
+ [SEMRESATTRS_SERVICE_NAME]: 'Test App Name',
});
let detectedResources= await detectResources({detectors:[browserDetector]});
resource=resource.merge(detectedResources);
@@ -51,4 +51,4 @@ start().then(()=> console.log("Instrumentation started"));
The browser identification attributes will be added to the resource spans when traces are created.
These attributes include platform, brands, mobile, language if the browser supports
-the userAgentData api, otherwise it will contain only the user_agent informations
+the userAgentData api, otherwise it will contain only the user_agent information
diff --git a/experimental/packages/opentelemetry-browser-detector/package.json b/experimental/packages/opentelemetry-browser-detector/package.json
index ce427dc1247..d5b92161b5a 100644
--- a/experimental/packages/opentelemetry-browser-detector/package.json
+++ b/experimental/packages/opentelemetry-browser-detector/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/opentelemetry-browser-detector",
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "OpenTelemetry Resource Detector for Browser",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@@ -13,7 +13,7 @@
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts'",
"test:browser": "karma start --single-run",
"tdd": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
@@ -22,7 +22,8 @@
"watch": "tsc --build --watch tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"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"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -53,27 +54,26 @@
"access": "public"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
- "babel-plugin-istanbul": "6.1.1",
+ "@types/sinon": "17.0.3",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
@@ -83,8 +83,7 @@
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.0"
+ "@opentelemetry/resources": "1.25.1"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/browser-detector"
}
diff --git a/experimental/packages/opentelemetry-browser-detector/src/types.ts b/experimental/packages/opentelemetry-browser-detector/src/types.ts
index c8567a4f95f..6cd6b020936 100644
--- a/experimental/packages/opentelemetry-browser-detector/src/types.ts
+++ b/experimental/packages/opentelemetry-browser-detector/src/types.ts
@@ -20,7 +20,7 @@ export type UserAgentData = {
};
export const BROWSER_ATTRIBUTES = {
- PLATFORM: 'browser.platform', //TODO replace with SemantecConventions attribute when available
+ PLATFORM: 'browser.platform', //TODO replace with SemanticConventions attribute when available
BRANDS: 'browser.brands',
MOBILE: 'browser.mobile',
LANGUAGE: 'browser.language',
diff --git a/experimental/packages/opentelemetry-browser-detector/tsconfig.esm.json b/experimental/packages/opentelemetry-browser-detector/tsconfig.esm.json
index 28f11090190..bd40c9fb1f1 100644
--- a/experimental/packages/opentelemetry-browser-detector/tsconfig.esm.json
+++ b/experimental/packages/opentelemetry-browser-detector/tsconfig.esm.json
@@ -14,9 +14,6 @@
},
{
"path": "../../../packages/opentelemetry-resources"
- },
- {
- "path": "../../../packages/opentelemetry-semantic-conventions"
}
]
}
diff --git a/experimental/packages/opentelemetry-browser-detector/tsconfig.esnext.json b/experimental/packages/opentelemetry-browser-detector/tsconfig.esnext.json
index ae74c831fed..3d1c53262e2 100644
--- a/experimental/packages/opentelemetry-browser-detector/tsconfig.esnext.json
+++ b/experimental/packages/opentelemetry-browser-detector/tsconfig.esnext.json
@@ -14,9 +14,6 @@
},
{
"path": "../../../packages/opentelemetry-resources"
- },
- {
- "path": "../../../packages/opentelemetry-semantic-conventions"
}
]
}
diff --git a/experimental/packages/opentelemetry-browser-detector/tsconfig.json b/experimental/packages/opentelemetry-browser-detector/tsconfig.json
index 3dbac056422..d5a0844c24a 100644
--- a/experimental/packages/opentelemetry-browser-detector/tsconfig.json
+++ b/experimental/packages/opentelemetry-browser-detector/tsconfig.json
@@ -15,9 +15,6 @@
},
{
"path": "../../../packages/opentelemetry-resources"
- },
- {
- "path": "../../../packages/opentelemetry-semantic-conventions"
}
]
}
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md
index 7a257ba1b75..5c87ab2527a 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md
@@ -94,6 +94,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-grpc
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-metrics-otlp-grpc.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/exporter-trace-otlp-grpc
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json
index 23a14f91036..ebd6842302f 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-metrics-otlp-grpc",
- "version": "0.49.1",
+ "version": "0.52.1",
"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",
@@ -12,13 +12,15 @@
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'",
+ "test": "nyc mocha 'test/**/*.test.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",
- "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../"
+ "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"
},
"keywords": [
"opentelemetry",
@@ -48,19 +50,17 @@
},
"devDependencies": {
"@grpc/proto-loader": "^0.7.10",
- "@opentelemetry/api": "1.8.0",
- "@types/mocha": "10.0.6",
+ "@opentelemetry/api": "1.9.0",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4"
},
"peerDependencies": {
@@ -68,12 +68,13 @@
},
"dependencies": {
"@grpc/grpc-js": "^1.7.1",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/exporter-metrics-otlp-http": "0.49.1",
- "@opentelemetry/otlp-grpc-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-metrics": "1.22.0"
+ "@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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc",
"sideEffects": false
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts
index 77d68d60a67..d7d3c1eea34 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts
@@ -24,15 +24,14 @@ import {
OTLPGRPCExporterNodeBase,
validateAndNormalizeUrl,
DEFAULT_COLLECTOR_URL,
- MetricsSerializer,
} from '@opentelemetry/otlp-grpc-exporter-base';
import { baggageUtils, getEnv } from '@opentelemetry/core';
import {
- createExportMetricsServiceRequest,
- IExportMetricsServiceRequest,
IExportMetricsServiceResponse,
+ ProtobufMetricsSerializer,
} from '@opentelemetry/otlp-transformer';
import { VERSION } from './version';
+import { parseHeaders } from '@opentelemetry/otlp-exporter-base';
const USER_AGENT = {
'User-Agent': `OTel-OTLP-Exporter-JavaScript/${VERSION}`,
@@ -40,7 +39,6 @@ const USER_AGENT = {
class OTLPMetricExporterProxy extends OTLPGRPCExporterNodeBase<
ResourceMetrics,
- IExportMetricsServiceRequest,
IExportMetricsServiceResponse
> {
constructor(config?: OTLPGRPCExporterConfigNode & OTLPMetricExporterOptions) {
@@ -49,14 +47,14 @@ class OTLPMetricExporterProxy extends OTLPGRPCExporterNodeBase<
...baggageUtils.parseKeyPairsIntoRecord(
getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS
),
- ...config?.headers,
+ ...parseHeaders(config?.headers),
};
super(
config,
signalSpecificMetadata,
'MetricsExportService',
'/opentelemetry.proto.collector.metrics.v1.MetricsService/Export',
- MetricsSerializer
+ ProtobufMetricsSerializer
);
}
@@ -64,10 +62,6 @@ class OTLPMetricExporterProxy extends OTLPGRPCExporterNodeBase<
return validateAndNormalizeUrl(this.getUrlFromConfig(config));
}
- convert(metrics: ResourceMetrics[]): IExportMetricsServiceRequest {
- return createExportMetricsServiceRequest(metrics);
- }
-
getUrlFromConfig(config: OTLPGRPCExporterConfigNode): string {
if (typeof config.url === 'string') {
return config.url;
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts
index 3ed034bde89..9ffd1d0d95c 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts
@@ -17,6 +17,7 @@
import * as protoLoader from '@grpc/proto-loader';
import { diag, DiagLogger } from '@opentelemetry/api';
import * as assert from 'assert';
+import * as crypto from 'crypto';
import * as fs from 'fs';
import * as grpc from '@grpc/grpc-js';
import * as path from 'path';
@@ -45,9 +46,7 @@ import { AggregationTemporalityPreference } from '@opentelemetry/exporter-metric
const metricsServiceProtoPath =
'opentelemetry/proto/collector/metrics/v1/metrics_service.proto';
-const includeDirs = [
- path.resolve(__dirname, '../../otlp-grpc-exporter-base/protos'),
-];
+const includeDirs = [path.resolve(__dirname, '../../otlp-transformer/protos')];
const httpAddr = 'https://localhost:1502';
const udsAddr = 'unix:///tmp/otlp-metrics.sock';
@@ -170,6 +169,24 @@ const testOTLPMetricExporter = (params: TestParams) => {
sinon.restore();
});
+ if (useTLS && crypto.X509Certificate) {
+ it('test certs are valid', () => {
+ const certPaths = [
+ './test/certs/ca.crt',
+ './test/certs/client.crt',
+ './test/certs/server.crt',
+ ];
+ certPaths.forEach(certPath => {
+ const cert = new crypto.X509Certificate(fs.readFileSync(certPath));
+ const now = new Date();
+ assert.ok(
+ new Date(cert.validTo) > now,
+ `TLS cert "${certPath}" is still valid: cert.validTo="${cert.validTo}" (if this fails use 'npm run maint:regenerate-test-certs')`
+ );
+ });
+ });
+ }
+
describe('instance', () => {
let warnStub: sinon.SinonStub;
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.crt b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.crt
index c194f049542..57decab97a0 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.crt
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.crt
@@ -1,33 +1,33 @@
-----BEGIN CERTIFICATE-----
-MIIFozCCA4ugAwIBAgIUFA6cfBQ2t0ZOpLTRUIE6VN+kGBkwDQYJKoZIhvcNAQEL
+MIIFozCCA4ugAwIBAgIUB0Ij1wY1Y97b9f57vy3qxdY3eyMwDQYJKoZIhvcNAQEL
BQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQHDBFPcGVuVGVs
ZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9vdDENMAsGA1UECwwEVGVzdDELMAkGA1UE
-AwwCY2EwHhcNMjMwNjA4MTY0NDIzWhcNMjQwNjA3MTY0NDIzWjBhMQswCQYDVQQG
+AwwCY2EwHhcNMjQwNjA4MTkxODUwWhcNMjUwNjA4MTkxODUwWjBhMQswCQYDVQQG
EwJDTDELMAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0w
CwYDVQQKDARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTCCAiIwDQYJ
-KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMm3OXVbMd0t2r4x+Pg4fecPeFhRzsg6
-sp7AM4UYlhb0Xkx8ij3q0E47uQM/OSari6qi7p1Un6nzgaXmhosaNkVXaKV4dQ4g
-zKqrvC2+nTYU4lwss4Rx32CQxOKXEvN5FPwLTNo903PP3wqJyVt8syN0CDW953m/
-hUdkNaOe/lXmDJ9TmTTGyuPZFSlNlufbaNsBUM5chVFgBYDQIVy0jls8MiYLfao5
-tfprj+yS+lnTDl54dDTVVyAgV22SY65cnUgvO4bu3nzhS/h2Xg4/6/yAuYaRI7GQ
-xvlA4pzx+aLaRDTJKiszRrHbQFv4PY+MmkVxvg2Oka4Vc2XMgDM87H0bd+beO8NH
-Tf7UHU5AmIr2j2R27LWeELOqanm1HYn2VK182lD7OwQ5u5yqZZuke8bMMPJQEPUm
-EwhIgXMVIlGps2+rDUEalPYkQ/BmAcs2g7fywW3RhIWCacggKoee1x9a6oiUM5yi
-oDJ6T/C4WUQzIVebdMC25zBBlxcy8fK4Yus/DFTqM/eXPl4NVzbH/yB5tlU2GU0Q
-V4tpGL1jsUy4b7r1bzuYVNfnKrarUGFF5TIHuvDo3voJNGb4hWBH/JdttG/9NaWA
-HomZ8CUWR+gNEzyPkwq7upkiblKxJV7HKo79Eex+dlWa+Ru1F3kwYE200Y+a/wOF
-Rj4+PfMu7WvpAgMBAAGjUzBRMB0GA1UdDgQWBBSwH/Wk2wTc+MEPAEornj1eGKra
-0zAfBgNVHSMEGDAWgBSwH/Wk2wTc+MEPAEornj1eGKra0zAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCNkzOjjqH3qeQ0wT/Has5PSoWwRwq+B1JT
-gg29bgEMD6dVkLdzgEuRVVkMtc/tCZAkA02pc0VN8+lNLW7ckNU/QhMTQYn+FgMR
-cG86vR9loTnwUrxR4dS6Nbx1sQ7hpe2GZkWpTNmjh1duHBNHv9nS2JmMkRypqRne
-oAI3/th1Qlrtl/zDn02/+P5/av0YJcMOcnRkULHnI62cbXHa2iPd/nENgH2xC6CA
-EuYN/bnmOEUPeKljU1IZS6asjGMLdWLmpLs7oOcHGLD3pax+om69Pmn7rps8Z071
-WsJDHFCftItCUrg4KWwpXr77Vq4WAN2tOBdDHEZsbES6a54+7sc1QKOVSWwPuGEd
-ShFHhTzoaB0dpwm6kLdYsEkC8JLIjV+Ikg5X3VTDITjUlHoJf2mxCGOzBiCnUr75
-Am0eBqlVcc/2aVk1tcVS9N7reY/KcMaAJvI314O9I94pYdIIm5jw3UmA9Y6HmpN0
-vYtQUF2sS5W82XoFD8bpOq/bx1o2ib2x32dfPQkVgd4sbmpsyN62Fy1HpHwXtXno
-xGVaDzGSWj/7RyYyKhNmp3nfQsU0Tt6iVkM+N30vl2heZqEUgXxCG9qHVzWv9z6x
-AJzuafjM8tviROpiHkvzsmq7uDhksGooKCi+m+eoEBJrd0J4gjngAi1NYjTsB2GT
-4mvPz05UkA==
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL5sOaALnaMG5LvsyTRf77a0iQj5A1QP
+N11tcWPQ5DvRtD6rKh3ISuKCPOX0BOeY0VdwqWP3dVP0qQgek48iGQw4Wl7SBQxO
+vX3+cmaIy17ZHPu4RZIbjbGbS61OHU2iM4Ek1styhccWTv8dDN9V1LGr9mOnqVkv
+4SZrmrGYAKyF5JLImafzAUUGttc5aeBpqWmjObk3GLFDWEvObkrI5sUqabJ3U4LS
+KVPAX4sXoEPmlmnqIe6/5edmYNbeK0Kr8gZLDqJXThIDsgbRNIOTYWohPR3/JlDy
+xnIH31GXygSWlGmDUxHynm7rvzY70Dm4G8JHI8F8hClRZ29XVYjyBMlS8qBHLa72
+mLU79WfsCbvdU/1AWg9g1FopSdf3G3z0Y4ZI8nTCMAbSJ0zQm3nIT9pNVPa9nk0e
+iOo1462+TZ40X3/E+t7G7PkGgIHyYrL3o6bMsp3B2pKbJHIybwwGNxiuyRKvzIyc
+Xcz7jbEzyL7rmcsxiNNuukk8ilpMexeCDu/Y+ndmvnNVWAsNf6HSbHlkip3Efi+p
+6pK0pWgNprkoQvigiEeSqep5u2v/ogTRflLwih1UDB9krJ3dzoE6TB5kDrgvmn/s
+Iohh/LWC7HipuQji1b+/ejFuQNy3mwDR2G09vrqk5PZXvfHRX+CCfTUZSFY8uEHr
+TAhfgiKEPaf5AgMBAAGjUzBRMB0GA1UdDgQWBBQJ4qWJUnKN4XrWuGJ8TN4YIN7R
+sjAfBgNVHSMEGDAWgBQJ4qWJUnKN4XrWuGJ8TN4YIN7RsjAPBgNVHRMBAf8EBTAD
+AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAYAu4AjPtl3Ji0n5u/p1mlp7DfmT4JpzZa
+nczi7M1ae9ILx58i037zXVB9Fk7Yk5CG3buVqf7hzRT6KERKpTyUsc4wiy+vaAw9
+euGnp4qmG3mj4GRDAqDruOHFrv8Dfq541aF4N+V1OOdCbG3B3wXBQ9LkBpWCgHSk
+M2h5jiLbbvwIbd4WoztLUOJtx89L+5TVM10fBTxekdJM/cVXOMzJgFzukc87sTAL
+dSj3dz9J3TH6R24NzWijSch8Zh9ymAfSCKthBOl1mWIfd8h4ygUjnouGj5MGIIpl
+q9ATAk0cka6VvjSzQ5OucZtrYkWIlLlqiUisYD7bJSn2zij4j3K2TQu+PTxM4/Oh
+Xzz3W8LuAp+mdcgtPt4GvmtML2LtIJi6EgNRMkUzYtaERxubrgPuJOh1/10kp1ww
+W8wdnweYid1I4nJXjGDhIvKk6ntzhBg6zV+5OSJf6o2RJKRsdxAz8o3wKbIXXGXh
+u4B1TQJEivUTAcaZJX4iOJI2VhLaSP5lzdihAaLiPpSMk/cTTs5OYHCvb4XxkT5L
+KH3UqSlvQBTQ2NfMfM5S4kLGtcCarOzcPYn++fjAOg24//TyZ2RAGbSCwjok/nKN
+62MwO+Npr0sSkBGvYG2xzTS7R00L14cWOA9L26v7EqjZbpFd2B6vE0sUWLvVlbNc
+wwZok4pFbw==
-----END CERTIFICATE-----
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.key b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.key
index 00ccb046224..b9f12f4f350 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.key
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAybc5dVsx3S3avjH4+Dh95w94WFHOyDqynsAzhRiWFvReTHyK
-PerQTju5Az85JquLqqLunVSfqfOBpeaGixo2RVdopXh1DiDMqqu8Lb6dNhTiXCyz
-hHHfYJDE4pcS83kU/AtM2j3Tc8/fConJW3yzI3QINb3neb+FR2Q1o57+VeYMn1OZ
-NMbK49kVKU2W59to2wFQzlyFUWAFgNAhXLSOWzwyJgt9qjm1+muP7JL6WdMOXnh0
-NNVXICBXbZJjrlydSC87hu7efOFL+HZeDj/r/IC5hpEjsZDG+UDinPH5otpENMkq
-KzNGsdtAW/g9j4yaRXG+DY6RrhVzZcyAMzzsfRt35t47w0dN/tQdTkCYivaPZHbs
-tZ4Qs6pqebUdifZUrXzaUPs7BDm7nKplm6R7xsww8lAQ9SYTCEiBcxUiUamzb6sN
-QRqU9iRD8GYByzaDt/LBbdGEhYJpyCAqh57XH1rqiJQznKKgMnpP8LhZRDMhV5t0
-wLbnMEGXFzLx8rhi6z8MVOoz95c+Xg1XNsf/IHm2VTYZTRBXi2kYvWOxTLhvuvVv
-O5hU1+cqtqtQYUXlMge68Oje+gk0ZviFYEf8l220b/01pYAeiZnwJRZH6A0TPI+T
-Cru6mSJuUrElXscqjv0R7H52VZr5G7UXeTBgTbTRj5r/A4VGPj498y7ta+kCAwEA
-AQKCAgEAvpLhsTN4d8ujtz+FRhYxNQTToTWhFGEIcp2Jzzw8SPGUydR70yWuqcsY
-761itFssOAl5QKE7u5g4q+GQyYj5Lyf20SZuCOwKEVDxF5LX+sleVtFQxVfEP/pm
-WOF8YRTLM5kFgccZqHgC9HTbDRlSMbOlMgj50XeVVq6hUrWa+tK+qCSWQVtzQjLN
-IFmSsfkEJq0mh+C3f/slF98LNgfL2vyTMIh4sEOX30CSGGOALS8Oi0hoGaZZixuj
-Hf1JOel8Gz+skL3K69b7LIHAONxBeyyumykyvMbYhZK8xqSCQk7OU8Sel3P5XX2U
-X4+3sZCYC/X7JdnFXuAbR1ke4cm0botnzZM+nVYdtWqBpW3lly33lmMXFvcj6m/U
-m9iSqKIw58sHF2v5cStsjnzZ5nznB+jcsHMf0syeZS7V5ASKeiYEp/5RDc3iEmvd
-mbb5hU0pd0bmaLtW7yGdFcBsOgDezbq/BkMlQJqtzUsjC+Ot/FxRSO7qMtIF2u0A
-OgQwaarTvh8ItdA89Qx1oKKvod415htj/CSHqaEhsYGp9V2t2uiaN5a1Gt7tu+BL
-HsOWRZh3n1+73mMXQEoosj8CvoSHhXOtBq4zL/3ICvTGfUBwqes4lvp7p4WKczS7
-ORRPRnl+80383pzlEnuKnYJ2iWYipye047sTIq6HmH8+DhEhdPUCggEBAPf3mMbk
-PzglXhveUug/YJ3cTpd2vzbHDU8y1EPCrGHTwx5dUWSCVnv9h8Lrjr4/Aulk0ORw
-w9n11Z9GHs7l0W3g6w2WlNF3/e1NQYyILnp8Zyl5onCjcxxlm/jsnrLemoX24+oK
-34r+K6X/LHX/3qqq+hf+J6EefTzXAmYisSsB9FfCc8r7U6YUaWqAcdpq30tkj5Tt
-1gEUferlcaVuZNEHVczIbiTvukMYtKO3pkzFmn5g3JKTfdakTW8tAEz4FBR+IaX6
-mvv3BcE/tc78yAn22hnY/RMpXAmLoOuVo/JUtQZT9DTKQZqDGhaKwIMjw/zjJsAv
-MR0uqvKwubqc9dsCggEBANBAD+2B7QQtVsnjUZgVI5nHUptczJ9qOURNrCToqe+S
-zkuwWhxWud5Q1ZgSH1xr/KIgSuHzqVnV/CRGsyo/VZmg0gsSHI5PToL7TqPPwCxV
-KM2wbwA24gN2v4Lkk53xq2ezcQ5qh2avJVFiftyRrzfSvzzB6yJ5bF4fW697OLlV
-9my+rnlF6DO4J8eGGw5NEYZT0x1JQhNz+oFsZOUxB5scst5IzP7uFAlDjmybqkdh
-sBLe5uPdK0+v1LSXw5CJK7YdJ2rAHp5eDALKJs3P3BX4fdngMufuALtVxLsLt9Wz
-rQijz+b9WHrn4FCojC+cj+TftIvhHApeWtvkKSN6KosCggEBAPOHa7gJ+jy+Fkrw
-ciQ9+jmPYHBI40p8+4lItkdGLd52By8PHxzDFQT43hiFF8+oOsfVh4KTbQXm9kJS
-r3crJh/vwWm69bUzT2N7eGD4bg1FmFuXZf2RyT+eWyyB1up8zO28p+H3g8wSC/Qf
-RB8viBO9j5l4tpr6Qq05zNVaRP2kEcEO7IHxixmU+mLqeua0B1EYFhuB6adt5KyJ
-Yq/CV6kitxVD00jbV+cFoIMZnm3PtAdiQb6CtBfVjWcenyj4i2AE8C7+jK/gzvoY
-BAqhICUJFvJDtWjYOdf2FbjJYhZhMthgI3qlGQESuNBivOcOfTEkNa6Rqn6qkqF/
-BylLdfkCggEAH5d4UxmAsT+HiPz5Jc8fJXb9ayA60nw0z83QrZC2Jufob8cDBIWL
-kNRGctlc9JJVMusfMQPbzwsNQxuOlnwhKjshYhiPSG9zg59IIMWla5RHqlx3mlq5
-Erly+BJg6nb8/7BTGFLE06kCSkRc5m0bXaaU6EyqtQIilGzBZe+VfVgzF/AdW7xl
-K2NmdXg8poC+hdg1kJ3KblULzZJ6A+LaOoeyAtKcdpf7ZiRfeM5smIOTSGmUMUEe
-Duqno/XZ7xVAElJ95k3a1z+BJvMvy80aoCKgROskDdcnOUQbohx2+O5W85aWNX59
-a7e9ab8H9TkVAy2EoCu4K0KBGhaUvxMLXQKCAQAORESNb5Ne+bBHbrSA6nVMH0Ti
-Gt9Nx2bgNLxgGPGHLIFkQPnR9akk8mm94T/Ow1y8Jrx/rE0bxR0ayVYbxLiF+Zqz
-i/G+CYGg72j+PXdugo4ocfGf17BpqR577uqUAycvtsk50zTgxYyoob5HxdXcFjnH
-PEiJBGSSSY1VJJlPxIftHLE6ULfwslyMkHPGBxh6NJe/nkM7obuQYMc7JGpNngLb
-G5NF6b8nV5yJ7a5hhhSbArFWuzlfbRsZwgqadWFDChXiAyCbzE5ey5gUOs22K4Ax
-M4Ky5evO6Srk3gtFGCWPqSxcDJk57DSy/on35IwerlQTI6Btz0OT6EmDWXOn
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+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
++pFcbZ4RROHkC2Vg2eaQxFXb0mnv
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.crt b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.crt
index fd05c9c40be..b85e18dffad 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.crt
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.crt
@@ -1,31 +1,32 @@
-----BEGIN CERTIFICATE-----
-MIIFPzCCAycCAQEwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNV
-BAgMAlJNMRowGAYDVQQHDBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9v
-dDENMAsGA1UECwwEVGVzdDELMAkGA1UEAwwCY2EwHhcNMjMwNjA4MTY0NDI2WhcN
-MjQwNjA3MTY0NDI2WjBqMQswCQYDVQQGEwJDTDELMAkGA1UECAwCUk0xGjAYBgNV
-BAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQKDARUZXN0MQ8wDQYDVQQLDAZD
-bGllbnQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBANewSXGnuCUsPcOnXPq7SUFTLaSM62x2FnJrzb6rne8KYQ615l6D
-d2Nm7MrttHWJUBQS6iDCsEGlF/AWYO5adVuZ+Xf+S+NoWMXPTUuJYq+5VEeAS8PM
-IriksA8Npn0hAMNTDrd/eNXQ5W4zLQOqUWnKcuE0P1M7gI3/rfX9/JXkZfUmkQGK
-OSva3qJHOcG7Bc7vqbJnkFebIw87e2iHxNnUf5IoJmrUaOMdFiQyHBBoJyTVJ3wp
-Ufr6Q2+d0sIyes9PV33DbB8DyKGdOfbLg4YmKsnAvnypC0p2Xw9yAnHlQX27Ngcq
-tfzcOXx3QlNPxQDF3oNHzi8GD7ysex1z7PRIsZlLVQLshAdOfA+naktPezj52R8V
-BtWaxgVFI7IA5X21reS25t01k/GXNcyIJxW5KSz00b1h8+mpz0n0R3Mz3HuZybAX
-g5bnZ+91jOeQmTt08eMXjwAGClxcOqfrssfDvOnUSZjDpzEGDaVuFGVPA9hR/eKN
-Bfo659rv45pYhtxoHLz1LJWoZ1uegmKrGF1w16K05k5mpzwH6fzqDzzbF1xyynGX
-yfbIqsvsBniuWGmhMjlfT5+l0VG2GgsD7Yijv6SV0YZrVf85iA5q6XdKTBuKYmin
-ZEbneEjw9kc9myMeC5ik7wHuksA/BQcja1TPwB4ZRbPEcfi2iFxbtsSzAgMBAAEw
-DQYJKoZIhvcNAQELBQADggIBAGdcqEI2l/dKxu9vPuRC2/VRgjgDBN4UJJCY111T
-2A7GsGzd7lRhtxB5ZzClF77UiRJG+cvFai00c9+L3wp8qy4sZWY4MaJIWoKRh72Q
-sRiH8AskeIl3uvvvaH86bbmpDo7M48Cs/zXZo9VhLzD8ZuHcS1mdjkOcnQzkbSzR
-YeM9ActeuJRmsdQ+gSzCTvFqmGutL6xvM8b9a6PwyY5nPxS+eh0/7KNp+EXBvp0U
-MWp6mMfq22nAwAQRLbvh5f+a/4GSwg73By6hwnsgb7tpBBJ6ppnKAIALRf7l5JwS
-V0LM5Vnpp4J4JjdYyQzk2xkxi+UGIP1IRigbeWc4K3qgg6BUUkfSf4W9oJD4JCa2
-cOsqnKqFxTwXT4b9j9qsPpg7mUQ2+UtU4Lv3h/7sXpbpx0ldb2Hnaq+JqUz0l/7c
-54y3+nzke7I4CWKtLJUSamQiyOC3CBVkRX0YEYUBhMXim6dKAfiOEV6K3bwiU+YZ
-aDe0lEeLbzAp87DKRTAvDYhRMIFtD3g2qmYrWpQ4gj8vSEorNAfg3kVHMFRGlk9o
-jaFduAz0hKk+QG5SgePXMph5ZRXGRq0FnDbF2gZ7WV+jZiIhsYGJ43+RBWHh4HO4
-P4h9eOWQG8AxpDRmOo2KmyPbV0V/eltC4N0oOAmWz+i0qqulnpG4dOzQKpinRBBr
-jPt5
+MIIFiDCCA3CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJDTDEL
+MAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQK
+DARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTAeFw0yNDA2MDgxOTE4
+NTFaFw0yNTA2MDgxOTE4NTFaMGoxCzAJBgNVBAYTAkNMMQswCQYDVQQIDAJSTTEa
+MBgGA1UEBwwRT3BlblRlbGVtZXRyeVRlc3QxDTALBgNVBAoMBFRlc3QxDzANBgNV
+BAsMBkNsaWVudDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAjTQGK0mcpE04z7FRBz2mYOeoIh7SToyII0cR8+6T3YEK
+R6SzZOLRXZ73/EucsQs0WxYEqXLgSlnxOBDQVttEwIi4VBxQnTc3T1itbZJeGnvf
+t108ntOX5czbFJMuey/4D5WPRFBFJfSgqRPq4h5zu9rm1eUXOCB6l6B+OK5Ev5/8
+OLHAXY/QqUNFPLYggUMom7OhnWqA0Z1HR504J4GkeEsIwI/asEclo1gS6WrV6VBh
+ZZFS7u//C52vw+jSZ+VAXLcgJ+9m6CPRdrhBh+yQ9hX2ZLb+TrUaPAsgtxrj6oB0
+uV62MYE7zNhNnrks6zwT8GDOu/rMSbII0bpF3L/M/fD57vpcbSu0t3TLgP2ZgV6L
+pwKesQmcl3m7G6mvhx1R9M5xlKkcOjcoxCMmCttkzyh49x7bVYZEm+mFV+WPkgoe
+CBg5eEbBxsVsIHkpU2GjnzIFMJlPpnwtDdgKKY/feQ88CLRlEF7+juJnjUS2tXmJ
+2tcGteugIi459PHw3ZcFaXPsheEXUa8zPkyPCbFYXLpYLpXZN8wIwzxlgtw62Owk
+ri6DA29F0rZy2N1Nf5R/mkVqN69ulZPxX9UYt5bCPYn4z2VKT46JpxsBTMV8TLbf
+RO8xOfLj3PARCGWHV4KmBC9fakLQmVsMKjlcoWN3m2oVLNAORlYdmo+I81JryasC
+AwEAAaNCMEAwHQYDVR0OBBYEFJUvzuLa8rgkuSbFYmQvj89kpe2QMB8GA1UdIwQY
+MBaAFAnipYlSco3heta4YnxM3hgg3tGyMA0GCSqGSIb3DQEBCwUAA4ICAQCIMXBi
+c0pTL0YAurUQUPtmU9GPLOxA2e0Uj4TjLY1hn4gUOHXcdxWsvL0B18z9AP74b/d6
+e57l944BDUXZsb0A9HqDR3HqVsCU9cEFmFEXcdx7kMCZzptRSWdUz/WRGChtjVIS
+0YhX6JNmAR6luNGarzt1brCNQi5BBJEo3OhH/WcuKXcWnCIcNCL7dTybXbu2d5aO
+d9wrAtZzmTtetlRAAia0jMmM/nAPYhN8cq5qkUdOsfnUyq09sfFh6JwmLAm9jT8T
+HLFY+44BpMB+4H4PluY22nSKg2DzlerxYsbcnGklEAG4bglNlVTiJ+d7hi0Vn1sx
+WxNzammg3b7RSEr7F2HXHztpx32QQO93igTHGXpb55yM2jt3eCivl3xynnPQMPhS
+ZZPv61zVeVXaqjJHX12AMP41PEjFvBlIB0PqsORDZv4+X5MOchRf5VepM4hd01LW
+9lTrX7oBSc0uzjDA5OyOZaqNDP06YfgezO0uF049cVbuGQ4NA+Iby6+nFILFgjcS
+50p29zV2mP2KJ4dLnFf3/6CPNUSGrY7SXh2rcTefs7oxvlBu6Jt+b+2XYIWl9+Iz
+Z/3dm5l5cEt9B4eogUb6HpFCfm3yba89wqUZK9o4O5WS/amx7MxPcQ4NPw5e+6EE
+If4hv5PmFbUJtzKCwwvtjg1eWRW0th/Il3ixgQ==
-----END CERTIFICATE-----
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.csr b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.csr
index b7838967259..190eb372ce1 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.csr
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.csr
@@ -2,27 +2,27 @@
MIIErzCCApcCAQAwajELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQH
DBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEVGVzdDEPMA0GA1UECwwGQ2xp
ZW50MRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
-ggIKAoICAQDXsElxp7glLD3Dp1z6u0lBUy2kjOtsdhZya82+q53vCmEOteZeg3dj
-ZuzK7bR1iVAUEuogwrBBpRfwFmDuWnVbmfl3/kvjaFjFz01LiWKvuVRHgEvDzCK4
-pLAPDaZ9IQDDUw63f3jV0OVuMy0DqlFpynLhND9TO4CN/631/fyV5GX1JpEBijkr
-2t6iRznBuwXO76myZ5BXmyMPO3toh8TZ1H+SKCZq1GjjHRYkMhwQaCck1Sd8KVH6
-+kNvndLCMnrPT1d9w2wfA8ihnTn2y4OGJirJwL58qQtKdl8PcgJx5UF9uzYHKrX8
-3Dl8d0JTT8UAxd6DR84vBg+8rHsdc+z0SLGZS1UC7IQHTnwPp2pLT3s4+dkfFQbV
-msYFRSOyAOV9ta3ktubdNZPxlzXMiCcVuSks9NG9YfPpqc9J9EdzM9x7mcmwF4OW
-52fvdYznkJk7dPHjF48ABgpcXDqn67LHw7zp1EmYw6cxBg2lbhRlTwPYUf3ijQX6
-Oufa7+OaWIbcaBy89SyVqGdbnoJiqxhdcNeitOZOZqc8B+n86g882xdccspxl8n2
-yKrL7AZ4rlhpoTI5X0+fpdFRthoLA+2Io7+kldGGa1X/OYgOaul3SkwbimJop2RG
-53hI8PZHPZsjHguYpO8B7pLAPwUHI2tUz8AeGUWzxHH4tohcW7bEswIDAQABoAAw
-DQYJKoZIhvcNAQELBQADggIBACboOarzimaArw3lDm6ET5yiU7NxTWtnWwFUOoSh
-qS2cvumnCokUlrDyMSSKoHl2i2biUd9uiHuEqlh0yufNgnTsyAXLg0UiBHAv5Tos
-Esc5A+JTV5ehy+Zrjpl3Ayh8difS8hJEBjMhH+7rCN3rhpvwkTSaXDCQTBzWPhQ1
-R0EIho/SNOh5mXQKAUWwhtleI0sEJC/PqezGfN+w+URHnzE7YMwg02bvoMxBEror
-YVddG4o0nIyd6CPg++K7TBzYGGOf1CUCrI9S1bBn3jcv2mq5YgZMdLEa0HkA9XzU
-J/dTSGz5pJbkoaX9IHv8a3uoc+V1jdNWZRmTUYG/cNoAFISoG+uuJLgesF5l+vxx
-GUwkE6wj4bNYR/Pqy5963oDmA3ndBzR1wtCZqIsLX3t3A9fLLtIEgeN/XDSvNDBs
-YdwBrx2HTatK7QCJ5e+4ACs6Wc2c1nnDviPddpxUgl0pHKcMbT+xNk7bY5fjl5Qr
-wzuBNgvQcsZxNNvI8bs13k/eBmKrKOV2WUP1mHRzSoxPX3gzGRSWCe/7QR51oWlB
-Qkb6OGVGLCKPnhIKFeZ6G1Qv8q7/hOOlmWGO4bN7s5fjAKEsm3JV1xrsqSKRofRG
-JfdPjQD88jewIAk6xGSMKmc4usQN+y/IfU8yZ57MHSHULccA1Wl/VXfgKCAxS5fK
-uXtm
+ggIKAoICAQCNNAYrSZykTTjPsVEHPaZg56giHtJOjIgjRxHz7pPdgQpHpLNk4tFd
+nvf8S5yxCzRbFgSpcuBKWfE4ENBW20TAiLhUHFCdNzdPWK1tkl4ae9+3XTye05fl
+zNsUky57L/gPlY9EUEUl9KCpE+riHnO72ubV5Rc4IHqXoH44rkS/n/w4scBdj9Cp
+Q0U8tiCBQyibs6GdaoDRnUdHnTgngaR4SwjAj9qwRyWjWBLpatXpUGFlkVLu7/8L
+na/D6NJn5UBctyAn72boI9F2uEGH7JD2FfZktv5OtRo8CyC3GuPqgHS5XrYxgTvM
+2E2euSzrPBPwYM67+sxJsgjRukXcv8z98Pnu+lxtK7S3dMuA/ZmBXounAp6xCZyX
+ebsbqa+HHVH0znGUqRw6NyjEIyYK22TPKHj3HttVhkSb6YVX5Y+SCh4IGDl4RsHG
+xWwgeSlTYaOfMgUwmU+mfC0N2Aopj995DzwItGUQXv6O4meNRLa1eYna1wa166Ai
+Ljn08fDdlwVpc+yF4RdRrzM+TI8JsVhculguldk3zAjDPGWC3DrY7CSuLoMDb0XS
+tnLY3U1/lH+aRWo3r26Vk/Ff1Ri3lsI9ifjPZUpPjomnGwFMxXxMtt9E7zE58uPc
+8BEIZYdXgqYEL19qQtCZWwwqOVyhY3ebahUs0A5GVh2aj4jzUmvJqwIDAQABoAAw
+DQYJKoZIhvcNAQELBQADggIBAGU0GhLOUGDMEnHNMebVO7hXewW2wc8pfMO/QwgV
+/KyqDe7FxZgmfGIw6lN8QMowSL5ZJx7S/lu5lHg3W+OgbRmXm8KocelLkVNXekRW
+qhgzPuWsrCBO+EoGvN5R3ZTW9uxWiI2XmfZmlBkWpl2ozPSjPL3muleU04nSza4k
+rUio6Qn3nwPEjjVrfeglO3B15wwkiEzyvA5sUdnJ2rHz5VvPjCUNQiGVwqZLLDP9
+9XLfImregy4/NKBN/M5RwF1HihdPOH5yeqBW+CF3WPvjatwlVwpduGdlhe2Kymu0
+wpys3mv/Y6cE6G9UmbUB14axhFhZ1DqrDLl7RvOOeezH94tCM8bG97nYgfJvkq9t
+Z1chPweaNugOBe/GAle0P8sxSMvVh2k3exeSCVyFguZKzmt6THciJ7ney3vkJP9w
+cnw5armWglVALEljMSZf5pNqBzvnXGxs0mHlH4KuJl01+fH/GMt6P/XMJ9vBVje/
+IqHexFtd9s8U7k885jkVCu+hTtEaOU71m5kGbfHX15Xbo5JSlX5L89PeZb4Xr5ts
+sSJ31F/RmNCbrNQbhXJ2Q/tS/ndxKU1F+rCXIxGMGRcJDjBJ7PB613URZN5Nl0TV
+NU356jMzURcAhRfdmN6GhTjM0cPz365hqywkHWryv20xrdLgGuYjxkNsU8DeQ7/R
+ZDny
-----END CERTIFICATE REQUEST-----
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.key b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.key
index 58414d8d59a..4ea34697a30 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.key
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+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
+rUDy/i3nw+6XSyDDV2kEJRodu+fA8Q==
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/regenerate.sh b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/regenerate.sh
index 84637be753d..cc052a4effe 100755
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/regenerate.sh
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/regenerate.sh
@@ -1,10 +1,9 @@
#!/usr/bin/env sh
#
-# Usage: regenerate.sh
+# Regenerate certificates that are used for tests using TLS.
+# Certs are generated with a one year expiry, so periodic regen is required.
#
-# regenerate.sh regenerates certificates that are used to test gRPC with TLS
-# Make sure you run it in test/certs directory.
-# It also serves as a documentation on how existing certificates were generated.
+# Usage: npm run maint:regenerate-test-certs
rm ca.crt ca.key client.crt client.csr client.key server.crt server.csr server.key
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.crt b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.crt
index ace156a29ee..e4e85c42df3 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.crt
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.crt
@@ -1,31 +1,32 @@
-----BEGIN CERTIFICATE-----
-MIIFPzCCAycCAQEwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNV
-BAgMAlJNMRowGAYDVQQHDBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9v
-dDENMAsGA1UECwwEVGVzdDELMAkGA1UEAwwCY2EwHhcNMjMwNjA4MTY0NDI0WhcN
-MjQwNjA3MTY0NDI0WjBqMQswCQYDVQQGEwJDTDELMAkGA1UECAwCUk0xGjAYBgNV
-BAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQKDARUZXN0MQ8wDQYDVQQLDAZT
-ZXJ2ZXIxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBAKtVnxPqCZheCuqePfLknxc+6MeyYkf494U8WWeZo+yirYV3zY70
-1KhKZ+M+XDqhrBXc7IQHZd2KKxYBGnrv9yvbllmtZRdnk3hnn8B4eNh3w5gCRKPo
-GSTeiNN7WEIRwYZNkr8AWgeoYT1jN8SAMn5+qSqKSd62Z1BPJNi0eQmTVxgLZqzx
-92AWBZQl9rOme+1zV6ohKcR22Of3yUl6476L1rYYcX0DXp0QFkhK0TFKNt3cHxqq
-WTRuMTnyCj7woWRtwclWTdO2buAkJe8cIde6rcbaUAX9jTdkbAgYAB9MctEKqasO
-MqFyMzweS3sG9oUnmd0/GRL9as314xTZuz8fFnfj5l0BN6thVMmvEEYU3rTLQRKf
-AKWzI2VrU+5wIxN8O/4ZbriQ5ae13p6TDYilSZ6kMxSzfOM/A00hlA+DKMS0o8g8
-V9Y3wcl3aSSjoZbH7XS/uDEueodudz9V3HxCk7Wc41SpunQPFprmPDWtjiW0jcMD
-3kHV819r2F8aidKN94Q+3KI+N/mwn1QdDVsquiCq0wbR54i3CoAkQbi5YeUdEZD6
-/mNLs/BABgzSbANw7Fn1Pd9gY/JIsRhMskcFRqXe9tOqKk8/GxMv/r9MgJn6HHlk
-iDa3OZsoOtFbjjOPFoy/Xq9YMi4ODnJkEhe7BSsVl/wkDAUdg7Zfu8XVAgMBAAEw
-DQYJKoZIhvcNAQELBQADggIBAEft+R+qGyKffiiJpYWLPn0C9SmpjZiWPK331n57
-Nk3GA8u9gRgD1gyqqLr19r86nLArF8jcB/nChPB1A9ysW3xyTNvpOlAwYvEjxWR2
-tJr8wiDucAd+SnQud6e+5PI5e8LnyxYoeoZ+i6hMbhNV70NthoINHMAQx+5NeSpa
-Q0GJ4d0XA3W/8Pu6oK7O0QkVovVut73Koz5DqsF91zFJp7SjVKaCnnjRKyU8wbg5
-uTO0TRheEtx3AeEXNps5Yhq0daLTnmnuFeyaJHm2F1QuBmma1TTwIF3HDclv2wLn
-Jp+MWG9yoN9oEJLqS/AvDu1BltPSuvnYgLZr7cl0os+TEqpzxroa4ziE98dEiy0D
-K4YQ59UTz6C8Ps0uX0hcs3jsvZOkBWptusvJBfZN59xLJAVmF2igkgIBKoiXvXmv
-fXDx0hsOBg2IPe2O8lLHlFKlJZlMc+prH1iD0Xv6HefSP4L1eZHU37zjrRf/GiNX
-r6GoEhJR2pKEoZQT81xpYp/w+qjzWcTl/mLD6FEePRzV92h3ubjRWBB36UhLtnEG
-LJgp7yq3aGu7rg9rnuz8J6DG8DStE9rNuRjkV1O2C/PvR97XmVoIqbrMlxX9MUQJ
-XxLm5dqBz7EVuhDJSyp4zCkDYsOj1y/SLL2O3cTyQQeZg6jlqripNqWnviAdTWe5
-JIPp
+MIIFiDCCA3CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJDTDEL
+MAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQK
+DARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTAeFw0yNDA2MDgxOTE4
+NTFaFw0yNTA2MDgxOTE4NTFaMGoxCzAJBgNVBAYTAkNMMQswCQYDVQQIDAJSTTEa
+MBgGA1UEBwwRT3BlblRlbGVtZXRyeVRlc3QxDTALBgNVBAoMBFRlc3QxDzANBgNV
+BAsMBlNlcnZlcjESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAsrgR40g2ius4P7h5mO6/2r9uD903m672EHRkYXKKKViV
+wMS/7kgNo8vbenmmO0Ra3Rk3J80M4HhWJsI5bWvjLtbLkG6CkiK0yCpSbsK+F13B
+oDvCeVEYaLz2IV2e/61l5y73Q5s6Iu2OTckIvGZr/jsCBJ+9457uuMd4Mvzi1jLo
+PmVYJZYG/8I2dIjrtxqm/gAiBjbrZ5Nmm702GArvm85VWL8o3b0C+9YXI8PHHGT9
+CYqBjKobDdM0lrZdBiy5JEwSI1L0MCGzcmEVCJIuHe9b66GUVWrAsvOKrBMkziSm
+BKjvAzDIsiRIS0Z2jiXpRwUhjpAphJDtsePGXvbSzvt4mUNUvSsnS4ImKURkDLVB
+BndzJMUX0/fJG2fh0cVmT0V6+otqpPTrf89i3dsSG9gBHVlp4u1p7krQ8KgZ0Fpw
+wbo+p41KrChQ8iwE4eEgcI2joQrC2ccpQzxyn/quH604gadtBTEw+NrCu8NB5hso
+hMGJV1jMJ0wENkRY0WjD51y87ieUhMQwUnM7Yi7CLq3SJA9N0KHbtg4U+42d63pH
+HmMwUw2cG7tVKJR/quZxwibqkA7mkUYp/pyILt6m1IOAwK5SgomMGCsstXSFXisR
+fCCNTEkQMvuylC3TsV6THPb6zJvhntIkLGbSFzxfLeGP5x0KhqWt76W//BnKfXsC
+AwEAAaNCMEAwHQYDVR0OBBYEFLNHcwOHiVPwk8X3kZnMBz/rezOiMB8GA1UdIwQY
+MBaAFAnipYlSco3heta4YnxM3hgg3tGyMA0GCSqGSIb3DQEBCwUAA4ICAQCqWBJL
++hOWGK4IUXXUodvHcctiXU6ktUP4ki8Ml0c1UWnRZECuBU/tlCiasgQlGc0eld/H
+q9h0zK3gUDoLXYb6uPuFUmhtJYY6ydIBR7XqCCTgBMfJ6gwxH2ybC/BTyp1cE9o1
+hMkaD+/r3JRGX0G5FPYRhfF5JDSGVAiWWFD1udPH4+UidjFAXTyi0bn5BsY5Aze9
+xVWvOMYNLxiaZEklfTGGgY7xbTECow+XR7ThguzL1Wg9GBJEAYWvfbdb+RKB5bqs
+ggKRTg21VWapTeSbfnjhvyrRN2FamGxeW1lqb8Ts1yyKiqtkj/cy2tIheEGAPt/a
+wWgFKAuSRN0YtSW8D8oOmY+4+ULDl0um/dhJ31/nF0qOgopHUozJXDj71GsNrokh
+3TmYYnuyZdAAyVFwNffXWingfqNOs2ozf/efBTLLAb094QOnpdit9pYPqE5ar72Y
+JdGACna1Mxz5PDa6Z7eQB7s7h/Q47JFXIOI4TdguKGYiDT0XXfEq6lKbvVYkheQ/
+kutiMFQQCwwv/LxRhjTeeFEnASyWgRhhvuTg0ndOqpCtgUJ8mEZ4c9RB+QA7XeOe
+FKx9QMLJRAOMNE2WoSPhgaJrf6glSKOvR6CuH/v1ekE3pJpVZGk+3GOs3H8k92Vv
+pV9S89yNX95tLzlOR/nKWLrX6n27fjE2BBXeBg==
-----END CERTIFICATE-----
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.csr b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.csr
index b421a7a60c9..642fbae3c42 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.csr
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.csr
@@ -2,27 +2,27 @@
MIIErzCCApcCAQAwajELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQH
DBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEVGVzdDEPMA0GA1UECwwGU2Vy
dmVyMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
-ggIKAoICAQCrVZ8T6gmYXgrqnj3y5J8XPujHsmJH+PeFPFlnmaPsoq2Fd82O9NSo
-SmfjPlw6oawV3OyEB2XdiisWARp67/cr25ZZrWUXZ5N4Z5/AeHjYd8OYAkSj6Bkk
-3ojTe1hCEcGGTZK/AFoHqGE9YzfEgDJ+fqkqiknetmdQTyTYtHkJk1cYC2as8fdg
-FgWUJfazpnvtc1eqISnEdtjn98lJeuO+i9a2GHF9A16dEBZIStExSjbd3B8aqlk0
-bjE58go+8KFkbcHJVk3Ttm7gJCXvHCHXuq3G2lAF/Y03ZGwIGAAfTHLRCqmrDjKh
-cjM8Hkt7BvaFJ5ndPxkS/WrN9eMU2bs/HxZ34+ZdATerYVTJrxBGFN60y0ESnwCl
-syNla1PucCMTfDv+GW64kOWntd6ekw2IpUmepDMUs3zjPwNNIZQPgyjEtKPIPFfW
-N8HJd2kko6GWx+10v7gxLnqHbnc/Vdx8QpO1nONUqbp0Dxaa5jw1rY4ltI3DA95B
-1fNfa9hfGonSjfeEPtyiPjf5sJ9UHQ1bKrogqtMG0eeItwqAJEG4uWHlHRGQ+v5j
-S7PwQAYM0mwDcOxZ9T3fYGPySLEYTLJHBUal3vbTqipPPxsTL/6/TICZ+hx5ZIg2
-tzmbKDrRW44zjxaMv16vWDIuDg5yZBIXuwUrFZf8JAwFHYO2X7vF1QIDAQABoAAw
-DQYJKoZIhvcNAQELBQADggIBAJCMEdjKyklN2izvOhd7+JMXm/ClW3hjowbu+csO
-JNz8NqUNLrKJjFyV3yAUGWuyp3z982S+XGfcm3nU7n9AJOjT4DLJId6opOtA6CSp
-KTRgVZmeViL6O6UqBLTacz5DDjwMQXxszc+QpU53cMT6Y7VMvIOhQ6AmIvz1v71u
-5gaYmlbfXVlmiPHEKRsQG9/DNIPe1mHP0p+S9qYKmCx7Jlpee7IstW/hNjt7alDn
-uFaxFjxmCCSdWaMRyMW/qNRks9q3VdhJPan+amFeXceoEG7SOKiFiOc8A7DribSm
-iKc2YlOw14xqc+cJutiKBvoBMri2eh1JgCbPT4ufVGFpbDkfYwAJxWx44Eg0X90j
-gJUw8IRuHQZkEYss6jwFMFcOqjpe+AqrssOl4GZmu5gcaiUnj8PkSVZLTOrLilPg
-sSDjzmoHdv4QcBppTrjj6PyR5Xd6DeGasWkMPvIPjiPN3mOhfxJ3C87atMqOhTLx
-em7vFOBegAW6g40J9JD1XMoI/zFnTU8NevZQgCyx/Tq1XNRmUeMA6y/qpfTNKi/f
-F7v/7nDWoxBgpOw3J0E9R+6rxD7Cjb2RWZEf20ZGdNBlPE+UG9c9b3HC3IHiwRHb
-L9Fi0251w+fkaPX8dojQKErCEknqJ1SCP5S5F5g1QCQby22Y7LQsggMMf94s/wQX
-4uMh
+ggIKAoICAQCyuBHjSDaK6zg/uHmY7r/av24P3TebrvYQdGRhcoopWJXAxL/uSA2j
+y9t6eaY7RFrdGTcnzQzgeFYmwjlta+Mu1suQboKSIrTIKlJuwr4XXcGgO8J5URho
+vPYhXZ7/rWXnLvdDmzoi7Y5NyQi8Zmv+OwIEn73jnu64x3gy/OLWMug+ZVgllgb/
+wjZ0iOu3Gqb+ACIGNutnk2abvTYYCu+bzlVYvyjdvQL71hcjw8ccZP0JioGMqhsN
+0zSWtl0GLLkkTBIjUvQwIbNyYRUIki4d71vroZRVasCy84qsEyTOJKYEqO8DMMiy
+JEhLRnaOJelHBSGOkCmEkO2x48Ze9tLO+3iZQ1S9KydLgiYpRGQMtUEGd3MkxRfT
+98kbZ+HRxWZPRXr6i2qk9Ot/z2Ld2xIb2AEdWWni7WnuStDwqBnQWnDBuj6njUqs
+KFDyLATh4SBwjaOhCsLZxylDPHKf+q4frTiBp20FMTD42sK7w0HmGyiEwYlXWMwn
+TAQ2RFjRaMPnXLzuJ5SExDBScztiLsIurdIkD03Qodu2DhT7jZ3rekceYzBTDZwb
+u1UolH+q5nHCJuqQDuaRRin+nIgu3qbUg4DArlKCiYwYKyy1dIVeKxF8II1MSRAy
++7KULdOxXpMc9vrMm+Ge0iQsZtIXPF8t4Y/nHQqGpa3vpb/8Gcp9ewIDAQABoAAw
+DQYJKoZIhvcNAQELBQADggIBAAvxaoCgCOM5mVOAFeLQoKGTORIWoT73yKeebLu8
+Ie26lrOZyItFneYCnyFocYb20mriC+C30lUgNM66mHWLW0QSDPhI0VeBMDRHYPMo
+S5EWkQNy0VQ1HZV/DITXqEBld0WdmBl71D7gOlZvDHHnrb5emOKOVP/7poitywC1
+NA/Ry0TJYAz1z9uu5GLmMNJwfkRAPVYJnzMTMQ6G8z2tUKTTDKbJvkkJ1tmjBToD
+/8JeXmxH0a0NuwC7QLDzR1Jl4XWj3uIAHUtcsHMFjOc3nAin3L7FGD7CaXTyz/Hw
+J7GkeIMGSYs+i+09l9dMLSrlIsh2sphV768dKajqA11C6nGOeEkJFziY+l9KNy9B
+MkW74Vj2SyN0l8Cn2X282UakAxQ0kCwpBQYSO+M6q2gVLhwTwmDUCpfuo03dOGrn
+kHPDYQUahTLfKNEe6seXHomGUxTpMnr5p3ftMOrc4uCWY1DkhEviw9Jea666gG/e
+5yiYcN4vSmru4GpmOV5N28GNC8oAgm7rPpPgXeiVET+p3wms8cZ8/Htpkxn2nTcc
+3tBvAYt8qql9Wt/2R4ewo39bzg4dPzl9AUWeQRpA6O0n6ZhtHhCzDSik5Tam9fh8
+lxTldG69Enm4+amCLja/YYRmaEE9KYM3jxSi6k+Xh2L+vI8WlwbkZKnYs9suDW22
+eoJ+
-----END CERTIFICATE REQUEST-----
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.key b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.key
index 80b9cea7bf3..1801be40223 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.key
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.key
@@ -1,51 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQCyuBHjSDaK6zg/
+uHmY7r/av24P3TebrvYQdGRhcoopWJXAxL/uSA2jy9t6eaY7RFrdGTcnzQzgeFYm
+wjlta+Mu1suQboKSIrTIKlJuwr4XXcGgO8J5URhovPYhXZ7/rWXnLvdDmzoi7Y5N
+yQi8Zmv+OwIEn73jnu64x3gy/OLWMug+ZVgllgb/wjZ0iOu3Gqb+ACIGNutnk2ab
+vTYYCu+bzlVYvyjdvQL71hcjw8ccZP0JioGMqhsN0zSWtl0GLLkkTBIjUvQwIbNy
+YRUIki4d71vroZRVasCy84qsEyTOJKYEqO8DMMiyJEhLRnaOJelHBSGOkCmEkO2x
+48Ze9tLO+3iZQ1S9KydLgiYpRGQMtUEGd3MkxRfT98kbZ+HRxWZPRXr6i2qk9Ot/
+z2Ld2xIb2AEdWWni7WnuStDwqBnQWnDBuj6njUqsKFDyLATh4SBwjaOhCsLZxylD
+PHKf+q4frTiBp20FMTD42sK7w0HmGyiEwYlXWMwnTAQ2RFjRaMPnXLzuJ5SExDBS
+cztiLsIurdIkD03Qodu2DhT7jZ3rekceYzBTDZwbu1UolH+q5nHCJuqQDuaRRin+
+nIgu3qbUg4DArlKCiYwYKyy1dIVeKxF8II1MSRAy+7KULdOxXpMc9vrMm+Ge0iQs
+ZtIXPF8t4Y/nHQqGpa3vpb/8Gcp9ewIDAQABAoICAAd1zuvkGcA19AtF+00TYqAv
+SZNc89knansXFcv40vuyNv24e7Tm8s4VPxIcaZepejSbJXGT1ZjoPQo3PH9EIGth
+tJxzr8Jx+UCLZv3y5fAxfJMmT9I0VBVJW3VmdaZS21WbA9/y5vvzFUUcyCT7VEBw
+qDlojXOD6wPCw9JlaTD8+XlL2ZqzUpNhWFhN+fTv99Sk8FJKLfVS1W4qYhz/FgzL
++nP3mVv4jqECd63PMbs87TkYPCcp+nJ9yl4kAF5Z19hyoEh5SiD8CVWfohgXLgcu
+3XExb83sExecgB6c/Q2Mkrj+nqMqUkoApub93zjy/YswtoFidfzYgv0C8RhPcZTJ
+Iw7RzhDcYMyAVg3izcfhMAVPMLx0LbyXw5Fyj4K8Ec+soWPScseAfGaOtmodB8mn
+XLTdfIpgJJKI5T58C5uXveotYJEcTMjJSoELTI+KrMgwhtaYeHyPINSDrgaCpzfl
+ATxcPbFgdzINg/e12GkYRsXnzWe1zeYkv0gh3zsUV5N4lBYvOSqJ/O3CuqgTucWO
+mjT5AdoWqGmuT7teUmK/ce6SEsH5f+wz1H51OcP1H659fKsdx/NE7NsItF9K7mTr
+D1OTUcUwzih5eDIHfb6cIs6BSo8xC7ux0NVpbChKoUOgmCNS/BDAn67Z1pD8ScOG
+1DmczC+YEwlVGZdXmfFNAoIBAQDu1eWPXIWwIffYkOeHTHP9D9uxUmGpSR0exXWU
+M+hVrzH6rLwIy4LjmzlFvo9Nvu8yjPzQDgDfY+hC8AZy0oNZVGEhULblESjfR3Qa
+SYC1usJuXF5E0xh+k4RRTZST+2Q/CDsnmE+8qQvPRv/sB4JJpzSadfjQi7k574QD
+uZt6iyZSMVqZ7vHKg9bBipVNF6ZiFwt9AhZ9VMUvi5pH7sQwdNAbRT4QLDfrKmkc
+K6HTALpH3ej6SfCxldrzDJ3SUYEyBus113tT/MdivkAvyTajhNKYSWYyhu0+296m
+fq1b5Hw6pGCho+J35thCJsIEb6y7bZ4xgH3aH8dSmxf2RmMNAoIBAQC/kCXVmbM2
+ja+I90JUlXWAyCfbhfmD6Hg4/TSCO2Qx488mw3dDdJS5CkzxAXi+chbIIyxqaiZL
+Wym886Iax1zAloi9l+801NYBbUiPnVA35MNxHkvTW3kyRLcMbM4wSEhVfjaL45S5
+7wNoRLW+8i3AQa8oO7v67PwCvspDGPgHwhshNP3z0XwIwob/fu7MLs70cLYbc3NZ
+k8jhxfNimxdptehZLIs+kYz0CBR+t6unHbba6bM3ZCGSjhg1yU4EkNrxW1YELWmk
+X+9BCsNxrqGko4h8XK1lNnNFhzf8kyPY0Vaa88BTo86r/p72Ezmx0sJhmb0R1wvq
+BieY8HRc52CnAoIBAAinubz7RmD+qiOwBKPzklR+aaDAcoeW/bYqw7sOMoJAahhC
+gEH1VhX3fxjW8gyIOdTkJRlJGKD/1t/uIN2yYU4wb6CscyRT/d4xkbSOK1rqnLcx
+I71sxPt5Txc/L345YwWhv7sMmv8kRShK02VzVDZlF9PtKIouNhUyZ99Wr5q+RjI+
+VaE0dpC3PGYhJo33qHDvktwB4lzCYK77aSjoLzXuVchXNwuQ/qnIDK0Xq7Kg2R9X
+nGTNnypgWuHp+CIyD/OHKqj12SNPCs66REs3CILegl9AcbKtDxXzE9uGxbOJ0TKy
+2EmjTca4l+e1zdwpS+Iy88Ope2YXNrr4oeKr5FUCggEAZ5ZcTzApD/P4GvmR/clA
+XB5gJz5AWgsoj7CkZ1QUb0IAL7b9VBXDongmeSDRmTJ6jUkv6G90O8WVQV8Bprdt
+uZrtYJC7QndhLi5ZUYfA7CihYxb969IILJ2p2mcv7D36F3kDqAutzgmobwbQvOua
+v98FB52dnifuctGW8EedQBy/rOpJ9UGvb9E5TQnnubQKJ3aXkyqQEr1uoF/5p7W0
+KG68sRP8TB5K+V8xLgDGKr1Ptvsu9WIJIYYDI3qy3Jc0PdWlIucnvEJAT4yxeVT0
+heIEmTNIdHXISa3AIa2zcbhpu6rZsqDeznUGooxs43LTuBF5gx8liyw+114XnnFj
++wKCAQBvYIspfu+hjHpR67Tv8NLAzH9pWcbpKJ66YYW5IaD3kytsML9C+x7NiuGy
+U2Svxfdin3otbG/TEPH+d5e5t23lWZEBmuQucjhpRZj7J8zzImdjCtYMekYHIepD
+1XMKAQdYqx251Gux2FHmYD8hbJbUJLrfuSyFksxvqDdkidQiKMfRDNS1IElkcRRz
+bhJUPzJ9XRJIlkIzZCQ8XgZWDyiSA0Gpq+jwZfqmn8v4ol1cmK9EEAFZ9cewvSdq
+YIxr/IvWouwSqVkn0p33g080Uv+Rc871XtnxMcdVFExVE2cPZFY7v8yWqpo7PNU+
+HvjeIanEQir29p2epOg8Epxewjc9
+-----END PRIVATE KEY-----
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json
index def89129d9b..edc3abfa075 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json
@@ -24,6 +24,9 @@
{
"path": "../opentelemetry-exporter-metrics-otlp-http"
},
+ {
+ "path": "../otlp-exporter-base"
+ },
{
"path": "../otlp-grpc-exporter-base"
},
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md
index ba449280b02..6458aaab672 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md
@@ -109,7 +109,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[npm-url-grpc]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-grpc
[npm-url-proto]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-proto
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-metrics-otlp-http.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
-[opentelemetry-spec-protocol-exporter]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options
[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/exporter-trace-otlp-http
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json
index 7ba023ad649..c5b6a144d9e 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-metrics-otlp-http",
- "version": "0.49.1",
+ "version": "0.52.1",
"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",
@@ -22,14 +22,15 @@
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.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",
"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 ../../../"
+ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -63,30 +64,28 @@
"access": "public"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
@@ -96,11 +95,11 @@
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/otlp-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-metrics": "1.22.0"
+ "@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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-http",
"sideEffects": false
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterBase.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterBase.ts
index 66a5bfb5963..76b7f74dfda 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterBase.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterBase.ts
@@ -29,7 +29,6 @@ import {
OTLPMetricExporterOptions,
} from './OTLPMetricExporterOptions';
import { OTLPExporterBase } from '@opentelemetry/otlp-exporter-base';
-import { IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer';
import { diag } from '@opentelemetry/api';
export const CumulativeTemporalitySelector: AggregationTemporalitySelector =
@@ -41,6 +40,7 @@ export const DeltaTemporalitySelector: AggregationTemporalitySelector = (
switch (instrumentType) {
case InstrumentType.COUNTER:
case InstrumentType.OBSERVABLE_COUNTER:
+ case InstrumentType.GAUGE:
case InstrumentType.HISTOGRAM:
case InstrumentType.OBSERVABLE_GAUGE:
return AggregationTemporality.DELTA;
@@ -57,6 +57,7 @@ export const LowMemoryTemporalitySelector: AggregationTemporalitySelector = (
case InstrumentType.COUNTER:
case InstrumentType.HISTOGRAM:
return AggregationTemporality.DELTA;
+ case InstrumentType.GAUGE:
case InstrumentType.UP_DOWN_COUNTER:
case InstrumentType.OBSERVABLE_UP_DOWN_COUNTER:
case InstrumentType.OBSERVABLE_COUNTER:
@@ -117,11 +118,7 @@ function chooseAggregationSelector(
}
export class OTLPMetricExporterBase<
- T extends OTLPExporterBase<
- OTLPMetricExporterOptions,
- ResourceMetrics,
- IExportMetricsServiceRequest
- >,
+ T extends OTLPExporterBase,
> implements PushMetricExporter
{
public _otlpExporter: T;
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts
index cff7a6ec002..0fa43efa784 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts
@@ -25,8 +25,8 @@ import {
appendRootPathToUrlIfNeeded,
} from '@opentelemetry/otlp-exporter-base';
import {
- createExportMetricsServiceRequest,
- IExportMetricsServiceRequest,
+ IExportMetricsServiceResponse,
+ JsonMetricsSerializer,
} from '@opentelemetry/otlp-transformer';
const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/metrics';
@@ -34,35 +34,39 @@ const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURC
class OTLPExporterBrowserProxy extends OTLPExporterBrowserBase<
ResourceMetrics,
- IExportMetricsServiceRequest
+ IExportMetricsServiceResponse
> {
constructor(config?: OTLPMetricExporterOptions & OTLPExporterConfigBase) {
- super(config);
+ super(config, JsonMetricsSerializer, 'application/json');
+ const env = getEnv();
this._headers = Object.assign(
this._headers,
baggageUtils.parseKeyPairsIntoRecord(
- getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS
+ env.OTEL_EXPORTER_OTLP_METRICS_HEADERS
)
);
}
getDefaultUrl(config: OTLPExporterConfigBase): string {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(
- getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
- )
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
- }
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(
+ env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
+ );
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
- convert(metrics: ResourceMetrics[]): IExportMetricsServiceRequest {
- return createExportMetricsServiceRequest(metrics, { useLongBits: false });
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts
index cd648ce8753..bf57b807dc3 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts
@@ -23,10 +23,11 @@ import {
OTLPExporterNodeConfigBase,
appendResourcePathToUrl,
appendRootPathToUrlIfNeeded,
+ parseHeaders,
} from '@opentelemetry/otlp-exporter-base';
import {
- createExportMetricsServiceRequest,
- IExportMetricsServiceRequest,
+ IExportMetricsServiceResponse,
+ JsonMetricsSerializer,
} from '@opentelemetry/otlp-transformer';
import { VERSION } from '../../version';
@@ -38,37 +39,39 @@ const USER_AGENT = {
class OTLPExporterNodeProxy extends OTLPExporterNodeBase<
ResourceMetrics,
- IExportMetricsServiceRequest
+ IExportMetricsServiceResponse
> {
constructor(config?: OTLPExporterNodeConfigBase & OTLPMetricExporterOptions) {
- super(config);
- this.headers = {
- ...this.headers,
- ...USER_AGENT,
+ super(config, JsonMetricsSerializer, {
...baggageUtils.parseKeyPairsIntoRecord(
getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS
),
- ...config?.headers,
- };
- }
-
- convert(metrics: ResourceMetrics[]): IExportMetricsServiceRequest {
- return createExportMetricsServiceRequest(metrics, { useLongBits: false });
+ ...parseHeaders(config?.headers),
+ ...USER_AGENT,
+ 'Content-Type': 'application/json',
+ });
}
getDefaultUrl(config: OTLPExporterNodeConfigBase): string {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(
- getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
- )
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
+
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(
+ env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
+ );
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
+
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts
index cc112a9b55a..1cdccbdbd82 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts
@@ -238,7 +238,10 @@ describe('OTLPMetricExporter - web', () => {
assert.strictEqual(request.url, 'http://foo.bar.com');
const body = request.requestBody;
- const json = JSON.parse(body) as IExportMetricsServiceRequest;
+ const decoder = new TextDecoder();
+ const json = JSON.parse(
+ decoder.decode(body)
+ ) as IExportMetricsServiceRequest;
// The order of the metrics is not guaranteed.
const counterIndex = metrics.scopeMetrics[0].metrics.findIndex(
it => it.descriptor.name === 'int-counter'
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/CollectorMetricExporter.test.ts
index 963328da75d..e4ae9f3926b 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/CollectorMetricExporter.test.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/CollectorMetricExporter.test.ts
@@ -29,14 +29,12 @@ import {
OTLPExporterBase,
OTLPExporterConfigBase,
} from '@opentelemetry/otlp-exporter-base';
-import { IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer';
type CollectorExporterConfig = OTLPExporterConfigBase;
class OTLPMetricExporter extends OTLPExporterBase<
CollectorExporterConfig,
- ResourceMetrics,
- IExportMetricsServiceRequest
+ ResourceMetrics
> {
onInit() {}
@@ -47,10 +45,6 @@ class OTLPMetricExporter extends OTLPExporterBase<
getDefaultUrl(config: CollectorExporterConfig) {
return config.url || '';
}
-
- convert(metrics: ResourceMetrics[]): IExportMetricsServiceRequest {
- return { resourceMetrics: [] };
- }
}
describe('OTLPMetricExporter - common', () => {
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts
index b72ed5f8cb8..7b19b84f029 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts
@@ -74,6 +74,9 @@ describe('OTLPMetricExporter - node with json over http', () => {
afterEach(async () => {
fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
await shutdown();
sinon.restore();
});
@@ -337,38 +340,62 @@ describe('OTLPMetricExporter - node with json over http', () => {
});
it('should use headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar';
- const collectorExporter = new OTLPMetricExporter();
- assert.strictEqual(collectorExporter._otlpExporter.headers.foo, 'bar');
+ const exporter = new OTLPMetricExporter();
+ assert.strictEqual(
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['foo'],
+ 'bar'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should include user agent in header', () => {
- const collectorExporter = new OTLPMetricExporter();
+ const exporter = new OTLPMetricExporter();
assert.strictEqual(
- collectorExporter._otlpExporter.headers['User-Agent'],
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['User-Agent'],
`OTel-OTLP-Exporter-JavaScript/${VERSION}`
);
});
it('should override global headers config with signal headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'foo=boo';
- const collectorExporter = new OTLPMetricExporter();
- assert.strictEqual(collectorExporter._otlpExporter.headers.foo, 'boo');
- assert.strictEqual(collectorExporter._otlpExporter.headers.bar, 'foo');
+ const exporter = new OTLPMetricExporter();
+ assert.strictEqual(
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['foo'],
+ 'boo'
+ );
+ assert.strictEqual(
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = '';
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should override headers defined via env with headers defined in constructor', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
- const collectorExporter = new OTLPMetricExporter({
+ const exporter = new OTLPMetricExporter({
headers: {
foo: 'constructor',
},
});
assert.strictEqual(
- collectorExporter._otlpExporter.headers.foo,
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['foo'],
'constructor'
);
- assert.strictEqual(collectorExporter._otlpExporter.headers.bar, 'foo');
+ assert.strictEqual(
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should use delta temporality defined via env', () => {
@@ -468,11 +495,13 @@ describe('OTLPMetricExporter - node with json over http', () => {
collectorExporter.export(metrics, () => {});
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
const options = args[0];
assert.strictEqual(options.hostname, 'foo.bar.com');
@@ -486,11 +515,14 @@ describe('OTLPMetricExporter - node with json over http', () => {
collectorExporter.export(metrics, () => {});
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
+
const options = args[0];
assert.strictEqual(options.headers['foo'], 'bar');
done();
@@ -501,11 +533,14 @@ describe('OTLPMetricExporter - node with json over http', () => {
collectorExporter.export(metrics, () => {});
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
const options = args[0];
const agent = options.agent;
assert.strictEqual(agent.keepAlive, true);
@@ -584,7 +619,7 @@ describe('OTLPMetricExporter - node with json over http', () => {
const callback = args[1];
callback(mockRes);
- mockRes.send('success');
+ mockRes.send(Buffer.from('success'));
});
it('should log the successful message', done => {
@@ -595,11 +630,15 @@ describe('OTLPMetricExporter - node with json over http', () => {
collectorExporter.export(metrics, responseSpy);
setTimeout(() => {
- const mockRes = new MockedResponse(200);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('success');
+
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ callback(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
+
setTimeout(() => {
assert.strictEqual(stubLoggerError.args.length, 0);
assert.strictEqual(
@@ -619,18 +658,20 @@ describe('OTLPMetricExporter - node with json over http', () => {
collectorExporter.export(metrics, responseSpy);
setTimeout(() => {
- const mockRes = new MockedResponse(400);
const args = stubRequest.args[0];
const callback = args[1];
- callback(mockRes);
- mockRes.send('failed');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(400);
+ callback(mockRes);
+ mockRes.send(Buffer.from('failure'));
+ });
+
setTimeout(() => {
const result = responseSpy.args[0][0] as core.ExportResult;
assert.strictEqual(result.code, core.ExportResultCode.FAILED);
const error = result.error as OTLPExporterError;
assert.ok(error !== undefined);
assert.strictEqual(error.code, 400);
- assert.strictEqual(error.data, 'failed');
done();
});
});
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/nodeHelpers.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/nodeHelpers.ts
index d2dce6517b2..e63d21b17c9 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/nodeHelpers.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/nodeHelpers.ts
@@ -24,7 +24,7 @@ export class MockedResponse extends Stream {
super();
}
- send(data: string) {
+ send(data: Uint8Array) {
this.emit('data', data);
this.emit('end');
}
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md
index 0056d2f3ca7..e1b3c9941a5 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md
@@ -75,6 +75,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-proto
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-metrics-otlp-proto.svg
-[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/exporter-trace-otlp-http
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json
index c273810cf7a..53d0feac224 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-metrics-otlp-proto",
- "version": "0.49.1",
+ "version": "0.52.1",
"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",
@@ -14,13 +14,14 @@
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
"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",
"prewatch": "npm run precompile",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
- "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../"
+ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -55,32 +56,29 @@
"access": "public"
},
"devDependencies": {
- "@opentelemetry/api": "1.8.0",
- "@types/mocha": "10.0.6",
+ "@opentelemetry/api": "1.9.0",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"codecov": "3.8.3",
- "cpx": "1.5.0",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/exporter-metrics-otlp-http": "0.49.1",
- "@opentelemetry/otlp-exporter-base": "0.49.1",
- "@opentelemetry/otlp-proto-exporter-base": "0.49.1",
- "@opentelemetry/otlp-transformer": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-metrics": "1.22.0"
+ "@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"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-proto",
"sideEffects": false
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts
index 52c9991e30a..4834c5a698f 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts
@@ -15,10 +15,6 @@
*/
import { OTLPMetricExporterOptions } from '@opentelemetry/exporter-metrics-otlp-http';
-import {
- ServiceClientType,
- OTLPProtoExporterNodeBase,
-} from '@opentelemetry/otlp-proto-exporter-base';
import { getEnv, baggageUtils } from '@opentelemetry/core';
import { ResourceMetrics } from '@opentelemetry/sdk-metrics';
import { OTLPMetricExporterBase } from '@opentelemetry/exporter-metrics-otlp-http';
@@ -26,10 +22,12 @@ import {
OTLPExporterNodeConfigBase,
appendResourcePathToUrl,
appendRootPathToUrlIfNeeded,
+ parseHeaders,
+ OTLPExporterNodeBase,
} from '@opentelemetry/otlp-exporter-base';
import {
- createExportMetricsServiceRequest,
- IExportMetricsServiceRequest,
+ IExportMetricsServiceResponse,
+ ProtobufMetricsSerializer,
} from '@opentelemetry/otlp-transformer';
import { VERSION } from './version';
@@ -39,43 +37,41 @@ const USER_AGENT = {
'User-Agent': `OTel-OTLP-Exporter-JavaScript/${VERSION}`,
};
-class OTLPMetricExporterNodeProxy extends OTLPProtoExporterNodeBase<
+class OTLPMetricExporterNodeProxy extends OTLPExporterNodeBase<
ResourceMetrics,
- IExportMetricsServiceRequest
+ IExportMetricsServiceResponse
> {
constructor(config?: OTLPExporterNodeConfigBase & OTLPMetricExporterOptions) {
- super(config);
- this.headers = {
- ...this.headers,
- ...USER_AGENT,
+ super(config, ProtobufMetricsSerializer, {
...baggageUtils.parseKeyPairsIntoRecord(
getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS
),
- ...config?.headers,
- };
+ ...parseHeaders(config?.headers),
+ ...USER_AGENT,
+ 'Content-Type': 'application/x-protobuf',
+ });
}
- convert(metrics: ResourceMetrics[]): IExportMetricsServiceRequest {
- return createExportMetricsServiceRequest(metrics);
- }
+ getDefaultUrl(config: OTLPExporterNodeConfigBase): string {
+ if (typeof config.url === 'string') {
+ return config.url;
+ }
- getDefaultUrl(config: OTLPExporterNodeConfigBase) {
- return typeof config.url === 'string'
- ? config.url
- : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0
- ? appendRootPathToUrlIfNeeded(
- getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
- )
- : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0
- ? appendResourcePathToUrl(
- getEnv().OTEL_EXPORTER_OTLP_ENDPOINT,
- DEFAULT_COLLECTOR_RESOURCE_PATH
- )
- : DEFAULT_COLLECTOR_URL;
- }
+ const env = getEnv();
+ if (env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0) {
+ return appendRootPathToUrlIfNeeded(
+ env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
+ );
+ }
+
+ if (env.OTEL_EXPORTER_OTLP_ENDPOINT.length > 0) {
+ return appendResourcePathToUrl(
+ env.OTEL_EXPORTER_OTLP_ENDPOINT,
+ DEFAULT_COLLECTOR_RESOURCE_PATH
+ );
+ }
- getServiceClientType() {
- return ServiceClientType.METRICS;
+ return DEFAULT_COLLECTOR_URL;
}
}
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts
index 51c175f8e6c..300fd8eb059 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts
@@ -16,10 +16,6 @@
import { diag } from '@opentelemetry/api';
import { ExportResultCode } from '@opentelemetry/core';
-import {
- getExportRequestProto,
- ServiceClientType,
-} from '@opentelemetry/otlp-proto-exporter-base';
import * as assert from 'assert';
import * as http from 'http';
import * as sinon from 'sinon';
@@ -46,9 +42,26 @@ import {
import { Stream, PassThrough } from 'stream';
import { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base';
import { VERSION } from '../src/version';
+import { Root } from 'protobufjs';
+import * as path from 'path';
let fakeRequest: PassThrough;
+const dir = path.resolve(__dirname, '../../otlp-transformer/protos');
+const root = new Root();
+root.resolvePath = function (origin, target) {
+ return `${dir}/${target}`;
+};
+const proto = root.loadSync([
+ 'opentelemetry/proto/common/v1/common.proto',
+ 'opentelemetry/proto/resource/v1/resource.proto',
+ 'opentelemetry/proto/metrics/v1/metrics.proto',
+ 'opentelemetry/proto/collector/metrics/v1/metrics_service.proto',
+]);
+const exportRequestServiceProto = proto?.lookupType(
+ 'ExportMetricsServiceRequest'
+);
+
describe('OTLPMetricExporter - node with proto over http', () => {
let collectorExporter: OTLPMetricExporter;
let collectorExporterConfig: OTLPExporterNodeConfigBase &
@@ -57,14 +70,19 @@ describe('OTLPMetricExporter - node with proto over http', () => {
afterEach(() => {
fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.restore();
});
describe('default behavior for headers', () => {
- const collectorExporter = new OTLPMetricExporter();
+ const exporter = new OTLPMetricExporter();
it('should include user agent in header', () => {
assert.strictEqual(
- collectorExporter._otlpExporter.headers['User-Agent'],
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['User-Agent'],
`OTel-OTLP-Exporter-JavaScript/${VERSION}`
);
});
@@ -162,31 +180,53 @@ describe('OTLPMetricExporter - node with proto over http', () => {
});
it('should use headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar';
- const collectorExporter = new OTLPMetricExporter();
- assert.strictEqual(collectorExporter._otlpExporter.headers.foo, 'bar');
+ const exporter = new OTLPMetricExporter();
+ assert.strictEqual(
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['foo'],
+ 'bar'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should override global headers config with signal headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'foo=boo';
- const collectorExporter = new OTLPMetricExporter();
- assert.strictEqual(collectorExporter._otlpExporter.headers.foo, 'boo');
- assert.strictEqual(collectorExporter._otlpExporter.headers.bar, 'foo');
+ const exporter = new OTLPMetricExporter();
+ assert.strictEqual(
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['foo'],
+ 'boo'
+ );
+ assert.strictEqual(
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = '';
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
it('should override headers defined via env with headers defined in constructor', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
- const collectorExporter = new OTLPMetricExporter({
+ const exporter = new OTLPMetricExporter({
headers: {
foo: 'constructor',
},
});
assert.strictEqual(
- collectorExporter._otlpExporter.headers.foo,
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['foo'],
'constructor'
);
- assert.strictEqual(collectorExporter._otlpExporter.headers.bar, 'foo');
+ assert.strictEqual(
+ exporter._otlpExporter['_transport']['_transport']['_parameters'][
+ 'headers'
+ ]['bar'],
+ 'foo'
+ );
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
});
});
@@ -228,160 +268,184 @@ describe('OTLPMetricExporter - node with proto over http', () => {
});
it('should open the connection', done => {
- collectorExporter.export(metrics, () => {});
-
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
assert.strictEqual(options.hostname, 'foo.bar.com');
assert.strictEqual(options.method, 'POST');
assert.strictEqual(options.path, '/');
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
- });
- it('should set custom headers', done => {
collectorExporter.export(metrics, () => {});
+ });
+ it('should set custom headers', done => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
assert.strictEqual(options.headers['foo'], 'bar');
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
-
- done();
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
return fakeRequest as any;
});
- });
- it('should have keep alive and keepAliveMsecs option set', done => {
collectorExporter.export(metrics, () => {});
+ });
+ it('should have keep alive and keepAliveMsecs option set', done => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- assert.strictEqual(options.agent.keepAlive, true);
- assert.strictEqual(options.agent.options.keepAliveMsecs, 2000);
-
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
-
- done();
+ try {
+ assert.strictEqual(options.agent.keepAlive, true);
+ assert.strictEqual(options.agent.options.keepAliveMsecs, 2000);
+
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ done();
+ });
+ } catch (e) {
+ done(e);
+ }
return fakeRequest as any;
});
+
+ collectorExporter.export(metrics, () => {});
});
it('should successfully send metrics', done => {
const fakeRequest = new Stream.PassThrough();
+ Object.defineProperty(fakeRequest, 'setTimeout', {
+ value: function (_timeout: number) {},
+ });
sinon.stub(http, 'request').returns(fakeRequest as any);
let buff = Buffer.from('');
- fakeRequest.on('end', () => {
- const ExportTraceServiceRequestProto = getExportRequestProto(
- ServiceClientType.METRICS
- );
- const data = ExportTraceServiceRequestProto.decode(buff);
- const json = data?.toJSON() as any;
-
- // The order of the metrics is not guaranteed.
- const counterIndex = metrics.scopeMetrics[0].metrics.findIndex(
- it => it.descriptor.name === 'int-counter'
- );
- const observableIndex = metrics.scopeMetrics[0].metrics.findIndex(
- it => it.descriptor.name === 'double-observable-gauge'
- );
- const histogramIndex = metrics.scopeMetrics[0].metrics.findIndex(
- it => it.descriptor.name === 'int-histogram'
- );
-
- const metric1 =
- json.resourceMetrics[0].scopeMetrics[0].metrics[counterIndex];
- const metric2 =
- json.resourceMetrics[0].scopeMetrics[0].metrics[observableIndex];
- const metric3 =
- json.resourceMetrics[0].scopeMetrics[0].metrics[histogramIndex];
-
- assert.ok(typeof metric1 !== 'undefined', "counter doesn't exist");
- ensureExportedCounterIsCorrect(
- metric1,
- metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime,
- metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime
- );
- assert.ok(
- typeof metric2 !== 'undefined',
- "observable gauge doesn't exist"
- );
- ensureExportedObservableGaugeIsCorrect(
- metric2,
- metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0]
- .endTime,
- metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0]
- .startTime
- );
- assert.ok(
- typeof metric3 !== 'undefined',
- "value recorder doesn't exist"
- );
- ensureExportedHistogramIsCorrect(
- metric3,
- metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime,
- metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0]
- .startTime,
- [0, 100],
- ['0', '2', '0']
- );
-
- ensureExportMetricsServiceRequestIsSet(json);
- done();
+ fakeRequest.on('finish', () => {
+ try {
+ const data = exportRequestServiceProto.decode(buff);
+ const json = data?.toJSON() as any;
+
+ // The order of the metrics is not guaranteed.
+ const counterIndex = metrics.scopeMetrics[0].metrics.findIndex(
+ it => it.descriptor.name === 'int-counter'
+ );
+ const observableIndex = metrics.scopeMetrics[0].metrics.findIndex(
+ it => it.descriptor.name === 'double-observable-gauge'
+ );
+ const histogramIndex = metrics.scopeMetrics[0].metrics.findIndex(
+ it => it.descriptor.name === 'int-histogram'
+ );
+
+ const metric1 =
+ json.resourceMetrics[0].scopeMetrics[0].metrics[counterIndex];
+ const metric2 =
+ json.resourceMetrics[0].scopeMetrics[0].metrics[observableIndex];
+ const metric3 =
+ json.resourceMetrics[0].scopeMetrics[0].metrics[histogramIndex];
+
+ assert.ok(typeof metric1 !== 'undefined', "counter doesn't exist");
+ ensureExportedCounterIsCorrect(
+ metric1,
+ metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime,
+ metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0]
+ .startTime
+ );
+ assert.ok(
+ typeof metric2 !== 'undefined',
+ "observable gauge doesn't exist"
+ );
+ ensureExportedObservableGaugeIsCorrect(
+ metric2,
+ metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0]
+ .endTime,
+ metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0]
+ .startTime
+ );
+ assert.ok(
+ typeof metric3 !== 'undefined',
+ "value recorder doesn't exist"
+ );
+ ensureExportedHistogramIsCorrect(
+ metric3,
+ metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0]
+ .endTime,
+ metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0]
+ .startTime,
+ [0, 100],
+ ['0', '2', '0']
+ );
+
+ ensureExportMetricsServiceRequestIsSet(json);
+ done();
+ } catch (e) {
+ done(e);
+ }
});
fakeRequest.on('data', chunk => {
buff = Buffer.concat([buff, chunk]);
});
- const clock = sinon.useFakeTimers();
- collectorExporter.export(metrics, () => {});
- clock.tick(200);
- clock.restore();
+ try {
+ collectorExporter.export(metrics, () => {});
+ } catch (error) {
+ done(error);
+ }
});
it('should log the successful message', done => {
// Need to stub/spy on the underlying logger as the "diag" instance is global
const spyLoggerError = sinon.stub(diag, 'error');
- collectorExporter.export(metrics, result => {
- assert.strictEqual(result.code, ExportResultCode.SUCCESS);
- assert.strictEqual(spyLoggerError.args.length, 0);
- done();
- });
-
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- const mockRes = new MockedResponse(200);
- cb(mockRes);
- mockRes.send('success');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(200);
+ cb(mockRes);
+ mockRes.send(Buffer.from('success'));
+ });
+
return fakeRequest as any;
});
- });
- it('should log the error message', done => {
collectorExporter.export(metrics, result => {
- assert.strictEqual(result.code, ExportResultCode.FAILED);
- // @ts-expect-error verify error code
- assert.strictEqual(result.error.code, 400);
+ assert.strictEqual(result.code, ExportResultCode.SUCCESS);
+ assert.strictEqual(spyLoggerError.args.length, 0);
done();
});
+ });
+ it('should return the error code message', done => {
sinon.stub(http, 'request').callsFake((options: any, cb: any) => {
- const mockResError = new MockedResponse(400);
- cb(mockResError);
- mockResError.send('failed');
+ queueMicrotask(() => {
+ const mockRes = new MockedResponse(400);
+ cb(mockRes);
+ mockRes.send(Buffer.from('failure'));
+ });
return fakeRequest as any;
});
+
+ collectorExporter.export(metrics, result => {
+ try {
+ assert.strictEqual(result.code, ExportResultCode.FAILED);
+ // @ts-expect-error verify error code
+ assert.strictEqual(result.error.code, 400);
+ done();
+ } catch (e) {
+ done(e);
+ }
+ });
});
});
});
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts
index ef70a75c054..effc732b370 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts
@@ -227,7 +227,7 @@ export class MockedResponse extends Stream {
super();
}
- send(data: string) {
+ send(data: Uint8Array) {
this.emit('data', data);
this.emit('end');
}
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.esm.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.esm.json
index b657f54211b..4fb587ea8d7 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.esm.json
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.esm.json
@@ -27,9 +27,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
}
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.esnext.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.esnext.json
index 31e46faedaf..8f77308fbd5 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.esnext.json
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.esnext.json
@@ -27,9 +27,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
}
diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json
index d3497ee2dd3..185c670198d 100644
--- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json
+++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json
@@ -27,9 +27,6 @@
{
"path": "../otlp-exporter-base"
},
- {
- "path": "../otlp-proto-exporter-base"
- },
{
"path": "../otlp-transformer"
}
diff --git a/experimental/packages/opentelemetry-exporter-prometheus/package.json b/experimental/packages/opentelemetry-exporter-prometheus/package.json
index f02054300a4..0995ee7c9c7 100644
--- a/experimental/packages/opentelemetry-exporter-prometheus/package.json
+++ b/experimental/packages/opentelemetry-exporter-prometheus/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/exporter-prometheus",
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "OpenTelemetry Exporter Prometheus provides a metrics endpoint for Prometheus",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@@ -9,7 +9,7 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build",
"clean": "tsc --build --clean",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'",
+ "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",
@@ -18,7 +18,8 @@
"watch": "tsc --build --watch",
"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"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -43,27 +44,26 @@
"access": "public"
},
"devDependencies": {
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/semantic-conventions": "1.22.0",
- "@types/mocha": "10.0.6",
+ "@opentelemetry/api": "1.9.0",
+ "@opentelemetry/semantic-conventions": "1.25.1",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-mocha": "10.0.0",
"typescript": "4.4.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-metrics": "1.22.0"
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/resources": "1.25.1",
+ "@opentelemetry/sdk-metrics": "1.25.1"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-prometheus",
"sideEffects": false
diff --git a/experimental/packages/opentelemetry-exporter-prometheus/test/util.ts b/experimental/packages/opentelemetry-exporter-prometheus/test/util.ts
index 2af8aa7f56c..7f3cea9a1bd 100644
--- a/experimental/packages/opentelemetry-exporter-prometheus/test/util.ts
+++ b/experimental/packages/opentelemetry-exporter-prometheus/test/util.ts
@@ -16,7 +16,12 @@
import * as sinon from 'sinon';
import { Resource } from '@opentelemetry/resources';
-import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMRESATTRS_SERVICE_NAME,
+ SEMRESATTRS_TELEMETRY_SDK_LANGUAGE,
+ SEMRESATTRS_TELEMETRY_SDK_NAME,
+ SEMRESATTRS_TELEMETRY_SDK_VERSION,
+} from '@opentelemetry/semantic-conventions';
export const mockedHrTimeMs = 1586347902211;
@@ -25,18 +30,18 @@ export function mockHrTime() {
}
export const serviceName = Resource.default()
- .attributes[SemanticResourceAttributes.SERVICE_NAME]?.toString()
+ .attributes[SEMRESATTRS_SERVICE_NAME]?.toString()
.replace(/\\/g, '\\\\')
.replace(/\n/g, '\\n');
export const sdkLanguage = Resource.default()
- .attributes[SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE]?.toString()
+ .attributes[SEMRESATTRS_TELEMETRY_SDK_LANGUAGE]?.toString()
.replace(/\\/g, '\\\\')
.replace(/\n/g, '\\n');
export const sdkName = Resource.default()
- .attributes[SemanticResourceAttributes.TELEMETRY_SDK_NAME]?.toString()
+ .attributes[SEMRESATTRS_TELEMETRY_SDK_NAME]?.toString()
.replace(/\\/g, '\\\\')
.replace(/\n/g, '\\n');
export const sdkVersion = Resource.default()
- .attributes[SemanticResourceAttributes.TELEMETRY_SDK_VERSION]?.toString()
+ .attributes[SEMRESATTRS_TELEMETRY_SDK_VERSION]?.toString()
.replace(/\\/g, '\\\\')
.replace(/\n/g, '\\n');
diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/README.md b/experimental/packages/opentelemetry-instrumentation-fetch/README.md
index 367d5c9ef1f..2d3c2d4aeed 100644
--- a/experimental/packages/opentelemetry-instrumentation-fetch/README.md
+++ b/experimental/packages/opentelemetry-instrumentation-fetch/README.md
@@ -6,7 +6,7 @@
**Note: This is an experimental package under active development. New releases may include breaking changes.**
This module provides auto instrumentation for web using [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch).
-(Note: This instrumentation does **not** instrument [Node.js' fetch](https://nodejs.org/api/globals.html#fetch). See [this issue](https://github.com/open-telemetry/opentelemetry-js/issues/4333).)
+(Note: This instrumentation does **not** instrument [Node.js' fetch](https://nodejs.org/api/globals.html#fetch). See [`@opentelemetry/instrumentation-undici`](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-undici/) for that.)
## Installation
@@ -72,6 +72,21 @@ Fetch instrumentation plugin has few options available to choose from. You can s
| [`applyCustomAttributesOnSpan`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L64) | `HttpCustomAttributeFunction` | Function for adding custom attributes |
| [`ignoreNetworkEvents`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L67) | `boolean` | Disable network events being added as span events (network events are added by default) |
+## 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)
+
+Attributes collected:
+
+| Attribute | Short Description |
+| ------------------------------------------- | ------------------------------------------------------------------------------ |
+| `http.status_code` | HTTP response status code |
+| `http.host` | The value of the HTTP host header |
+| `http.user_agent` | Value of the HTTP User-Agent header sent by the client |
+| `http.scheme` | The URI scheme identifying the used protocol |
+| `http.url` | Full HTTP request URL |
+| `http.method` | HTTP request method |
+
## Useful links
- For more information on OpenTelemetry, visit:
diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/package.json b/experimental/packages/opentelemetry-instrumentation-fetch/package.json
index 55c58486e41..e8681ceaf7b 100644
--- a/experimental/packages/opentelemetry-instrumentation-fetch/package.json
+++ b/experimental/packages/opentelemetry-instrumentation-fetch/package.json
@@ -1,7 +1,7 @@
{
"name": "@opentelemetry/instrumentation-fetch",
- "version": "0.49.1",
- "description": "OpenTelemetry fetch automatic instrumentation package.",
+ "version": "0.52.1",
+ "description": "OpenTelemetry instrumentation for fetch http client in web browsers",
"main": "build/src/index.js",
"module": "build/esm/index.js",
"esnext": "build/esnext/index.js",
@@ -20,7 +20,8 @@
"watch": "tsc --build --watch tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "node ../../../scripts/version-update.js",
- "peer-api-check": "node ../../../scripts/peer-api-check.js"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"fetch",
@@ -54,32 +55,31 @@
"access": "public"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/context-zone": "1.22.0",
- "@opentelemetry/propagator-b3": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@opentelemetry/context-zone": "1.25.1",
+ "@opentelemetry/propagator-b3": "1.25.1",
+ "@opentelemetry/sdk-trace-base": "1.25.1",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
@@ -89,10 +89,10 @@
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/sdk-trace-web": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.0"
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/instrumentation": "0.52.1",
+ "@opentelemetry/sdk-trace-web": "1.25.1",
+ "@opentelemetry/semantic-conventions": "1.25.1"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-fetch",
"sideEffects": false
diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts b/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts
index 1f80bfd953a..fedb495d685 100644
--- a/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts
+++ b/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts
@@ -24,7 +24,14 @@ import {
import * as core from '@opentelemetry/core';
import * as web from '@opentelemetry/sdk-trace-web';
import { AttributeNames } from './enums/AttributeNames';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_HTTP_HOST,
+ SEMATTRS_HTTP_USER_AGENT,
+ SEMATTRS_HTTP_SCHEME,
+ SEMATTRS_HTTP_URL,
+ SEMATTRS_HTTP_METHOD,
+} from '@opentelemetry/semantic-conventions';
import { FetchError, FetchResponse, SpanData } from './types';
import { VERSION } from './version';
import { _globalThis } from '@opentelemetry/core';
@@ -72,25 +79,19 @@ export interface FetchInstrumentationConfig extends InstrumentationConfig {
/**
* This class represents a fetch plugin for auto instrumentation
*/
-export class FetchInstrumentation extends InstrumentationBase<
- Promise
-> {
+export class FetchInstrumentation extends InstrumentationBase {
readonly component: string = 'fetch';
readonly version: string = VERSION;
moduleName = this.component;
private _usedResources = new WeakSet();
private _tasksCount = 0;
- constructor(config?: FetchInstrumentationConfig) {
+ constructor(config: FetchInstrumentationConfig = {}) {
super('@opentelemetry/instrumentation-fetch', VERSION, config);
}
init(): void {}
- private _getConfig(): FetchInstrumentationConfig {
- return this._config;
- }
-
/**
* Add cors pre flight child span
* @param span
@@ -107,7 +108,7 @@ export class FetchInstrumentation extends InstrumentationBase<
},
api.trace.setSpan(api.context.active(), span)
);
- if (!this._getConfig().ignoreNetworkEvents) {
+ if (!this.getConfig().ignoreNetworkEvents) {
web.addSpanNetworkEvents(childSpan, corsPreFlightRequest);
}
childSpan.end(
@@ -125,20 +126,17 @@ export class FetchInstrumentation extends InstrumentationBase<
response: FetchResponse
): void {
const parsedUrl = web.parseUrl(response.url);
- span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, response.status);
+ span.setAttribute(SEMATTRS_HTTP_STATUS_CODE, response.status);
if (response.statusText != null) {
span.setAttribute(AttributeNames.HTTP_STATUS_TEXT, response.statusText);
}
- span.setAttribute(SemanticAttributes.HTTP_HOST, parsedUrl.host);
+ span.setAttribute(SEMATTRS_HTTP_HOST, parsedUrl.host);
span.setAttribute(
- SemanticAttributes.HTTP_SCHEME,
+ SEMATTRS_HTTP_SCHEME,
parsedUrl.protocol.replace(':', '')
);
if (typeof navigator !== 'undefined') {
- span.setAttribute(
- SemanticAttributes.HTTP_USER_AGENT,
- navigator.userAgent
- );
+ span.setAttribute(SEMATTRS_HTTP_USER_AGENT, navigator.userAgent);
}
}
@@ -151,7 +149,7 @@ export class FetchInstrumentation extends InstrumentationBase<
if (
!web.shouldPropagateTraceHeaders(
spanUrl,
- this._getConfig().propagateTraceHeaderCorsUrls
+ this.getConfig().propagateTraceHeaderCorsUrls
)
) {
const headers: Partial> = {};
@@ -188,7 +186,7 @@ export class FetchInstrumentation extends InstrumentationBase<
* @private
*/
private _clearResources() {
- if (this._tasksCount === 0 && this._getConfig().clearTimingResources) {
+ if (this._tasksCount === 0 && this.getConfig().clearTimingResources) {
performance.clearResourceTimings();
this._usedResources = new WeakSet();
}
@@ -203,7 +201,7 @@ export class FetchInstrumentation extends InstrumentationBase<
url: string,
options: Partial = {}
): api.Span | undefined {
- if (core.isUrlIgnored(url, this._getConfig().ignoreUrls)) {
+ if (core.isUrlIgnored(url, this.getConfig().ignoreUrls)) {
this._diag.debug('ignoring span as url matches ignored url');
return;
}
@@ -213,8 +211,8 @@ export class FetchInstrumentation extends InstrumentationBase<
kind: api.SpanKind.CLIENT,
attributes: {
[AttributeNames.COMPONENT]: this.moduleName,
- [SemanticAttributes.HTTP_METHOD]: method,
- [SemanticAttributes.HTTP_URL]: url,
+ [SEMATTRS_HTTP_METHOD]: method,
+ [SEMATTRS_HTTP_URL]: url,
},
});
}
@@ -260,7 +258,7 @@ export class FetchInstrumentation extends InstrumentationBase<
this._addChildSpan(span, corsPreFlightRequest);
this._markResourceAsUsed(corsPreFlightRequest);
}
- if (!this._getConfig().ignoreNetworkEvents) {
+ if (!this.getConfig().ignoreNetworkEvents) {
web.addSpanNetworkEvents(span, mainRequest);
}
}
@@ -421,7 +419,7 @@ export class FetchInstrumentation extends InstrumentationBase<
result: Response | FetchError
) {
const applyCustomAttributesOnSpan =
- this._getConfig().applyCustomAttributesOnSpan;
+ this.getConfig().applyCustomAttributesOnSpan;
if (applyCustomAttributesOnSpan) {
safeExecuteInTheMiddle(
() => applyCustomAttributesOnSpan(span, request, result),
diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/test/fetch.test.ts b/experimental/packages/opentelemetry-instrumentation-fetch/test/fetch.test.ts
index 832b2d89990..7e14cc35883 100644
--- a/experimental/packages/opentelemetry-instrumentation-fetch/test/fetch.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation-fetch/test/fetch.test.ts
@@ -41,7 +41,15 @@ import {
FetchCustomAttributeFunction,
} from '../src';
import { AttributeNames } from '../src/enums/AttributeNames';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_HTTP_HOST,
+ SEMATTRS_HTTP_METHOD,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH,
+ SEMATTRS_HTTP_SCHEME,
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_HTTP_URL,
+ SEMATTRS_HTTP_USER_AGENT,
+} from '@opentelemetry/semantic-conventions';
class DummySpanExporter implements tracing.SpanExporter {
export(spans: any) {}
@@ -374,17 +382,17 @@ describe('fetch', () => {
assert.strictEqual(
attributes[keys[1]],
'GET',
- `attributes ${SemanticAttributes.HTTP_METHOD} is wrong`
+ `attributes ${SEMATTRS_HTTP_METHOD} is wrong`
);
assert.strictEqual(
attributes[keys[2]],
url,
- `attributes ${SemanticAttributes.HTTP_URL} is wrong`
+ `attributes ${SEMATTRS_HTTP_URL} is wrong`
);
assert.strictEqual(
attributes[keys[3]],
200,
- `attributes ${SemanticAttributes.HTTP_STATUS_CODE} is wrong`
+ `attributes ${SEMATTRS_HTTP_STATUS_CODE} is wrong`
);
assert.ok(
attributes[keys[4]] === 'OK' || attributes[keys[4]] === '',
@@ -392,19 +400,19 @@ describe('fetch', () => {
);
assert.ok(
(attributes[keys[5]] as string).indexOf('localhost') === 0,
- `attributes ${SemanticAttributes.HTTP_HOST} is wrong`
+ `attributes ${SEMATTRS_HTTP_HOST} is wrong`
);
assert.ok(
attributes[keys[6]] === 'http' || attributes[keys[6]] === 'https',
- `attributes ${SemanticAttributes.HTTP_SCHEME} is wrong`
+ `attributes ${SEMATTRS_HTTP_SCHEME} is wrong`
);
assert.ok(
attributes[keys[7]] !== '',
- `attributes ${SemanticAttributes.HTTP_USER_AGENT} is not defined`
+ `attributes ${SEMATTRS_HTTP_USER_AGENT} is not defined`
);
assert.ok(
(attributes[keys[8]] as number) > 0,
- `attributes ${SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH} is <= 0`
+ `attributes ${SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH} is <= 0`
);
assert.strictEqual(keys.length, 9, 'number of attributes is wrong');
@@ -654,7 +662,7 @@ describe('fetch', () => {
clearData();
});
- it('applies attributes when the request is succesful', async () => {
+ it('applies attributes when the request is successful', async () => {
await prepare(url, span => {
span.setAttribute(CUSTOM_ATTRIBUTE_KEY, 'custom value');
});
@@ -865,9 +873,9 @@ describe('fetch', () => {
const attributes = span.attributes;
assert.strictEqual(
- attributes[SemanticAttributes.HTTP_URL],
+ attributes[SEMATTRS_HTTP_URL],
location.origin + '/get',
- `attributes ${SemanticAttributes.HTTP_URL} is wrong`
+ `attributes ${SEMATTRS_HTTP_URL} is wrong`
);
});
});
@@ -934,7 +942,7 @@ describe('fetch', () => {
assert.strictEqual(
attributes[keys[3]],
200,
- `Missing basic attribute ${SemanticAttributes.HTTP_STATUS_CODE}`
+ `Missing basic attribute ${SEMATTRS_HTTP_STATUS_CODE}`
);
});
});
diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/README.md b/experimental/packages/opentelemetry-instrumentation-grpc/README.md
index 8916054eb48..e887ef2e429 100644
--- a/experimental/packages/opentelemetry-instrumentation-grpc/README.md
+++ b/experimental/packages/opentelemetry-instrumentation-grpc/README.md
@@ -16,6 +16,10 @@ For automatic instrumentation see the
npm install --save @opentelemetry/instrumentation-grpc
```
+## Supported Versions
+
+- [`@grpc/grpc-js`](https://www.npmjs.com/package/@grpc/grpc-js) versions `^1.0.0`
+
## Usage
OpenTelemetry gRPC Instrumentation allows the user to automatically collect trace data and export them to the backend of choice, to give observability to distributed systems when working with ([grpc-js](https://www.npmjs.com/package/@grpc/grpc-js)).
diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/package.json b/experimental/packages/opentelemetry-instrumentation-grpc/package.json
index 4c454367355..8c923432328 100644
--- a/experimental/packages/opentelemetry-instrumentation-grpc/package.json
+++ b/experimental/packages/opentelemetry-instrumentation-grpc/package.json
@@ -1,7 +1,7 @@
{
"name": "@opentelemetry/instrumentation-grpc",
- "version": "0.49.1",
- "description": "OpenTelemetry grpc automatic instrumentation package.",
+ "version": "0.52.1",
+ "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",
"repository": "open-telemetry/opentelemetry-js",
@@ -9,7 +9,7 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build",
"clean": "tsc --build --clean",
- "test": "npm run protos:generate && nyc ts-mocha -p tsconfig.json test/**/*.test.ts",
+ "test": "npm run protos:generate && nyc mocha test/**/*.test.ts",
"tdd": "npm run test -- --watch-extensions ts --watch",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
@@ -19,7 +19,8 @@
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "node ../../../scripts/version-update.js",
"peer-api-check": "node ../../../scripts/peer-api-check.js",
- "protos:generate": "cd test/fixtures && buf generate"
+ "protos:generate": "cd test/fixtures && buf generate",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -49,33 +50,32 @@
"@bufbuild/buf": "1.21.0-1",
"@grpc/grpc-js": "^1.7.1",
"@grpc/proto-loader": "^0.7.10",
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/context-async-hooks": "1.22.0",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@opentelemetry/sdk-trace-node": "1.22.0",
- "@protobuf-ts/grpc-transport": "2.9.3",
- "@protobuf-ts/runtime": "2.9.3",
- "@protobuf-ts/runtime-rpc": "2.9.3",
- "@types/mocha": "10.0.6",
+ "@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",
+ "@protobuf-ts/grpc-transport": "2.9.4",
+ "@protobuf-ts/runtime": "2.9.4",
+ "@protobuf-ts/runtime-rpc": "2.9.4",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/semver": "7.5.6",
- "@types/sinon": "10.0.20",
+ "@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.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-mocha": "10.0.0",
"typescript": "4.4.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/semantic-conventions": "1.22.0"
+ "@opentelemetry/instrumentation": "0.52.1",
+ "@opentelemetry/semantic-conventions": "1.25.1"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-grpc",
"sideEffects": false
diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/clientUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/clientUtils.ts
index f4c5470d16c..0974b239482 100644
--- a/experimental/packages/opentelemetry-instrumentation-grpc/src/clientUtils.ts
+++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/clientUtils.ts
@@ -26,7 +26,7 @@ import type {
} from './internal-types';
import { propagation, context } from '@opentelemetry/api';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import { SEMATTRS_RPC_GRPC_STATUS_CODE } from '@opentelemetry/semantic-conventions';
import { AttributeNames } from './enums/AttributeNames';
import { GRPC_STATUS_CODE_OK } from './status-code';
import {
@@ -81,17 +81,14 @@ export function patchedCallback(
if (err) {
if (err.code) {
span.setStatus(_grpcStatusCodeToSpanStatus(err.code));
- span.setAttribute(SemanticAttributes.RPC_GRPC_STATUS_CODE, err.code);
+ span.setAttribute(SEMATTRS_RPC_GRPC_STATUS_CODE, err.code);
}
span.setAttributes({
[AttributeNames.GRPC_ERROR_NAME]: err.name,
[AttributeNames.GRPC_ERROR_MESSAGE]: err.message,
});
} else {
- span.setAttribute(
- SemanticAttributes.RPC_GRPC_STATUS_CODE,
- GRPC_STATUS_CODE_OK
- );
+ span.setAttribute(SEMATTRS_RPC_GRPC_STATUS_CODE, GRPC_STATUS_CODE_OK);
}
span.end();
@@ -133,7 +130,7 @@ export function patchResponseStreamEvents(span: Span, call: EventEmitter) {
span.setAttributes({
[AttributeNames.GRPC_ERROR_NAME]: err.name,
[AttributeNames.GRPC_ERROR_MESSAGE]: err.message,
- [SemanticAttributes.RPC_GRPC_STATUS_CODE]: err.code,
+ [SEMATTRS_RPC_GRPC_STATUS_CODE]: err.code,
});
endSpan();
@@ -145,14 +142,14 @@ export function patchResponseStreamEvents(span: Span, call: EventEmitter) {
}
span.setStatus(_grpcStatusCodeToSpanStatus(status.code));
- span.setAttribute(SemanticAttributes.RPC_GRPC_STATUS_CODE, status.code);
+ span.setAttribute(SEMATTRS_RPC_GRPC_STATUS_CODE, status.code);
endSpan();
});
}
/**
- * Execute grpc client call. Apply completitionspan properties and end the
+ * Execute grpc client call. Apply completion span properties and end the
* span on callback or receiving an emitted event.
*/
export function makeGrpcClientRemoteCall(
diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts
index 3a04c24e1fd..3daec0b63c5 100644
--- a/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts
+++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts
@@ -53,10 +53,15 @@ import {
} from '@opentelemetry/api';
import {
InstrumentationNodeModuleDefinition,
- isWrapped,
InstrumentationBase,
} from '@opentelemetry/instrumentation';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_NET_PEER_NAME,
+ SEMATTRS_NET_PEER_PORT,
+ SEMATTRS_RPC_METHOD,
+ SEMATTRS_RPC_SERVICE,
+ SEMATTRS_RPC_SYSTEM,
+} from '@opentelemetry/semantic-conventions';
import {
shouldNotTraceServerCall,
@@ -82,24 +87,20 @@ import {
import { AttributeValues } from './enums/AttributeValues';
import { VERSION } from './version';
-export class GrpcInstrumentation extends InstrumentationBase {
+export class GrpcInstrumentation extends InstrumentationBase {
private _metadataCapture: metadataCaptureType;
- constructor(config?: GrpcInstrumentationConfig) {
+ constructor(config: GrpcInstrumentationConfig = {}) {
super('@opentelemetry/instrumentation-grpc', VERSION, config);
this._metadataCapture = this._createMetadataCapture();
}
init() {
return [
- new InstrumentationNodeModuleDefinition(
+ new InstrumentationNodeModuleDefinition(
'@grpc/grpc-js',
- ['1.*'],
- (moduleExports, version) => {
- this._diag.debug(`Applying patch for @grpc/grpc-js@${version}`);
- if (isWrapped(moduleExports.Server.prototype.register)) {
- this._unwrap(moduleExports.Server.prototype, 'register');
- }
+ ['^1.0.0'],
+ moduleExports => {
// Patch Server methods
this._wrap(
moduleExports.Server.prototype,
@@ -107,45 +108,21 @@ export class GrpcInstrumentation extends InstrumentationBase {
this._patchServer()
);
// Patch Client methods
- if (isWrapped(moduleExports.makeGenericClientConstructor)) {
- this._unwrap(moduleExports, 'makeGenericClientConstructor');
- }
this._wrap(
moduleExports,
'makeGenericClientConstructor',
this._patchClient(moduleExports)
);
- if (isWrapped(moduleExports.makeClientConstructor)) {
- this._unwrap(moduleExports, 'makeClientConstructor');
- }
this._wrap(
moduleExports,
'makeClientConstructor',
this._patchClient(moduleExports)
);
- if (isWrapped(moduleExports.loadPackageDefinition)) {
- this._unwrap(moduleExports, 'loadPackageDefinition');
- }
this._wrap(
moduleExports,
'loadPackageDefinition',
this._patchLoadPackageDefinition(moduleExports)
);
- if (isWrapped(moduleExports.Client.prototype)) {
- this._unwrap(moduleExports.Client.prototype, 'makeUnaryRequest');
- this._unwrap(
- moduleExports.Client.prototype,
- 'makeClientStreamRequest'
- );
- this._unwrap(
- moduleExports.Client.prototype,
- 'makeServerStreamRequest'
- );
- this._unwrap(
- moduleExports.Client.prototype,
- 'makeBidiStreamRequest'
- );
- }
this._wrap(
moduleExports.Client.prototype,
'makeUnaryRequest',
@@ -168,9 +145,8 @@ export class GrpcInstrumentation extends InstrumentationBase {
);
return moduleExports;
},
- (moduleExports, version) => {
+ moduleExports => {
if (moduleExports === undefined) return;
- this._diag.debug(`Removing patch for @grpc/grpc-js@${version}`);
this._unwrap(moduleExports.Server.prototype, 'register');
this._unwrap(moduleExports, 'makeClientConstructor');
@@ -191,16 +167,7 @@ export class GrpcInstrumentation extends InstrumentationBase {
];
}
- /**
- * @internal
- * Public reference to the protected BaseInstrumentation `_config` instance to be used by this
- * plugin's external helper functions
- */
- override getConfig(): GrpcInstrumentationConfig {
- return super.getConfig();
- }
-
- override setConfig(config?: GrpcInstrumentationConfig): void {
+ override setConfig(config: GrpcInstrumentationConfig = {}): void {
super.setConfig(config);
this._metadataCapture = this._createMetadataCapture();
}
@@ -274,10 +241,9 @@ export class GrpcInstrumentation extends InstrumentationBase {
const span = instrumentation.tracer
.startSpan(spanName, spanOptions)
.setAttributes({
- [SemanticAttributes.RPC_SYSTEM]:
- AttributeValues.RPC_SYSTEM,
- [SemanticAttributes.RPC_METHOD]: method,
- [SemanticAttributes.RPC_SERVICE]: service,
+ [SEMATTRS_RPC_SYSTEM]: AttributeValues.RPC_SYSTEM,
+ [SEMATTRS_RPC_METHOD]: method,
+ [SEMATTRS_RPC_SERVICE]: service,
});
instrumentation._metadataCapture.server.captureRequestMetadata(
@@ -469,9 +435,9 @@ export class GrpcInstrumentation extends InstrumentationBase {
const span = instrumentation.tracer
.startSpan(name, { kind: SpanKind.CLIENT })
.setAttributes({
- [SemanticAttributes.RPC_SYSTEM]: 'grpc',
- [SemanticAttributes.RPC_METHOD]: method,
- [SemanticAttributes.RPC_SERVICE]: service,
+ [SEMATTRS_RPC_SYSTEM]: 'grpc',
+ [SEMATTRS_RPC_METHOD]: method,
+ [SEMATTRS_RPC_SERVICE]: service,
});
instrumentation.extractNetMetadata(this, span);
@@ -514,9 +480,9 @@ export class GrpcInstrumentation extends InstrumentationBase {
const span = this.tracer
.startSpan(name, { kind: SpanKind.CLIENT })
.setAttributes({
- [SemanticAttributes.RPC_SYSTEM]: 'grpc',
- [SemanticAttributes.RPC_METHOD]: methodAttributeValue,
- [SemanticAttributes.RPC_SERVICE]: service,
+ [SEMATTRS_RPC_SYSTEM]: 'grpc',
+ [SEMATTRS_RPC_METHOD]: methodAttributeValue,
+ [SEMATTRS_RPC_SERVICE]: service,
});
if (metadata != null) {
@@ -529,12 +495,9 @@ export class GrpcInstrumentation extends InstrumentationBase {
// set net.peer.* from target (e.g., "dns:otel-productcatalogservice:8080") as a hint to APMs
const parsedUri = URI_REGEX.exec(client.getChannel().getTarget());
if (parsedUri != null && parsedUri.groups != null) {
+ span.setAttribute(SEMATTRS_NET_PEER_NAME, parsedUri.groups['name']);
span.setAttribute(
- SemanticAttributes.NET_PEER_NAME,
- parsedUri.groups['name']
- );
- span.setAttribute(
- SemanticAttributes.NET_PEER_PORT,
+ SEMATTRS_NET_PEER_PORT,
parseInt(parsedUri.groups['port'])
);
}
diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/serverUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/serverUtils.ts
index 142c65f3ce9..c22d9dfca63 100644
--- a/experimental/packages/opentelemetry-instrumentation-grpc/src/serverUtils.ts
+++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/serverUtils.ts
@@ -38,7 +38,7 @@ import type {
import type { IgnoreMatcher } from './types';
import { context, SpanStatusCode } from '@opentelemetry/api';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import { SEMATTRS_RPC_GRPC_STATUS_CODE } from '@opentelemetry/semantic-conventions';
import {
_grpcStatusCodeToOpenTelemetryStatusCode,
@@ -81,10 +81,7 @@ function serverStreamAndBidiHandler(
span.setStatus({
code: SpanStatusCode.UNSET,
});
- span.setAttribute(
- SemanticAttributes.RPC_GRPC_STATUS_CODE,
- GRPC_STATUS_CODE_OK
- );
+ span.setAttribute(SEMATTRS_RPC_GRPC_STATUS_CODE, GRPC_STATUS_CODE_OK);
endSpan();
});
@@ -104,7 +101,7 @@ function serverStreamAndBidiHandler(
span.setAttributes({
[AttributeNames.GRPC_ERROR_NAME]: err.name,
[AttributeNames.GRPC_ERROR_MESSAGE]: err.message,
- [SemanticAttributes.RPC_GRPC_STATUS_CODE]: err.code,
+ [SEMATTRS_RPC_GRPC_STATUS_CODE]: err.code,
});
endSpan();
});
@@ -134,7 +131,7 @@ function clientStreamAndUnaryHandler(
code: _grpcStatusCodeToOpenTelemetryStatusCode(err.code),
message: err.message,
});
- span.setAttribute(SemanticAttributes.RPC_GRPC_STATUS_CODE, err.code);
+ span.setAttribute(SEMATTRS_RPC_GRPC_STATUS_CODE, err.code);
}
span.setAttributes({
[AttributeNames.GRPC_ERROR_NAME]: err.name,
@@ -142,10 +139,7 @@ function clientStreamAndUnaryHandler(
});
} else {
span.setStatus({ code: SpanStatusCode.UNSET });
- span.setAttribute(
- SemanticAttributes.RPC_GRPC_STATUS_CODE,
- GRPC_STATUS_CODE_OK
- );
+ span.setAttribute(SEMATTRS_RPC_GRPC_STATUS_CODE, GRPC_STATUS_CODE_OK);
}
span.end();
diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/test/helper.ts b/experimental/packages/opentelemetry-instrumentation-grpc/test/helper.ts
index 9d861fd6512..131dde04b4b 100644
--- a/experimental/packages/opentelemetry-instrumentation-grpc/test/helper.ts
+++ b/experimental/packages/opentelemetry-instrumentation-grpc/test/helper.ts
@@ -136,7 +136,7 @@ export async function startServer(proto: any, port: number) {
server.addService(proto.GrpcTester.service, {
// An error is emitted every time
// request.num <= MAX_ERROR_STATUS = (status.UNAUTHENTICATED)
- // in those cases, erro.code = request.num
+ // in those cases, error.code = request.num
// This method returns the request
// This method returns the request
diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/test/protobuf-ts-utils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/test/protobuf-ts-utils.ts
index 2fc2a3d1bec..95233aa52ec 100644
--- a/experimental/packages/opentelemetry-instrumentation-grpc/test/protobuf-ts-utils.ts
+++ b/experimental/packages/opentelemetry-instrumentation-grpc/test/protobuf-ts-utils.ts
@@ -21,7 +21,10 @@ import {
ReadableSpan,
} from '@opentelemetry/sdk-trace-base';
import { assertPropagation, assertSpan } from './utils/assertionUtils';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_RPC_METHOD,
+ SEMATTRS_RPC_SERVICE,
+} from '@opentelemetry/semantic-conventions';
export type SpanAssertionFunction = (
exporter: InMemorySpanExporter,
@@ -60,14 +63,8 @@ function validateSpans(
assertSpan('grpc', serverSpan, SpanKind.SERVER, validations);
assertSpan('grpc', clientSpan, SpanKind.CLIENT, validations);
- assert.strictEqual(
- clientSpan.attributes[SemanticAttributes.RPC_METHOD],
- rpcMethod
- );
- assert.strictEqual(
- clientSpan.attributes[SemanticAttributes.RPC_SERVICE],
- rpcService
- );
+ assert.strictEqual(clientSpan.attributes[SEMATTRS_RPC_METHOD], rpcMethod);
+ assert.strictEqual(clientSpan.attributes[SEMATTRS_RPC_SERVICE], rpcService);
}
export function assertNoSpansExported(
diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/test/utils/assertionUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/test/utils/assertionUtils.ts
index 1b7966639e0..ccc35cf7ad9 100644
--- a/experimental/packages/opentelemetry-instrumentation-grpc/test/utils/assertionUtils.ts
+++ b/experimental/packages/opentelemetry-instrumentation-grpc/test/utils/assertionUtils.ts
@@ -22,7 +22,11 @@ import {
hrTimeToMilliseconds,
hrTimeToMicroseconds,
} from '@opentelemetry/core';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_NET_PEER_NAME,
+ SEMATTRS_NET_PEER_PORT,
+ SEMATTRS_RPC_GRPC_STATUS_CODE,
+} from '@opentelemetry/semantic-conventions';
export const grpcStatusCodeToOpenTelemetryStatusCode = (
status: GrpcStatus
@@ -66,11 +70,11 @@ export const assertSpan = (
validations.netPeerPort !== undefined
) {
assert.strictEqual(
- span.attributes[SemanticAttributes.NET_PEER_NAME],
+ span.attributes[SEMATTRS_NET_PEER_NAME],
validations.netPeerName
);
assert.strictEqual(
- span.attributes[SemanticAttributes.NET_PEER_PORT],
+ span.attributes[SEMATTRS_NET_PEER_PORT],
validations.netPeerPort
);
}
@@ -82,7 +86,7 @@ export const assertSpan = (
grpcStatusCodeToOpenTelemetryStatusCode(validations.status)
);
assert.strictEqual(
- span.attributes[SemanticAttributes.RPC_GRPC_STATUS_CODE],
+ span.attributes[SEMATTRS_RPC_GRPC_STATUS_CODE],
validations.status
);
};
diff --git a/experimental/packages/opentelemetry-instrumentation-http/README.md b/experimental/packages/opentelemetry-instrumentation-http/README.md
index 312eb73bd76..530205ac775 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/README.md
+++ b/experimental/packages/opentelemetry-instrumentation-http/README.md
@@ -16,6 +16,10 @@ For automatic instrumentation see the
npm install --save @opentelemetry/instrumentation-http
```
+## Supported Versions
+
+- Nodejs `>=14`
+
## Usage
OpenTelemetry HTTP Instrumentation allows the user to automatically collect trace data and export them to their backend of choice, to give observability to distributed systems.
@@ -57,6 +61,8 @@ Http instrumentation has few options available to choose from. You can set the f
| [`startOutgoingSpanHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L99) | `StartOutgoingSpanCustomAttributeFunction` | Function for adding custom attributes before a span is started in outgoingRequest |
| `ignoreIncomingRequestHook` | `IgnoreIncomingRequestFunction` | Http instrumentation will not trace all incoming requests that matched with custom function |
| `ignoreOutgoingRequestHook` | `IgnoreOutgoingRequestFunction` | Http instrumentation will not trace all outgoing requests that matched with custom function |
+| `disableOutgoingRequestInstrumentation` | `boolean` | Set to true to avoid instrumenting outgoing requests at all. This can be helpful when another instrumentation handles outgoing requests. |
+| `disableIncomingRequestInstrumentation` | `boolean` | Set to true to avoid instrumenting incoming requests at all. This can be helpful when another instrumentation handles incoming requests. |
| [`serverName`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L101) | `string` | The primary server name of the matched virtual host. |
| [`requireParentforOutgoingSpans`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L103) | Boolean | Require that is a parent span to create new span for outgoing requests. |
| [`requireParentforIncomingSpans`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L105) | Boolean | Require that is a parent span to create new span for incoming requests. |
@@ -67,7 +73,39 @@ The following options are deprecated:
| Options | Type | Description |
| ------- | ---- | ----------- |
| `ignoreIncomingPaths` | `IgnoreMatcher[]` | Http instrumentation will not trace all incoming requests that match paths |
-| `ignoreOutgoingUrls` | `IgnoreMatcher[]` | Http instrumentation will not trace all outgoing requests that match urls |
+
+## 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)
+
+Attributes collected:
+
+| Attribute | Short Description |
+| ------------------------------------------- | ------------------------------------------------------------------------------ |
+| `ip_tcp` | Transport protocol used |
+| `ip_udp` | Transport protocol used |
+| `http.client_ip` | The IP address of the original client behind all proxies, if known |
+| `http.flavor` | Kind of HTTP protocol used |
+| `http.host` | The value of the HTTP host header |
+| `http.method` | HTTP request method |
+| `http.request_content_length` | The size of the request payload body in bytes |
+| `http.request_content_length_uncompressed` | The size of the uncompressed request payload body after transport decoding |
+| `http.response_content_length` | The size of the response payload body in bytes |
+| `http.response_content_length_uncompressed` | The size of the uncompressed response payload body after transport decoding |
+| `http.route` | The matched route (path template). |
+| `http.scheme` | The URI scheme identifying the used protocol |
+| `http.server_name` | The primary server name of the matched virtual host |
+| `http.status_code` | HTTP response status code |
+| `http.target` | The full request target as passed in a HTTP request line or equivalent |
+| `http.url` | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]` |
+| `http.user_agent` | Value of the HTTP User-Agent header sent by the client |
+| `net.host.ip` | Like net.peer.ip but for the host IP. Useful in case of a multi-IP host |
+| `net.host.name` | Local hostname or similar |
+| `net.host.port` | Like net.peer.port but for the host port |
+| `net.peer.ip.` | Remote address of the peer (dotted decimal for IPv4 or RFC5952 for IPv6) |
+| `net.peer.name` | Remote hostname or similar |
+| `net.peer.port` | Remote port number |
+| `net.transport` | Transport protocol used |
## Useful links
diff --git a/experimental/packages/opentelemetry-instrumentation-http/package.json b/experimental/packages/opentelemetry-instrumentation-http/package.json
index da4e3231eb6..346adc86343 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/package.json
+++ b/experimental/packages/opentelemetry-instrumentation-http/package.json
@@ -1,7 +1,7 @@
{
"name": "@opentelemetry/instrumentation-http",
- "version": "0.49.1",
- "description": "OpenTelemetry http/https automatic instrumentation package.",
+ "version": "0.52.1",
+ "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",
"repository": "open-telemetry/opentelemetry-js",
@@ -9,7 +9,9 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build",
"clean": "tsc --build --clean",
- "test": "nyc ts-mocha -p tsconfig.json test/**/*.test.ts",
+ "test:cjs": "nyc mocha test/**/*.test.ts",
+ "test:esm": "nyc node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ../../../node_modules/mocha/bin/mocha 'test/**/*.test.mjs'",
+ "test": "npm run test:cjs && npm run test:esm",
"tdd": "npm run test -- --watch-extensions ts --watch",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
@@ -18,7 +20,9 @@
"watch": "tsc --build --watch",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "node ../../../scripts/version-update.js",
- "peer-api-check": "node ../../../scripts/peer-api-check.js"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js",
+ "maint:regenerate-test-certs": "cd test/fixtures && ./regenerate.sh"
},
"keywords": [
"opentelemetry",
@@ -45,18 +49,18 @@
"access": "public"
},
"devDependencies": {
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/context-async-hooks": "1.22.0",
- "@opentelemetry/sdk-metrics": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@opentelemetry/sdk-trace-node": "1.22.0",
- "@types/mocha": "10.0.6",
+ "@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",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
"@types/request-promise-native": "1.0.21",
- "@types/semver": "7.5.6",
- "@types/sinon": "10.0.20",
- "@types/superagent": "4.1.24",
- "axios": "1.5.1",
+ "@types/semver": "7.5.8",
+ "@types/sinon": "17.0.3",
+ "@types/superagent": "8.1.8",
+ "axios": "1.6.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
"lerna": "6.6.2",
@@ -66,17 +70,16 @@
"request": "2.88.2",
"request-promise-native": "1.0.9",
"sinon": "15.1.2",
- "superagent": "8.0.9",
- "ts-mocha": "10.0.0",
+ "superagent": "9.0.2",
"typescript": "4.4.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/semantic-conventions": "1.22.0",
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/instrumentation": "0.52.1",
+ "@opentelemetry/semantic-conventions": "1.25.1",
"semver": "^7.5.2"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http",
diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts
index 959eb5de961..f227051b6fc 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts
@@ -52,24 +52,23 @@ import { VERSION } from './version';
import {
InstrumentationBase,
InstrumentationNodeModuleDefinition,
- isWrapped,
safeExecuteInTheMiddle,
} from '@opentelemetry/instrumentation';
import { RPCMetadata, RPCType, setRPCMetadata } from '@opentelemetry/core';
import { errorMonitor } from 'events';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import { SEMATTRS_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';
/**
* Http instrumentation instrumentation for Opentelemetry
*/
-export class HttpInstrumentation extends InstrumentationBase {
+export class HttpInstrumentation extends InstrumentationBase {
/** keep track on spans not ended */
private readonly _spanNotEnded: WeakSet = new WeakSet();
private _headerCapture;
private _httpServerDurationHistogram!: Histogram;
private _httpClientDurationHistogram!: Histogram;
- constructor(config?: HttpInstrumentationConfig) {
+ constructor(config: HttpInstrumentationConfig = {}) {
super('@opentelemetry/instrumentation-http', VERSION, config);
this._headerCapture = this._createHeaderCapture();
}
@@ -93,106 +92,94 @@ export class HttpInstrumentation extends InstrumentationBase {
);
}
- private _getConfig(): HttpInstrumentationConfig {
- return this._config;
- }
-
- override setConfig(config?: HttpInstrumentationConfig): void {
+ override setConfig(config: HttpInstrumentationConfig = {}): void {
super.setConfig(config);
this._headerCapture = this._createHeaderCapture();
}
init(): [
- InstrumentationNodeModuleDefinition,
- InstrumentationNodeModuleDefinition,
+ InstrumentationNodeModuleDefinition,
+ InstrumentationNodeModuleDefinition,
] {
return [this._getHttpsInstrumentation(), this._getHttpInstrumentation()];
}
private _getHttpInstrumentation() {
- const version = process.versions.node;
- return new InstrumentationNodeModuleDefinition(
+ return new InstrumentationNodeModuleDefinition(
'http',
['*'],
- moduleExports => {
- this._diag.debug(`Applying patch for http@${version}`);
- if (isWrapped(moduleExports.request)) {
- this._unwrap(moduleExports, 'request');
- }
- this._wrap(
- moduleExports,
- 'request',
- this._getPatchOutgoingRequestFunction('http')
- );
- if (isWrapped(moduleExports.get)) {
- this._unwrap(moduleExports, 'get');
+ (moduleExports: Http): Http => {
+ if (!this.getConfig().disableOutgoingRequestInstrumentation) {
+ const patchedRequest = this._wrap(
+ moduleExports,
+ 'request',
+ this._getPatchOutgoingRequestFunction('http')
+ ) as unknown as Func;
+ this._wrap(
+ moduleExports,
+ 'get',
+ this._getPatchOutgoingGetFunction(patchedRequest)
+ );
}
- this._wrap(
- moduleExports,
- 'get',
- this._getPatchOutgoingGetFunction(moduleExports.request)
- );
- if (isWrapped(moduleExports.Server.prototype.emit)) {
- this._unwrap(moduleExports.Server.prototype, 'emit');
+ if (!this.getConfig().disableIncomingRequestInstrumentation) {
+ this._wrap(
+ moduleExports.Server.prototype,
+ 'emit',
+ this._getPatchIncomingRequestFunction('http')
+ );
}
- this._wrap(
- moduleExports.Server.prototype,
- 'emit',
- this._getPatchIncomingRequestFunction('http')
- );
return moduleExports;
},
- moduleExports => {
+ (moduleExports: Http) => {
if (moduleExports === undefined) return;
- this._diag.debug(`Removing patch for http@${version}`);
- this._unwrap(moduleExports, 'request');
- this._unwrap(moduleExports, 'get');
- this._unwrap(moduleExports.Server.prototype, 'emit');
+ if (!this.getConfig().disableOutgoingRequestInstrumentation) {
+ this._unwrap(moduleExports, 'request');
+ this._unwrap(moduleExports, 'get');
+ }
+ if (!this.getConfig().disableIncomingRequestInstrumentation) {
+ this._unwrap(moduleExports.Server.prototype, 'emit');
+ }
}
);
}
private _getHttpsInstrumentation() {
- const version = process.versions.node;
- return new InstrumentationNodeModuleDefinition(
+ return new InstrumentationNodeModuleDefinition(
'https',
['*'],
- moduleExports => {
- this._diag.debug(`Applying patch for https@${version}`);
- if (isWrapped(moduleExports.request)) {
- this._unwrap(moduleExports, 'request');
- }
- this._wrap(
- moduleExports,
- 'request',
- this._getPatchHttpsOutgoingRequestFunction('https')
- );
- if (isWrapped(moduleExports.get)) {
- this._unwrap(moduleExports, 'get');
+ (moduleExports: Https): Https => {
+ if (!this.getConfig().disableOutgoingRequestInstrumentation) {
+ const patchedRequest = this._wrap(
+ moduleExports,
+ 'request',
+ this._getPatchHttpsOutgoingRequestFunction('https')
+ ) as unknown as Func;
+ this._wrap(
+ moduleExports,
+ 'get',
+ this._getPatchHttpsOutgoingGetFunction(patchedRequest)
+ );
}
- this._wrap(
- moduleExports,
- 'get',
- this._getPatchHttpsOutgoingGetFunction(moduleExports.request)
- );
- if (isWrapped(moduleExports.Server.prototype.emit)) {
- this._unwrap(moduleExports.Server.prototype, 'emit');
+ if (!this.getConfig().disableIncomingRequestInstrumentation) {
+ this._wrap(
+ moduleExports.Server.prototype,
+ 'emit',
+ this._getPatchIncomingRequestFunction('https')
+ );
}
- this._wrap(
- moduleExports.Server.prototype,
- 'emit',
- this._getPatchIncomingRequestFunction('https')
- );
return moduleExports;
},
- moduleExports => {
+ (moduleExports: Https) => {
if (moduleExports === undefined) return;
- this._diag.debug(`Removing patch for https@${version}`);
- this._unwrap(moduleExports, 'request');
- this._unwrap(moduleExports, 'get');
- this._unwrap(moduleExports.Server.prototype, 'emit');
+ if (!this.getConfig().disableOutgoingRequestInstrumentation) {
+ this._unwrap(moduleExports, 'request');
+ this._unwrap(moduleExports, 'get');
+ }
+ if (!this.getConfig().disableIncomingRequestInstrumentation) {
+ this._unwrap(moduleExports.Server.prototype, 'emit');
+ }
}
);
}
@@ -311,7 +298,7 @@ export class HttpInstrumentation extends InstrumentationBase {
startTime: HrTime,
metricAttributes: MetricAttributes
): http.ClientRequest {
- if (this._getConfig().requestHook) {
+ if (this.getConfig().requestHook) {
this._callRequestHook(span, request);
}
@@ -340,7 +327,7 @@ export class HttpInstrumentation extends InstrumentationBase {
utils.getOutgoingRequestMetricAttributesOnResponse(responseAttributes)
);
- if (this._getConfig().responseHook) {
+ if (this.getConfig().responseHook) {
this._callResponseHook(span, response);
}
@@ -375,10 +362,10 @@ export class HttpInstrumentation extends InstrumentationBase {
span.setStatus(status);
- if (this._getConfig().applyCustomAttributesOnSpan) {
+ if (this.getConfig().applyCustomAttributesOnSpan) {
safeExecuteInTheMiddle(
() =>
- this._getConfig().applyCustomAttributesOnSpan!(
+ this.getConfig().applyCustomAttributesOnSpan!(
span,
request,
response
@@ -468,13 +455,13 @@ export class HttpInstrumentation extends InstrumentationBase {
if (
utils.isIgnored(
pathname,
- instrumentation._getConfig().ignoreIncomingPaths,
+ instrumentation.getConfig().ignoreIncomingPaths,
(e: unknown) =>
instrumentation._diag.error('caught ignoreIncomingPaths error: ', e)
) ||
safeExecuteInTheMiddle(
() =>
- instrumentation._getConfig().ignoreIncomingRequestHook?.(request),
+ instrumentation.getConfig().ignoreIncomingRequestHook?.(request),
(e: unknown) => {
if (e != null) {
instrumentation._diag.error(
@@ -497,10 +484,10 @@ export class HttpInstrumentation extends InstrumentationBase {
const spanAttributes = utils.getIncomingRequestAttributes(request, {
component: component,
- serverName: instrumentation._getConfig().serverName,
+ serverName: instrumentation.getConfig().serverName,
hookAttributes: instrumentation._callStartSpanHook(
request,
- instrumentation._getConfig().startIncomingSpanHook
+ instrumentation.getConfig().startIncomingSpanHook
),
});
@@ -526,10 +513,10 @@ export class HttpInstrumentation extends InstrumentationBase {
context.bind(context.active(), request);
context.bind(context.active(), response);
- if (instrumentation._getConfig().requestHook) {
+ if (instrumentation.getConfig().requestHook) {
instrumentation._callRequestHook(span, request);
}
- if (instrumentation._getConfig().responseHook) {
+ if (instrumentation.getConfig().responseHook) {
instrumentation._callResponseHook(span, response);
}
@@ -608,14 +595,14 @@ export class HttpInstrumentation extends InstrumentationBase {
if (
utils.isIgnored(
origin + pathname,
- instrumentation._getConfig().ignoreOutgoingUrls,
+ instrumentation.getConfig().ignoreOutgoingUrls,
(e: unknown) =>
instrumentation._diag.error('caught ignoreOutgoingUrls error: ', e)
) ||
safeExecuteInTheMiddle(
() =>
instrumentation
- ._getConfig()
+ .getConfig()
.ignoreOutgoingRequestHook?.(optionsParsed),
(e: unknown) => {
if (e != null) {
@@ -639,7 +626,7 @@ export class HttpInstrumentation extends InstrumentationBase {
hostname,
hookAttributes: instrumentation._callStartSpanHook(
optionsParsed,
- instrumentation._getConfig().startOutgoingSpanHook
+ instrumentation.getConfig().startOutgoingSpanHook
),
});
@@ -729,15 +716,15 @@ export class HttpInstrumentation extends InstrumentationBase {
code: utils.parseResponseStatus(SpanKind.SERVER, response.statusCode),
});
- const route = attributes[SemanticAttributes.HTTP_ROUTE];
+ const route = attributes[SEMATTRS_HTTP_ROUTE];
if (route) {
span.updateName(`${request.method || 'GET'} ${route}`);
}
- if (this._getConfig().applyCustomAttributesOnSpan) {
+ if (this.getConfig().applyCustomAttributesOnSpan) {
safeExecuteInTheMiddle(
() =>
- this._getConfig().applyCustomAttributesOnSpan!(
+ this.getConfig().applyCustomAttributesOnSpan!(
span,
request,
response
@@ -771,8 +758,8 @@ export class HttpInstrumentation extends InstrumentationBase {
*/
const requireParent =
options.kind === SpanKind.CLIENT
- ? this._getConfig().requireParentforOutgoingSpans
- : this._getConfig().requireParentforIncomingSpans;
+ ? this.getConfig().requireParentforOutgoingSpans
+ : this.getConfig().requireParentforIncomingSpans;
let span: Span;
const currentSpan = trace.getSpan(ctx);
@@ -815,7 +802,7 @@ export class HttpInstrumentation extends InstrumentationBase {
response: http.IncomingMessage | http.ServerResponse
) {
safeExecuteInTheMiddle(
- () => this._getConfig().responseHook!(span, response),
+ () => this.getConfig().responseHook!(span, response),
() => {},
true
);
@@ -826,7 +813,7 @@ export class HttpInstrumentation extends InstrumentationBase {
request: http.ClientRequest | http.IncomingMessage
) {
safeExecuteInTheMiddle(
- () => this._getConfig().requestHook!(span, request),
+ () => this.getConfig().requestHook!(span, request),
() => {},
true
);
@@ -846,7 +833,7 @@ export class HttpInstrumentation extends InstrumentationBase {
}
private _createHeaderCapture() {
- const config = this._getConfig();
+ const config = this.getConfig();
return {
client: {
diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/types.ts b/experimental/packages/opentelemetry-instrumentation-http/src/types.ts
index 5cc09341d43..a0e783a1bdb 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/src/types.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/src/types.ts
@@ -98,6 +98,10 @@ export interface HttpInstrumentationConfig extends InstrumentationConfig {
ignoreOutgoingUrls?: IgnoreMatcher[];
/** Not trace all outgoing requests that matched with custom function */
ignoreOutgoingRequestHook?: IgnoreOutgoingRequestFunction;
+ /** If set to true, incoming requests will not be instrumented at all. */
+ disableIncomingRequestInstrumentation?: boolean;
+ /** If set to true, outgoing requests will not be instrumented at all. */
+ disableOutgoingRequestInstrumentation?: boolean;
/** Function for adding custom attributes after response is handled */
applyCustomAttributesOnSpan?: HttpCustomAttributeFunction;
/** Function for adding custom attributes before request is handled */
diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts b/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts
index a70dd3de854..8191af242f3 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts
@@ -22,8 +22,30 @@ import {
SpanKind,
} from '@opentelemetry/api';
import {
- NetTransportValues,
- SemanticAttributes,
+ NETTRANSPORTVALUES_IP_TCP,
+ NETTRANSPORTVALUES_IP_UDP,
+ SEMATTRS_HTTP_CLIENT_IP,
+ SEMATTRS_HTTP_FLAVOR,
+ SEMATTRS_HTTP_HOST,
+ SEMATTRS_HTTP_METHOD,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_ROUTE,
+ SEMATTRS_HTTP_SCHEME,
+ SEMATTRS_HTTP_SERVER_NAME,
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_HTTP_TARGET,
+ SEMATTRS_HTTP_URL,
+ SEMATTRS_HTTP_USER_AGENT,
+ SEMATTRS_NET_HOST_IP,
+ SEMATTRS_NET_HOST_NAME,
+ SEMATTRS_NET_HOST_PORT,
+ SEMATTRS_NET_PEER_IP,
+ SEMATTRS_NET_PEER_NAME,
+ SEMATTRS_NET_PEER_PORT,
+ SEMATTRS_NET_TRANSPORT,
} from '@opentelemetry/semantic-conventions';
import {
IncomingHttpHeaders,
@@ -145,11 +167,8 @@ export const isIgnored = (
export const setSpanWithError = (span: Span, error: Err): void => {
const message = error.message;
- span.setAttributes({
- [AttributeNames.HTTP_ERROR_NAME]: error.name,
- [AttributeNames.HTTP_ERROR_MESSAGE]: message,
- });
-
+ span.setAttribute(AttributeNames.HTTP_ERROR_NAME, error.name);
+ span.setAttribute(AttributeNames.HTTP_ERROR_MESSAGE, message);
span.setStatus({ code: SpanStatusCode.ERROR, message });
span.recordException(error);
};
@@ -167,10 +186,9 @@ export const setRequestContentLengthAttribute = (
if (length === null) return;
if (isCompressed(request.headers)) {
- attributes[SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH] = length;
+ attributes[SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH] = length;
} else {
- attributes[SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED] =
- length;
+ attributes[SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED] = length;
}
};
@@ -187,10 +205,9 @@ export const setResponseContentLengthAttribute = (
if (length === null) return;
if (isCompressed(response.headers)) {
- attributes[SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH] = length;
+ attributes[SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH] = length;
} else {
- attributes[SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED] =
- length;
+ attributes[SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED] = length;
}
};
@@ -343,20 +360,19 @@ export const getOutgoingRequestAttributes = (
const headers = requestOptions.headers || {};
const userAgent = headers['user-agent'];
const attributes: SpanAttributes = {
- [SemanticAttributes.HTTP_URL]: getAbsoluteUrl(
+ [SEMATTRS_HTTP_URL]: getAbsoluteUrl(
requestOptions,
headers,
`${options.component}:`
),
- [SemanticAttributes.HTTP_METHOD]: method,
- [SemanticAttributes.HTTP_TARGET]: requestOptions.path || '/',
- [SemanticAttributes.NET_PEER_NAME]: hostname,
- [SemanticAttributes.HTTP_HOST]:
- requestOptions.headers?.host ?? `${hostname}:${port}`,
+ [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[SemanticAttributes.HTTP_USER_AGENT] = userAgent;
+ attributes[SEMATTRS_HTTP_USER_AGENT] = userAgent;
}
return Object.assign(attributes, options.hookAttributes);
};
@@ -369,11 +385,10 @@ export const getOutgoingRequestMetricAttributes = (
spanAttributes: SpanAttributes
): MetricAttributes => {
const metricAttributes: MetricAttributes = {};
- metricAttributes[SemanticAttributes.HTTP_METHOD] =
- spanAttributes[SemanticAttributes.HTTP_METHOD];
- metricAttributes[SemanticAttributes.NET_PEER_NAME] =
- spanAttributes[SemanticAttributes.NET_PEER_NAME];
- //TODO: http.url attribute, it should susbtitute any parameters to avoid high cardinality.
+ metricAttributes[SEMATTRS_HTTP_METHOD] = spanAttributes[SEMATTRS_HTTP_METHOD];
+ metricAttributes[SEMATTRS_NET_PEER_NAME] =
+ spanAttributes[SEMATTRS_NET_PEER_NAME];
+ //TODO: http.url attribute, it should substitute any parameters to avoid high cardinality.
return metricAttributes;
};
@@ -381,17 +396,18 @@ export const getOutgoingRequestMetricAttributes = (
* Returns attributes related to the kind of HTTP protocol used
* @param {string} [kind] Kind of HTTP protocol used: "1.0", "1.1", "2", "SPDY" or "QUIC".
*/
-export const getAttributesFromHttpKind = (kind?: string): SpanAttributes => {
- const attributes: SpanAttributes = {};
+export const setAttributesFromHttpKind = (
+ kind: string | undefined,
+ attributes: SpanAttributes
+): void => {
if (kind) {
- attributes[SemanticAttributes.HTTP_FLAVOR] = kind;
+ attributes[SEMATTRS_HTTP_FLAVOR] = kind;
if (kind.toUpperCase() !== 'QUIC') {
- attributes[SemanticAttributes.NET_TRANSPORT] = NetTransportValues.IP_TCP;
+ attributes[SEMATTRS_NET_TRANSPORT] = NETTRANSPORTVALUES_IP_TCP;
} else {
- attributes[SemanticAttributes.NET_TRANSPORT] = NetTransportValues.IP_UDP;
+ attributes[SEMATTRS_NET_TRANSPORT] = NETTRANSPORTVALUES_IP_UDP;
}
}
- return attributes;
};
/**
@@ -406,20 +422,20 @@ export const getOutgoingRequestAttributesOnResponse = (
const attributes: SpanAttributes = {};
if (socket) {
const { remoteAddress, remotePort } = socket;
- attributes[SemanticAttributes.NET_PEER_IP] = remoteAddress;
- attributes[SemanticAttributes.NET_PEER_PORT] = remotePort;
+ attributes[SEMATTRS_NET_PEER_IP] = remoteAddress;
+ attributes[SEMATTRS_NET_PEER_PORT] = remotePort;
}
setResponseContentLengthAttribute(response, attributes);
if (statusCode) {
- attributes[SemanticAttributes.HTTP_STATUS_CODE] = statusCode;
+ attributes[SEMATTRS_HTTP_STATUS_CODE] = statusCode;
attributes[AttributeNames.HTTP_STATUS_TEXT] = (
statusMessage || ''
).toUpperCase();
}
- const httpKindAttributes = getAttributesFromHttpKind(httpVersion);
- return Object.assign(attributes, httpKindAttributes);
+ setAttributesFromHttpKind(httpVersion, attributes);
+ return attributes;
};
/**
@@ -430,12 +446,11 @@ export const getOutgoingRequestMetricAttributesOnResponse = (
spanAttributes: SpanAttributes
): MetricAttributes => {
const metricAttributes: MetricAttributes = {};
- metricAttributes[SemanticAttributes.NET_PEER_PORT] =
- spanAttributes[SemanticAttributes.NET_PEER_PORT];
- metricAttributes[SemanticAttributes.HTTP_STATUS_CODE] =
- spanAttributes[SemanticAttributes.HTTP_STATUS_CODE];
- metricAttributes[SemanticAttributes.HTTP_FLAVOR] =
- spanAttributes[SemanticAttributes.HTTP_FLAVOR];
+ metricAttributes[SEMATTRS_NET_PEER_PORT] =
+ spanAttributes[SEMATTRS_NET_PEER_PORT];
+ metricAttributes[SEMATTRS_HTTP_STATUS_CODE] =
+ spanAttributes[SEMATTRS_HTTP_STATUS_CODE];
+ metricAttributes[SEMATTRS_HTTP_FLAVOR] = spanAttributes[SEMATTRS_HTTP_FLAVOR];
return metricAttributes;
};
@@ -465,36 +480,35 @@ export const getIncomingRequestAttributes = (
'localhost';
const serverName = options.serverName;
const attributes: SpanAttributes = {
- [SemanticAttributes.HTTP_URL]: getAbsoluteUrl(
+ [SEMATTRS_HTTP_URL]: getAbsoluteUrl(
requestUrl,
headers,
`${options.component}:`
),
- [SemanticAttributes.HTTP_HOST]: host,
- [SemanticAttributes.NET_HOST_NAME]: hostname,
- [SemanticAttributes.HTTP_METHOD]: method,
- [SemanticAttributes.HTTP_SCHEME]: options.component,
+ [SEMATTRS_HTTP_HOST]: host,
+ [SEMATTRS_NET_HOST_NAME]: hostname,
+ [SEMATTRS_HTTP_METHOD]: method,
+ [SEMATTRS_HTTP_SCHEME]: options.component,
};
if (typeof ips === 'string') {
- attributes[SemanticAttributes.HTTP_CLIENT_IP] = ips.split(',')[0];
+ attributes[SEMATTRS_HTTP_CLIENT_IP] = ips.split(',')[0];
}
if (typeof serverName === 'string') {
- attributes[SemanticAttributes.HTTP_SERVER_NAME] = serverName;
+ attributes[SEMATTRS_HTTP_SERVER_NAME] = serverName;
}
if (requestUrl) {
- attributes[SemanticAttributes.HTTP_TARGET] = requestUrl.path || '/';
+ attributes[SEMATTRS_HTTP_TARGET] = requestUrl.path || '/';
}
if (userAgent !== undefined) {
- attributes[SemanticAttributes.HTTP_USER_AGENT] = userAgent;
+ attributes[SEMATTRS_HTTP_USER_AGENT] = userAgent;
}
setRequestContentLengthAttribute(request, attributes);
-
- const httpKindAttributes = getAttributesFromHttpKind(httpVersion);
- return Object.assign(attributes, httpKindAttributes, options.hookAttributes);
+ setAttributesFromHttpKind(httpVersion, attributes);
+ return Object.assign(attributes, options.hookAttributes);
};
/**
@@ -506,15 +520,12 @@ export const getIncomingRequestMetricAttributes = (
spanAttributes: SpanAttributes
): MetricAttributes => {
const metricAttributes: MetricAttributes = {};
- metricAttributes[SemanticAttributes.HTTP_SCHEME] =
- spanAttributes[SemanticAttributes.HTTP_SCHEME];
- metricAttributes[SemanticAttributes.HTTP_METHOD] =
- spanAttributes[SemanticAttributes.HTTP_METHOD];
- metricAttributes[SemanticAttributes.NET_HOST_NAME] =
- spanAttributes[SemanticAttributes.NET_HOST_NAME];
- metricAttributes[SemanticAttributes.HTTP_FLAVOR] =
- spanAttributes[SemanticAttributes.HTTP_FLAVOR];
- //TODO: http.target attribute, it should susbtitute any parameters to avoid high cardinality.
+ metricAttributes[SEMATTRS_HTTP_SCHEME] = spanAttributes[SEMATTRS_HTTP_SCHEME];
+ metricAttributes[SEMATTRS_HTTP_METHOD] = spanAttributes[SEMATTRS_HTTP_METHOD];
+ metricAttributes[SEMATTRS_NET_HOST_NAME] =
+ spanAttributes[SEMATTRS_NET_HOST_NAME];
+ metricAttributes[SEMATTRS_HTTP_FLAVOR] = spanAttributes[SEMATTRS_HTTP_FLAVOR];
+ //TODO: http.target attribute, it should substitute any parameters to avoid high cardinality.
return metricAttributes;
};
@@ -535,18 +546,18 @@ export const getIncomingRequestAttributesOnResponse = (
const attributes: SpanAttributes = {};
if (socket) {
const { localAddress, localPort, remoteAddress, remotePort } = socket;
- attributes[SemanticAttributes.NET_HOST_IP] = localAddress;
- attributes[SemanticAttributes.NET_HOST_PORT] = localPort;
- attributes[SemanticAttributes.NET_PEER_IP] = remoteAddress;
- attributes[SemanticAttributes.NET_PEER_PORT] = remotePort;
+ attributes[SEMATTRS_NET_HOST_IP] = localAddress;
+ attributes[SEMATTRS_NET_HOST_PORT] = localPort;
+ attributes[SEMATTRS_NET_PEER_IP] = remoteAddress;
+ attributes[SEMATTRS_NET_PEER_PORT] = remotePort;
}
- attributes[SemanticAttributes.HTTP_STATUS_CODE] = statusCode;
+ attributes[SEMATTRS_HTTP_STATUS_CODE] = statusCode;
attributes[AttributeNames.HTTP_STATUS_TEXT] = (
statusMessage || ''
).toUpperCase();
if (rpcMetadata?.type === RPCType.HTTP && rpcMetadata.route !== undefined) {
- attributes[SemanticAttributes.HTTP_ROUTE] = rpcMetadata.route;
+ attributes[SEMATTRS_HTTP_ROUTE] = rpcMetadata.route;
}
return attributes;
};
@@ -559,36 +570,35 @@ export const getIncomingRequestMetricAttributesOnResponse = (
spanAttributes: SpanAttributes
): MetricAttributes => {
const metricAttributes: MetricAttributes = {};
- metricAttributes[SemanticAttributes.HTTP_STATUS_CODE] =
- spanAttributes[SemanticAttributes.HTTP_STATUS_CODE];
- metricAttributes[SemanticAttributes.NET_HOST_PORT] =
- spanAttributes[SemanticAttributes.NET_HOST_PORT];
- if (spanAttributes[SemanticAttributes.HTTP_ROUTE] !== undefined) {
- metricAttributes[SemanticAttributes.HTTP_ROUTE] =
- spanAttributes[SemanticAttributes.HTTP_ROUTE];
+ metricAttributes[SEMATTRS_HTTP_STATUS_CODE] =
+ spanAttributes[SEMATTRS_HTTP_STATUS_CODE];
+ metricAttributes[SEMATTRS_NET_HOST_PORT] =
+ spanAttributes[SEMATTRS_NET_HOST_PORT];
+ if (spanAttributes[SEMATTRS_HTTP_ROUTE] !== undefined) {
+ metricAttributes[SEMATTRS_HTTP_ROUTE] = spanAttributes[SEMATTRS_HTTP_ROUTE];
}
return metricAttributes;
};
export function headerCapture(type: 'request' | 'response', headers: string[]) {
- const normalizedHeaders = new Map(
- headers.map(header => [
- header.toLowerCase(),
- header.toLowerCase().replace(/-/g, '_'),
- ])
- );
+ const normalizedHeaders = new Map();
+ for (let i = 0, len = headers.length; i < len; i++) {
+ const capturedHeader = headers[i].toLowerCase();
+ normalizedHeaders.set(capturedHeader, capturedHeader.replace(/-/g, '_'));
+ }
return (
span: Span,
getHeader: (key: string) => undefined | string | string[] | number
) => {
- for (const [capturedHeader, normalizedHeader] of normalizedHeaders) {
+ for (const capturedHeader of normalizedHeaders.keys()) {
const value = getHeader(capturedHeader);
if (value === undefined) {
continue;
}
+ const normalizedHeader = normalizedHeaders.get(capturedHeader);
const key = `http.${type}.header.${normalizedHeader}`;
if (typeof value === 'string') {
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/regenerate.sh b/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/regenerate.sh
index af9c63e310f..af7d26ef7c3 100755
--- a/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/regenerate.sh
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/regenerate.sh
@@ -1,10 +1,10 @@
#!/usr/bin/env sh
#
-# Usage: regenerate.sh
-#
-# regenerate.sh regenerates private key and certificate used in https tests and example
+# Regenerate TLS certificates that are used by "examples/https/".
+# Certs are generated with a one year expiry, so periodic regen is required.
#
+# Usage: npm run maint:regenerate-test-certs
-EXAMPLE_DIR="../../../../examples/https"
+EXAMPLE_DIR="../../../../../examples/https"
openssl req -x509 -nodes -newkey rsa -keyout server-key.pem -out server-cert.pem -days 3650 -subj "/C=CL/ST=RM/L=OpenTelemetryTest/O=Root/OU=Test/CN=ca"
cp ./server-*.pem "$EXAMPLE_DIR/"
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/server-cert.pem b/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/server-cert.pem
index 4dd904f0882..5e957ab5b25 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/server-cert.pem
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/server-cert.pem
@@ -1,22 +1,22 @@
-----BEGIN CERTIFICATE-----
-MIIDozCCAougAwIBAgIUZdBdHwmbcYbMUvOesYRyYlg11JMwDQYJKoZIhvcNAQEL
+MIIDozCCAougAwIBAgIUNmVva8tI/hqzZAB7FZzPmNr/Q0owDQYJKoZIhvcNAQEL
BQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQHDBFPcGVuVGVs
ZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9vdDENMAsGA1UECwwEVGVzdDELMAkGA1UE
-AwwCY2EwHhcNMjEwNjA4MDgxNTE2WhcNMzEwNjA2MDgxNTE2WjBhMQswCQYDVQQG
+AwwCY2EwHhcNMjQwNjA4MTkxODUyWhcNMzQwNjA2MTkxODUyWjBhMQswCQYDVQQG
EwJDTDELMAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0w
CwYDVQQKDARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBALw9Shaqp1O1zgYK8z5pnvuHK3o9cUNT
-+EJz5KLADn11HSgfj5S96s6lDP9mUy8oDXdk9zSH8QsPp/maVh0AM1WrPDDTBJT5
-vdPyUezzn4wvBrJSG/mmy/p4QU1srmE0ueuhgot97GZa9qu+gOqGei3YTjrbx14H
-jyvexx+QhqrpUg46qAm67pJHC5jN6LmufoIvepyvQCEbKN+n2B2tAn9on1wo7UmB
-igTEiWxk1Gn70IJuyTEbpHoLFviQ5kvTYXM/2KHMOXjZM9fQxtbseNUmj8VK3+tS
-5jBdIROZxKxh3r9rV7SBHrblTWB3CZ/NsJblZuzMazLWkYS1/JZud9ECAwEAAaNT
-MFEwHQYDVR0OBBYEFP6+DMoQBCg7tOYrSUpWKQrbfJ5yMB8GA1UdIwQYMBaAFP6+
-DMoQBCg7tOYrSUpWKQrbfJ5yMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
-BQADggEBAGbkwraWuKnhcE8GrLCO0qLq5GaF+WvxqVzgPvG3G6bQJuEnS6LT65nR
-ICU82vCQBikW6lDfpsiwcVqOmgefUmjI99Aw5S1dkYy2J+WZrU/EgX445JLGJMpB
-Bh0QajFT6gdQiuURqTmxAhNj4VrUqtrNapP8vFKerR7nTrORG0ELEcvzVYCLNvDm
-OYWvLEMZifNWKY6hRdhZXho5hfu7/YPUhZUpcSxkTUsDnG3gzkTyX1TzeWe7wlJr
-dtNIk50lUCR6TlSpTaVB+6uhVjaLZpZwBAT5H0dWQXm0Ww5AYsEAT9Uzh9fZYu4m
-iMhztKH3PWjDB+jSzcOv9FXeYWgprWk=
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAM80Psz6Kc4/x1Qx4OmYuacrCDL4JNY+
+SWzEm1kb25/E1+TrxYC8XluJtXwi9JRC7ovR8UIbZNVgWwPHlSXrTQsVe2sISr4K
+oRg87vmcRYzsOval+ZViFelUo9t5sYeiX0xBuMP1ENfEL+gtu2QrkmgDhy/XdRpm
+qpcrtJxXaIXedy82y7Av5da7jJyJ+9oaTq0Am0qyZjpzTs3jKEh1roWoc3pd6T4d
+asNHLeKrsq3bTasEH/Lo9k4t+2n1j5C+L5gWhPcCv8yzhGsrSiqxn+P9m/USXY/w
+HH9AyV7Dk4Jh8BjUOlYaqOLIEow7hwdxVBk1BO6Jmpxv8KI3qQjtLWsCAwEAAaNT
+MFEwHQYDVR0OBBYEFOueTx80MsHFiBvP0RO99CpVdj0ZMB8GA1UdIwQYMBaAFOue
+Tx80MsHFiBvP0RO99CpVdj0ZMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAJYqqU3wCDX+YZDZ4zd8k725MSfKk1omCxDzDzjuNAjqD/vuSE0YfdFB
+bTWMiBGsCqa6FgWwyT2oMPnJKShScZReFEZcM2s+/odfwUTwF4lD/UvZf6PdDhJ5
+kxqhoej2ZT8NY+m+rddmg5MaurIcIfOhOxRjarmhs2lrg5qmGKznauettsmA1ZpR
+d2ZZA10WstCKN7jHOUqUmSB/2oC/NZno09yXqgbNwIEwBgsUDNaYkGzIzsKD+mOy
+NTxLo/PJ5venVgboomDkWJqOOm+HtqfD64rczWyTS/ZdQhuFlk+aCYAwOhYZZH9Z
+IEkKcW8xN5+q8Bi9nsst5F1cuw84LD4=
-----END CERTIFICATE-----
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/server-key.pem b/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/server-key.pem
index 267ed0464e2..81c27246449 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/server-key.pem
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/fixtures/server-key.pem
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8PUoWqqdTtc4G
-CvM+aZ77hyt6PXFDU/hCc+SiwA59dR0oH4+UverOpQz/ZlMvKA13ZPc0h/ELD6f5
-mlYdADNVqzww0wSU+b3T8lHs85+MLwayUhv5psv6eEFNbK5hNLnroYKLfexmWvar
-voDqhnot2E4628deB48r3scfkIaq6VIOOqgJuu6SRwuYzei5rn6CL3qcr0AhGyjf
-p9gdrQJ/aJ9cKO1JgYoExIlsZNRp+9CCbskxG6R6Cxb4kOZL02FzP9ihzDl42TPX
-0MbW7HjVJo/FSt/rUuYwXSETmcSsYd6/a1e0gR625U1gdwmfzbCW5WbszGsy1pGE
-tfyWbnfRAgMBAAECggEAP1YT7qp+4ICkkI3wqEhbkOA7Ncckq/W964YZINWkSnw0
-UkLESdTZA6yvQeQJCy3b0hdrwgYXiZQ7/ZT7coiVvTZ/ayIlQYcCYyT+gc67GSzd
-gPR1qzt/GIiL2GRADD70a58NUKgO+aWTp9fSgpa612AXemBmpXG/r5Amya0UUr7Y
-KdSpBuOgomZMqEm2mYDdI4LRw2xbWoWTVvCndhypbXTJ2D8/QhbNfliWTG9MBy90
-UAQpaQGNwHzmCgwBJ03QJuE+OXjX80XcOOIYh6l68wkDeSfqaYx95OQZ3oOr6QT8
-TLYv08M9Grrrj5rPttpycBoxVbtLxkhE0Rt0q9K4HQKBgQD0EuR35CNTIIx/gikO
-CxdbSroPW9r92+IXCWcbbtRbVruHBpXzsMeHse4uqhtYmFNbgfgh12dC6OX7NzJx
-3Ds4NW8DvcZ3mVq8iEiOZnX5ydeeYMetlDWhXx2/0be5vqmrUkkWdfXsFUCyS8Lw
-vGRc9BiNqFePg2HsoVd2tezrwwKBgQDFb/eef/nOM1Eq5h+u+0Pyyg07iRuxxNup
-YXY9hwNJyF+NUoIWx2Jfyh+dQfMC18g/4hN4Hwfm/nC85SkPheKJnXYgMWMXp2Y7
-PBgdZGCX/546xiS5VGAoRuLd8oO2AlDfgU4tw6U0WZguJ6hMXlePlKz/uAJ237FB
-gcPyGNeY2wKBgQDOD4038zInolk75YYHxzFm78X55ZETtipBTLzyGjXLD4SvUM4U
-uXEbjQsL9q2ztJbbsPTujU8u3DYeS9GY81hD8kjRnc0LeDt05JJtNu/vfYs+uXKb
-h39nyEfzhHlapi/U5lmyTtDbCm5emTvxxvvsxmBcaH3UOhXYk7amEJ3/xQKBgA+s
-svj3agqv0krYmD1ZH2zgE6rdWMCFQ3cwEKYT2PP7n3Jl0YQjcjDuqBHhEXzxSqmf
-tjH8LLFvE947R0Y/N9v7D0zA/v/6v0gGnld/B5gpqBM8dd/szfGEpzA9t600g90q
-s904Qh5k2osXhOoDN2pjwFRQ9Ikhez4bIkZPKJavAoGAV2YPXyw5rrAZtCtybqsO
-B+15Lh+KC+vs0rBBhb0MUpXQPgQ6SX8ozpLHtqlsUpNfHwOk5K958jMrM9Rx4dhS
-Z6WuTa+9QpmXzYTnCDBbEU06+YB1QR2QfU4BlAAu1RtUbbt84/7OAoNh2IqOO4XJ
-THlhj8odimsk4R1B0RipBis=
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDPND7M+inOP8dU
+MeDpmLmnKwgy+CTWPklsxJtZG9ufxNfk68WAvF5bibV8IvSUQu6L0fFCG2TVYFsD
+x5Ul600LFXtrCEq+CqEYPO75nEWM7Dr2pfmVYhXpVKPbebGHol9MQbjD9RDXxC/o
+LbtkK5JoA4cv13UaZqqXK7ScV2iF3ncvNsuwL+XWu4ycifvaGk6tAJtKsmY6c07N
+4yhIda6FqHN6Xek+HWrDRy3iq7Kt202rBB/y6PZOLftp9Y+Qvi+YFoT3Ar/Ms4Rr
+K0oqsZ/j/Zv1El2P8Bx/QMlew5OCYfAY1DpWGqjiyBKMO4cHcVQZNQTuiZqcb/Ci
+N6kI7S1rAgMBAAECggEAA4u31WckhwCFZzXxTN4Ns0QjwEeJzdbEB+X3aJd28y15
+qlO0jgbrMHLTVbv9ZnocvezKTaDNYW9kL1TfgwYbS+jCs2qxaL4i0pjcWA4qDIbQ
+XX8qnblPea42nZ9f/9ux+MqZIFVVw/N6BGWf8s9iEoCY9CMiQGDoY2zeitxeEAhe
+KGZHozaTUVAClrwMqKYlablWjX8zcoi6bKffUwz/MwecI2iVW72y9/xIGTlwhdZW
+8kDlkBOea3QV5yafcJQ1VsHrvUX3rf4C5uknCenwKbC3Au4+kBdQjv+bUk6aMR38
+OdnMCaUcnuT/UzbbtOSgJ+sVcGW9Jqo0DfS5CNPhuQKBgQD2EtOhjkUErc8KUhPW
+Pt8FNBAuoKsk4mRHpFsY2OjGYA50oiCtiphqfTzkQLbNhVtq83AHNUNWUKBjnMUd
+nAOIIvhpiEI7O+RuOafBtcFBIrUo2Ey5dwfvLJrpb7pEnYj8DNFVPQ/aBxP+mD4b
+RrHRY8DZdVHU9TDMDK7ObpKScwKBgQDXkASnc7O/D0iFxev004sqdTrGo3cBCJUH
+h/c68BrUvPw5u6fFulq5Wt6OOaFoWQmUSVyrhZD3vfrZ1Jocid3wn9uuu9vOazcz
+M3EOF1rz5bgjwb/vk6CyGh1MfmeVCRnuQ3mBIXQ0xwS4QY71Vvw3099fhbtbMHez
+5gyQv1ojKQKBgHkXBqGHmxsUVL/lZ/GT+rdayWPImK+L4IEItfNiOhn0huiKJ75+
+Z0Zv3pkL52j3aOcWaFiDs2E0R9j8+lr5vRsu6kM0VDNF48ECCjVetXzSEYfJ+OeD
+VZoyvwCEhIrjYtd1j0V8yOInfYVZcaaGgVZi2jGoc95x0dN3okXfT61VAoGAVrCA
+bqdFPizzSXkTL15ztRt4C7JphWziIik37+fnom5uMPmauxX6rlgw8JmUo9ZK1+u4
+7PHGHxuz6i5p29hF/SMMwfSirRzJEjo52STjWvqjVx3wBnUkRvvhlIWxOmpylzNj
+hd7iUOdIqqES0O+udvUp+8xYUI/pU9vMadnKciECgYB3cJ+7EPNgJgdpQ9Pslex8
+6iHdQH9DIyIb/KqQVe7em5NZXwANCAOQ6KqzhszM/eH7NoSeN7C9Z9uHHIHDfz4m
+QO896l7rM1k1R/USaUK4By/O/t/V/aIGjOnPsXxEGrEPDXXBtzUAEs5yAa+Ne1m7
+BiP9MuDgBTVkV1iJx37eqg==
-----END PRIVATE KEY-----
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts
index e5b2cebb97b..77d90b4fa3f 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts
@@ -30,8 +30,14 @@ import {
SimpleSpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import {
- NetTransportValues,
- SemanticAttributes,
+ NETTRANSPORTVALUES_IP_TCP,
+ SEMATTRS_HTTP_CLIENT_IP,
+ SEMATTRS_HTTP_FLAVOR,
+ SEMATTRS_HTTP_ROUTE,
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_NET_HOST_PORT,
+ SEMATTRS_NET_PEER_PORT,
+ SEMATTRS_NET_TRANSPORT,
} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import * as nock from 'nock';
@@ -211,16 +217,65 @@ describe('HttpInstrumentation', () => {
assertSpan(incomingSpan, SpanKind.SERVER, validations);
assertSpan(outgoingSpan, SpanKind.CLIENT, validations);
assert.strictEqual(
- incomingSpan.attributes[SemanticAttributes.NET_HOST_PORT],
+ incomingSpan.attributes[SEMATTRS_NET_HOST_PORT],
serverPort
);
assert.strictEqual(
- outgoingSpan.attributes[SemanticAttributes.NET_PEER_PORT],
+ outgoingSpan.attributes[SEMATTRS_NET_PEER_PORT],
serverPort
);
});
});
+ describe('partially disable instrumentation', () => {
+ beforeEach(() => {
+ memoryExporter.reset();
+ });
+
+ afterEach(() => {
+ server.close();
+ instrumentation.disable();
+ });
+
+ it('allows to disable outgoing request instrumentation', () => {
+ server.close();
+ instrumentation.disable();
+
+ instrumentation.setConfig({
+ disableOutgoingRequestInstrumentation: true,
+ });
+ instrumentation.enable();
+ server = http.createServer((_request, response) => {
+ response.end('Test Server Response');
+ });
+
+ server.listen(serverPort);
+
+ 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', () => {
+ server.close();
+ instrumentation.disable();
+
+ instrumentation.setConfig({
+ disableIncomingRequestInstrumentation: true,
+ });
+ instrumentation.enable();
+ server = http.createServer((_request, response) => {
+ response.end('Test Server Response');
+ });
+
+ server.listen(serverPort);
+
+ assert.strictEqual(isWrapped(http.Server.prototype.emit), false);
+ assert.strictEqual(isWrapped(http.get), true);
+ assert.strictEqual(isWrapped(http.request), true);
+ });
+ });
+
describe('with good instrumentation options', () => {
beforeEach(() => {
memoryExporter.reset();
@@ -329,28 +384,25 @@ describe('HttpInstrumentation', () => {
assert.strictEqual(spans.length, 2);
assert.strictEqual(
- incomingSpan.attributes[SemanticAttributes.HTTP_CLIENT_IP],
+ incomingSpan.attributes[SEMATTRS_HTTP_CLIENT_IP],
''
);
assert.strictEqual(
- incomingSpan.attributes[SemanticAttributes.NET_HOST_PORT],
+ incomingSpan.attributes[SEMATTRS_NET_HOST_PORT],
serverPort
);
assert.strictEqual(
- outgoingSpan.attributes[SemanticAttributes.NET_PEER_PORT],
+ outgoingSpan.attributes[SEMATTRS_NET_PEER_PORT],
serverPort
);
[
{ span: incomingSpan, kind: SpanKind.SERVER },
{ span: outgoingSpan, kind: SpanKind.CLIENT },
].forEach(({ span, kind }) => {
+ assert.strictEqual(span.attributes[SEMATTRS_HTTP_FLAVOR], '1.1');
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_FLAVOR],
- '1.1'
- );
- assert.strictEqual(
- span.attributes[SemanticAttributes.NET_TRANSPORT],
- NetTransportValues.IP_TCP
+ span.attributes[SEMATTRS_NET_TRANSPORT],
+ NETTRANSPORTVALUES_IP_TCP
);
assertSpan(span, kind, validations);
});
@@ -363,10 +415,7 @@ describe('HttpInstrumentation', () => {
const span = memoryExporter.getFinishedSpans()[0];
assert.strictEqual(span.kind, SpanKind.SERVER);
- assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_ROUTE],
- 'TheRoute'
- );
+ assert.strictEqual(span.attributes[SEMATTRS_HTTP_ROUTE], 'TheRoute');
assert.strictEqual(span.name, 'GET TheRoute');
});
@@ -555,7 +604,7 @@ describe('HttpInstrumentation', () => {
});
for (const arg of ['string', {}, new Date()]) {
- it(`should be tracable and not throw exception in ${protocol} instrumentation when passing the following argument ${JSON.stringify(
+ it(`should be traceable and not throw exception in ${protocol} instrumentation when passing the following argument ${JSON.stringify(
arg
)}`, async () => {
try {
@@ -796,10 +845,7 @@ describe('HttpInstrumentation', () => {
const [span] = spans;
assert.strictEqual(spans.length, 1);
assert.ok(Object.keys(span.attributes).length > 6);
- assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_STATUS_CODE],
- 404
- );
+ assert.strictEqual(span.attributes[SEMATTRS_HTTP_STATUS_CODE], 404);
assert.strictEqual(span.status.code, SpanStatusCode.ERROR);
done();
});
@@ -1101,10 +1147,10 @@ describe('HttpInstrumentation', () => {
it('should set rpc metadata for incoming http request', async () => {
server = http.createServer((request, response) => {
- const rpcMemadata = getRPCMetadata(context.active());
- assert(typeof rpcMemadata !== 'undefined');
- assert(rpcMemadata.type === RPCType.HTTP);
- assert(rpcMemadata.span.setAttribute('key', 'value'));
+ const rpcMetadata = getRPCMetadata(context.active());
+ assert(typeof rpcMetadata !== 'undefined');
+ assert(rpcMetadata.type === RPCType.HTTP);
+ assert(rpcMetadata.span.setAttribute('key', 'value'));
response.end('Test Server Response');
});
await new Promise(resolve => server.listen(serverPort, resolve));
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts
index 0f484f08bf8..599865107c6 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts
@@ -20,7 +20,16 @@ import {
MeterProvider,
} from '@opentelemetry/sdk-metrics';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_HTTP_FLAVOR,
+ SEMATTRS_HTTP_METHOD,
+ SEMATTRS_HTTP_SCHEME,
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_NET_HOST_NAME,
+ SEMATTRS_NET_HOST_PORT,
+ SEMATTRS_NET_PEER_NAME,
+ SEMATTRS_NET_PEER_PORT,
+} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import { HttpInstrumentation } from '../../src/http';
import { httpRequest } from '../utils/httpRequest';
@@ -91,27 +100,27 @@ describe('metrics', () => {
requestCount
);
assert.strictEqual(
- metrics[0].dataPoints[0].attributes[SemanticAttributes.HTTP_SCHEME],
+ metrics[0].dataPoints[0].attributes[SEMATTRS_HTTP_SCHEME],
'http'
);
assert.strictEqual(
- metrics[0].dataPoints[0].attributes[SemanticAttributes.HTTP_METHOD],
+ metrics[0].dataPoints[0].attributes[SEMATTRS_HTTP_METHOD],
'GET'
);
assert.strictEqual(
- metrics[0].dataPoints[0].attributes[SemanticAttributes.HTTP_FLAVOR],
+ metrics[0].dataPoints[0].attributes[SEMATTRS_HTTP_FLAVOR],
'1.1'
);
assert.strictEqual(
- metrics[0].dataPoints[0].attributes[SemanticAttributes.NET_HOST_NAME],
+ metrics[0].dataPoints[0].attributes[SEMATTRS_NET_HOST_NAME],
'localhost'
);
assert.strictEqual(
- metrics[0].dataPoints[0].attributes[SemanticAttributes.HTTP_STATUS_CODE],
+ metrics[0].dataPoints[0].attributes[SEMATTRS_HTTP_STATUS_CODE],
200
);
assert.strictEqual(
- metrics[0].dataPoints[0].attributes[SemanticAttributes.NET_HOST_PORT],
+ metrics[0].dataPoints[0].attributes[SEMATTRS_NET_HOST_PORT],
22346
);
@@ -128,23 +137,23 @@ describe('metrics', () => {
requestCount
);
assert.strictEqual(
- metrics[1].dataPoints[0].attributes[SemanticAttributes.HTTP_METHOD],
+ metrics[1].dataPoints[0].attributes[SEMATTRS_HTTP_METHOD],
'GET'
);
assert.strictEqual(
- metrics[1].dataPoints[0].attributes[SemanticAttributes.NET_PEER_NAME],
+ metrics[1].dataPoints[0].attributes[SEMATTRS_NET_PEER_NAME],
'localhost'
);
assert.strictEqual(
- metrics[1].dataPoints[0].attributes[SemanticAttributes.NET_PEER_PORT],
+ metrics[1].dataPoints[0].attributes[SEMATTRS_NET_PEER_PORT],
22346
);
assert.strictEqual(
- metrics[1].dataPoints[0].attributes[SemanticAttributes.HTTP_STATUS_CODE],
+ metrics[1].dataPoints[0].attributes[SEMATTRS_HTTP_STATUS_CODE],
200
);
assert.strictEqual(
- metrics[1].dataPoints[0].attributes[SemanticAttributes.HTTP_FLAVOR],
+ metrics[1].dataPoints[0].attributes[SEMATTRS_HTTP_FLAVOR],
'1.1'
);
});
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts
index 9da1c115b45..0f48a30ae72 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts
@@ -30,8 +30,13 @@ import {
SimpleSpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import {
- NetTransportValues,
- SemanticAttributes,
+ NETTRANSPORTVALUES_IP_TCP,
+ SEMATTRS_HTTP_CLIENT_IP,
+ SEMATTRS_HTTP_FLAVOR,
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_NET_HOST_PORT,
+ SEMATTRS_NET_PEER_PORT,
+ SEMATTRS_NET_TRANSPORT,
} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import * as fs from 'fs';
@@ -170,15 +175,16 @@ describe('HttpsInstrumentation', () => {
assertSpan(incomingSpan, SpanKind.SERVER, validations);
assertSpan(outgoingSpan, SpanKind.CLIENT, validations);
assert.strictEqual(
- incomingSpan.attributes[SemanticAttributes.NET_HOST_PORT],
+ incomingSpan.attributes[SEMATTRS_NET_HOST_PORT],
serverPort
);
assert.strictEqual(
- outgoingSpan.attributes[SemanticAttributes.NET_PEER_PORT],
+ outgoingSpan.attributes[SEMATTRS_NET_PEER_PORT],
serverPort
);
});
});
+
describe('with good instrumentation options', () => {
beforeEach(() => {
memoryExporter.reset();
@@ -264,15 +270,15 @@ describe('HttpsInstrumentation', () => {
assert.strictEqual(spans.length, 2);
assert.strictEqual(
- incomingSpan.attributes[SemanticAttributes.HTTP_CLIENT_IP],
+ incomingSpan.attributes[SEMATTRS_HTTP_CLIENT_IP],
''
);
assert.strictEqual(
- incomingSpan.attributes[SemanticAttributes.NET_HOST_PORT],
+ incomingSpan.attributes[SEMATTRS_NET_HOST_PORT],
serverPort
);
assert.strictEqual(
- outgoingSpan.attributes[SemanticAttributes.NET_PEER_PORT],
+ outgoingSpan.attributes[SEMATTRS_NET_PEER_PORT],
serverPort
);
@@ -280,13 +286,10 @@ describe('HttpsInstrumentation', () => {
{ span: incomingSpan, kind: SpanKind.SERVER },
{ span: outgoingSpan, kind: SpanKind.CLIENT },
].forEach(({ span, kind }) => {
+ assert.strictEqual(span.attributes[SEMATTRS_HTTP_FLAVOR], '1.1');
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_FLAVOR],
- '1.1'
- );
- assert.strictEqual(
- span.attributes[SemanticAttributes.NET_TRANSPORT],
- NetTransportValues.IP_TCP
+ span.attributes[SEMATTRS_NET_TRANSPORT],
+ NETTRANSPORTVALUES_IP_TCP
);
assertSpan(span, kind, validations);
});
@@ -465,7 +468,7 @@ describe('HttpsInstrumentation', () => {
});
for (const arg of ['string', {}, new Date()]) {
- it(`should be tracable and not throw exception in ${protocol} instrumentation when passing the following argument ${JSON.stringify(
+ it(`should be traceable and not throw exception in ${protocol} instrumentation when passing the following argument ${JSON.stringify(
arg
)}`, async () => {
try {
@@ -694,10 +697,7 @@ describe('HttpsInstrumentation', () => {
const [span] = spans;
assert.strictEqual(spans.length, 1);
assert.ok(Object.keys(span.attributes).length > 6);
- assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_STATUS_CODE],
- 404
- );
+ assert.strictEqual(span.attributes[SEMATTRS_HTTP_STATUS_CODE], 404);
assert.strictEqual(span.status.code, SpanStatusCode.ERROR);
done();
});
@@ -705,5 +705,60 @@ describe('HttpsInstrumentation', () => {
req.end();
});
});
+
+ describe('partially disable instrumentation', () => {
+ beforeEach(() => {
+ memoryExporter.reset();
+ });
+
+ afterEach(() => {
+ server.close();
+ instrumentation.disable();
+ });
+
+ it('allows to disable outgoing request instrumentation', () => {
+ instrumentation.setConfig({
+ disableOutgoingRequestInstrumentation: true,
+ });
+ instrumentation.enable();
+ server = https.createServer(
+ {
+ key: fs.readFileSync('test/fixtures/server-key.pem'),
+ cert: fs.readFileSync('test/fixtures/server-cert.pem'),
+ },
+ (request, response) => {
+ response.end('Test Server Response');
+ }
+ );
+
+ server.listen(serverPort);
+
+ 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', () => {
+ instrumentation.setConfig({
+ disableIncomingRequestInstrumentation: true,
+ });
+ instrumentation.enable();
+ server = https.createServer(
+ {
+ key: fs.readFileSync('test/fixtures/server-key.pem'),
+ cert: fs.readFileSync('test/fixtures/server-cert.pem'),
+ },
+ (request, response) => {
+ response.end('Test Server Response');
+ }
+ );
+
+ server.listen(serverPort);
+
+ assert.strictEqual(isWrapped(http.Server.prototype.emit), false);
+ assert.strictEqual(isWrapped(http.get), true);
+ assert.strictEqual(isWrapped(http.request), true);
+ });
+ });
});
});
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts
index 35b3c1ab5bc..39260fd7cce 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts
@@ -23,7 +23,14 @@ import {
Attributes,
} from '@opentelemetry/api';
import { BasicTracerProvider, Span } from '@opentelemetry/sdk-trace-base';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_ROUTE,
+ SEMATTRS_HTTP_TARGET,
+} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import { IncomingMessage, ServerResponse } from 'http';
import { Socket } from 'net';
@@ -301,37 +308,34 @@ describe('Utility', () => {
request,
{} as ServerResponse
);
- assert.deepStrictEqual(
- attributes[SemanticAttributes.HTTP_ROUTE],
- '/user/:id'
- );
+ assert.deepStrictEqual(attributes[SEMATTRS_HTTP_ROUTE], '/user/:id');
context.disable();
return done();
}
);
});
- it('should succesfully process without middleware stack', () => {
+ it('should successfully process without middleware stack', () => {
const request = {
socket: {},
} as IncomingMessage;
const attributes = utils.getIncomingRequestAttributesOnResponse(request, {
socket: {},
} as ServerResponse & { socket: Socket });
- assert.deepEqual(attributes[SemanticAttributes.HTTP_ROUTE], undefined);
+ assert.deepEqual(attributes[SEMATTRS_HTTP_ROUTE], undefined);
});
});
describe('getIncomingRequestMetricAttributesOnResponse()', () => {
it('should correctly add http_route if span has it', () => {
const spanAttributes: Attributes = {
- [SemanticAttributes.HTTP_ROUTE]: '/user/:id',
+ [SEMATTRS_HTTP_ROUTE]: '/user/:id',
};
const metricAttributes =
utils.getIncomingRequestMetricAttributesOnResponse(spanAttributes);
assert.deepStrictEqual(
- metricAttributes[SemanticAttributes.HTTP_ROUTE],
+ metricAttributes[SEMATTRS_HTTP_ROUTE],
'/user/:id'
);
});
@@ -340,10 +344,7 @@ describe('Utility', () => {
const spanAttributes: Attributes = {};
const metricAttributes =
utils.getIncomingRequestMetricAttributesOnResponse(spanAttributes);
- assert.deepEqual(
- metricAttributes[SemanticAttributes.HTTP_ROUTE],
- undefined
- );
+ assert.deepEqual(metricAttributes[SEMATTRS_HTTP_ROUTE], undefined);
});
});
// Verify the key in the given attributes is set to the given value,
@@ -354,10 +355,10 @@ describe('Utility', () => {
value: number
) {
const SemanticAttributess = [
- SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
- SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
- SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
- SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH,
];
for (const attr of SemanticAttributess) {
@@ -381,7 +382,7 @@ describe('Utility', () => {
verifyValueInAttributes(
attributes,
- SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
1200
);
});
@@ -397,7 +398,7 @@ describe('Utility', () => {
verifyValueInAttributes(
attributes,
- SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
1200
);
});
@@ -413,7 +414,7 @@ describe('Utility', () => {
verifyValueInAttributes(
attributes,
- SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH,
1200
);
});
@@ -432,7 +433,7 @@ describe('Utility', () => {
verifyValueInAttributes(
attributes,
- SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
1200
);
});
@@ -451,7 +452,7 @@ describe('Utility', () => {
verifyValueInAttributes(
attributes,
- SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
1200
);
});
@@ -470,7 +471,7 @@ describe('Utility', () => {
verifyValueInAttributes(
attributes,
- SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH,
1200
);
});
@@ -501,7 +502,7 @@ describe('Utility', () => {
const attributes = utils.getIncomingRequestAttributes(request, {
component: 'http',
});
- assert.strictEqual(attributes[SemanticAttributes.HTTP_ROUTE], undefined);
+ assert.strictEqual(attributes[SEMATTRS_HTTP_ROUTE], undefined);
});
it('should set http.target as path in http span attributes', () => {
@@ -515,10 +516,7 @@ describe('Utility', () => {
const attributes = utils.getIncomingRequestAttributes(request, {
component: 'http',
});
- assert.strictEqual(
- attributes[SemanticAttributes.HTTP_TARGET],
- '/user/?q=val'
- );
+ assert.strictEqual(attributes[SEMATTRS_HTTP_TARGET], '/user/?q=val');
});
});
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs b/experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
new file mode 100644
index 00000000000..db35b4ee455
--- /dev/null
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
@@ -0,0 +1,219 @@
+/*
+ * 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.
+ */
+
+// Test that instrumentation-http works when used from ESM code.
+
+import * as assert from 'assert';
+import * as fs from 'fs';
+import * as http from 'http';
+import * as https from 'https';
+
+import { SpanKind } from '@opentelemetry/api';
+import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
+import {
+ InMemorySpanExporter,
+ SimpleSpanProcessor,
+} from '@opentelemetry/sdk-trace-base';
+
+import { assertSpan } from '../../build/test/utils/assertSpan.js';
+import { HttpInstrumentation } from '../../build/src/index.js';
+
+const provider = new NodeTracerProvider();
+const memoryExporter = new InMemorySpanExporter();
+provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter));
+const instrumentation = new HttpInstrumentation();
+instrumentation.setTracerProvider(provider);
+
+describe('HttpInstrumentation ESM Integration tests', () => {
+ let port;
+ let server;
+
+ before(done => {
+ server = http.createServer((req, res) => {
+ req.resume();
+ req.on('end', () => {
+ res.writeHead(200);
+ res.end('pong');
+ });
+ });
+
+ server.listen(0, '127.0.0.1', () => {
+ port = server.address().port;
+ assert.ok(Number.isInteger(port));
+ done();
+ });
+ });
+
+ after(done => {
+ server.close(done);
+ });
+
+ beforeEach(() => {
+ memoryExporter.reset();
+ });
+
+ it('should instrument http requests using http.request', async () => {
+ const spanValidations = {
+ httpStatusCode: 200,
+ httpMethod: 'GET',
+ hostname: '127.0.0.1',
+ pathname: '/http.request',
+ component: 'http',
+ };
+
+ await new Promise(resolve => {
+ const clientReq = http.request(
+ `http://127.0.0.1:${port}/http.request`,
+ clientRes => {
+ spanValidations.resHeaders = clientRes.headers;
+ clientRes.resume();
+ clientRes.on('end', resolve);
+ }
+ );
+ clientReq.end();
+ });
+
+ let spans = memoryExporter.getFinishedSpans();
+ assert.strictEqual(spans.length, 2);
+ const span = spans.find(s => s.kind === SpanKind.CLIENT);
+ assert.strictEqual(span.name, 'GET');
+ assertSpan(span, SpanKind.CLIENT, spanValidations);
+ });
+
+ it('should instrument http requests using http.get', async () => {
+ const spanValidations = {
+ httpStatusCode: 200,
+ httpMethod: 'GET',
+ hostname: '127.0.0.1',
+ pathname: '/http.get',
+ component: 'http',
+ };
+
+ await new Promise(resolve => {
+ http.get(`http://127.0.0.1:${port}/http.get`, clientRes => {
+ spanValidations.resHeaders = clientRes.headers;
+ clientRes.resume();
+ clientRes.on('end', resolve);
+ });
+ });
+
+ let spans = memoryExporter.getFinishedSpans();
+ assert.strictEqual(spans.length, 2);
+ const span = spans.find(s => s.kind === SpanKind.CLIENT);
+ assert.strictEqual(span.name, 'GET');
+ assertSpan(span, SpanKind.CLIENT, spanValidations);
+ });
+});
+
+describe('HttpsInstrumentation ESM Integration tests', () => {
+ let port;
+ let server;
+
+ before(done => {
+ server = https.createServer(
+ {
+ key: fs.readFileSync(
+ new URL('../fixtures/server-key.pem', import.meta.url)
+ ),
+ cert: fs.readFileSync(
+ new URL('../fixtures/server-cert.pem', import.meta.url)
+ ),
+ },
+ (req, res) => {
+ req.resume();
+ req.on('end', () => {
+ res.writeHead(200);
+ res.end('pong');
+ });
+ }
+ );
+
+ server.listen(0, '127.0.0.1', () => {
+ port = server.address().port;
+ assert.ok(Number.isInteger(port));
+ done();
+ });
+ });
+
+ after(done => {
+ server.close(done);
+ });
+
+ beforeEach(() => {
+ memoryExporter.reset();
+ });
+
+ it('should instrument https requests using https.request', async () => {
+ const spanValidations = {
+ httpStatusCode: 200,
+ httpMethod: 'GET',
+ hostname: '127.0.0.1',
+ pathname: '/https.request',
+ component: 'https',
+ };
+
+ await new Promise(resolve => {
+ const clientReq = https.request(
+ `https://127.0.0.1:${port}/https.request`,
+ {
+ rejectUnauthorized: false,
+ },
+ clientRes => {
+ spanValidations.resHeaders = clientRes.headers;
+ clientRes.resume();
+ clientRes.on('end', resolve);
+ }
+ );
+ clientReq.end();
+ });
+
+ let spans = memoryExporter.getFinishedSpans();
+ assert.strictEqual(spans.length, 2);
+ const span = spans.find(s => s.kind === SpanKind.CLIENT);
+ assert.strictEqual(span.name, 'GET');
+ assertSpan(span, SpanKind.CLIENT, spanValidations);
+ });
+
+ it('should instrument http requests using https.get', async () => {
+ const spanValidations = {
+ httpStatusCode: 200,
+ httpMethod: 'GET',
+ hostname: '127.0.0.1',
+ pathname: '/https.get',
+ component: 'https',
+ };
+
+ await new Promise(resolve => {
+ https.get(
+ `https://127.0.0.1:${port}/https.get`,
+ {
+ rejectUnauthorized: false,
+ },
+ clientRes => {
+ spanValidations.resHeaders = clientRes.headers;
+ clientRes.resume();
+ clientRes.on('end', resolve);
+ }
+ );
+ });
+
+ let spans = memoryExporter.getFinishedSpans();
+ assert.strictEqual(spans.length, 2);
+ const span = spans.find(s => s.kind === SpanKind.CLIENT);
+ assert.strictEqual(span.name, 'GET');
+ assertSpan(span, SpanKind.CLIENT, spanValidations);
+ });
+});
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/integrations/http-enable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/integrations/http-enable.test.ts
index a04027a2c95..1f7829c4d22 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/integrations/http-enable.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/integrations/http-enable.test.ts
@@ -16,9 +16,11 @@
import { SpanKind, Span, context, propagation } from '@opentelemetry/api';
import {
- HttpFlavorValues,
- NetTransportValues,
- SemanticAttributes,
+ HTTPFLAVORVALUES_HTTP_1_1,
+ NETTRANSPORTVALUES_IP_TCP,
+ SEMATTRS_HTTP_FLAVOR,
+ SEMATTRS_HTTP_HOST,
+ SEMATTRS_NET_TRANSPORT,
} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import * as url from 'url';
@@ -236,12 +238,12 @@ describe('HttpInstrumentation Integration tests', () => {
assert.strictEqual(span.name, 'GET');
assert.strictEqual(result.reqHeaders['x-foo'], 'foo');
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_FLAVOR],
- HttpFlavorValues.HTTP_1_1
+ span.attributes[SEMATTRS_HTTP_FLAVOR],
+ HTTPFLAVORVALUES_HTTP_1_1
);
assert.strictEqual(
- span.attributes[SemanticAttributes.NET_TRANSPORT],
- NetTransportValues.IP_TCP
+ span.attributes[SEMATTRS_NET_TRANSPORT],
+ NETTRANSPORTVALUES_IP_TCP
);
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -397,7 +399,7 @@ describe('HttpInstrumentation Integration tests', () => {
assert.ok(span);
assert.strictEqual(span.name, 'GET');
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_HOST],
+ span.attributes[SEMATTRS_HTTP_HOST],
`localhost:${mockServerPort}`
);
});
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/integrations/https-enable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/integrations/https-enable.test.ts
index 10afe76a803..aa19a8629f9 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/integrations/https-enable.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/integrations/https-enable.test.ts
@@ -16,9 +16,10 @@
import { SpanKind, Span, context, propagation } from '@opentelemetry/api';
import {
- HttpFlavorValues,
- NetTransportValues,
- SemanticAttributes,
+ HTTPFLAVORVALUES_HTTP_1_1,
+ NETTRANSPORTVALUES_IP_TCP,
+ SEMATTRS_HTTP_FLAVOR,
+ SEMATTRS_NET_TRANSPORT,
} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import * as http from 'http';
@@ -240,12 +241,12 @@ describe('HttpsInstrumentation Integration tests', () => {
assert.strictEqual(span.name, 'GET');
assert.strictEqual(result.reqHeaders['x-foo'], 'foo');
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_FLAVOR],
- HttpFlavorValues.HTTP_1_1
+ span.attributes[SEMATTRS_HTTP_FLAVOR],
+ HTTPFLAVORVALUES_HTTP_1_1
);
assert.strictEqual(
- span.attributes[SemanticAttributes.NET_TRANSPORT],
- NetTransportValues.IP_TCP
+ span.attributes[SEMATTRS_NET_TRANSPORT],
+ NETTRANSPORTVALUES_IP_TCP
);
assertSpan(span, SpanKind.CLIENT, validations);
});
diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts b/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts
index 1f1b0518c8c..24cac71298f 100644
--- a/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts
+++ b/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts
@@ -21,7 +21,24 @@ import {
} from '@opentelemetry/api';
import { hrTimeToNanoseconds } from '@opentelemetry/core';
import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_HTTP_METHOD,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED,
+ SEMATTRS_HTTP_SCHEME,
+ SEMATTRS_HTTP_SERVER_NAME,
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_HTTP_TARGET,
+ SEMATTRS_HTTP_URL,
+ SEMATTRS_HTTP_USER_AGENT,
+ SEMATTRS_NET_HOST_IP,
+ SEMATTRS_NET_HOST_PORT,
+ SEMATTRS_NET_PEER_IP,
+ SEMATTRS_NET_PEER_NAME,
+ SEMATTRS_NET_PEER_PORT,
+} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import * as http from 'http';
import * as utils from '../../src/utils';
@@ -55,15 +72,15 @@ export const assertSpan = (
span.status.message
);
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_METHOD],
+ span.attributes[SEMATTRS_HTTP_METHOD],
validations.httpMethod
);
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_TARGET],
+ span.attributes[SEMATTRS_HTTP_TARGET],
validations.path || validations.pathname
);
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_STATUS_CODE],
+ span.attributes[SEMATTRS_HTTP_STATUS_CODE],
validations.httpStatusCode
);
@@ -97,10 +114,7 @@ export const assertSpan = (
if (validations.reqHeaders) {
const userAgent = validations.reqHeaders['user-agent'];
if (userAgent) {
- assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_USER_AGENT],
- userAgent
- );
+ assert.strictEqual(span.attributes[SEMATTRS_HTTP_USER_AGENT], userAgent);
}
}
if (span.kind === SpanKind.CLIENT) {
@@ -112,36 +126,28 @@ export const assertSpan = (
validations.resHeaders['content-encoding'] !== 'identity'
) {
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH],
+ span.attributes[SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH],
contentLength
);
} else {
assert.strictEqual(
- span.attributes[
- SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED
- ],
+ span.attributes[SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED],
contentLength
);
}
}
assert.strictEqual(
- span.attributes[SemanticAttributes.NET_PEER_NAME],
+ span.attributes[SEMATTRS_NET_PEER_NAME],
validations.hostname,
'must be consistent (PEER_NAME and hostname)'
);
if (!validations.noNetPeer) {
- assert.ok(
- span.attributes[SemanticAttributes.NET_PEER_IP],
- 'must have PEER_IP'
- );
- assert.ok(
- span.attributes[SemanticAttributes.NET_PEER_PORT],
- 'must have PEER_PORT'
- );
+ assert.ok(span.attributes[SEMATTRS_NET_PEER_IP], 'must have PEER_IP');
+ assert.ok(span.attributes[SEMATTRS_NET_PEER_PORT], 'must have PEER_PORT');
}
assert.ok(
- (span.attributes[SemanticAttributes.HTTP_URL] as string).indexOf(
- span.attributes[SemanticAttributes.NET_PEER_NAME] as string
+ (span.attributes[SEMATTRS_HTTP_URL] as string).indexOf(
+ span.attributes[SEMATTRS_NET_PEER_NAME] as string
) > -1,
'must be consistent'
);
@@ -155,35 +161,27 @@ export const assertSpan = (
validations.reqHeaders['content-encoding'] !== 'identity'
) {
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH],
+ span.attributes[SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH],
contentLength
);
} else {
assert.strictEqual(
- span.attributes[
- SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED
- ],
+ span.attributes[SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED],
contentLength
);
}
}
if (validations.serverName) {
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_SERVER_NAME],
+ span.attributes[SEMATTRS_HTTP_SERVER_NAME],
validations.serverName,
' must have serverName attribute'
);
- assert.ok(
- span.attributes[SemanticAttributes.NET_HOST_PORT],
- 'must have HOST_PORT'
- );
- assert.ok(
- span.attributes[SemanticAttributes.NET_HOST_IP],
- 'must have HOST_IP'
- );
+ assert.ok(span.attributes[SEMATTRS_NET_HOST_PORT], 'must have HOST_PORT');
+ assert.ok(span.attributes[SEMATTRS_NET_HOST_IP], 'must have HOST_IP');
}
assert.strictEqual(
- span.attributes[SemanticAttributes.HTTP_SCHEME],
+ span.attributes[SEMATTRS_HTTP_SCHEME],
validations.component,
' must have http.scheme attribute'
);
diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/README.md b/experimental/packages/opentelemetry-instrumentation-xml-http-request/README.md
index 8c968694603..8c706ffa61f 100644
--- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/README.md
+++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/README.md
@@ -64,6 +64,15 @@ req.send();
```
+### XHR Instrumentation options
+
+XHR instrumentation plugin has few options available to choose from. You can set the following:
+
+| Options | Type | Description |
+|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------|-----------------------------------------------------------------------------------------|
+| [`applyCustomAttributesOnSpan`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts#L76) | `XHRCustomAttributeFunction` | Function for adding custom attributes |
+| [`ignoreNetworkEvents`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts#L78) | `boolean` | Disable network events being added as span events (network events are added by default) |
+
## Example Screenshots
![Screenshot of the running example](images/main.jpg)
diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json
index 4824f420ffb..3e967c15a65 100644
--- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json
+++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json
@@ -1,7 +1,7 @@
{
"name": "@opentelemetry/instrumentation-xml-http-request",
- "version": "0.49.1",
- "description": "OpenTelemetry XMLHttpRequest automatic instrumentation package.",
+ "version": "0.52.1",
+ "description": "OpenTelemetry instrumentation for XMLHttpRequest http client in web browsers",
"main": "build/src/index.js",
"module": "build/esm/index.js",
"esnext": "build/esnext/index.js",
@@ -20,7 +20,8 @@
"watch": "tsc --build --watch tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
"prewatch": "node ../../../scripts/version-update.js",
- "peer-api-check": "node ../../../scripts/peer-api-check.js"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -54,32 +55,31 @@
"access": "public"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/context-zone": "1.22.0",
- "@opentelemetry/propagator-b3": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@opentelemetry/context-zone": "1.25.1",
+ "@opentelemetry/propagator-b3": "1.25.1",
+ "@opentelemetry/sdk-trace-base": "1.25.1",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
+ "@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
@@ -89,10 +89,10 @@
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/sdk-trace-web": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.0"
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/instrumentation": "0.52.1",
+ "@opentelemetry/sdk-trace-web": "1.25.1",
+ "@opentelemetry/semantic-conventions": "1.25.1"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-xml-http-request",
"sideEffects": false
diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts b/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts
index 42eb9abb0bb..5a8ba3012cb 100644
--- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts
+++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts
@@ -22,7 +22,14 @@ import {
safeExecuteInTheMiddle,
} from '@opentelemetry/instrumentation';
import { hrTime, isUrlIgnored, otperformance } from '@opentelemetry/core';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_HTTP_HOST,
+ SEMATTRS_HTTP_METHOD,
+ SEMATTRS_HTTP_SCHEME,
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_HTTP_URL,
+ SEMATTRS_HTTP_USER_AGENT,
+} from '@opentelemetry/semantic-conventions';
import {
addSpanNetworkEvents,
getResource,
@@ -74,12 +81,14 @@ export interface XMLHttpRequestInstrumentationConfig
ignoreUrls?: Array;
/** Function for adding custom attributes on the span */
applyCustomAttributesOnSpan?: XHRCustomAttributeFunction;
+ /** Ignore adding network events as span events */
+ ignoreNetworkEvents?: boolean;
}
/**
* This class represents a XMLHttpRequest plugin for auto instrumentation
*/
-export class XMLHttpRequestInstrumentation extends InstrumentationBase {
+export class XMLHttpRequestInstrumentation extends InstrumentationBase {
readonly component: string = 'xml-http-request';
readonly version: string = VERSION;
moduleName = this.component;
@@ -88,16 +97,12 @@ export class XMLHttpRequestInstrumentation extends InstrumentationBase();
private _usedResources = new WeakSet();
- constructor(config?: XMLHttpRequestInstrumentationConfig) {
+ constructor(config: XMLHttpRequestInstrumentationConfig = {}) {
super('@opentelemetry/instrumentation-xml-http-request', VERSION, config);
}
init() {}
- private _getConfig(): XMLHttpRequestInstrumentationConfig {
- return this._config;
- }
-
/**
* Adds custom headers to XMLHttpRequest
* @param xhr
@@ -109,7 +114,7 @@ export class XMLHttpRequestInstrumentation extends InstrumentationBase> = {};
@@ -140,7 +145,9 @@ export class XMLHttpRequestInstrumentation extends InstrumentationBase applyCustomAttributesOnSpan(span, xhr),
@@ -240,7 +244,7 @@ export class XMLHttpRequestInstrumentation extends InstrumentationBase();
this._usedResources = new WeakSet();
@@ -292,7 +296,9 @@ export class XMLHttpRequestInstrumentation extends InstrumentationBase {
// content length comes from the PerformanceTiming resource; this ensures that our
// matching logic found the right one
assert.ok(
- (span.attributes[
- SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH
- ] as any) > 0
+ (span.attributes[SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH] as any) > 0
);
done();
}, 500);
diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/test/xhr.test.ts b/experimental/packages/opentelemetry-instrumentation-xml-http-request/test/xhr.test.ts
index c3614a42e82..f3685e06a13 100644
--- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/test/xhr.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/test/xhr.test.ts
@@ -25,7 +25,16 @@ import {
} from '@opentelemetry/propagator-b3';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import * as tracing from '@opentelemetry/sdk-trace-base';
-import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
+import {
+ SEMATTRS_HTTP_HOST,
+ SEMATTRS_HTTP_METHOD,
+ SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH,
+ SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH,
+ SEMATTRS_HTTP_SCHEME,
+ SEMATTRS_HTTP_STATUS_CODE,
+ SEMATTRS_HTTP_URL,
+ SEMATTRS_HTTP_USER_AGENT,
+} from '@opentelemetry/semantic-conventions';
import {
PerformanceTimingNames as PTN,
WebTracerProvider,
@@ -356,21 +365,21 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[0]],
'GET',
- `attributes ${SemanticAttributes.HTTP_METHOD} is wrong`
+ `attributes ${SEMATTRS_HTTP_METHOD} is wrong`
);
assert.strictEqual(
attributes[keys[1]],
url,
- `attributes ${SemanticAttributes.HTTP_URL} is wrong`
+ `attributes ${SEMATTRS_HTTP_URL} is wrong`
);
assert.ok(
(attributes[keys[2]] as number) > 0,
- 'attributes ${SemanticAttributess.HTTP_RESPONSE_CONTENT_SIZE} <= 0'
+ `attributes ${SEMATTRS_HTTP_RESPONSE_CONTENT_LENGTH} <= 0`
);
assert.strictEqual(
attributes[keys[3]],
200,
- `attributes ${SemanticAttributes.HTTP_STATUS_CODE} is wrong`
+ `attributes ${SEMATTRS_HTTP_STATUS_CODE} is wrong`
);
assert.strictEqual(
attributes[keys[4]],
@@ -380,15 +389,15 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[5]],
parseUrl(url).host,
- `attributes ${SemanticAttributes.HTTP_HOST} is wrong`
+ `attributes ${SEMATTRS_HTTP_HOST} is wrong`
);
assert.ok(
attributes[keys[6]] === 'http' || attributes[keys[6]] === 'https',
- `attributes ${SemanticAttributes.HTTP_SCHEME} is wrong`
+ `attributes ${SEMATTRS_HTTP_SCHEME} is wrong`
);
assert.ok(
attributes[keys[7]] !== '',
- `attributes ${SemanticAttributes.HTTP_USER_AGENT} is not defined`
+ `attributes ${SEMATTRS_HTTP_USER_AGENT} is not defined`
);
assert.strictEqual(keys.length, 8, 'number of attributes is wrong');
@@ -713,7 +722,7 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[1]],
secondUrl,
- `attribute ${SemanticAttributes.HTTP_URL} is wrong`
+ `attribute ${SEMATTRS_HTTP_URL} is wrong`
);
});
});
@@ -777,12 +786,26 @@ describe('xhr', () => {
const attributes = span.attributes;
assert.strictEqual(
- attributes[SemanticAttributes.HTTP_URL],
+ attributes[SEMATTRS_HTTP_URL],
location.origin + '/get',
- `attributes ${SemanticAttributes.HTTP_URL} is wrong`
+ `attributes ${SEMATTRS_HTTP_URL} is wrong`
);
});
});
+
+ describe('when network events are ignored', () => {
+ beforeEach(done => {
+ clearData();
+ prepareData(done, url, {
+ ignoreNetworkEvents: true,
+ });
+ });
+ it('should NOT add network events', () => {
+ const span: tracing.ReadableSpan = exportSpy.args[1][0][0];
+ const events = span.events;
+ assert.strictEqual(events.length, 3, 'number of events is wrong');
+ });
+ });
});
describe('when request is NOT successful', () => {
@@ -941,22 +964,22 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[0]],
'GET',
- `attributes ${SemanticAttributes.HTTP_METHOD} is wrong`
+ `attributes ${SEMATTRS_HTTP_METHOD} is wrong`
);
assert.strictEqual(
attributes[keys[1]],
url,
- `attributes ${SemanticAttributes.HTTP_URL} is wrong`
+ `attributes ${SEMATTRS_HTTP_URL} is wrong`
);
assert.strictEqual(
attributes[keys[2]],
0,
- `attributes ${SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH} is wrong`
+ `attributes ${SEMATTRS_HTTP_REQUEST_CONTENT_LENGTH} is wrong`
);
assert.strictEqual(
attributes[keys[3]],
400,
- `attributes ${SemanticAttributes.HTTP_STATUS_CODE} is wrong`
+ `attributes ${SEMATTRS_HTTP_STATUS_CODE} is wrong`
);
assert.strictEqual(
attributes[keys[4]],
@@ -966,15 +989,15 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[5]],
'raw.githubusercontent.com',
- `attributes ${SemanticAttributes.HTTP_HOST} is wrong`
+ `attributes ${SEMATTRS_HTTP_HOST} is wrong`
);
assert.ok(
attributes[keys[6]] === 'http' || attributes[keys[6]] === 'https',
- `attributes ${SemanticAttributes.HTTP_SCHEME} is wrong`
+ `attributes ${SEMATTRS_HTTP_SCHEME} is wrong`
);
assert.ok(
attributes[keys[7]] !== '',
- `attributes ${SemanticAttributes.HTTP_USER_AGENT} is not defined`
+ `attributes ${SEMATTRS_HTTP_USER_AGENT} is not defined`
);
assert.strictEqual(keys.length, 8, 'number of attributes is wrong');
@@ -1015,17 +1038,17 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[0]],
'GET',
- `attributes ${SemanticAttributes.HTTP_METHOD} is wrong`
+ `attributes ${SEMATTRS_HTTP_METHOD} is wrong`
);
assert.strictEqual(
attributes[keys[1]],
url,
- `attributes ${SemanticAttributes.HTTP_URL} is wrong`
+ `attributes ${SEMATTRS_HTTP_URL} is wrong`
);
assert.strictEqual(
attributes[keys[2]],
0,
- `attributes ${SemanticAttributes.HTTP_STATUS_CODE} is wrong`
+ `attributes ${SEMATTRS_HTTP_STATUS_CODE} is wrong`
);
assert.strictEqual(
attributes[keys[3]],
@@ -1035,15 +1058,15 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[4]],
'raw.githubusercontent.com',
- `attributes ${SemanticAttributes.HTTP_HOST} is wrong`
+ `attributes ${SEMATTRS_HTTP_HOST} is wrong`
);
assert.ok(
attributes[keys[5]] === 'http' || attributes[keys[5]] === 'https',
- `attributes ${SemanticAttributes.HTTP_SCHEME} is wrong`
+ `attributes ${SEMATTRS_HTTP_SCHEME} is wrong`
);
assert.ok(
attributes[keys[6]] !== '',
- `attributes ${SemanticAttributes.HTTP_USER_AGENT} is not defined`
+ `attributes ${SEMATTRS_HTTP_USER_AGENT} is not defined`
);
assert.strictEqual(keys.length, 7, 'number of attributes is wrong');
@@ -1081,17 +1104,17 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[0]],
'GET',
- `attributes ${SemanticAttributes.HTTP_METHOD} is wrong`
+ `attributes ${SEMATTRS_HTTP_METHOD} is wrong`
);
assert.strictEqual(
attributes[keys[1]],
url,
- `attributes ${SemanticAttributes.HTTP_URL} is wrong`
+ `attributes ${SEMATTRS_HTTP_URL} is wrong`
);
assert.strictEqual(
attributes[keys[2]],
0,
- `attributes ${SemanticAttributes.HTTP_STATUS_CODE} is wrong`
+ `attributes ${SEMATTRS_HTTP_STATUS_CODE} is wrong`
);
assert.strictEqual(
attributes[keys[3]],
@@ -1101,15 +1124,15 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[4]],
'raw.githubusercontent.com',
- `attributes ${SemanticAttributes.HTTP_HOST} is wrong`
+ `attributes ${SEMATTRS_HTTP_HOST} is wrong`
);
assert.ok(
attributes[keys[5]] === 'http' || attributes[keys[5]] === 'https',
- `attributes ${SemanticAttributes.HTTP_SCHEME} is wrong`
+ `attributes ${SEMATTRS_HTTP_SCHEME} is wrong`
);
assert.ok(
attributes[keys[6]] !== '',
- `attributes ${SemanticAttributes.HTTP_USER_AGENT} is not defined`
+ `attributes ${SEMATTRS_HTTP_USER_AGENT} is not defined`
);
assert.strictEqual(keys.length, 7, 'number of attributes is wrong');
@@ -1147,17 +1170,17 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[0]],
'GET',
- `attributes ${SemanticAttributes.HTTP_METHOD} is wrong`
+ `attributes ${SEMATTRS_HTTP_METHOD} is wrong`
);
assert.strictEqual(
attributes[keys[1]],
url,
- `attributes ${SemanticAttributes.HTTP_URL} is wrong`
+ `attributes ${SEMATTRS_HTTP_URL} is wrong`
);
assert.strictEqual(
attributes[keys[2]],
0,
- `attributes ${SemanticAttributes.HTTP_STATUS_CODE} is wrong`
+ `attributes ${SEMATTRS_HTTP_STATUS_CODE} is wrong`
);
assert.strictEqual(
attributes[keys[3]],
@@ -1167,15 +1190,15 @@ describe('xhr', () => {
assert.strictEqual(
attributes[keys[4]],
'raw.githubusercontent.com',
- `attributes ${SemanticAttributes.HTTP_HOST} is wrong`
+ `attributes ${SEMATTRS_HTTP_HOST} is wrong`
);
assert.ok(
attributes[keys[5]] === 'http' || attributes[keys[5]] === 'https',
- `attributes ${SemanticAttributes.HTTP_SCHEME} is wrong`
+ `attributes ${SEMATTRS_HTTP_SCHEME} is wrong`
);
assert.ok(
attributes[keys[6]] !== '',
- `attributes ${SemanticAttributes.HTTP_USER_AGENT} is not defined`
+ `attributes ${SEMATTRS_HTTP_USER_AGENT} is not defined`
);
assert.strictEqual(keys.length, 7, 'number of attributes is wrong');
diff --git a/experimental/packages/opentelemetry-instrumentation/README.md b/experimental/packages/opentelemetry-instrumentation/README.md
index 6c27e3d36d0..3e422a59d63 100644
--- a/experimental/packages/opentelemetry-instrumentation/README.md
+++ b/experimental/packages/opentelemetry-instrumentation/README.md
@@ -36,7 +36,7 @@ export class MyInstrumentation extends InstrumentationBase {
* the plugin should patch multiple modules or versions.
*/
protected init() {
- const module = new InstrumentationNodeModuleDefinition(
+ const module = new InstrumentationNodeModuleDefinition(
'module_name_to_be_patched',
['1.*'],
this._onPatchMain,
@@ -63,8 +63,8 @@ export class MyInstrumentation extends InstrumentationBase {
this._unwrap(moduleExports, 'mainMethodName');
}
- private _addPatchingMethod(): InstrumentationNodeModuleFile {
- const file = new InstrumentationNodeModuleFile(
+ private _addPatchingMethod(): InstrumentationNodeModuleFile {
+ const file = new InstrumentationNodeModuleFile(
'module_name_to_be_patched/src/some_file.js',
this._onPatchMethodName,
this._onUnPatchMethodName,
@@ -216,13 +216,13 @@ registerInstrumentations({
The `registerInstrumentations()` API allows to specify which `TracerProvider` and/or `MeterProvider` to use by the given options object.
If nothing is specified the global registered provider is used. Usually this is what most users want therefore it's recommended to keep this default.
-There might be usecase where someone has the need for more providers within an application. Please note that special care must be takes in such setups
+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 NodeJS (experimental)
+## Instrumentation for ES Modules 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 NodeJS is experimental, so is our support for it. Feel free to provide feedback or report issues about it.
+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.
**Note**: ESM Instrumentation is not yet supported for Node 20.
@@ -230,8 +230,8 @@ As the ESM module loader from NodeJS is experimental, so is our support for it.
Instrumentations for external modules (e.g. express, mongodb,...) hooks the `require` call or `import` statement. Therefore following conditions need to be met that this mechanism can work:
-* Instrumentations are registered **before** the module to instrument is `require`ed (CJS only)
-* modules are not included in a bundle. Tools like `esbuild`, `webpack`, ... usually have some mechanism to exclude specific modules from bundling
+- Instrumentations are registered **before** the module to instrument is `require`ed (CJS only)
+- modules are not included in a bundle. Tools like `esbuild`, `webpack`, ... usually have some mechanism to exclude specific modules from bundling
## License
@@ -239,8 +239,8 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
## Useful links
-* For more information on OpenTelemetry, visit:
-* For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
+- For more information on OpenTelemetry, visit:
+- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]
[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/LICENSE
diff --git a/experimental/packages/opentelemetry-instrumentation/package.json b/experimental/packages/opentelemetry-instrumentation/package.json
index c6a8f8088d0..92746c89ca4 100644
--- a/experimental/packages/opentelemetry-instrumentation/package.json
+++ b/experimental/packages/opentelemetry-instrumentation/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/instrumentation",
- "version": "0.49.1",
+ "version": "0.52.1",
"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",
@@ -48,15 +48,16 @@
"tdd": "npm run tdd:node",
"tdd:node": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
- "test:cjs": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
- "test:esm": "nyc node --experimental-loader=./hook.mjs ../../../node_modules/mocha/bin/mocha 'test/node/*.test.mjs' test/node/*.test.mjs",
+ "test:cjs": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
+ "test:esm": "nyc node --experimental-loader=./hook.mjs ../../../node_modules/mocha/bin/mocha 'test/node/*.test.mjs'",
"test": "npm run test:cjs && npm run test:esm",
"test:browser": "karma start --single-run",
"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",
"prewatch": "node ../../../scripts/version-update.js",
- "peer-api-check": "node ../../../scripts/peer-api-check.js"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -71,9 +72,9 @@
"url": "https://github.com/open-telemetry/opentelemetry-js/issues"
},
"dependencies": {
- "@opentelemetry/api-logs": "0.49.1",
- "@types/shimmer": "^1.0.2",
- "import-in-the-middle": "1.7.1",
+ "@opentelemetry/api-logs": "0.52.1",
+ "@types/shimmer": "^1.2.0",
+ "import-in-the-middle": "^1.8.1",
"require-in-the-middle": "^7.1.1",
"semver": "^7.5.2",
"shimmer": "^1.2.1"
@@ -82,33 +83,31 @@
"@opentelemetry/api": "^1.3.0"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/api-logs": "0.47.0",
- "@opentelemetry/sdk-metrics": "1.22.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@opentelemetry/sdk-metrics": "1.25.1",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/semver": "7.5.6",
- "@types/sinon": "10.0.20",
+ "@types/semver": "7.5.8",
+ "@types/sinon": "17.0.3",
"@types/webpack-env": "1.16.3",
"babel-loader": "8.3.0",
- "babel-plugin-istanbul": "6.1.1",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
- "cpx": "1.5.0",
+ "cpx2": "2.0.0",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
diff --git a/experimental/packages/opentelemetry-instrumentation/src/autoLoader.ts b/experimental/packages/opentelemetry-instrumentation/src/autoLoader.ts
index 266648bcf6d..3c862f25e68 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/autoLoader.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/autoLoader.ts
@@ -19,7 +19,6 @@ import { logs } from '@opentelemetry/api-logs';
import {
disableInstrumentations,
enableInstrumentations,
- parseInstrumentationOptions,
} from './autoLoaderUtils';
import { AutoLoaderOptions } from './types_internal';
@@ -32,12 +31,10 @@ import { AutoLoaderOptions } from './types_internal';
export function registerInstrumentations(
options: AutoLoaderOptions
): () => void {
- const { instrumentations } = parseInstrumentationOptions(
- options.instrumentations
- );
const tracerProvider = options.tracerProvider || trace.getTracerProvider();
const meterProvider = options.meterProvider || metrics.getMeterProvider();
const loggerProvider = options.loggerProvider || logs.getLoggerProvider();
+ const instrumentations = options.instrumentations?.flat() ?? [];
enableInstrumentations(
instrumentations,
diff --git a/experimental/packages/opentelemetry-instrumentation/src/autoLoaderUtils.ts b/experimental/packages/opentelemetry-instrumentation/src/autoLoaderUtils.ts
index 91ef7a653de..05107b2f196 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/autoLoaderUtils.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/autoLoaderUtils.ts
@@ -16,34 +16,8 @@
import { TracerProvider, MeterProvider } from '@opentelemetry/api';
import { Instrumentation } from './types';
-import { AutoLoaderResult, InstrumentationOption } from './types_internal';
import { LoggerProvider } from '@opentelemetry/api-logs';
-/**
- * Parses the options and returns instrumentations, node plugins and
- * web plugins
- * @param options
- */
-export function parseInstrumentationOptions(
- options: InstrumentationOption[] = []
-): AutoLoaderResult {
- let instrumentations: Instrumentation[] = [];
- for (let i = 0, j = options.length; i < j; i++) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const option = options[i] as any;
- if (Array.isArray(option)) {
- const results = parseInstrumentationOptions(option);
- instrumentations = instrumentations.concat(results.instrumentations);
- } else if (typeof option === 'function') {
- instrumentations.push(new option());
- } else if ((option as Instrumentation).instrumentationName) {
- instrumentations.push(option);
- }
- }
-
- return { instrumentations };
-}
-
/**
* Enable instrumentations
* @param instrumentations
diff --git a/experimental/packages/opentelemetry-instrumentation/src/index.ts b/experimental/packages/opentelemetry-instrumentation/src/index.ts
index 0185bfc79d8..1e351471923 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/index.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/index.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-export * from './autoLoader';
+export { registerInstrumentations } from './autoLoader';
export { InstrumentationBase } from './platform/index';
export { InstrumentationNodeModuleDefinition } from './instrumentationNodeModuleDefinition';
export { InstrumentationNodeModuleFile } from './instrumentationNodeModuleFile';
diff --git a/experimental/packages/opentelemetry-instrumentation/src/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation/src/instrumentation.ts
index ed619bd1391..f7e2c2758d6 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/instrumentation.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/instrumentation.ts
@@ -23,6 +23,7 @@ import {
trace,
Tracer,
TracerProvider,
+ Span,
} from '@opentelemetry/api';
import { Logger, LoggerProvider, logs } from '@opentelemetry/api-logs';
import * as shimmer from 'shimmer';
@@ -30,15 +31,17 @@ import {
InstrumentationModuleDefinition,
Instrumentation,
InstrumentationConfig,
+ SpanCustomizationHook,
} from './types';
/**
* Base abstract internal class for instrumenting node and web plugins
*/
-export abstract class InstrumentationAbstract
- implements Instrumentation
+export abstract class InstrumentationAbstract<
+ ConfigType extends InstrumentationConfig = InstrumentationConfig,
+> implements Instrumentation
{
- protected _config: InstrumentationConfig;
+ protected _config: ConfigType;
private _tracer: Tracer;
private _meter: Meter;
@@ -48,8 +51,10 @@ export abstract class InstrumentationAbstract
constructor(
public readonly instrumentationName: string,
public readonly instrumentationVersion: string,
- config: InstrumentationConfig = {}
+ 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,
@@ -116,7 +121,7 @@ export abstract class InstrumentationAbstract
*
* @returns an array of {@link InstrumentationModuleDefinition}
*/
- public getModuleDefinitions(): InstrumentationModuleDefinition[] {
+ public getModuleDefinitions(): InstrumentationModuleDefinition[] {
const initResult = this.init() ?? [];
if (!Array.isArray(initResult)) {
return [initResult];
@@ -133,7 +138,7 @@ export abstract class InstrumentationAbstract
}
/* Returns InstrumentationConfig */
- public getConfig(): InstrumentationConfig {
+ public getConfig(): ConfigType {
return this._config;
}
@@ -141,8 +146,10 @@ export abstract class InstrumentationAbstract
* Sets InstrumentationConfig to this plugin
* @param InstrumentationConfig
*/
- public setConfig(config: InstrumentationConfig = {}): void {
- this._config = Object.assign({}, 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 };
}
/**
@@ -161,10 +168,10 @@ export abstract class InstrumentationAbstract
return this._tracer;
}
- /* Disable plugin */
+ /* Enable plugin */
public abstract enable(): void;
- /* Enable plugin */
+ /* Disable plugin */
public abstract disable(): void;
/**
@@ -172,7 +179,36 @@ export abstract class InstrumentationAbstract
* methods.
*/
protected abstract init():
- | InstrumentationModuleDefinition
- | InstrumentationModuleDefinition[]
+ | InstrumentationModuleDefinition
+ | InstrumentationModuleDefinition[]
| void;
+
+ /**
+ * Execute span customization hook, if configured, and log any errors.
+ * Any semantics of the trigger and info are defined by the specific instrumentation.
+ * @param hookHandler The optional hook handler which the user has configured via instrumentation config
+ * @param triggerName The name of the trigger for executing the hook for logging purposes
+ * @param span The span to which the hook should be applied
+ * @param info The info object to be passed to the hook, with useful data the hook may use
+ */
+ protected _runSpanCustomizationHook(
+ hookHandler: SpanCustomizationHook | undefined,
+ triggerName: string,
+ span: Span,
+ info: SpanCustomizationInfoType
+ ) {
+ if (!hookHandler) {
+ return;
+ }
+
+ try {
+ hookHandler(span, info);
+ } catch (e) {
+ this._diag.error(
+ `Error running span customization hook due to exception in handler`,
+ { triggerName },
+ e
+ );
+ }
+ }
}
diff --git a/experimental/packages/opentelemetry-instrumentation/src/instrumentationNodeModuleDefinition.ts b/experimental/packages/opentelemetry-instrumentation/src/instrumentationNodeModuleDefinition.ts
index e45a943a7fc..2d17ce3cf3d 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/instrumentationNodeModuleDefinition.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/instrumentationNodeModuleDefinition.ts
@@ -19,16 +19,18 @@ import {
InstrumentationModuleFile,
} from './types';
-export class InstrumentationNodeModuleDefinition
- implements InstrumentationModuleDefinition
+export class InstrumentationNodeModuleDefinition
+ implements InstrumentationModuleDefinition
{
- files: InstrumentationModuleFile[];
+ files: InstrumentationModuleFile[];
constructor(
public name: string,
public supportedVersions: string[],
- public patch?: (exports: T, moduleVersion?: string) => T,
- public unpatch?: (exports: T, moduleVersion?: string) => void,
- files?: InstrumentationModuleFile[]
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ public patch?: (exports: any, moduleVersion?: string) => any,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ public unpatch?: (exports: any, moduleVersion?: string) => void,
+ files?: InstrumentationModuleFile[]
) {
this.files = files || [];
}
diff --git a/experimental/packages/opentelemetry-instrumentation/src/instrumentationNodeModuleFile.ts b/experimental/packages/opentelemetry-instrumentation/src/instrumentationNodeModuleFile.ts
index edbe8ba72eb..b821552b9f5 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/instrumentationNodeModuleFile.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/instrumentationNodeModuleFile.ts
@@ -17,15 +17,17 @@
import { InstrumentationModuleFile } from './types';
import { normalize } from './platform/index';
-export class InstrumentationNodeModuleFile
- implements InstrumentationModuleFile
+export class InstrumentationNodeModuleFile
+ implements InstrumentationModuleFile
{
public name: string;
constructor(
name: string,
public supportedVersions: string[],
- public patch: (moduleExports: T, moduleVersion?: string) => T,
- public unpatch: (moduleExports?: T, moduleVersion?: string) => void
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ public patch: (moduleExports: any, moduleVersion?: string) => any,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ public unpatch: (moduleExports?: any, moduleVersion?: string) => void
) {
this.name = normalize(name);
}
diff --git a/experimental/packages/opentelemetry-instrumentation/src/platform/browser/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation/src/platform/browser/instrumentation.ts
index 0458357a731..e5b13b80bb3 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/platform/browser/instrumentation.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/platform/browser/instrumentation.ts
@@ -16,18 +16,21 @@
import { InstrumentationAbstract } from '../../instrumentation';
import * as types from '../../types';
+import { InstrumentationConfig } from '../../types';
/**
* Base abstract class for instrumenting web plugins
*/
-export abstract class InstrumentationBase
- extends InstrumentationAbstract
- implements types.Instrumentation
+export abstract class InstrumentationBase<
+ ConfigType extends InstrumentationConfig = InstrumentationConfig,
+ >
+ extends InstrumentationAbstract
+ implements types.Instrumentation
{
constructor(
instrumentationName: string,
instrumentationVersion: string,
- config: types.InstrumentationConfig = {}
+ config: ConfigType
) {
super(instrumentationName, instrumentationVersion, config);
diff --git a/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts
index c639bc8bd48..cad74be5a08 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts
@@ -25,21 +25,28 @@ import {
Hooked,
} from './RequireInTheMiddleSingleton';
import type { HookFn } from 'import-in-the-middle';
-import * as ImportInTheMiddle from 'import-in-the-middle';
-import { InstrumentationModuleDefinition } from '../../types';
+import { Hook as HookImport } from 'import-in-the-middle';
+import {
+ InstrumentationConfig,
+ InstrumentationModuleDefinition,
+} from '../../types';
import { diag } from '@opentelemetry/api';
import type { OnRequireFn } from 'require-in-the-middle';
-import { Hook } from 'require-in-the-middle';
+import { Hook as HookRequire } from 'require-in-the-middle';
+import { readFileSync } from 'fs';
+import { isWrapped } from '../../utils';
/**
* Base abstract class for instrumenting node plugins
*/
-export abstract class InstrumentationBase
- extends InstrumentationAbstract
- implements types.Instrumentation
+export abstract class InstrumentationBase<
+ ConfigType extends InstrumentationConfig = InstrumentationConfig,
+ >
+ extends InstrumentationAbstract
+ implements types.Instrumentation
{
- private _modules: InstrumentationModuleDefinition[];
- private _hooks: (Hooked | Hook)[] = [];
+ private _modules: InstrumentationModuleDefinition[];
+ private _hooks: (Hooked | HookRequire)[] = [];
private _requireInTheMiddleSingleton: RequireInTheMiddleSingleton =
RequireInTheMiddleSingleton.getInstance();
private _enabled = false;
@@ -47,7 +54,7 @@ export abstract class InstrumentationBase
constructor(
instrumentationName: string,
instrumentationVersion: string,
- config: types.InstrumentationConfig = {}
+ config: ConfigType
) {
super(instrumentationName, instrumentationVersion, config);
@@ -57,7 +64,7 @@ export abstract class InstrumentationBase
modules = [modules];
}
- this._modules = (modules as InstrumentationModuleDefinition[]) || [];
+ this._modules = (modules as InstrumentationModuleDefinition[]) || [];
if (this._modules.length === 0) {
diag.debug(
@@ -73,14 +80,17 @@ export abstract class InstrumentationBase
}
protected override _wrap: typeof wrap = (moduleExports, name, wrapper) => {
+ if (isWrapped(moduleExports[name])) {
+ this._unwrap(moduleExports, name);
+ }
if (!utilTypes.isProxy(moduleExports)) {
return wrap(moduleExports, name, wrapper);
} else {
const wrapped = wrap(Object.assign({}, moduleExports), name, wrapper);
-
- return Object.defineProperty(moduleExports, name, {
+ Object.defineProperty(moduleExports, name, {
value: wrapped,
});
+ return wrapped;
}
};
@@ -142,7 +152,7 @@ export abstract class InstrumentationBase
};
private _warnOnPreloadedModules(): void {
- this._modules.forEach((module: InstrumentationModuleDefinition) => {
+ this._modules.forEach((module: InstrumentationModuleDefinition) => {
const { name } = module;
try {
const resolvedModule = require.resolve(name);
@@ -160,8 +170,10 @@ export abstract class InstrumentationBase
private _extractPackageVersion(baseDir: string): string | undefined {
try {
- // eslint-disable-next-line @typescript-eslint/no-var-requires
- const version = require(path.join(baseDir, 'package.json')).version;
+ const json = readFileSync(path.join(baseDir, 'package.json'), {
+ encoding: 'utf8',
+ });
+ const version = JSON.parse(json).version;
return typeof version === 'string' ? version : undefined;
} catch (error) {
diag.warn('Failed extracting version', baseDir);
@@ -171,7 +183,7 @@ export abstract class InstrumentationBase
}
private _onRequire(
- module: InstrumentationModuleDefinition,
+ module: InstrumentationModuleDefinition,
exports: T,
name: string,
baseDir?: string | void
@@ -180,6 +192,12 @@ export abstract class InstrumentationBase
if (typeof module.patch === 'function') {
module.moduleExports = exports;
if (this._enabled) {
+ this._diag.debug(
+ 'Applying instrumentation patch for nodejs core module on require hook',
+ {
+ module: module.name,
+ }
+ );
return module.patch(exports);
}
}
@@ -196,6 +214,14 @@ export abstract class InstrumentationBase
if (typeof module.patch === 'function') {
module.moduleExports = exports;
if (this._enabled) {
+ this._diag.debug(
+ 'Applying instrumentation patch for module on require hook',
+ {
+ module: module.name,
+ version: module.moduleVersion,
+ baseDir,
+ }
+ );
return module.patch(exports, module.moduleVersion);
}
}
@@ -213,7 +239,18 @@ export abstract class InstrumentationBase
return supportedFileInstrumentations.reduce((patchedExports, file) => {
file.moduleExports = patchedExports;
if (this._enabled) {
- return file.patch(patchedExports, module.moduleVersion);
+ this._diag.debug(
+ 'Applying instrumentation patch for nodejs module file on require hook',
+ {
+ module: module.name,
+ version: module.moduleVersion,
+ fileName: file.name,
+ baseDir,
+ }
+ );
+
+ // patch signature is not typed, so we cast it assuming it's correct
+ return file.patch(patchedExports, module.moduleVersion) as T;
}
return patchedExports;
}, exports);
@@ -229,10 +266,25 @@ export abstract class InstrumentationBase
if (this._hooks.length > 0) {
for (const module of this._modules) {
if (typeof module.patch === 'function' && module.moduleExports) {
+ this._diag.debug(
+ 'Applying instrumentation patch for nodejs module on instrumentation enabled',
+ {
+ module: module.name,
+ version: module.moduleVersion,
+ }
+ );
module.patch(module.moduleExports, module.moduleVersion);
}
for (const file of module.files) {
if (file.moduleExports) {
+ this._diag.debug(
+ 'Applying instrumentation patch for nodejs module file on instrumentation enabled',
+ {
+ module: module.name,
+ version: module.moduleVersion,
+ fileName: file.name,
+ }
+ );
file.patch(file.moduleExports, module.moduleVersion);
}
}
@@ -243,36 +295,25 @@ export abstract class InstrumentationBase
this._warnOnPreloadedModules();
for (const module of this._modules) {
const hookFn: HookFn = (exports, name, baseDir) => {
- return this._onRequire(
- module as unknown as InstrumentationModuleDefinition,
- exports,
- name,
- baseDir
- );
+ return this._onRequire(module, exports, name, baseDir);
};
const onRequire: OnRequireFn = (exports, name, baseDir) => {
- return this._onRequire(
- module as unknown as InstrumentationModuleDefinition,
- exports,
- name,
- baseDir
- );
+ return this._onRequire(module, exports, name, baseDir);
};
// `RequireInTheMiddleSingleton` does not support absolute paths.
// For an absolute paths, we must create a separate instance of the
// require-in-the-middle `Hook`.
const hook = path.isAbsolute(module.name)
- ? new Hook([module.name], { internals: true }, onRequire)
+ ? new HookRequire([module.name], { internals: true }, onRequire)
: this._requireInTheMiddleSingleton.register(module.name, onRequire);
this._hooks.push(hook);
- const esmHook =
- new (ImportInTheMiddle as unknown as typeof ImportInTheMiddle.default)(
- [module.name],
- { internals: false },
- hookFn
- );
+ const esmHook = new HookImport(
+ [module.name],
+ { internals: false },
+ hookFn
+ );
this._hooks.push(esmHook);
}
}
@@ -285,10 +326,25 @@ export abstract class InstrumentationBase
for (const module of this._modules) {
if (typeof module.unpatch === 'function' && module.moduleExports) {
+ this._diag.debug(
+ 'Removing instrumentation patch for nodejs module on instrumentation disabled',
+ {
+ module: module.name,
+ version: module.moduleVersion,
+ }
+ );
module.unpatch(module.moduleExports, module.moduleVersion);
}
for (const file of module.files) {
if (file.moduleExports) {
+ this._diag.debug(
+ 'Removing instrumentation patch for nodejs module file on instrumentation disabled',
+ {
+ module: module.name,
+ version: module.moduleVersion,
+ fileName: file.name,
+ }
+ );
file.unpatch(file.moduleExports, module.moduleVersion);
}
}
diff --git a/experimental/packages/opentelemetry-instrumentation/src/types.ts b/experimental/packages/opentelemetry-instrumentation/src/types.ts
index 3ef070f8290..2fa567ff012 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/types.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/types.ts
@@ -14,24 +14,19 @@
* limitations under the License.
*/
-import { TracerProvider, MeterProvider } from '@opentelemetry/api';
+import { TracerProvider, MeterProvider, Span } from '@opentelemetry/api';
import { LoggerProvider } from '@opentelemetry/api-logs';
/** Interface Instrumentation to apply patch. */
-export interface Instrumentation {
+export interface Instrumentation<
+ ConfigType extends InstrumentationConfig = InstrumentationConfig,
+> {
/** Instrumentation Name */
instrumentationName: string;
/** Instrumentation Version */
instrumentationVersion: string;
- /**
- * Instrumentation Description - please describe all useful information
- * as Instrumentation might patch different version of different modules,
- * or support different browsers etc.
- */
- instrumentationDescription?: string;
-
/** Method to disable the instrumentation */
disable(): void;
@@ -48,20 +43,18 @@ export interface Instrumentation {
setLoggerProvider?(loggerProvider: LoggerProvider): void;
/** Method to set instrumentation config */
- setConfig(config: InstrumentationConfig): void;
+ setConfig(config: ConfigType): void;
/** Method to get instrumentation config */
- getConfig(): InstrumentationConfig;
-
- /**
- * Contains all supported versions.
- * All versions must be compatible with [semver](https://semver.org/spec/v2.0.0.html) format.
- * If the version is not supported, we won't apply instrumentation patch (see `enable` method).
- * If omitted, all versions of the module will be patched.
- */
- supportedVersions?: string[];
+ getConfig(): ConfigType;
}
+/**
+ * Base interface for configuration options common to all instrumentations.
+ * This interface can be extended by individual instrumentations to include
+ * additional configuration options specific to that instrumentation.
+ * All configuration options must be optional.
+ */
export interface InstrumentationConfig {
/**
* Whether to enable the plugin.
@@ -82,46 +75,91 @@ export interface ShimWrapped extends Function {
__original: Function;
}
-export interface InstrumentationModuleFile {
+export interface InstrumentationModuleFile {
/** Name of file to be patched with relative path */
name: string;
- moduleExports?: T;
+ moduleExports?: unknown;
- /** Supported version this file */
+ /** Supported versions for the file.
+ *
+ * A module version is supported if one of the supportedVersions in the array satisfies the module version.
+ * The syntax of the version is checked with the `satisfies` function of "The semantic versioner for npm", see
+ * [`semver` package](https://www.npmjs.com/package/semver)
+ * If the version is not supported, we won't apply instrumentation patch.
+ * If omitted, all versions of the module will be patched.
+ *
+ * It is recommended to always specify a range that is bound to a major version, to avoid breaking changes.
+ * New major versions should be reviewed and tested before being added to the supportedVersions array.
+ *
+ * Example: ['>=1.2.3 <3']
+ */
supportedVersions: string[];
/** Method to patch the instrumentation */
- patch(moduleExports: T, moduleVersion?: string): T;
-
- /** Method to patch the instrumentation */
+ patch(moduleExports: unknown, moduleVersion?: string): unknown;
/** Method to unpatch the instrumentation */
- unpatch(moduleExports?: T, moduleVersion?: string): void;
+ unpatch(moduleExports?: unknown, moduleVersion?: string): void;
}
-export interface InstrumentationModuleDefinition {
+export interface InstrumentationModuleDefinition {
/** Module name or path */
name: string;
- moduleExports?: T;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ moduleExports?: any;
/** Instrumented module version */
moduleVersion?: string;
- /** Supported version of module */
+ /** Supported version of module.
+ *
+ * A module version is supported if one of the supportedVersions in the array satisfies the module version.
+ * The syntax of the version is checked with the `satisfies` function of "The semantic versioner for npm", see
+ * [`semver` package](https://www.npmjs.com/package/semver)
+ * If the version is not supported, we won't apply instrumentation patch (see `enable` method).
+ * If omitted, all versions of the module will be patched.
+ *
+ * It is recommended to always specify a range that is bound to a major version, to avoid breaking changes.
+ * New major versions should be reviewed and tested before being added to the supportedVersions array.
+ *
+ * Example: ['>=1.2.3 <3']
+ */
supportedVersions: string[];
/** Module internal files to be patched */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- files: InstrumentationModuleFile[];
+ files: InstrumentationModuleFile[];
/** If set to true, the includePrerelease check will be included when calling semver.satisfies */
includePrerelease?: boolean;
/** Method to patch the instrumentation */
- patch?: (moduleExports: T, moduleVersion?: string) => T;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ patch?: (moduleExports: any, moduleVersion?: string) => any;
/** Method to unpatch the instrumentation */
- unpatch?: (moduleExports: T, moduleVersion?: string) => void;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ unpatch?: (moduleExports: any, moduleVersion?: string) => void;
}
+
+/**
+ * SpanCustomizationHook is a common way for instrumentations to expose extension points
+ * where users can add custom behavior to a span based on info object passed to the hook at different times of the span lifecycle.
+ * This is an advanced feature, commonly used to add additional or non-spec-compliant attributes to the span,
+ * capture payloads, modify the span in some way, or carry some other side effect.
+ *
+ * The hook is registered with the instrumentation specific config by implementing an handler function with this signature,
+ * and if the hook is present, it will be called with the span and the event information
+ * when the event is emitted.
+ *
+ * When and under what conditions the hook is called and what data is passed
+ * in the info argument, is specific to each instrumentation and life-cycle event
+ * and should be documented where it is used.
+ *
+ * Instrumentation may define multiple hooks, for different spans, or different span life-cycle events.
+ */
+export type SpanCustomizationHook = (
+ span: Span,
+ info: SpanCustomizationInfoType
+) => void;
diff --git a/experimental/packages/opentelemetry-instrumentation/src/types_internal.ts b/experimental/packages/opentelemetry-instrumentation/src/types_internal.ts
index ad71821fc3a..6d678fea907 100644
--- a/experimental/packages/opentelemetry-instrumentation/src/types_internal.ts
+++ b/experimental/packages/opentelemetry-instrumentation/src/types_internal.ts
@@ -15,22 +15,15 @@
*/
import { TracerProvider, MeterProvider } from '@opentelemetry/api';
-import { InstrumentationBase } from './platform';
import { Instrumentation } from './types';
import { LoggerProvider } from '@opentelemetry/api-logs';
-export type InstrumentationOption =
- | typeof InstrumentationBase
- | (typeof InstrumentationBase)[]
- | Instrumentation
- | Instrumentation[];
-
export interface AutoLoaderResult {
instrumentations: Instrumentation[];
}
export interface AutoLoaderOptions {
- instrumentations?: InstrumentationOption[];
+ instrumentations?: (Instrumentation | Instrumentation[])[];
tracerProvider?: TracerProvider;
meterProvider?: MeterProvider;
loggerProvider?: LoggerProvider;
diff --git a/experimental/packages/opentelemetry-instrumentation/test/common/Instrumentation.test.ts b/experimental/packages/opentelemetry-instrumentation/test/common/Instrumentation.test.ts
index fde0c2c34e6..9b0e916762a 100644
--- a/experimental/packages/opentelemetry-instrumentation/test/common/Instrumentation.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation/test/common/Instrumentation.test.ts
@@ -20,6 +20,7 @@ import {
InstrumentationBase,
InstrumentationConfig,
InstrumentationModuleDefinition,
+ SpanCustomizationHook,
} from '../../src';
import { MeterProvider } from '@opentelemetry/sdk-metrics';
@@ -36,6 +37,12 @@ class TestInstrumentation extends InstrumentationBase {
override enable() {}
override disable() {}
init() {}
+
+ // the runInstrumentationEventHook, so we have to invoke it from the class for testing
+ testRunHook(hookHandler?: SpanCustomizationHook) {
+ const span = this.tracer.startSpan('test');
+ this._runSpanCustomizationHook(hookHandler, 'test', span, {});
+ }
}
describe('BaseInstrumentation', () => {
@@ -135,7 +142,7 @@ describe('BaseInstrumentation', () => {
});
describe('getModuleDefinitions', () => {
- const moduleDefinition: InstrumentationModuleDefinition = {
+ const moduleDefinition: InstrumentationModuleDefinition = {
name: 'foo',
patch: moduleExports => {},
unpatch: moduleExports => {},
@@ -182,5 +189,30 @@ describe('BaseInstrumentation', () => {
assert.deepStrictEqual(instrumentation.getModuleDefinitions(), []);
});
+
+ describe('runInstrumentationEventHook', () => {
+ it('should call the hook', () => {
+ const instrumentation = new TestInstrumentation({});
+ let called = false;
+ const hook = () => {
+ called = true;
+ };
+ instrumentation.testRunHook(hook);
+ assert.strictEqual(called, true);
+ });
+
+ it('empty hook should work', () => {
+ const instrumentation = new TestInstrumentation({});
+ instrumentation.testRunHook(undefined);
+ });
+
+ it('exception in hook should not crash', () => {
+ const instrumentation = new TestInstrumentation({});
+ const hook = () => {
+ throw new Error('test');
+ };
+ instrumentation.testRunHook(hook);
+ });
+ });
});
});
diff --git a/experimental/packages/opentelemetry-instrumentation/test/common/autoLoaderUtils.test.ts b/experimental/packages/opentelemetry-instrumentation/test/common/autoLoaderUtils.test.ts
deleted file mode 100644
index 24772250046..00000000000
--- a/experimental/packages/opentelemetry-instrumentation/test/common/autoLoaderUtils.test.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 { InstrumentationBase } from '../../src';
-import { parseInstrumentationOptions } from '../../src/autoLoaderUtils';
-
-class FooInstrumentation extends InstrumentationBase {
- constructor() {
- super('foo', '1', {});
- }
-
- init() {
- return [];
- }
-
- override enable() {}
-
- override disable() {}
-}
-
-// const fooInstrumentation = new FooInstrumentation();
-
-describe('autoLoaderUtils', () => {
- describe('parseInstrumentationOptions', () => {
- it('should create a new instrumentation from class', () => {
- const { instrumentations } = parseInstrumentationOptions([
- FooInstrumentation,
- ]);
- assert.strictEqual(instrumentations.length, 1);
- const instrumentation = instrumentations[0];
- assert.ok(instrumentation instanceof InstrumentationBase);
- });
-
- it('should return an instrumentation from Instrumentation', () => {
- const { instrumentations } = parseInstrumentationOptions([
- new FooInstrumentation(),
- ]);
- assert.strictEqual(instrumentations.length, 1);
- const instrumentation = instrumentations[0];
- assert.ok(instrumentation instanceof InstrumentationBase);
- });
- });
-});
diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/EsmInstrumentation.test.mjs b/experimental/packages/opentelemetry-instrumentation/test/node/EsmInstrumentation.test.mjs
index f09097cd796..a46fdc0fd3e 100644
--- a/experimental/packages/opentelemetry-instrumentation/test/node/EsmInstrumentation.test.mjs
+++ b/experimental/packages/opentelemetry-instrumentation/test/node/EsmInstrumentation.test.mjs
@@ -26,14 +26,21 @@ class TestInstrumentationWrapFn extends InstrumentationBase {
super('test-esm-instrumentation', '0.0.1', config);
}
init() {
- console.log('test-esm-instrumentation initialized!');
return new InstrumentationNodeModuleDefinition(
'test-esm-module',
['*'],
moduleExports => {
- this._wrap(moduleExports, 'testFunction', () => {
- return () => 'patched';
+ const wrapRetval = this._wrap(moduleExports, 'testFunction', () => {
+ return function wrappedTestFunction() {
+ return 'patched';
+ };
});
+ assert.strictEqual(typeof wrapRetval, 'function');
+ assert.strictEqual(
+ wrapRetval.name,
+ 'wrappedTestFunction',
+ '_wrap(..., "testFunction", ...) return value is the wrapped function'
+ );
return moduleExports;
},
moduleExports => {
@@ -49,7 +56,6 @@ class TestInstrumentationMasswrapFn extends InstrumentationBase {
super('test-esm-instrumentation', '0.0.1', config);
}
init() {
- console.log('test-esm-instrumentation initialized!');
return new InstrumentationNodeModuleDefinition(
'test-esm-module',
['*'],
@@ -79,7 +85,6 @@ class TestInstrumentationSimple extends InstrumentationBase {
super('test-esm-instrumentation', '0.0.1', config);
}
init() {
- console.log('test-esm-instrumentation initialized!');
return new InstrumentationNodeModuleDefinition(
'test-esm-module',
['*'],
diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts b/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts
index 74d856da006..fd732c2bd9a 100644
--- a/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts
@@ -33,7 +33,7 @@ const CORE_MODULE = 'random_core';
class TestInstrumentation extends InstrumentationBase {
constructor() {
- super(MODULE_NAME, MODULE_VERSION);
+ super(MODULE_NAME, MODULE_VERSION, {});
}
init() {}
@@ -56,7 +56,7 @@ describe('InstrumentationBase', () => {
const instrumentationModule = {
name: CORE_MODULE,
patch: modulePatchSpy as unknown,
- } as InstrumentationModuleDefinition;
+ } as InstrumentationModuleDefinition;
// @ts-expect-error access internal property for testing
instrumentation._onRequire(
@@ -79,7 +79,7 @@ describe('InstrumentationBase', () => {
const instrumentationModule = {
name: CORE_MODULE,
patch: modulePatchSpy as unknown,
- } as InstrumentationModuleDefinition;
+ } as InstrumentationModuleDefinition;
// @ts-expect-error access internal property for testing
instrumentation._onRequire(
@@ -117,7 +117,7 @@ describe('InstrumentationBase', () => {
supportedVersions: [`^${MODULE_VERSION}`],
name: MODULE_NAME,
patch: modulePatchSpy as unknown,
- } as InstrumentationModuleDefinition;
+ } as InstrumentationModuleDefinition;
// @ts-expect-error access internal property for testing
instrumentation._onRequire(
@@ -140,7 +140,7 @@ describe('InstrumentationBase', () => {
supportedVersions: [`^${MODULE_VERSION}`, WILDCARD_VERSION],
name: MODULE_NAME,
patch: modulePatchSpy as unknown,
- } as InstrumentationModuleDefinition;
+ } as InstrumentationModuleDefinition;
// @ts-expect-error access internal property for testing
instrumentation._onRequire(
@@ -186,7 +186,7 @@ describe('InstrumentationBase', () => {
patch: filePatchSpy as unknown,
},
],
- } as InstrumentationModuleDefinition;
+ } as InstrumentationModuleDefinition;
// @ts-expect-error access internal property for testing
instrumentation._onRequire(
@@ -218,7 +218,7 @@ describe('InstrumentationBase', () => {
patch: filePatchSpy as unknown,
},
],
- } as InstrumentationModuleDefinition;
+ } as InstrumentationModuleDefinition;
// @ts-expect-error access internal property for testing
instrumentation._onRequire(
@@ -262,7 +262,7 @@ describe('InstrumentationBase', () => {
patch: filePatchSpy as unknown,
},
],
- } as InstrumentationModuleDefinition;
+ } as InstrumentationModuleDefinition;
// @ts-expect-error access internal property for testing
instrumentation._onRequire(
@@ -293,15 +293,15 @@ describe('InstrumentationBase', () => {
type Exports = Record;
type ExportsPatched = Exports & { __patched?: boolean };
const moduleName = 'net';
- class TestInstrumentation extends InstrumentationBase {
+ class TestInstrumentation extends InstrumentationBase {
constructor() {
super('@opentelemetry/instrumentation-net-test', '0.0.0', {
enabled: false,
});
}
- init(): InstrumentationNodeModuleDefinition[] {
+ init(): InstrumentationNodeModuleDefinition[] {
return [
- new InstrumentationNodeModuleDefinition(
+ new InstrumentationNodeModuleDefinition(
moduleName,
['*'],
(exports: ExportsPatched) => {
@@ -335,15 +335,15 @@ describe('InstrumentationBase', () => {
type ExportsPatched = Exports & { __patched?: boolean };
const moduleName = 'absolutePathTestFixture';
const fileName = path.join(__dirname, 'fixtures', `${moduleName}.js`);
- class TestInstrumentation extends InstrumentationBase {
+ class TestInstrumentation extends InstrumentationBase {
constructor() {
super('@opentelemetry/instrumentation-absolute-path-test', '0.0.0', {
enabled: false,
});
}
- init(): InstrumentationNodeModuleDefinition[] {
+ init(): InstrumentationNodeModuleDefinition[] {
return [
- new InstrumentationNodeModuleDefinition(
+ new InstrumentationNodeModuleDefinition(
fileName,
['*'],
undefined,
diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/RequireInTheMiddleSingleton.test.ts b/experimental/packages/opentelemetry-instrumentation/test/node/RequireInTheMiddleSingleton.test.ts
index d6401d1faa7..75cd0ad6282 100644
--- a/experimental/packages/opentelemetry-instrumentation/test/node/RequireInTheMiddleSingleton.test.ts
+++ b/experimental/packages/opentelemetry-instrumentation/test/node/RequireInTheMiddleSingleton.test.ts
@@ -39,8 +39,8 @@ describe('RequireInTheMiddleSingleton', () => {
const onRequireFsPromisesStub = makeOnRequiresStub('fs-promises');
const onRequireCodecovStub = makeOnRequiresStub('codecov');
const onRequireCodecovLibStub = makeOnRequiresStub('codecov-lib');
- const onRequireCpxStub = makeOnRequiresStub('cpx');
- const onRequireCpxLibStub = makeOnRequiresStub('cpx-lib');
+ const onRequireCpxStub = makeOnRequiresStub('cpx2');
+ const onRequireCpxLibStub = makeOnRequiresStub('cpx2-lib');
before(() => {
requireInTheMiddleSingleton.register('fs', onRequireFsStub);
@@ -53,9 +53,9 @@ describe('RequireInTheMiddleSingleton', () => {
'codecov/lib/codecov.js',
onRequireCodecovLibStub
);
- requireInTheMiddleSingleton.register('cpx', onRequireCpxStub);
+ requireInTheMiddleSingleton.register('cpx2', onRequireCpxStub);
requireInTheMiddleSingleton.register(
- 'cpx/lib/copy-sync.js',
+ 'cpx2/lib/copy-sync.js',
onRequireCpxLibStub
);
});
@@ -150,16 +150,19 @@ describe('RequireInTheMiddleSingleton', () => {
describe('non-core module with sub-path', () => {
describe('AND module name matches', () => {
const baseDir = path.resolve(
- path.dirname(require.resolve('cpx')),
+ path.dirname(require.resolve('cpx2')),
'..'
);
- const modulePath = path.join('cpx', 'lib', 'copy-sync.js');
+ const modulePath = path.join('cpx2', 'lib', 'copy-sync.js');
it('should call `onRequire`', () => {
- const exports = require('cpx/lib/copy-sync');
- assert.deepStrictEqual(exports.__ritmOnRequires, ['cpx', 'cpx-lib']);
+ const exports = require('cpx2/lib/copy-sync');
+ assert.deepStrictEqual(exports.__ritmOnRequires, [
+ 'cpx2',
+ 'cpx2-lib',
+ ]);
sinon.assert.calledWithMatch(
onRequireCpxStub,
- { __ritmOnRequires: ['cpx', 'cpx-lib'] },
+ { __ritmOnRequires: ['cpx2', 'cpx2-lib'] },
modulePath,
baseDir
);
@@ -175,7 +178,7 @@ describe('RequireInTheMiddleSingleton', () => {
modulePath,
baseDir
);
- });
+ }).timeout(30000);
});
});
});
diff --git a/experimental/packages/opentelemetry-sdk-node/LICENSE b/experimental/packages/opentelemetry-sdk-node/LICENSE
index 5d6f747bfde..261eeb9e9f8 100644
--- a/experimental/packages/opentelemetry-sdk-node/LICENSE
+++ b/experimental/packages/opentelemetry-sdk-node/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2020 The OpenTelemetry Authors
+ 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.
diff --git a/experimental/packages/opentelemetry-sdk-node/README.md b/experimental/packages/opentelemetry-sdk-node/README.md
index 0afe166c719..147d1725251 100644
--- a/experimental/packages/opentelemetry-sdk-node/README.md
+++ b/experimental/packages/opentelemetry-sdk-node/README.md
@@ -115,9 +115,26 @@ Configure a resource. Resources may also be detected by using the `autoDetectRes
### resourceDetectors
-Configure resource detectors. By default, the resource detectors are [envDetector, processDetector].
+Configure resource detectors. By default, the resource detectors are [envDetector, processDetector, hostDetector].
NOTE: In order to enable the detection, the parameter `autoDetectResources` has to be `true`.
+If `resourceDetectors` was not set, you can also use the environment variable `OTEL_NODE_RESOURCE_DETECTORS` to enable only certain detectors, or completely disable them:
+
+- `env`
+- `host`
+- `os`
+- `process`
+- `serviceinstance` (experimental)
+- `all` - enable all resource detectors above
+ - **NOTE:** future versions of `@opentelemetry/sdk-node` may include additional detectors that will be covered by this scope.
+- `none` - disable resource detection
+
+For example, to enable only the `env`, `host` detectors:
+
+```shell
+export OTEL_NODE_RESOURCE_DETECTORS="env,host"
+```
+
### sampler
Configure a custom sampler. By default, all traces will be sampled.
@@ -132,7 +149,7 @@ An array of span processors to register to the tracer provider.
### traceExporter
-Configure a trace exporter. If an exporter is configured, it will be used with a [BatchSpanProcessor](../../../packages/opentelemetry-sdk-trace-base/src/platform/node/export/BatchSpanProcessor.ts). If an exporter OR span processor is not configured programatically, this package will auto setup the default `otlp` exporter with `http/protobuf` protocol with a `BatchSpanProcessor`.
+Configure a trace exporter. If an exporter is configured, it will be used with a [BatchSpanProcessor](../../../packages/opentelemetry-sdk-trace-base/src/platform/node/export/BatchSpanProcessor.ts). If an exporter OR span processor is not configured programmatically, this package will auto setup the default `otlp` exporter with `http/protobuf` protocol with a `BatchSpanProcessor`.
### spanLimits
@@ -168,7 +185,7 @@ This is an alternative to programmatically configuring an exporter or span proce
| 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_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. |
### OTLP Exporter
diff --git a/experimental/packages/opentelemetry-sdk-node/package.json b/experimental/packages/opentelemetry-sdk-node/package.json
index ccc89654863..742738062ac 100644
--- a/experimental/packages/opentelemetry-sdk-node/package.json
+++ b/experimental/packages/opentelemetry-sdk-node/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/sdk-node",
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "OpenTelemetry SDK for Node.js",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
@@ -9,7 +9,7 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build",
"clean": "tsc --build --clean",
- "test": "nyc ts-mocha -p tsconfig.json test/**/*.test.ts",
+ "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",
@@ -17,7 +17,8 @@
"watch": "tsc --build --watch",
"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"
+ "peer-api-check": "node ../../../scripts/peer-api-check.js",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -44,39 +45,38 @@
"access": "public"
},
"dependencies": {
- "@opentelemetry/api-logs": "0.49.1",
- "@opentelemetry/core": "1.22.0",
- "@opentelemetry/exporter-trace-otlp-grpc": "0.49.1",
- "@opentelemetry/exporter-trace-otlp-http": "0.49.1",
- "@opentelemetry/exporter-trace-otlp-proto": "0.49.1",
- "@opentelemetry/exporter-zipkin": "1.22.0",
- "@opentelemetry/instrumentation": "0.49.1",
- "@opentelemetry/resources": "1.22.0",
- "@opentelemetry/sdk-logs": "0.49.1",
- "@opentelemetry/sdk-metrics": "1.22.0",
- "@opentelemetry/sdk-trace-base": "1.22.0",
- "@opentelemetry/sdk-trace-node": "1.22.0",
- "@opentelemetry/semantic-conventions": "1.22.0"
+ "@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-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"
},
"peerDependencies": {
- "@opentelemetry/api": ">=1.3.0 <1.9.0"
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
},
"devDependencies": {
- "@opentelemetry/api": "1.8.0",
- "@opentelemetry/context-async-hooks": "1.22.0",
- "@opentelemetry/exporter-jaeger": "1.22.0",
- "@types/mocha": "10.0.6",
+ "@opentelemetry/api": "1.9.0",
+ "@opentelemetry/context-async-hooks": "1.25.1",
+ "@opentelemetry/exporter-jaeger": "1.25.1",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/semver": "7.5.6",
- "@types/sinon": "10.0.20",
+ "@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.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-node",
diff --git a/experimental/packages/opentelemetry-sdk-node/src/sdk.ts b/experimental/packages/opentelemetry-sdk-node/src/sdk.ts
index c8ebfb48a7e..24a7d2332d0 100644
--- a/experimental/packages/opentelemetry-sdk-node/src/sdk.ts
+++ b/experimental/packages/opentelemetry-sdk-node/src/sdk.ts
@@ -23,7 +23,7 @@ import {
} from '@opentelemetry/api';
import { logs } from '@opentelemetry/api-logs';
import {
- InstrumentationOption,
+ Instrumentation,
registerInstrumentations,
} from '@opentelemetry/instrumentation';
import {
@@ -31,6 +31,7 @@ import {
DetectorSync,
detectResourcesSync,
envDetector,
+ hostDetector,
IResource,
processDetector,
Resource,
@@ -46,11 +47,11 @@ import {
NodeTracerConfig,
NodeTracerProvider,
} from '@opentelemetry/sdk-trace-node';
-import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
+import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { NodeSDKConfiguration } from './types';
import { TracerProviderWithEnvExporters } from './TracerProviderWithEnvExporter';
import { getEnv, getEnvWithoutDefaults } from '@opentelemetry/core';
-import { parseInstrumentationOptions } from './utils';
+import { getResourceDetectorsFromEnv } from './utils';
/** This class represents everything needed to register a fully configured OpenTelemetry Node.js SDK */
@@ -81,7 +82,7 @@ export class NodeSDK {
};
private _loggerProviderConfig?: LoggerProviderConfig;
private _meterProviderConfig?: MeterProviderConfig;
- private _instrumentations: InstrumentationOption[];
+ private _instrumentations: Instrumentation[];
private _resource: IResource;
private _resourceDetectors: Array;
@@ -120,15 +121,19 @@ export class NodeSDK {
this._configuration = configuration;
this._resource = configuration.resource ?? new Resource({});
- this._resourceDetectors = configuration.resourceDetectors ?? [
- envDetector,
- processDetector,
- ];
+ this._autoDetectResources = configuration.autoDetectResources ?? true;
+ if (!this._autoDetectResources) {
+ this._resourceDetectors = [];
+ } else if (configuration.resourceDetectors != null) {
+ this._resourceDetectors = configuration.resourceDetectors;
+ } else if (process.env.OTEL_NODE_RESOURCE_DETECTORS != null) {
+ this._resourceDetectors = getResourceDetectorsFromEnv();
+ } else {
+ this._resourceDetectors = [envDetector, processDetector, hostDetector];
+ }
this._serviceName = configuration.serviceName;
- this._autoDetectResources = configuration.autoDetectResources ?? true;
-
// If a tracer provider can be created from manual configuration, create it
if (
configuration.traceExporter ||
@@ -155,23 +160,23 @@ export class NodeSDK {
const spanProcessor =
configuration.spanProcessor ??
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
new BatchSpanProcessor(configuration.traceExporter!);
const spanProcessors = configuration.spanProcessors ?? [spanProcessor];
- this.configureTracerProvider(
- tracerProviderConfig,
+ this._tracerProviderConfig = {
+ tracerConfig: tracerProviderConfig,
spanProcessors,
- configuration.contextManager,
- configuration.textMapPropagator
- );
+ contextManager: configuration.contextManager,
+ textMapPropagator: configuration.textMapPropagator,
+ };
}
if (configuration.logRecordProcessor) {
- const loggerProviderConfig: LoggerProviderConfig = {
+ this._loggerProviderConfig = {
logRecordProcessor: configuration.logRecordProcessor,
};
- this.configureLoggerProvider(loggerProviderConfig);
}
if (configuration.metricReader || configuration.views) {
@@ -184,127 +189,10 @@ export class NodeSDK {
meterProviderConfig.views = configuration.views;
}
- this.configureMeterProvider(meterProviderConfig);
- }
-
- let instrumentations: InstrumentationOption[] = [];
- if (configuration.instrumentations) {
- instrumentations = configuration.instrumentations;
- }
- this._instrumentations = instrumentations;
- }
-
- /**
- *
- * @deprecated Please pass {@code sampler}, {@code generalLimits}, {@code spanLimits}, {@code resource},
- * {@code IdGenerator}, {@code spanProcessor}, {@code contextManager} and {@code textMapPropagator},
- * to the constructor options instead.
- *
- * Set configurations needed to register a TracerProvider
- */
- public configureTracerProvider(
- tracerConfig: NodeTracerConfig,
- spanProcessors: SpanProcessor[],
- contextManager?: ContextManager,
- textMapPropagator?: TextMapPropagator
- ): void {
- this._tracerProviderConfig = {
- tracerConfig,
- spanProcessors,
- contextManager,
- textMapPropagator,
- };
- }
-
- /**
- * @deprecated Please pass {@code logRecordProcessor} to the constructor options instead.
- *
- * Set configurations needed to register a LoggerProvider
- */
- public configureLoggerProvider(config: LoggerProviderConfig): void {
- // nothing is set yet, we can set config and then return
- if (this._loggerProviderConfig == null) {
- this._loggerProviderConfig = config;
- return;
- }
-
- // make sure we do not override existing logRecordProcessor with other logRecordProcessors.
- if (
- this._loggerProviderConfig.logRecordProcessor != null &&
- config.logRecordProcessor != null
- ) {
- throw new Error(
- 'LogRecordProcessor passed but LogRecordProcessor has already been configured.'
- );
+ this._meterProviderConfig = meterProviderConfig;
}
- // set logRecordProcessor, but make sure we do not override existing logRecordProcessors with null/undefined.
- if (config.logRecordProcessor != null) {
- this._loggerProviderConfig.logRecordProcessor = config.logRecordProcessor;
- }
- }
-
- /**
- * @deprecated Please pass {@code views} and {@code reader} to the constructor options instead.
- *
- * Set configurations needed to register a MeterProvider
- */
- public configureMeterProvider(config: MeterProviderConfig): void {
- // nothing is set yet, we can set config and return.
- if (this._meterProviderConfig == null) {
- this._meterProviderConfig = config;
- return;
- }
-
- // make sure we do not override existing views with other views.
- if (this._meterProviderConfig.views != null && config.views != null) {
- throw new Error('Views passed but Views have already been configured.');
- }
-
- // set views, but make sure we do not override existing views with null/undefined.
- if (config.views != null) {
- this._meterProviderConfig.views = config.views;
- }
-
- // make sure we do not override existing reader with another reader.
- if (this._meterProviderConfig.reader != null && config.reader != null) {
- throw new Error(
- 'MetricReader passed but MetricReader has already been configured.'
- );
- }
-
- // set reader, but make sure we do not override existing reader with null/undefined.
- if (config.reader != null) {
- this._meterProviderConfig.reader = config.reader;
- }
- }
-
- /**
- * @deprecated Resources are detected automatically on {@link NodeSDK.start()}, when the {@code autoDetectResources}
- * constructor option is set to {@code true} or left {@code undefined}.
- *
- * Detect resource attributes
- */
- public detectResources(): void {
- if (this._disabled) {
- return;
- }
-
- const internalConfig: ResourceDetectionConfig = {
- detectors: this._resourceDetectors,
- };
-
- this.addResource(detectResourcesSync(internalConfig));
- }
-
- /**
- * @deprecated Please pre-merge resources and pass them to the constructor
- *
- * Manually add a Resource
- * @param resource
- */
- public addResource(resource: IResource): void {
- this._resource = this._resource.merge(resource);
+ this._instrumentations = configuration.instrumentations?.flat() ?? [];
}
/**
@@ -320,7 +208,13 @@ export class NodeSDK {
});
if (this._autoDetectResources) {
- this.detectResources();
+ const internalConfig: ResourceDetectionConfig = {
+ detectors: this._resourceDetectors,
+ };
+
+ this._resource = this._resource.merge(
+ detectResourcesSync(internalConfig)
+ );
}
this._resource =
@@ -328,7 +222,7 @@ export class NodeSDK {
? this._resource
: this._resource.merge(
new Resource({
- [SemanticResourceAttributes.SERVICE_NAME]: this._serviceName,
+ [SEMRESATTRS_SERVICE_NAME]: this._serviceName,
})
);
@@ -352,7 +246,10 @@ export class NodeSDK {
}
tracerProvider.register({
- contextManager: this._tracerProviderConfig?.contextManager,
+ contextManager:
+ this._tracerProviderConfig?.contextManager ??
+ // _tracerProviderConfig may be undefined if trace-specific settings are not provided - fall back to raw config
+ this._configuration?.contextManager,
propagator: this._tracerProviderConfig?.textMapPropagator,
});
@@ -387,9 +284,7 @@ export class NodeSDK {
// TODO: This is a workaround to fix https://github.com/open-telemetry/opentelemetry-js/issues/3609
// If the MeterProvider is not yet registered when instrumentations are registered, all metrics are dropped.
// This code is obsolete once https://github.com/open-telemetry/opentelemetry-js/issues/3622 is implemented.
- for (const instrumentation of parseInstrumentationOptions(
- this._instrumentations
- )) {
+ for (const instrumentation of this._instrumentations) {
instrumentation.setMeterProvider(metrics.getMeterProvider());
}
}
diff --git a/experimental/packages/opentelemetry-sdk-node/src/types.ts b/experimental/packages/opentelemetry-sdk-node/src/types.ts
index 2ed7cae48dd..c3b2a1cd84c 100644
--- a/experimental/packages/opentelemetry-sdk-node/src/types.ts
+++ b/experimental/packages/opentelemetry-sdk-node/src/types.ts
@@ -16,7 +16,7 @@
import type { ContextManager } from '@opentelemetry/api';
import { TextMapPropagator } from '@opentelemetry/api';
-import { InstrumentationOption } from '@opentelemetry/instrumentation';
+import { Instrumentation } from '@opentelemetry/instrumentation';
import { Detector, DetectorSync, IResource } from '@opentelemetry/resources';
import { LogRecordProcessor } from '@opentelemetry/sdk-logs';
import { MetricReader, View } from '@opentelemetry/sdk-metrics';
@@ -35,7 +35,7 @@ export interface NodeSDKConfiguration {
logRecordProcessor: LogRecordProcessor;
metricReader: MetricReader;
views: View[];
- instrumentations: InstrumentationOption[];
+ instrumentations: (Instrumentation | Instrumentation[])[];
resource: IResource;
resourceDetectors: Array;
sampler: Sampler;
diff --git a/experimental/packages/opentelemetry-sdk-node/src/utils.ts b/experimental/packages/opentelemetry-sdk-node/src/utils.ts
index a3d83147477..4bc696f402b 100644
--- a/experimental/packages/opentelemetry-sdk-node/src/utils.ts
+++ b/experimental/packages/opentelemetry-sdk-node/src/utils.ts
@@ -14,30 +14,50 @@
* limitations under the License.
*/
+import { diag } from '@opentelemetry/api';
import {
- Instrumentation,
- InstrumentationOption,
-} from '@opentelemetry/instrumentation';
+ DetectorSync,
+ envDetectorSync,
+ hostDetectorSync,
+ osDetectorSync,
+ processDetectorSync,
+ serviceInstanceIdDetectorSync,
+} from '@opentelemetry/resources';
-// TODO: This part of a workaround to fix https://github.com/open-telemetry/opentelemetry-js/issues/3609
-// If the MeterProvider is not yet registered when instrumentations are registered, all metrics are dropped.
-// This code is obsolete once https://github.com/open-telemetry/opentelemetry-js/issues/3622 is implemented.
-export function parseInstrumentationOptions(
- options: InstrumentationOption[] = []
-): Instrumentation[] {
- let instrumentations: Instrumentation[] = [];
- for (let i = 0, j = options.length; i < j; i++) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const option = options[i] as any;
- if (Array.isArray(option)) {
- const results = parseInstrumentationOptions(option);
- instrumentations = instrumentations.concat(results);
- } else if (typeof option === 'function') {
- instrumentations.push(new option());
- } else if ((option as Instrumentation).instrumentationName) {
- instrumentations.push(option);
- }
+const RESOURCE_DETECTOR_ENVIRONMENT = 'env';
+const RESOURCE_DETECTOR_HOST = 'host';
+const RESOURCE_DETECTOR_OS = 'os';
+const RESOURCE_DETECTOR_PROCESS = 'process';
+const RESOURCE_DETECTOR_SERVICE_INSTANCE_ID = 'serviceinstance';
+
+export function getResourceDetectorsFromEnv(): Array {
+ // When updating this list, make sure to also update the section `resourceDetectors` on README.
+ const resourceDetectors = new Map([
+ [RESOURCE_DETECTOR_ENVIRONMENT, envDetectorSync],
+ [RESOURCE_DETECTOR_HOST, hostDetectorSync],
+ [RESOURCE_DETECTOR_OS, osDetectorSync],
+ [RESOURCE_DETECTOR_SERVICE_INSTANCE_ID, serviceInstanceIdDetectorSync],
+ [RESOURCE_DETECTOR_PROCESS, processDetectorSync],
+ ]);
+
+ const resourceDetectorsFromEnv =
+ process.env.OTEL_NODE_RESOURCE_DETECTORS?.split(',') ?? ['all'];
+
+ if (resourceDetectorsFromEnv.includes('all')) {
+ return [...resourceDetectors.values()].flat();
}
- return instrumentations;
+ if (resourceDetectorsFromEnv.includes('none')) {
+ return [];
+ }
+
+ return resourceDetectorsFromEnv.flatMap(detector => {
+ const resourceDetector = resourceDetectors.get(detector);
+ if (!resourceDetector) {
+ diag.error(
+ `Invalid resource detector "${detector}" specified in the environment variable OTEL_NODE_RESOURCE_DETECTORS`
+ );
+ }
+ return resourceDetector || [];
+ });
}
diff --git a/experimental/packages/opentelemetry-sdk-node/test/TracerProviderWithEnvExporter.test.ts b/experimental/packages/opentelemetry-sdk-node/test/TracerProviderWithEnvExporter.test.ts
index 7ceb5e3dce7..21a1fa93d79 100644
--- a/experimental/packages/opentelemetry-sdk-node/test/TracerProviderWithEnvExporter.test.ts
+++ b/experimental/packages/opentelemetry-sdk-node/test/TracerProviderWithEnvExporter.test.ts
@@ -132,7 +132,7 @@ describe('set up trace exporter with env exporters', () => {
assert(listOfProcessors === undefined);
delete env.OTEL_TRACES_EXPORTER;
});
- it('log warning that sdk will not be initalized when exporter is set to none', async () => {
+ it('log warning that sdk will not be initialized when exporter is set to none', async () => {
env.OTEL_TRACES_EXPORTER = 'none';
new TracerProviderWithEnvExporters();
diff --git a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
index 95ab97b7cef..280564ff79f 100644
--- a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
+++ b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
@@ -39,7 +39,10 @@ import {
View,
} from '@opentelemetry/sdk-metrics';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
-import { assertServiceResource } from './util/resource-assertions';
+import {
+ assertServiceInstanceIdIsUUID,
+ assertServiceResource,
+} from './util/resource-assertions';
import {
ConsoleSpanExporter,
SimpleSpanProcessor,
@@ -56,8 +59,11 @@ import { env } from 'process';
import { TracerProviderWithEnvExporters } from '../src/TracerProviderWithEnvExporter';
import {
envDetector,
+ envDetectorSync,
processDetector,
+ hostDetector,
Resource,
+ serviceInstanceIdDetectorSync,
} from '@opentelemetry/resources';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { logs } from '@opentelemetry/api-logs';
@@ -66,6 +72,10 @@ import {
InMemoryLogRecordExporter,
LoggerProvider,
} from '@opentelemetry/sdk-logs';
+import {
+ SEMRESATTRS_HOST_NAME,
+ SEMRESATTRS_PROCESS_PID,
+} from '@opentelemetry/semantic-conventions';
const DefaultContextManager = semver.gte(process.version, '14.8.0')
? AsyncLocalStorageContextManager
@@ -121,6 +131,7 @@ describe('Node SDK', () => {
assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));
assert.ok(!(logs.getLoggerProvider() instanceof LoggerProvider));
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
it('should register a diag logger with OTEL_LOG_LEVEL', () => {
@@ -140,6 +151,7 @@ describe('Node SDK', () => {
});
delete env.OTEL_LOG_LEVEL;
+ sdk.shutdown();
});
it('should not register a diag logger with OTEL_LOG_LEVEL unset', () => {
@@ -153,6 +165,7 @@ describe('Node SDK', () => {
sdk.start();
assert.strictEqual(spy.callCount, 0);
+ sdk.shutdown();
});
it('should register a tracer provider if an exporter is provided', async () => {
@@ -175,6 +188,7 @@ describe('Node SDK', () => {
const apiTracerProvider =
trace.getTracerProvider() as ProxyTracerProvider;
assert.ok(apiTracerProvider.getDelegate() instanceof NodeTracerProvider);
+ await sdk.shutdown();
});
it('should register a tracer provider if an exporter is provided via env', async () => {
@@ -198,6 +212,7 @@ describe('Node SDK', () => {
trace.getTracerProvider() as ProxyTracerProvider;
assert.ok(apiTracerProvider.getDelegate() instanceof NodeTracerProvider);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
it('should register a tracer provider if span processors are provided', async () => {
@@ -235,6 +250,7 @@ describe('Node SDK', () => {
assert(listOfProcessors[0] instanceof NoopSpanProcessor);
assert(listOfProcessors[1] instanceof SimpleSpanProcessor);
assert(listOfProcessors[2] instanceof BatchSpanProcessor);
+ await sdk.shutdown();
});
it('should register a meter provider if a reader is provided', async () => {
@@ -310,6 +326,22 @@ describe('Node SDK', () => {
await sdk.shutdown();
delete env.OTEL_TRACES_EXPORTER;
});
+
+ it('should register a context manager if only a context manager is provided', async () => {
+ // arrange
+ const expectedContextManager = new AsyncHooksContextManager();
+ const sdk = new NodeSDK({
+ contextManager: expectedContextManager,
+ });
+
+ // act
+ sdk.start();
+
+ // assert
+ const actualContextManager = context['_getContextManager']();
+ assert.equal(actualContextManager, expectedContextManager);
+ await sdk.shutdown();
+ });
});
async function waitForNumberOfMetrics(
@@ -404,107 +436,6 @@ describe('Node SDK', () => {
delete env.OTEL_TRACES_EXPORTER;
});
- it('should throw error when calling configureMeterProvider when views are already configured', () => {
- const exporter = new InMemoryMetricExporter(
- AggregationTemporality.CUMULATIVE
- );
- const metricReader = new PeriodicExportingMetricReader({
- exporter: exporter,
- exportIntervalMillis: 100,
- exportTimeoutMillis: 100,
- });
-
- const sdk = new NodeSDK({
- metricReader: metricReader,
- views: [
- new View({
- name: 'test-view',
- instrumentName: 'test_counter',
- instrumentType: InstrumentType.COUNTER,
- }),
- ],
- autoDetectResources: false,
- });
-
- assert.throws(
- () => {
- sdk.configureMeterProvider({
- reader: metricReader,
- views: [
- new View({
- name: 'test-view',
- instrumentName: 'test_counter',
- instrumentType: InstrumentType.COUNTER,
- }),
- ],
- });
- },
- (error: Error) => {
- return error.message.includes(
- 'Views passed but Views have already been configured'
- );
- }
- );
- });
-
- it('should throw error when calling configureMeterProvider when metricReader is already configured', () => {
- const exporter = new InMemoryMetricExporter(
- AggregationTemporality.CUMULATIVE
- );
- const metricReader = new PeriodicExportingMetricReader({
- exporter: exporter,
- exportIntervalMillis: 100,
- exportTimeoutMillis: 100,
- });
-
- const sdk = new NodeSDK({
- metricReader: metricReader,
- views: [
- new View({
- name: 'test-view',
- instrumentName: 'test_counter',
- instrumentType: InstrumentType.COUNTER,
- }),
- ],
- autoDetectResources: false,
- });
-
- assert.throws(
- () => {
- sdk.configureMeterProvider({
- reader: metricReader,
- });
- },
- (error: Error) => {
- return error.message.includes(
- 'MetricReader passed but MetricReader has already been configured.'
- );
- }
- );
- });
-
- it('should throw error when calling configureLoggerProvider when logRecordProcessor is already configured', () => {
- const logRecordExporter = new InMemoryLogRecordExporter();
- const logRecordProcessor = new SimpleLogRecordProcessor(logRecordExporter);
- const sdk = new NodeSDK({
- logRecordProcessor: logRecordProcessor,
- autoDetectResources: false,
- });
-
- assert.throws(
- () => {
- sdk.configureLoggerProvider({
- logRecordProcessor: logRecordProcessor,
- });
- },
- (error: Error) => {
- return error.message.includes(
- 'LogRecordProcessor passed but LogRecordProcessor has already been configured.'
- );
- }
- );
- });
-
describe('detectResources', async () => {
beforeEach(() => {
process.env.OTEL_RESOURCE_ATTRIBUTES =
@@ -527,9 +458,10 @@ describe('Node SDK', () => {
},
},
envDetector,
+ hostDetector,
],
});
- sdk.detectResources();
+ sdk.start();
const resource = sdk['_resource'];
await resource.waitForAsyncAttributes?.();
@@ -541,6 +473,29 @@ describe('Node SDK', () => {
namespace: 'default',
version: '0.0.1',
});
+ await sdk.shutdown();
+ });
+ });
+
+ describe('default resource detectors', () => {
+ it('default detectors populate values properly', async () => {
+ const sdk = new NodeSDK();
+ sdk.start();
+ const resource = sdk['_resource'];
+ await resource.waitForAsyncAttributes?.();
+
+ assertServiceResource(resource, {
+ instanceId: '627cc493',
+ name: 'my-service',
+ namespace: 'default',
+ version: '0.0.1',
+ });
+
+ assert.notEqual(
+ resource.attributes[SEMRESATTRS_PROCESS_PID],
+ undefined
+ );
+ assert.notEqual(resource.attributes[SEMRESATTRS_HOST_NAME], undefined);
});
});
@@ -556,10 +511,11 @@ describe('Node SDK', () => {
},
},
envDetector,
+ hostDetector,
],
});
- sdk.detectResources();
+ sdk.start();
const resource = sdk['_resource'];
await resource.waitForAsyncAttributes?.();
@@ -569,10 +525,11 @@ describe('Node SDK', () => {
namespace: 'default',
version: '0.0.1',
});
+ await sdk.shutdown();
});
});
- describe('with a debug logger', () => {
+ describe('with a diag logger', () => {
// Local functions to test if a mocked method is ever called with a specific argument or regex matching for an argument.
// Needed because of race condition with parallel detectors.
const callArgsContains = (
@@ -609,7 +566,7 @@ describe('Node SDK', () => {
DiagLogLevel.VERBOSE
);
- sdk.detectResources();
+ sdk.start();
await sdk['_resource'].waitForAsyncAttributes?.();
// Test that the Env Detector successfully found its resource and populated it with the right values.
@@ -623,6 +580,54 @@ describe('Node SDK', () => {
/{\s+"service\.instance\.id":\s+"627cc493",\s+"service\.name":\s+"my-service",\s+"service\.namespace":\s+"default",\s+"service\.version":\s+"0.0.1"\s+}\s*/gm
)
);
+ await sdk.shutdown();
+ });
+
+ describe('with unknown OTEL_NODE_RESOURCE_DETECTORS value', () => {
+ before(() => {
+ process.env.OTEL_NODE_RESOURCE_DETECTORS = 'env,os,no-such-detector';
+ });
+
+ after(() => {
+ delete process.env.OTEL_NODE_RESOURCE_DETECTORS;
+ });
+
+ // 1. If not auto-detecting resources, then NodeSDK should not
+ // complain about `OTEL_NODE_RESOURCE_DETECTORS` values.
+ // 2. If given resourceDetectors, then NodeSDK should not complain
+ // about `OTEL_NODE_RESOURCE_DETECTORS` values.
+ //
+ // Practically, these tests help ensure that there is no spurious
+ // diag error message when using OTEL_NODE_RESOURCE_DETECTORS with
+ // @opentelemetry/auto-instrumentations-node, which supports more values
+ // than this package (e.g. 'gcp').
+ it('does not diag.warn when not using the envvar', async () => {
+ const diagMocks = {
+ error: Sinon.fake(),
+ warn: Sinon.fake(),
+ info: Sinon.fake(),
+ debug: Sinon.fake(),
+ verbose: Sinon.fake(),
+ };
+ diag.setLogger(diagMocks, DiagLogLevel.DEBUG);
+
+ const sdk1 = new NodeSDK({
+ autoDetectResources: false,
+ });
+ sdk1.start();
+ await sdk1.shutdown();
+
+ const sdk2 = new NodeSDK({
+ resourceDetectors: [envDetectorSync],
+ });
+ sdk2.start();
+ await sdk2.shutdown();
+
+ assert.ok(
+ !callArgsMatches(diagMocks.error, /no-such-detector/),
+ 'diag.error() messages do not mention "no-such-detector"'
+ );
+ });
});
describe('with a faulty environment variable', () => {
@@ -642,7 +647,7 @@ describe('Node SDK', () => {
DiagLogLevel.DEBUG
);
- sdk.detectResources();
+ sdk.start();
assert.ok(
callArgsContains(
@@ -650,6 +655,7 @@ describe('Node SDK', () => {
'EnvDetector failed: Attribute value should be a ASCII string with a length not exceed 255 characters.'
)
);
+ await sdk.shutdown();
});
});
});
@@ -667,6 +673,7 @@ describe('Node SDK', () => {
assertServiceResource(resource, {
name: 'config-set-name',
});
+ await sdk.shutdown();
});
it('should configure service name via OTEL_SERVICE_NAME env var', async () => {
@@ -681,6 +688,7 @@ describe('Node SDK', () => {
name: 'env-set-name',
});
delete process.env.OTEL_SERVICE_NAME;
+ await sdk.shutdown();
});
it('should favor config set service name over OTEL_SERVICE_NAME env set service name', async () => {
@@ -697,11 +705,12 @@ describe('Node SDK', () => {
name: 'config-set-name',
});
delete process.env.OTEL_SERVICE_NAME;
+ await sdk.shutdown();
});
it('should configure service name via OTEL_RESOURCE_ATTRIBUTES env var', async () => {
process.env.OTEL_RESOURCE_ATTRIBUTES =
- 'service.name=resource-env-set-name';
+ 'service.name=resource-env-set-name,service.instance.id=my-instance-id';
const sdk = new NodeSDK();
sdk.start();
@@ -710,13 +719,15 @@ describe('Node SDK', () => {
assertServiceResource(resource, {
name: 'resource-env-set-name',
+ instanceId: 'my-instance-id',
});
delete process.env.OTEL_RESOURCE_ATTRIBUTES;
+ await sdk.shutdown();
});
it('should favor config set service name over OTEL_RESOURCE_ATTRIBUTES env set service name', async () => {
process.env.OTEL_RESOURCE_ATTRIBUTES =
- 'service.name=resource-env-set-name';
+ 'service.name=resource-env-set-name,service.instance.id=my-instance-id';
const sdk = new NodeSDK({
serviceName: 'config-set-name',
});
@@ -727,8 +738,61 @@ describe('Node SDK', () => {
assertServiceResource(resource, {
name: 'config-set-name',
+ instanceId: 'my-instance-id',
+ });
+ delete process.env.OTEL_RESOURCE_ATTRIBUTES;
+ await sdk.shutdown();
+ });
+ });
+
+ describe('configureServiceInstanceId', async () => {
+ it('should configure service instance id via OTEL_RESOURCE_ATTRIBUTES env var', async () => {
+ process.env.OTEL_RESOURCE_ATTRIBUTES =
+ 'service.instance.id=627cc493,service.name=my-service,service.namespace';
+ const sdk = new NodeSDK();
+
+ sdk.start();
+ const resource = sdk['_resource'];
+ await resource.waitForAsyncAttributes?.();
+
+ assertServiceResource(resource, {
+ name: 'my-service',
+ instanceId: '627cc493',
});
delete process.env.OTEL_RESOURCE_ATTRIBUTES;
+ await sdk.shutdown();
+ });
+
+ it('should configure service instance id via OTEL_NODE_RESOURCE_DETECTORS env var', async () => {
+ process.env.OTEL_NODE_RESOURCE_DETECTORS = 'env,host,os,serviceinstance';
+ const sdk = new NodeSDK();
+
+ sdk.start();
+ const resource = sdk['_resource'];
+ await resource.waitForAsyncAttributes?.();
+
+ assertServiceInstanceIdIsUUID(resource);
+ delete process.env.OTEL_NODE_RESOURCE_DETECTORS;
+ await sdk.shutdown();
+ });
+
+ it('should configure service instance id with random UUID', async () => {
+ const sdk = new NodeSDK({
+ autoDetectResources: true,
+ resourceDetectors: [
+ processDetector,
+ envDetector,
+ hostDetector,
+ serviceInstanceIdDetectorSync,
+ ],
+ });
+
+ sdk.start();
+ const resource = sdk['_resource'];
+ await resource.waitForAsyncAttributes?.();
+
+ assertServiceInstanceIdIsUUID(resource);
+ await sdk.shutdown();
});
});
@@ -743,7 +807,7 @@ describe('Node SDK', () => {
it('should not register a trace provider', async () => {
const sdk = new NodeSDK({});
- await sdk.start();
+ sdk.start();
assert.strictEqual(
(trace.getTracerProvider() as ProxyTracerProvider).getDelegate(),
@@ -766,7 +830,7 @@ describe('Node SDK', () => {
metricReader: metricReader,
autoDetectResources: false,
});
- await sdk.start();
+ sdk.start();
assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));
@@ -794,13 +858,15 @@ describe('Node SDK', () => {
},
},
envDetector,
+ hostDetector,
],
});
- sdk.detectResources();
+ sdk.start();
const resource = sdk['_resource'];
await resource.waitForAsyncAttributes?.();
assert.deepStrictEqual(resource, Resource.empty());
+ await sdk.shutdown();
});
});
});
@@ -829,6 +895,7 @@ describe('Node SDK', () => {
assert.strictEqual(span.spanContext().spanId, 'constant-test-span-id');
assert.strictEqual(span.spanContext().traceId, 'constant-test-trace-id');
+ await sdk.shutdown();
});
});
});
@@ -857,6 +924,7 @@ describe('setup exporter from env', () => {
assert(sdk['_tracerProvider'] instanceof TracerProviderWithEnvExporters);
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
+ await sdk.shutdown();
});
it('ignore env exporter when user provides exporter to sdk config', async () => {
const traceExporter = new ConsoleSpanExporter();
@@ -873,6 +941,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof SimpleSpanProcessor === false);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
+ await sdk.shutdown();
});
it('ignores default env exporter when user provides span processor to sdk config', async () => {
const traceExporter = new ConsoleSpanExporter();
@@ -890,6 +959,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof SimpleSpanProcessor);
assert(listOfProcessors[0] instanceof BatchSpanProcessor === false);
+ await sdk.shutdown();
});
it('ignores env exporter when user provides tracer exporter to sdk config and sets exporter via env', async () => {
env.OTEL_TRACES_EXPORTER = 'console';
@@ -908,6 +978,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof SimpleSpanProcessor === false);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
it('should only create one span processor when configured using env vars and config', async () => {
env.OTEL_TRACES_EXPORTER = 'console';
@@ -923,6 +994,7 @@ describe('setup exporter from env', () => {
);
assert.strictEqual(listOfProcessors.length, 1);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
it('use otlp exporter and defined exporter protocol env value', async () => {
env.OTEL_TRACES_EXPORTER = 'otlp';
@@ -937,6 +1009,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
delete env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
+ await sdk.shutdown();
});
it('use noop span processor when user sets env exporter to none', async () => {
env.OTEL_TRACES_EXPORTER = 'none';
@@ -950,8 +1023,9 @@ describe('setup exporter from env', () => {
assert(listOfProcessors.length === 0);
assert(activeProcessor instanceof NoopSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
- it('log warning that sdk will not be initalized when exporter is set to none', async () => {
+ it('log warning that sdk will not be initialized when exporter is set to none', async () => {
env.OTEL_TRACES_EXPORTER = 'none';
const sdk = new NodeSDK();
sdk.start();
@@ -961,16 +1035,18 @@ describe('setup exporter from env', () => {
'OTEL_TRACES_EXPORTER contains "none". SDK will not be initialized.'
);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
it('use default otlp exporter when user does not set exporter via env or config', async () => {
const sdk = new NodeSDK();
- await sdk.start();
+ sdk.start();
const listOfProcessors =
sdk['_tracerProvider']!['_registeredSpanProcessors']!;
assert(sdk['_tracerProvider'] instanceof TracerProviderWithEnvExporters);
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
+ await sdk.shutdown();
});
it('use default otlp exporter when empty value is provided for exporter via env', async () => {
env.OTEL_TRACES_EXPORTER = '';
@@ -983,6 +1059,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors.length === 1);
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
env.OTEL_TRACES_EXPORTER = '';
+ await sdk.shutdown();
});
it('use only default exporter when none value is provided with other exporters', async () => {
@@ -997,6 +1074,7 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
it('log warning that only default exporter will be used since exporter list contains none with other exports ', async () => {
env.OTEL_TRACES_EXPORTER = 'otlp,zipkin,none';
@@ -1008,6 +1086,7 @@ describe('setup exporter from env', () => {
'OTEL_TRACES_EXPORTER contains "none" along with other exporters. Using default otlp exporter.'
);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
it('should warn that provided exporter value is unrecognized and not able to be set up', async () => {
env.OTEL_TRACES_EXPORTER = 'invalid';
@@ -1025,6 +1104,7 @@ describe('setup exporter from env', () => {
);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
it('setup zipkin, jaeger and otlp exporters', async () => {
env.OTEL_TRACES_EXPORTER = 'zipkin, otlp, jaeger';
@@ -1042,6 +1122,7 @@ describe('setup exporter from env', () => {
delete env.OTEL_TRACES_EXPORTER;
delete env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
+ await sdk.shutdown();
});
it('use the console exporter', async () => {
env.OTEL_TRACES_EXPORTER = 'console, otlp';
@@ -1054,5 +1135,6 @@ describe('setup exporter from env', () => {
assert(listOfProcessors[0] instanceof SimpleSpanProcessor);
assert(listOfProcessors[1] instanceof BatchSpanProcessor);
delete env.OTEL_TRACES_EXPORTER;
+ await sdk.shutdown();
});
});
diff --git a/experimental/packages/opentelemetry-sdk-node/test/util/resource-assertions.ts b/experimental/packages/opentelemetry-sdk-node/test/util/resource-assertions.ts
index 80c8c04ecca..930d3fe61ec 100644
--- a/experimental/packages/opentelemetry-sdk-node/test/util/resource-assertions.ts
+++ b/experimental/packages/opentelemetry-sdk-node/test/util/resource-assertions.ts
@@ -18,11 +18,37 @@ import { SDK_INFO } from '@opentelemetry/core';
import * as assert from 'assert';
import { IResource, Resource } from '@opentelemetry/resources';
import {
+ SEMRESATTRS_CLOUD_ACCOUNT_ID,
+ SEMRESATTRS_CLOUD_AVAILABILITY_ZONE,
+ SEMRESATTRS_CLOUD_PROVIDER,
+ SEMRESATTRS_CLOUD_REGION,
+ SEMRESATTRS_CONTAINER_ID,
+ SEMRESATTRS_CONTAINER_IMAGE_NAME,
+ SEMRESATTRS_CONTAINER_IMAGE_TAG,
+ SEMRESATTRS_CONTAINER_NAME,
+ SEMRESATTRS_HOST_ID,
+ SEMRESATTRS_HOST_IMAGE_ID,
+ SEMRESATTRS_HOST_IMAGE_NAME,
+ SEMRESATTRS_HOST_IMAGE_VERSION,
+ SEMRESATTRS_HOST_NAME,
+ SEMRESATTRS_HOST_TYPE,
+ SEMRESATTRS_K8S_CLUSTER_NAME,
+ SEMRESATTRS_K8S_DEPLOYMENT_NAME,
+ SEMRESATTRS_K8S_NAMESPACE_NAME,
+ SEMRESATTRS_K8S_POD_NAME,
+ SEMRESATTRS_PROCESS_COMMAND,
+ SEMRESATTRS_PROCESS_COMMAND_LINE,
+ SEMRESATTRS_PROCESS_EXECUTABLE_NAME,
+ SEMRESATTRS_PROCESS_PID,
+ SEMRESATTRS_SERVICE_INSTANCE_ID,
+ SEMRESATTRS_SERVICE_NAME,
+ SEMRESATTRS_SERVICE_NAMESPACE,
+ SEMRESATTRS_SERVICE_VERSION,
SEMRESATTRS_TELEMETRY_SDK_LANGUAGE,
SEMRESATTRS_TELEMETRY_SDK_NAME,
SEMRESATTRS_TELEMETRY_SDK_VERSION,
- SemanticResourceAttributes,
} from '@opentelemetry/semantic-conventions';
+import * as semconv from '@opentelemetry/semantic-conventions';
/**
* Test utility method to validate a cloud resource
@@ -42,22 +68,22 @@ export const assertCloudResource = (
assertHasOneLabel('CLOUD', resource);
if (validations.provider)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.CLOUD_PROVIDER],
+ resource.attributes[SEMRESATTRS_CLOUD_PROVIDER],
validations.provider
);
if (validations.accountId)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.CLOUD_ACCOUNT_ID],
+ resource.attributes[SEMRESATTRS_CLOUD_ACCOUNT_ID],
validations.accountId
);
if (validations.region)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.CLOUD_REGION],
+ resource.attributes[SEMRESATTRS_CLOUD_REGION],
validations.region
);
if (validations.zone)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.CLOUD_AVAILABILITY_ZONE],
+ resource.attributes[SEMRESATTRS_CLOUD_AVAILABILITY_ZONE],
validations.zone
);
};
@@ -80,22 +106,22 @@ export const assertContainerResource = (
assertHasOneLabel('CONTAINER', resource);
if (validations.name)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.CONTAINER_NAME],
+ resource.attributes[SEMRESATTRS_CONTAINER_NAME],
validations.name
);
if (validations.id)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.CONTAINER_ID],
+ resource.attributes[SEMRESATTRS_CONTAINER_ID],
validations.id
);
if (validations.imageName)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.CONTAINER_IMAGE_NAME],
+ resource.attributes[SEMRESATTRS_CONTAINER_IMAGE_NAME],
validations.imageName
);
if (validations.imageTag)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.CONTAINER_IMAGE_TAG],
+ resource.attributes[SEMRESATTRS_CONTAINER_IMAGE_TAG],
validations.imageTag
);
};
@@ -121,32 +147,32 @@ export const assertHostResource = (
assertHasOneLabel('HOST', resource);
if (validations.id)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.HOST_ID],
+ resource.attributes[SEMRESATTRS_HOST_ID],
validations.id
);
if (validations.name)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.HOST_NAME],
+ resource.attributes[SEMRESATTRS_HOST_NAME],
validations.name
);
if (validations.hostType)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.HOST_TYPE],
+ resource.attributes[SEMRESATTRS_HOST_TYPE],
validations.hostType
);
if (validations.imageName)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.HOST_IMAGE_NAME],
+ resource.attributes[SEMRESATTRS_HOST_IMAGE_NAME],
validations.imageName
);
if (validations.imageId)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.HOST_IMAGE_ID],
+ resource.attributes[SEMRESATTRS_HOST_IMAGE_ID],
validations.imageId
);
if (validations.imageVersion)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.HOST_IMAGE_VERSION],
+ resource.attributes[SEMRESATTRS_HOST_IMAGE_VERSION],
validations.imageVersion
);
};
@@ -169,22 +195,22 @@ export const assertK8sResource = (
assertHasOneLabel('K8S', resource);
if (validations.clusterName)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.K8S_CLUSTER_NAME],
+ resource.attributes[SEMRESATTRS_K8S_CLUSTER_NAME],
validations.clusterName
);
if (validations.namespaceName)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.K8S_NAMESPACE_NAME],
+ resource.attributes[SEMRESATTRS_K8S_NAMESPACE_NAME],
validations.namespaceName
);
if (validations.podName)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.K8S_POD_NAME],
+ resource.attributes[SEMRESATTRS_K8S_POD_NAME],
validations.podName
);
if (validations.deploymentName)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.K8S_DEPLOYMENT_NAME],
+ resource.attributes[SEMRESATTRS_K8S_DEPLOYMENT_NAME],
validations.deploymentName
);
};
@@ -212,17 +238,17 @@ export const assertTelemetrySDKResource = (
if (validations.name)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.TELEMETRY_SDK_NAME],
+ resource.attributes[SEMRESATTRS_TELEMETRY_SDK_NAME],
validations.name
);
if (validations.language)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE],
+ resource.attributes[SEMRESATTRS_TELEMETRY_SDK_LANGUAGE],
validations.language
);
if (validations.version)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.TELEMETRY_SDK_VERSION],
+ resource.attributes[SEMRESATTRS_TELEMETRY_SDK_VERSION],
validations.version
);
};
@@ -243,21 +269,21 @@ export const assertServiceResource = (
}
) => {
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.SERVICE_NAME],
+ resource.attributes[SEMRESATTRS_SERVICE_NAME],
validations.name
);
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.SERVICE_INSTANCE_ID],
+ resource.attributes[SEMRESATTRS_SERVICE_INSTANCE_ID],
validations.instanceId
);
if (validations.namespace)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.SERVICE_NAMESPACE],
+ resource.attributes[SEMRESATTRS_SERVICE_NAMESPACE],
validations.namespace
);
if (validations.version)
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.SERVICE_VERSION],
+ resource.attributes[SEMRESATTRS_SERVICE_VERSION],
validations.version
);
};
@@ -278,24 +304,24 @@ export const assertProcessResource = (
}
) => {
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.PROCESS_PID],
+ resource.attributes[SEMRESATTRS_PROCESS_PID],
validations.pid
);
if (validations.name) {
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.PROCESS_EXECUTABLE_NAME],
+ resource.attributes[SEMRESATTRS_PROCESS_EXECUTABLE_NAME],
validations.name
);
}
if (validations.command) {
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.PROCESS_COMMAND],
+ resource.attributes[SEMRESATTRS_PROCESS_COMMAND],
validations.command
);
}
if (validations.commandLine) {
assert.strictEqual(
- resource.attributes[SemanticResourceAttributes.PROCESS_COMMAND_LINE],
+ resource.attributes[SEMRESATTRS_PROCESS_COMMAND_LINE],
validations.commandLine
);
}
@@ -310,29 +336,39 @@ export const assertEmptyResource = (resource: Resource) => {
assert.strictEqual(Object.keys(resource.attributes).length, 0);
};
+/**
+ * Assert that the `resource` has at least one known attribute with the given
+ * `prefix`. By "known", we mean it is an attribute defined in semconv.
+ */
const assertHasOneLabel = (prefix: string, resource: Resource): void => {
- const hasOne = Object.entries(SemanticResourceAttributes).find(
- ([key, value]) => {
- return (
- key.startsWith(prefix) &&
- Object.prototype.hasOwnProperty.call(resource.attributes, value)
- );
- }
+ const semconvModPrefix = `SEMRESATTRS_${prefix.toUpperCase()}_`;
+ const knownAttrs: Set = new Set(
+ Object.entries(semconv)
+ .filter(
+ ([k, v]) => typeof v === 'string' && k.startsWith(semconvModPrefix)
+ )
+ .map(([, v]) => v as string)
+ );
+ const hasAttrs = Object.keys(resource.attributes).filter(k =>
+ knownAttrs.has(k)
);
-
assert.ok(
- hasOne,
- 'Must have one node Resource(s) starting with [' +
+ hasAttrs.length > 0,
+ 'Must have one Resource(s) starting with [' +
prefix +
'] matching the following attributes: ' +
- Object.entries(SemanticResourceAttributes)
- .reduce((result, [key, value]) => {
- if (key.startsWith(prefix)) {
- result.push(value);
- }
- return result;
- })
- .join(', ') +
- JSON.stringify(Object.keys(SemanticResourceAttributes))
+ Array.from(knownAttrs).join(', ') +
+ JSON.stringify(Object.keys(semconv))
+ );
+};
+
+export const assertServiceInstanceIdIsUUID = (resource: Resource): void => {
+ const UUID_REGEX =
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
+ assert.equal(
+ UUID_REGEX.test(
+ resource.attributes[SEMRESATTRS_SERVICE_INSTANCE_ID]?.toString() || ''
+ ),
+ true
);
};
diff --git a/experimental/packages/otlp-exporter-base/LICENSE b/experimental/packages/otlp-exporter-base/LICENSE
index 5d6f747bfde..261eeb9e9f8 100644
--- a/experimental/packages/otlp-exporter-base/LICENSE
+++ b/experimental/packages/otlp-exporter-base/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2020 The OpenTelemetry Authors
+ 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.
diff --git a/experimental/packages/otlp-exporter-base/package.json b/experimental/packages/otlp-exporter-base/package.json
index 66c3f7505e9..b8c748e7c5e 100644
--- a/experimental/packages/otlp-exporter-base/package.json
+++ b/experimental/packages/otlp-exporter-base/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentelemetry/otlp-exporter-base",
- "version": "0.49.1",
+ "version": "0.52.1",
"description": "OpenTelemetry OTLP Exporter base (for internal use only)",
"main": "build/src/index.js",
"module": "build/esm/index.js",
@@ -23,12 +23,13 @@
"lint:fix": "eslint . --ext .ts --fix",
"tdd": "npm run test -- --watch-extensions ts --watch",
"tdd:browser": "karma start",
- "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
+ "test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.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",
"precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies",
- "prewatch": "npm run precompile"
+ "prewatch": "npm run precompile",
+ "align-api-deps": "node ../../../scripts/align-api-deps.js"
},
"keywords": [
"opentelemetry",
@@ -61,30 +62,30 @@
"access": "public"
},
"dependencies": {
- "@opentelemetry/core": "1.22.0"
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/otlp-transformer": "0.52.1"
},
"devDependencies": {
- "@babel/core": "7.23.6",
- "@babel/preset-env": "7.22.20",
- "@opentelemetry/api": "1.8.0",
- "@types/mocha": "10.0.6",
+ "@babel/core": "7.24.9",
+ "@babel/preset-env": "7.24.7",
+ "@opentelemetry/api": "1.9.0",
+ "@types/mocha": "10.0.7",
"@types/node": "18.6.5",
- "@types/sinon": "10.0.20",
- "babel-plugin-istanbul": "6.1.1",
+ "@types/sinon": "17.0.3",
+ "babel-plugin-istanbul": "7.0.0",
"codecov": "3.8.3",
"cross-var": "1.1.0",
- "karma": "6.4.2",
+ "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": "4.0.2",
+ "karma-webpack": "5.0.1",
"lerna": "6.6.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"sinon": "15.1.2",
- "ts-loader": "8.4.0",
- "ts-mocha": "10.0.0",
+ "ts-loader": "9.5.1",
"typescript": "4.4.4",
"webpack": "5.89.0",
"webpack-cli": "5.1.4",
diff --git a/experimental/packages/otlp-exporter-base/src/OTLPExporterBase.ts b/experimental/packages/otlp-exporter-base/src/OTLPExporterBase.ts
index 8a008dacb91..0e8c37f00d2 100644
--- a/experimental/packages/otlp-exporter-base/src/OTLPExporterBase.ts
+++ b/experimental/packages/otlp-exporter-base/src/OTLPExporterBase.ts
@@ -33,9 +33,11 @@ import { configureExporterTimeout } from './util';
export abstract class OTLPExporterBase<
T extends OTLPExporterConfigBase,
ExportItem,
- ServiceRequest,
> {
public readonly url: string;
+ /**
+ * @deprecated scheduled for removal. This is only used in tests.
+ */
public readonly hostname: string | undefined;
public readonly timeoutMillis: number;
protected _concurrencyLimit: number;
@@ -143,5 +145,4 @@ export abstract class OTLPExporterBase<
onError: (error: OTLPExporterError) => void
): void;
abstract getDefaultUrl(config: T): string;
- abstract convert(objects: ExportItem[]): ServiceRequest;
}
diff --git a/experimental/packages/otlp-grpc-exporter-base/src/export-response.ts b/experimental/packages/otlp-exporter-base/src/export-response.ts
similarity index 79%
rename from experimental/packages/otlp-grpc-exporter-base/src/export-response.ts
rename to experimental/packages/otlp-exporter-base/src/export-response.ts
index c13af631e13..4e0eb9703e8 100644
--- a/experimental/packages/otlp-grpc-exporter-base/src/export-response.ts
+++ b/experimental/packages/otlp-exporter-base/src/export-response.ts
@@ -24,4 +24,12 @@ export interface ExportResponseFailure {
error: Error;
}
-export type ExportResponse = ExportResponseSuccess | ExportResponseFailure;
+export interface ExportResponseRetryable {
+ status: 'retryable';
+ retryInMillis?: number;
+}
+
+export type ExportResponse =
+ | ExportResponseSuccess
+ | ExportResponseFailure
+ | ExportResponseRetryable;
diff --git a/experimental/packages/otlp-grpc-exporter-base/src/exporter-transport.ts b/experimental/packages/otlp-exporter-base/src/exporter-transport.ts
similarity index 100%
rename from experimental/packages/otlp-grpc-exporter-base/src/exporter-transport.ts
rename to experimental/packages/otlp-exporter-base/src/exporter-transport.ts
diff --git a/experimental/packages/otlp-exporter-base/src/index.ts b/experimental/packages/otlp-exporter-base/src/index.ts
index 9ded1037826..a2722f7ef5d 100644
--- a/experimental/packages/otlp-exporter-base/src/index.ts
+++ b/experimental/packages/otlp-exporter-base/src/index.ts
@@ -27,3 +27,12 @@ export {
configureExporterTimeout,
invalidTimeout,
} from './util';
+
+export {
+ ExportResponse,
+ ExportResponseFailure,
+ ExportResponseSuccess,
+ ExportResponseRetryable,
+} from './export-response';
+
+export { IExporterTransport } from './exporter-transport';
diff --git a/experimental/packages/otlp-exporter-base/src/is-export-retryable.ts b/experimental/packages/otlp-exporter-base/src/is-export-retryable.ts
new file mode 100644
index 00000000000..8b4569987bb
--- /dev/null
+++ b/experimental/packages/otlp-exporter-base/src/is-export-retryable.ts
@@ -0,0 +1,40 @@
+/*
+ * 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 function isExportRetryable(statusCode: number): boolean {
+ const retryCodes = [429, 502, 503, 504];
+ return retryCodes.includes(statusCode);
+}
+
+export function parseRetryAfterToMills(
+ retryAfter?: string | undefined | null
+): number | undefined {
+ if (retryAfter == null) {
+ return undefined;
+ }
+
+ const seconds = Number.parseInt(retryAfter, 10);
+ if (Number.isInteger(seconds)) {
+ return seconds > 0 ? seconds * 1000 : -1;
+ }
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After#directives
+ const delay = new Date(retryAfter).getTime() - Date.now();
+
+ if (delay >= 0) {
+ return delay;
+ }
+ return 0;
+}
diff --git a/experimental/packages/otlp-exporter-base/src/platform/browser/OTLPExporterBrowserBase.ts b/experimental/packages/otlp-exporter-base/src/platform/browser/OTLPExporterBrowserBase.ts
index 1c3715055a2..2eed5d3e562 100644
--- a/experimental/packages/otlp-exporter-base/src/platform/browser/OTLPExporterBrowserBase.ts
+++ b/experimental/packages/otlp-exporter-base/src/platform/browser/OTLPExporterBrowserBase.ts
@@ -21,22 +21,33 @@ import { parseHeaders } from '../../util';
import { sendWithBeacon, sendWithXhr } from './util';
import { diag } from '@opentelemetry/api';
import { getEnv, baggageUtils } from '@opentelemetry/core';
+import { ISerializer } from '@opentelemetry/otlp-transformer';
/**
* Collector Metric Exporter abstract base class
*/
export abstract class OTLPExporterBrowserBase<
ExportItem,
- ServiceRequest,
-> extends OTLPExporterBase {
+ ServiceResponse,
+> extends OTLPExporterBase {
protected _headers: Record;
private _useXHR: boolean = false;
+ private _contentType: string;
+ private _serializer: ISerializer;
/**
* @param config
+ * @param serializer
+ * @param contentType
*/
- constructor(config: OTLPExporterConfigBase = {}) {
+ constructor(
+ config: OTLPExporterConfigBase = {},
+ serializer: ISerializer,
+ contentType: string
+ ) {
super(config);
+ this._serializer = serializer;
+ this._contentType = contentType;
this._useXHR =
!!config.headers || typeof navigator.sendBeacon !== 'function';
if (this._useXHR) {
@@ -65,15 +76,17 @@ export abstract class OTLPExporterBrowserBase<
diag.debug('Shutdown already started. Cannot send objects');
return;
}
- const serviceRequest = this.convert(items);
- const body = JSON.stringify(serviceRequest);
+ const body = this._serializer.serializeRequest(items) ?? new Uint8Array();
const promise = new Promise((resolve, reject) => {
if (this._useXHR) {
sendWithXhr(
body,
this.url,
- this._headers,
+ {
+ ...this._headers,
+ 'Content-Type': this._contentType,
+ },
this.timeoutMillis,
resolve,
reject
@@ -82,7 +95,7 @@ export abstract class OTLPExporterBrowserBase<
sendWithBeacon(
body,
this.url,
- { type: 'application/json' },
+ { type: this._contentType },
resolve,
reject
);
diff --git a/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts b/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts
index fade4afa88b..d82688b97ca 100644
--- a/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts
+++ b/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts
@@ -33,7 +33,7 @@ import {
* @param onError
*/
export function sendWithBeacon(
- body: string,
+ body: Uint8Array,
url: string,
blobPropertyBag: BlobPropertyBag,
onSuccess: () => void,
@@ -58,7 +58,7 @@ export function sendWithBeacon(
* @param onError
*/
export function sendWithXhr(
- body: string | Blob,
+ body: Uint8Array,
url: string,
headers: Record,
exporterTimeout: number,
diff --git a/experimental/packages/otlp-exporter-base/src/platform/index.ts b/experimental/packages/otlp-exporter-base/src/platform/index.ts
index fc857a58020..08a2b63613f 100644
--- a/experimental/packages/otlp-exporter-base/src/platform/index.ts
+++ b/experimental/packages/otlp-exporter-base/src/platform/index.ts
@@ -16,9 +16,6 @@
export {
OTLPExporterNodeBase,
- sendWithHttp,
- createHttpAgent,
- configureCompression,
OTLPExporterNodeConfigBase,
CompressionAlgorithm,
} from './node';
diff --git a/experimental/packages/otlp-exporter-base/src/platform/node/OTLPExporterNodeBase.ts b/experimental/packages/otlp-exporter-base/src/platform/node/OTLPExporterNodeBase.ts
index 5a8b1dfdfa5..5ab20427f06 100644
--- a/experimental/packages/otlp-exporter-base/src/platform/node/OTLPExporterNodeBase.ts
+++ b/experimental/packages/otlp-exporter-base/src/platform/node/OTLPExporterNodeBase.ts
@@ -14,46 +14,71 @@
* limitations under the License.
*/
-import type * as http from 'http';
-import type * as https from 'https';
-
import { OTLPExporterBase } from '../../OTLPExporterBase';
-import { OTLPExporterNodeConfigBase, CompressionAlgorithm } from './types';
-import * as otlpTypes from '../../types';
-import { parseHeaders } from '../../util';
-import { createHttpAgent, sendWithHttp, configureCompression } from './util';
+import { OTLPExporterNodeConfigBase } from './types';
+import { configureCompression } from './util';
import { diag } from '@opentelemetry/api';
import { getEnv, baggageUtils } from '@opentelemetry/core';
+import { ISerializer } from '@opentelemetry/otlp-transformer';
+import { IExporterTransport } from '../../exporter-transport';
+import { createHttpExporterTransport } from './http-exporter-transport';
+import { OTLPExporterError } from '../../types';
+import { createRetryingTransport } from '../../retryable-transport';
/**
* Collector Metric Exporter abstract base class
*/
export abstract class OTLPExporterNodeBase<
ExportItem,
- ServiceRequest,
-> extends OTLPExporterBase<
- OTLPExporterNodeConfigBase,
- ExportItem,
- ServiceRequest
-> {
- DEFAULT_HEADERS: Record = {};
- headers: Record;
- agent: http.Agent | https.Agent | undefined;
- compression: CompressionAlgorithm;
+ ServiceResponse,
+> extends OTLPExporterBase {
+ private _serializer: ISerializer;
+ private _transport: IExporterTransport;
- constructor(config: OTLPExporterNodeConfigBase = {}) {
+ constructor(
+ config: OTLPExporterNodeConfigBase = {},
+ serializer: ISerializer,
+ signalSpecificHeaders: Record
+ ) {
super(config);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((config as any).metadata) {
diag.warn('Metadata cannot be set when using http');
}
- this.headers = Object.assign(
- this.DEFAULT_HEADERS,
- parseHeaders(config.headers),
- baggageUtils.parseKeyPairsIntoRecord(getEnv().OTEL_EXPORTER_OTLP_HEADERS)
+ this._serializer = serializer;
+
+ // populate keepAlive for use with new settings
+ if (config?.keepAlive != null) {
+ if (config.httpAgentOptions != null) {
+ if (config.httpAgentOptions.keepAlive == null) {
+ // specific setting is not set, populate with non-specific setting.
+ config.httpAgentOptions.keepAlive = config.keepAlive;
+ }
+ // do nothing, use specific setting otherwise
+ } else {
+ // populate specific option if AgentOptions does not exist.
+ config.httpAgentOptions = {
+ keepAlive: config.keepAlive,
+ };
+ }
+ }
+ const nonSignalSpecificHeaders = baggageUtils.parseKeyPairsIntoRecord(
+ getEnv().OTEL_EXPORTER_OTLP_HEADERS
);
- this.agent = createHttpAgent(config);
- this.compression = configureCompression(config.compression);
+
+ this._transport = createRetryingTransport({
+ transport: createHttpExporterTransport({
+ agentOptions: config.httpAgentOptions ?? { keepAlive: true },
+ compression: configureCompression(config.compression),
+ headers: Object.assign(
+ {},
+ nonSignalSpecificHeaders,
+ signalSpecificHeaders
+ ),
+ url: this.url,
+ timeoutMillis: this.timeoutMillis,
+ }),
+ });
}
onInit(_config: OTLPExporterNodeConfigBase): void {}
@@ -61,23 +86,30 @@ export abstract class OTLPExporterNodeBase<
send(
objects: ExportItem[],
onSuccess: () => void,
- onError: (error: otlpTypes.OTLPExporterError) => void
+ onError: (error: OTLPExporterError) => void
): void {
if (this._shutdownOnce.isCalled) {
diag.debug('Shutdown already started. Cannot send objects');
return;
}
- const serviceRequest = this.convert(objects);
- const promise = new Promise((resolve, reject) => {
- sendWithHttp(
- this,
- JSON.stringify(serviceRequest),
- 'application/json',
- resolve,
- reject
- );
- }).then(onSuccess, onError);
+ const data = this._serializer.serializeRequest(objects);
+
+ if (data == null) {
+ onError(new Error('Could not serialize message'));
+ return;
+ }
+
+ const promise = this._transport.send(data).then(response => {
+ if (response.status === 'success') {
+ onSuccess();
+ return;
+ }
+ if (response.status === 'failure' && response.error) {
+ onError(response.error);
+ }
+ onError(new OTLPExporterError('Export failed with unknown error'));
+ }, onError);
this._sendingPromises.push(promise);
const popPromise = () => {
diff --git a/experimental/packages/otlp-exporter-base/src/platform/node/http-exporter-transport.ts b/experimental/packages/otlp-exporter-base/src/platform/node/http-exporter-transport.ts
new file mode 100644
index 00000000000..79647f1d9b3
--- /dev/null
+++ b/experimental/packages/otlp-exporter-base/src/platform/node/http-exporter-transport.ts
@@ -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 type {
+ HttpRequestParameters,
+ sendWithHttp,
+} from './http-transport-types';
+
+// NOTE: do not change these type imports to actual imports. Doing so WILL break `@opentelemetry/instrumentation-http`,
+// as they'd be imported before the http/https modules can be wrapped.
+import type * as https from 'https';
+import type * as http from 'http';
+import { ExportResponse } from '../../export-response';
+import { IExporterTransport } from '../../exporter-transport';
+
+class HttpExporterTransport implements IExporterTransport {
+ private _send: sendWithHttp | null = null;
+ private _agent: http.Agent | https.Agent | null = null;
+
+ constructor(private _parameters: HttpRequestParameters) {}
+
+ async send(data: Uint8Array): Promise {
+ if (this._send == null) {
+ // Lazy require to ensure that http/https is not required before instrumentations can wrap it.
+ const {
+ sendWithHttp,
+ createHttpAgent,
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
+ } = require('./http-transport-utils');
+ this._agent = createHttpAgent(
+ this._parameters.url,
+ this._parameters.agentOptions
+ );
+ this._send = sendWithHttp;
+ }
+
+ return new Promise(resolve => {
+ // this will always be defined
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this._send?.(this._parameters, this._agent!, data, result => {
+ resolve(result);
+ });
+ });
+ }
+ shutdown() {
+ // intentionally left empty, nothing to do.
+ }
+}
+
+export function createHttpExporterTransport(
+ parameters: HttpRequestParameters
+): IExporterTransport {
+ return new HttpExporterTransport(parameters);
+}
diff --git a/experimental/packages/otlp-exporter-base/src/platform/node/http-transport-types.ts b/experimental/packages/otlp-exporter-base/src/platform/node/http-transport-types.ts
new file mode 100644
index 00000000000..da33d02cd93
--- /dev/null
+++ b/experimental/packages/otlp-exporter-base/src/platform/node/http-transport-types.ts
@@ -0,0 +1,34 @@
+/*
+ * 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 type * as http from 'http';
+import type * as https from 'https';
+import { ExportResponse } from '../../export-response';
+
+export type sendWithHttp = (
+ params: HttpRequestParameters,
+ agent: http.Agent | https.Agent,
+ data: Uint8Array,
+ onDone: (response: ExportResponse) => void
+) => void;
+
+export interface HttpRequestParameters {
+ timeoutMillis: number;
+ url: string;
+ headers: Record;
+ compression: 'gzip' | 'none';
+ agentOptions: http.AgentOptions | https.AgentOptions;
+}
diff --git a/experimental/packages/otlp-exporter-base/src/platform/node/http-transport-utils.ts b/experimental/packages/otlp-exporter-base/src/platform/node/http-transport-utils.ts
new file mode 100644
index 00000000000..e1c13855a55
--- /dev/null
+++ b/experimental/packages/otlp-exporter-base/src/platform/node/http-transport-utils.ts
@@ -0,0 +1,153 @@
+/*
+ * 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 http from 'http';
+import * as https from 'https';
+import * as zlib from 'zlib';
+import { Readable } from 'stream';
+import { HttpRequestParameters } from './http-transport-types';
+import { ExportResponse } from '../../export-response';
+import {
+ isExportRetryable,
+ parseRetryAfterToMills,
+} from '../../is-export-retryable';
+import { OTLPExporterError } from '../../types';
+
+export const DEFAULT_EXPORT_INITIAL_BACKOFF = 1000;
+export const DEFAULT_EXPORT_MAX_BACKOFF = 5000;
+export const DEFAULT_EXPORT_BACKOFF_MULTIPLIER = 1.5;
+
+/**
+ * Sends data using http
+ * @param params
+ * @param agent
+ * @param data
+ * @param onDone
+ */
+export function sendWithHttp(
+ params: HttpRequestParameters,
+ agent: http.Agent | https.Agent,
+ data: Uint8Array,
+ onDone: (response: ExportResponse) => void
+): void {
+ const parsedUrl = new URL(params.url);
+ const nodeVersion = Number(process.versions.node.split('.')[0]);
+
+ const options: http.RequestOptions | https.RequestOptions = {
+ hostname: parsedUrl.hostname,
+ port: parsedUrl.port,
+ path: parsedUrl.pathname,
+ method: 'POST',
+ headers: {
+ ...params.headers,
+ },
+ agent: agent,
+ };
+
+ const request = parsedUrl.protocol === 'http:' ? http.request : https.request;
+
+ const req = request(options, (res: http.IncomingMessage) => {
+ const responseData: Buffer[] = [];
+ res.on('data', chunk => responseData.push(chunk));
+
+ res.on('end', () => {
+ if (req.destroyed) {
+ return;
+ }
+ if (res.statusCode && res.statusCode < 299) {
+ onDone({
+ status: 'success',
+ data: Buffer.concat(responseData),
+ });
+ } else if (res.statusCode && isExportRetryable(res.statusCode)) {
+ onDone({
+ status: 'retryable',
+ retryInMillis: parseRetryAfterToMills(res.headers['retry-after']),
+ });
+ } else {
+ const error = new OTLPExporterError(res.statusMessage, res.statusCode);
+ onDone({
+ status: 'failure',
+ error,
+ });
+ }
+ });
+ });
+
+ req.setTimeout(params.timeoutMillis, () => {
+ req.destroy();
+ onDone({
+ status: 'failure',
+ error: new Error('Request Timeout'),
+ });
+ });
+ req.on('error', (error: Error | any) => {
+ onDone({
+ status: 'failure',
+ error: error,
+ });
+ });
+
+ const reportTimeoutErrorEvent = nodeVersion >= 14 ? 'close' : 'abort';
+ req.on(reportTimeoutErrorEvent, () => {
+ onDone({
+ status: 'failure',
+ error: new Error('Request timed out'),
+ });
+ });
+
+ compressAndSend(req, params.compression, data, (error: Error) => {
+ onDone({
+ status: 'failure',
+ error,
+ });
+ });
+}
+
+function compressAndSend(
+ req: http.ClientRequest,
+ compression: 'gzip' | 'none',
+ data: Uint8Array,
+ onError: (error: Error) => void
+) {
+ let dataStream = readableFromUint8Array(data);
+
+ if (compression === 'gzip') {
+ req.setHeader('Content-Encoding', 'gzip');
+ dataStream = dataStream
+ .on('error', onError)
+ .pipe(zlib.createGzip())
+ .on('error', onError);
+ }
+
+ dataStream.pipe(req);
+}
+
+function readableFromUint8Array(buff: string | Uint8Array): Readable {
+ const readable = new Readable();
+ readable.push(buff);
+ readable.push(null);
+
+ return readable;
+}
+
+export function createHttpAgent(
+ rawUrl: string,
+ agentOptions: http.AgentOptions | https.AgentOptions
+) {
+ const parsedUrl = new URL(rawUrl);
+ const Agent = parsedUrl.protocol === 'http:' ? http.Agent : https.Agent;
+ return new Agent(agentOptions);
+}
diff --git a/experimental/packages/otlp-exporter-base/src/platform/node/index.ts b/experimental/packages/otlp-exporter-base/src/platform/node/index.ts
index b8b13bda202..fcfca512a86 100644
--- a/experimental/packages/otlp-exporter-base/src/platform/node/index.ts
+++ b/experimental/packages/otlp-exporter-base/src/platform/node/index.ts
@@ -15,5 +15,4 @@
*/
export { OTLPExporterNodeBase } from './OTLPExporterNodeBase';
-export { sendWithHttp, createHttpAgent, configureCompression } from './util';
export { OTLPExporterNodeConfigBase, CompressionAlgorithm } from './types';
diff --git a/experimental/packages/otlp-exporter-base/src/platform/node/util.ts b/experimental/packages/otlp-exporter-base/src/platform/node/util.ts
index 18e90f2a3e0..06a55af9ed0 100644
--- a/experimental/packages/otlp-exporter-base/src/platform/node/util.ts
+++ b/experimental/packages/otlp-exporter-base/src/platform/node/util.ts
@@ -16,177 +16,10 @@
import * as url from 'url';
import * as http from 'http';
import * as https from 'https';
-import * as zlib from 'zlib';
-import { Readable } from 'stream';
-import { OTLPExporterNodeBase } from './OTLPExporterNodeBase';
import { OTLPExporterNodeConfigBase } from '.';
import { diag } from '@opentelemetry/api';
import { CompressionAlgorithm } from './types';
import { getEnv } from '@opentelemetry/core';
-import { OTLPExporterError } from '../../types';
-import {
- DEFAULT_EXPORT_MAX_ATTEMPTS,
- DEFAULT_EXPORT_INITIAL_BACKOFF,
- DEFAULT_EXPORT_BACKOFF_MULTIPLIER,
- DEFAULT_EXPORT_MAX_BACKOFF,
- isExportRetryable,
- parseRetryAfterToMills,
-} from '../../util';
-
-/**
- * Sends data using http
- * @param collector
- * @param data
- * @param contentType
- * @param onSuccess
- * @param onError
- */
-export function sendWithHttp(
- collector: OTLPExporterNodeBase,
- data: string | Buffer,
- contentType: string,
- onSuccess: () => void,
- onError: (error: OTLPExporterError) => void
-): void {
- const exporterTimeout = collector.timeoutMillis;
- const parsedUrl = new url.URL(collector.url);
- let retryTimer: ReturnType;
- let req: http.ClientRequest;
- let reqIsDestroyed = false;
-
- const exporterTimer = setTimeout(() => {
- clearTimeout(retryTimer);
- reqIsDestroyed = true;
-
- if (req.destroyed) {
- const err = new OTLPExporterError('Request Timeout');
- onError(err);
- } else {
- req.destroy();
- }
- }, exporterTimeout);
-
- const options: http.RequestOptions | https.RequestOptions = {
- hostname: parsedUrl.hostname,
- port: parsedUrl.port,
- path: parsedUrl.pathname,
- method: 'POST',
- headers: {
- 'Content-Type': contentType,
- ...collector.headers,
- },
- agent: collector.agent,
- };
-
- const request = parsedUrl.protocol === 'http:' ? http.request : https.request;
-
- const sendWithRetry = (
- retries = DEFAULT_EXPORT_MAX_ATTEMPTS,
- minDelay = DEFAULT_EXPORT_INITIAL_BACKOFF
- ) => {
- req = request(options, (res: http.IncomingMessage) => {
- let responseData = '';
- res.on('data', chunk => (responseData += chunk));
-
- res.on('aborted', () => {
- if (reqIsDestroyed) {
- const err = new OTLPExporterError('Request Timeout');
- onError(err);
- }
- });
-
- res.on('end', () => {
- if (reqIsDestroyed === false) {
- if (res.statusCode && res.statusCode < 299) {
- diag.debug(`statusCode: ${res.statusCode}`, responseData);
- onSuccess();
- // clear all timers since request was completed and promise was resolved
- clearTimeout(exporterTimer);
- clearTimeout(retryTimer);
- } else if (
- res.statusCode &&
- isExportRetryable(res.statusCode) &&
- retries > 0
- ) {
- let retryTime: number;
- minDelay = DEFAULT_EXPORT_BACKOFF_MULTIPLIER * minDelay;
-
- // retry after interval specified in Retry-After header
- if (res.headers['retry-after']) {
- retryTime = parseRetryAfterToMills(res.headers['retry-after']!);
- } else {
- // exponential backoff with jitter
- retryTime = Math.round(
- Math.random() * (DEFAULT_EXPORT_MAX_BACKOFF - minDelay) +
- minDelay
- );
- }
-
- retryTimer = setTimeout(() => {
- sendWithRetry(retries - 1, minDelay);
- }, retryTime);
- } else {
- const error = new OTLPExporterError(
- res.statusMessage,
- res.statusCode,
- responseData
- );
- onError(error);
- // clear all timers since request was completed and promise was resolved
- clearTimeout(exporterTimer);
- clearTimeout(retryTimer);
- }
- }
- });
- });
-
- req.on('error', (error: Error | any) => {
- if (reqIsDestroyed) {
- const err = new OTLPExporterError('Request Timeout', error.code);
- onError(err);
- } else {
- onError(error);
- }
- clearTimeout(exporterTimer);
- clearTimeout(retryTimer);
- });
-
- req.on('abort', () => {
- if (reqIsDestroyed) {
- const err = new OTLPExporterError('Request Timeout');
- onError(err);
- }
- clearTimeout(exporterTimer);
- clearTimeout(retryTimer);
- });
-
- switch (collector.compression) {
- case CompressionAlgorithm.GZIP: {
- req.setHeader('Content-Encoding', 'gzip');
- const dataStream = readableFromBuffer(data);
- dataStream
- .on('error', onError)
- .pipe(zlib.createGzip())
- .on('error', onError)
- .pipe(req);
-
- break;
- }
- default:
- req.end(data);
- break;
- }
- };
- sendWithRetry();
-}
-
-function readableFromBuffer(buff: string | Buffer): Readable {
- const readable = new Readable();
- readable.push(buff);
- readable.push(null);
-
- return readable;
-}
export function createHttpAgent(
config: OTLPExporterNodeConfigBase
diff --git a/experimental/packages/otlp-exporter-base/src/retryable-transport.ts b/experimental/packages/otlp-exporter-base/src/retryable-transport.ts
new file mode 100644
index 00000000000..e48192c1fd2
--- /dev/null
+++ b/experimental/packages/otlp-exporter-base/src/retryable-transport.ts
@@ -0,0 +1,72 @@
+/*
+ * 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 { IExporterTransport } from './exporter-transport';
+import { ExportResponse } from './export-response';
+
+const MAX_ATTEMPTS = 5;
+const INITIAL_BACKOFF = 1000;
+const MAX_BACKOFF = 5000;
+const BACKOFF_MULTIPLIER = 1.5;
+const JITTER = 0.2;
+
+/**
+ * Get a pseudo-random jitter that falls in the range of [-JITTER, +JITTER]
+ */
+function getJitter() {
+ return Math.random() * (2 * JITTER) - JITTER;
+}
+
+class RetryingTransport implements IExporterTransport {
+ constructor(private _transport: IExporterTransport) {}
+
+ private retry(data: Uint8Array, inMillis: number): Promise {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ this._transport.send(data).then(resolve, reject);
+ }, inMillis);
+ });
+ }
+
+ async send(data: Uint8Array): Promise {
+ let result = await this._transport.send(data);
+ let attempts = MAX_ATTEMPTS;
+ let nextBackoff = INITIAL_BACKOFF;
+
+ while (result.status === 'retryable' && attempts > 0) {
+ attempts--;
+ const backoff = Math.min(nextBackoff, MAX_BACKOFF) + getJitter();
+ nextBackoff = nextBackoff * BACKOFF_MULTIPLIER;
+ result = await this.retry(data, result.retryInMillis ?? backoff);
+ }
+
+ return result;
+ }
+
+ shutdown() {
+ return this._transport.shutdown();
+ }
+}
+
+/**
+ * Creates an Exporter Transport that retries on 'retryable' response.
+ */
+export function createRetryingTransport(options: {
+ // Underlying transport to wrap.
+ transport: IExporterTransport;
+}): IExporterTransport {
+ return new RetryingTransport(options.transport);
+}
diff --git a/experimental/packages/otlp-exporter-base/src/util.ts b/experimental/packages/otlp-exporter-base/src/util.ts
index f5dc70c9e88..2824752e100 100644
--- a/experimental/packages/otlp-exporter-base/src/util.ts
+++ b/experimental/packages/otlp-exporter-base/src/util.ts
@@ -35,7 +35,9 @@ export function parseHeaders(
if (typeof value !== 'undefined') {
headers[key] = String(value);
} else {
- diag.warn(`Header "${key}" has wrong value and will be ignored`);
+ diag.warn(
+ `Header "${key}" has invalid value (${value}) and will be ignored`
+ );
}
});
return headers;
diff --git a/experimental/packages/otlp-exporter-base/test/browser/util.test.ts b/experimental/packages/otlp-exporter-base/test/browser/util.test.ts
index 1dd3b77d588..367c51a2f15 100644
--- a/experimental/packages/otlp-exporter-base/test/browser/util.test.ts
+++ b/experimental/packages/otlp-exporter-base/test/browser/util.test.ts
@@ -21,7 +21,7 @@ import { ensureHeadersContain } from '../testHelper';
describe('util - browser', () => {
let server: any;
- const body = '';
+ const body = new Uint8Array();
const url = '';
let onSuccessStub: sinon.SinonStub;
diff --git a/experimental/packages/otlp-exporter-base/test/common/CollectorExporter.test.ts b/experimental/packages/otlp-exporter-base/test/common/CollectorExporter.test.ts
index e3b36e704d4..c6be6965e66 100644
--- a/experimental/packages/otlp-exporter-base/test/common/CollectorExporter.test.ts
+++ b/experimental/packages/otlp-exporter-base/test/common/CollectorExporter.test.ts
@@ -22,15 +22,10 @@ import { OTLPExporterConfigBase } from '../../src/types';
import { ComplexTestObject, mockedComplexTestObject } from '../testHelper';
import * as otlpTypes from '../../src/types';
-interface ExportRequest {
- resourceSpans: object[];
-}
-
type CollectorExporterConfig = OTLPExporterConfigBase;
class OTLPTraceExporter extends OTLPExporterBase<
CollectorExporterConfig,
- ComplexTestObject,
- ExportRequest
+ ComplexTestObject
> {
onInit() {}
onShutdown() {}
@@ -49,10 +44,6 @@ class OTLPTraceExporter extends OTLPExporterBase<
getDefaultUrl(config: CollectorExporterConfig): string {
return config.url || '';
}
-
- convert(spans: ComplexTestObject[]): ExportRequest {
- return { resourceSpans: [] };
- }
}
describe('OTLPTraceExporter - common', () => {
diff --git a/experimental/packages/otlp-exporter-base/test/common/retrying-transport.test.ts b/experimental/packages/otlp-exporter-base/test/common/retrying-transport.test.ts
new file mode 100644
index 00000000000..cd7be6ebbbe
--- /dev/null
+++ b/experimental/packages/otlp-exporter-base/test/common/retrying-transport.test.ts
@@ -0,0 +1,180 @@
+/*
+ * 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 sinon from 'sinon';
+import * as assert from 'assert';
+import { IExporterTransport } from '../../src';
+import { createRetryingTransport } from '../../src/retryable-transport';
+import { ExportResponse } from '../../src';
+import { assertRejects } from '../testHelper';
+
+describe('RetryingTransport', function () {
+ describe('send', function () {
+ it('does not retry when underlying transport succeeds', async function () {
+ // arrange
+ const expectedResponse: ExportResponse = {
+ status: 'success',
+ };
+ const mockData = Uint8Array.from([1, 2, 3]);
+
+ const transportStubs = {
+ // make transport succeed
+ send: sinon.stub().returns(Promise.resolve(expectedResponse)),
+ shutdown: sinon.stub(),
+ };
+ const mockTransport = transportStubs;
+ const transport = createRetryingTransport({ transport: mockTransport });
+
+ // act
+ const actualResponse = await transport.send(mockData);
+
+ // assert
+ sinon.assert.calledOnceWithExactly(transportStubs.send, mockData);
+ assert.deepEqual(actualResponse, expectedResponse);
+ });
+
+ it('does not retry when underlying transport fails', async function () {
+ // arrange
+ const expectedResponse: ExportResponse = {
+ status: 'failure',
+ error: new Error(),
+ };
+ const mockData = Uint8Array.from([1, 2, 3]);
+
+ const transportStubs = {
+ // make transport fail
+ send: sinon.stub().returns(Promise.resolve(expectedResponse)),
+ shutdown: sinon.stub(),
+ };
+ const mockTransport = transportStubs;
+ const transport = createRetryingTransport({ transport: mockTransport });
+
+ // act
+ const actualResponse = await transport.send(mockData);
+
+ // assert
+ sinon.assert.calledOnceWithExactly(transportStubs.send, mockData);
+ assert.deepEqual(actualResponse, expectedResponse);
+ });
+
+ it('does not retry when underlying transport rejects', async function () {
+ // arrange
+ const expectedError = new Error('error');
+ const mockData = Uint8Array.from([1, 2, 3]);
+
+ const transportStubs = {
+ // make transport reject
+ send: sinon.stub().rejects(expectedError),
+ shutdown: sinon.stub(),
+ };
+ const mockTransport = transportStubs;
+ const transport = createRetryingTransport({ transport: mockTransport });
+
+ // act
+ await assertRejects(() => transport.send(mockData));
+
+ // assert
+ sinon.assert.calledOnceWithExactly(transportStubs.send, mockData);
+ });
+
+ it('does retry when the underlying transport returns retryable', async function () {
+ // arrange
+ const retryResponse: ExportResponse = {
+ status: 'retryable',
+ };
+ const successResponse: ExportResponse = {
+ status: 'success',
+ };
+ const mockData = Uint8Array.from([1, 2, 3]);
+
+ const transportStubs = {
+ send: sinon
+ .stub()
+ .onFirstCall()
+ .returns(Promise.resolve(retryResponse))
+ .onSecondCall()
+ .returns(Promise.resolve(successResponse)),
+ shutdown: sinon.stub(),
+ };
+ const mockTransport = transportStubs;
+ const transport = createRetryingTransport({ transport: mockTransport });
+
+ // act
+ const actualResponse = await transport.send(mockData);
+
+ // assert
+ sinon.assert.calledTwice(transportStubs.send);
+ sinon.assert.alwaysCalledWithExactly(transportStubs.send, mockData);
+ assert.deepEqual(actualResponse, successResponse);
+ });
+
+ it('does reject when the underlying transport rejects on retry', async function () {
+ // arrange
+ const expectedError = new Error('error');
+ const retryResponse: ExportResponse = {
+ status: 'retryable',
+ };
+
+ const mockData = Uint8Array.from([1, 2, 3]);
+
+ const transportStubs = {
+ send: sinon
+ .stub()
+ .onFirstCall()
+ .resolves(retryResponse)
+ .onSecondCall()
+ .rejects(expectedError),
+ shutdown: sinon.stub(),
+ };
+ const mockTransport = transportStubs;
+ const transport = createRetryingTransport({ transport: mockTransport });
+
+ // act
+ await assertRejects(() => transport.send(mockData));
+
+ // assert
+ sinon.assert.calledTwice(transportStubs.send);
+ sinon.assert.alwaysCalledWithExactly(transportStubs.send, mockData);
+ });
+
+ it('does retry 5 times, then resolves as retryable', async function () {
+ // arrange
+ // make random return a negative value so that what's passed to setTimeout() is negative and therefore gets executed immediately.
+ Math.random = sinon.stub().returns(-Infinity);
+
+ const retryResponse: ExportResponse = {
+ status: 'retryable',
+ };
+
+ const mockData = Uint8Array.from([1, 2, 3]);
+
+ const transportStubs = {
+ send: sinon.stub().resolves(retryResponse),
+ shutdown: sinon.stub(),
+ };
+ const mockTransport = transportStubs;
+ const transport = createRetryingTransport({ transport: mockTransport });
+
+ // act
+ const result = await transport.send(mockData);
+
+ // assert
+ sinon.assert.callCount(transportStubs.send, 6); // 1 initial try and 5 retries
+ sinon.assert.alwaysCalledWithExactly(transportStubs.send, mockData);
+ assert.strictEqual(result, retryResponse);
+ });
+ });
+});
diff --git a/experimental/packages/otlp-exporter-base/test/common/util.test.ts b/experimental/packages/otlp-exporter-base/test/common/util.test.ts
index b00d1f36a5c..4448ec06da0 100644
--- a/experimental/packages/otlp-exporter-base/test/common/util.test.ts
+++ b/experimental/packages/otlp-exporter-base/test/common/util.test.ts
@@ -46,7 +46,7 @@ describe('utils', () => {
const args = spyWarn.args[0];
assert.strictEqual(
args[0],
- 'Header "foo1" has wrong value and will be ignored'
+ 'Header "foo1" has invalid value (undefined) and will be ignored'
);
});
@@ -72,7 +72,7 @@ describe('utils', () => {
const finalUrl = appendResourcePathToUrl(url, resourcePath);
assert.strictEqual(finalUrl, url + '/' + resourcePath);
});
- it('should append resourse path even when url already contains path ', () => {
+ it('should append resource path even when url already contains path ', () => {
const url = 'http://foo.bar/v1/traces';
const resourcePath = 'v1/traces';
@@ -82,7 +82,7 @@ describe('utils', () => {
});
// only invoked with signal specific endpoint
- describe('appendRootPathToUrlIfNeeded - specifc signal http endpoint', () => {
+ describe('appendRootPathToUrlIfNeeded - specific signal http endpoint', () => {
it('should append root path when missing', () => {
const url = 'http://foo.bar';
@@ -110,7 +110,7 @@ describe('utils', () => {
}
});
- it('should not change string when url is not parseable', () => {
+ it('should not change string when url is not parsable', () => {
const url = 'this is not a URL';
const finalUrl = appendRootPathToUrlIfNeeded(url);
diff --git a/experimental/packages/otlp-exporter-base/test/node/util.test.ts b/experimental/packages/otlp-exporter-base/test/node/util.test.ts
index b279e57b9a1..19abbee9520 100644
--- a/experimental/packages/otlp-exporter-base/test/node/util.test.ts
+++ b/experimental/packages/otlp-exporter-base/test/node/util.test.ts
@@ -16,7 +16,6 @@
import * as assert from 'assert';
import { configureExporterTimeout, invalidTimeout } from '../../src/util';
-import { sendWithHttp } from '../../src/platform/node/util';
import { CompressionAlgorithm } from '../../src/platform/node/types';
import { configureCompression } from '../../src/platform/node/util';
import { diag } from '@opentelemetry/api';
@@ -24,29 +23,7 @@ import * as sinon from 'sinon';
import { OTLPExporterNodeBase } from '../../src/platform/node/OTLPExporterNodeBase';
import { OTLPExporterNodeConfigBase } from '../../src/platform/node/types';
-import { OTLPExporterError } from '../../src/types';
-import { PassThrough } from 'stream';
-import * as http from 'http';
-import * as zlib from 'zlib';
-
-// Meant to simulate http.IncomingMessage, at least the parts that sendWithHttp cares about
-// but make it a PassThrough so we can inspect it for the test
-class HttpResponse extends PassThrough {
- statusCode: number;
- statusMessage: string;
-
- constructor(statusCode = 200, statusMessage = 'OK') {
- super();
- this.statusCode = statusCode;
- this.statusMessage = statusMessage;
- }
-}
-
-// Meant to simulate http.ClientRequest, at least the parts that sendWithHttp cares about
-// but make it a PassThrough so we can inspect it for the test
-class HttpRequest extends PassThrough {
- setHeader(name: string, value: string) {}
-}
+import { ISerializer } from '@opentelemetry/otlp-transformer';
// Barebones exporter for use by sendWithHttp
type ExporterConfig = OTLPExporterNodeConfigBase;
@@ -54,15 +31,20 @@ class Exporter extends OTLPExporterNodeBase