diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 571b4af38eb..21c99fbf5e9 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -54,6 +54,46 @@ jobs: - name: Report Coverage run: npm run codecov if: ${{ matrix.node_version == '14' }} + node-windows-tests: + strategy: + fail-fast: false + runs-on: windows-latest + env: + NPM_CONFIG_UNSAFE_PERM: true + steps: + - name: Checkout + uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + node-version: '16' + + - run: npm install -g npm@latest + + - name: restore lerna + id: cache + uses: actions/cache@v3 + with: + path: | + node_modules + package-lock.json + packages/*/node_modules + packages/*/package-lock.json + experimental/packages/*/node_modules + experimental/packages/*/package-lock.json + key: node-windows-tests-${{ runner.os }}-${{ hashFiles('package.json', 'packages/*/package.json', 'experimental/packages/*/package.json') }} + + - name: Bootstrap + run: | + npm install --ignore-scripts + npx lerna bootstrap --no-ci --hoist --nohoist='zone.js' --ignore @opentelemetry/selenium-tests + + - name: Build 🔧 + run: | + npm run compile + + - name: Unit tests + run: npm run test browser-tests: runs-on: ubuntu-latest container: diff --git a/CHANGELOG.md b/CHANGELOG.md index 741b1d5da3c..48de348db05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,20 @@ All notable changes to this project will be documented in this file. ### :rocket: (Enhancement) +### :bug: (Bug Fix) + +### :books: (Refine Doc) + +### :house: (Internal) + +## 1.6.0 + +### :rocket: (Enhancement) + +* perf(opentelemetry-core): improve hexToBase64 performance [#3178](https://github.com/open-telemetry/opentelemetry-js/pull/3178) * feat(sdk-trace-base): move Sampler declaration into sdk-trace-base [#3088](https://github.com/open-telemetry/opentelemetry-js/pull/3088) @legendecas * fix(grpc-instrumentation): added grpc attributes in instrumentation [#3127](https://github.com/open-telemetry/opentelemetry-js/pull/3127) @andrewzenkov +* feat: support latest `@opentelemetry/api` [#3177](https://github.com/open-telemetry/opentelemetry-js/pull/3177) @dyladan ### :bug: (Bug Fix) diff --git a/README.md b/README.md index ee56336d0c7..f52b0a4ad2c 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,10 @@ This is the JavaScript version of [OpenTelemetry](https://opentelemetry.io/), a | API Version | Core version | Experimental Packages | | ----------- | ------------ | --------------------- | -| 1.1.x | 1.3.x | 0.30.x | -| 1.1.x | 1.2.x | 0.29.x | +| 1.2.x | 1.6.x | 0.32.x | +| 1.1.x | 1.5.x | 0.31.x | +| 1.1.x | 1.4.x | 0.30.x | +| 1.1.x | 1.2.x, 1.3.x | 0.29.x | | 1.1.x | 1.1.x | 0.28.x | | 1.0.x | 1.0.x | 0.26.x, 0.27.x | | 1.0.x | 0.26.x | ----- | @@ -186,7 +188,7 @@ Approvers ([@open-telemetry/js-approvers](https://github.com/orgs/open-telemetry - [Naseem K. Ullah](https://github.com/naseemkullah), Transit - [Neville Wylie](https://github.com/MSNev), Microsoft - [Olivier Albertini](https://github.com/OlivierAlbertini), Ville de Montréal -- [Rauno Viskus](https://github.com/Rauno56), Splunk +- [Svetlana Brennan](https://github.com/svetlanabrennan), New Relic *Find more about the approver role in [community repository](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver).* @@ -225,12 +227,12 @@ Maintainers ([@open-telemetry/js-maintainers](https://github.com/orgs/open-telem ### Implementation / SDKs -| Package | Description | -| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [@opentelemetry/sdk-trace-base][otel-tracing] | This module provides a full control over instrumentation and span creation. It doesn't load [`async_hooks`](https://nodejs.org/api/async_hooks.html) or any instrumentation by default. It is intended for use both on the server and in the browser. | -| [@opentelemetry/sdk-metrics-base][otel-metrics] | This module provides instruments and meters for reporting of time series data. | -| [@opentelemetry/sdk-trace-node][otel-node] | This module provides automatic tracing for Node.js applications. It is intended for use on the server only. | -| [@opentelemetry/sdk-trace-web][otel-web] | This module provides automated instrumentation and tracing for Web applications. It is intended for use in the browser only. | +| Package | Description | +| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [@opentelemetry/sdk-trace-base][otel-tracing] | This module provides a full control over instrumentation and span creation. It doesn't load [`async_hooks`](https://nodejs.org/api/async_hooks.html) or any instrumentation by default. It is intended for use both on the server and in the browser. | +| [@opentelemetry/sdk-metrics][otel-metrics] | This module provides instruments and meters for reporting of time series data. | +| [@opentelemetry/sdk-trace-node][otel-node] | This module provides automatic tracing for Node.js applications. It is intended for use on the server only. | +| [@opentelemetry/sdk-trace-web][otel-web] | This module provides automated instrumentation and tracing for Web applications. It is intended for use in the browser only. | ### Compatible Exporters @@ -540,7 +542,7 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [compliance-matrix]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md [CONTRIBUTING]: https://github.com/open-telemetry/opentelemetry-js/blob/main/CONTRIBUTING.md -[otel-metrics]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-metrics-base +[otel-metrics]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-metrics [otel-node]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node [otel-instrumentation-fetch]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-fetch diff --git a/doc/processor-api.md b/doc/processor-api.md index 60b4c167522..58d7916e57b 100644 --- a/doc/processor-api.md +++ b/doc/processor-api.md @@ -11,7 +11,7 @@ Sometimes you may want to use a specific aggregator for one of your metric, expo Here is what an aggregator that does that would look like: ```ts -import { Aggregator } from '@opentelemetry/sdk-metrics-base'; +import { Aggregator } from '@opentelemetry/sdk-metrics'; import { hrTime } from '@opentelemetry/core'; export class AverageAggregator implements Aggregator { @@ -54,7 +54,7 @@ import { CounterSumAggregator, ObserverAggregator, MeasureExactAggregator, -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; export class CustomProcessor extends UngroupedProcessor { aggregatorFor (metricDescriptor: MetricDescriptor) { @@ -86,7 +86,7 @@ import { MeasureExactAggregator, MeterProvider, Aggregator, -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import { hrTime } from '@opentelemetry/core'; export class AverageAggregator implements Aggregator { diff --git a/eslint.config.js b/eslint.config.js index 3c657006994..5e8f1b50e64 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -13,7 +13,7 @@ module.exports = { "indent": ["error", 2, { "SwitchCase": 1 }], "no-trailing-spaces": "error", "eol-last": "error", - "quotes": [2, "single", { "avoidEscape": true }], + "quotes": ["error", "single", { "avoidEscape": true }], "brace-style": ["error", "1tbs"], "eqeqeq": [ "error", @@ -24,7 +24,7 @@ module.exports = { "no-shadow": "off", "arrow-parens": ["error", "as-needed"], "node/no-deprecated-api": ["warn"], - "header/header": [2, "block", [{ + "header/header": ["error", "block", [{ pattern: / \* Copyright The OpenTelemetry Authors[\r\n]+ \*[\r\n]+ \* Licensed under the Apache License, Version 2\.0 \(the \"License\"\);[\r\n]+ \* you may not use this file except in compliance with the License\.[\r\n]+ \* You may obtain a copy of the License at[\r\n]+ \*[\r\n]+ \* https:\/\/www\.apache\.org\/licenses\/LICENSE-2\.0[\r\n]+ \*[\r\n]+ \* Unless required by applicable law or agreed to in writing, software[\r\n]+ \* distributed under the License is distributed on an \"AS IS\" BASIS,[\r\n]+ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.[\r\n]+ \* See the License for the specific language governing permissions and[\r\n]+ \* limitations under the License\./gm, template: `\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ` @@ -34,7 +34,7 @@ module.exports = { { files: ['*.ts'], rules: { - "@typescript-eslint/no-floating-promises": 2, + "@typescript-eslint/no-floating-promises": "error", "@typescript-eslint/no-this-alias": "off", "@typescript-eslint/naming-convention": [ "error", @@ -45,7 +45,6 @@ module.exports = { "leadingUnderscore": "require" } ], - "@typescript-eslint/no-shadow": ["warn"], "@typescript-eslint/no-unused-vars": ["error", {"argsIgnorePattern": "^_", "args": "after-used"}], "@typescript-eslint/no-inferrable-types": ["error", { ignoreProperties: true }], "@typescript-eslint/no-empty-function": ["off"], @@ -65,7 +64,6 @@ module.exports = { "@typescript-eslint/ban-ts-ignore": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-floating-promises": 1, "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/no-shadow": ["off"], diff --git a/examples/https/package.json b/examples/https/package.json index bd57e3f14cd..c6eee81462c 100644 --- a/examples/https/package.json +++ b/examples/https/package.json @@ -1,7 +1,7 @@ { "name": "https-example", "private": true, - "version": "0.31.0", + "version": "0.32.0", "description": "Example of HTTPs integration with OpenTelemetry", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -33,14 +33,14 @@ }, "dependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/exporter-jaeger": "1.5.0", - "@opentelemetry/exporter-zipkin": "1.5.0", - "@opentelemetry/instrumentation": "0.31.0", - "@opentelemetry/instrumentation-http": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/sdk-trace-node": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/exporter-jaeger": "1.6.0", + "@opentelemetry/exporter-zipkin": "1.6.0", + "@opentelemetry/instrumentation": "0.32.0", + "@opentelemetry/instrumentation-http": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/sdk-trace-node": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/https", "devDependencies": { diff --git a/examples/opentelemetry-web/examples/metrics/index.js b/examples/opentelemetry-web/examples/metrics/index.js index a63adfb4b4f..e036f1e8d24 100644 --- a/examples/opentelemetry-web/examples/metrics/index.js +++ b/examples/opentelemetry-web/examples/metrics/index.js @@ -1,7 +1,7 @@ const { DiagConsoleLogger, DiagLogLevel, diag } = require('@opentelemetry/api'); const { metrics } = require('@opentelemetry/api-metrics'); const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http'); -const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics-base'); +const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); // Optional and only needed to see the internal diagnostic logging (during development) diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); diff --git a/examples/opentelemetry-web/package.json b/examples/opentelemetry-web/package.json index 7b5ebf5d3ce..f1159103b57 100644 --- a/examples/opentelemetry-web/package.json +++ b/examples/opentelemetry-web/package.json @@ -1,8 +1,8 @@ { "name": "web-opentelemetry-example", "private": true, - "version": "0.31.0", - "description": "Example of using @opentelemetry/sdk-trace-web and @opentelemetry/sdk-metrics-base in browser", + "version": "0.32.0", + "description": "Example of using @opentelemetry/sdk-trace-web and @opentelemetry/sdk-metrics in browser", "main": "index.js", "scripts": { "start": "webpack serve --progress --color --port 8090 --config webpack.dev.config.js --hot --host 0.0.0.0 --compress", @@ -43,20 +43,20 @@ }, "dependencies": { "@opentelemetry/api": "^1.0.2", - "@opentelemetry/api-metrics": "0.31.0", - "@opentelemetry/context-zone": "^1.0.1", - "@opentelemetry/core": "^1.0.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.31.0", - "@opentelemetry/exporter-trace-otlp-http": "0.31.0", - "@opentelemetry/exporter-zipkin": "^1.0.1", - "@opentelemetry/instrumentation": "0.31.0", - "@opentelemetry/instrumentation-fetch": "0.31.0", - "@opentelemetry/instrumentation-xml-http-request": "0.31.0", - "@opentelemetry/propagator-b3": "^1.0.1", - "@opentelemetry/sdk-metrics-base": "0.31.0", - "@opentelemetry/sdk-trace-base": "^1.0.1", - "@opentelemetry/sdk-trace-web": "^1.0.1", - "@opentelemetry/semantic-conventions": "^1.0.1" + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/context-zone": "1.6.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.32.0", + "@opentelemetry/exporter-trace-otlp-http": "0.32.0", + "@opentelemetry/exporter-zipkin": "1.6.0", + "@opentelemetry/instrumentation": "0.32.0", + "@opentelemetry/instrumentation-fetch": "0.32.0", + "@opentelemetry/instrumentation-xml-http-request": "0.32.0", + "@opentelemetry/propagator-b3": "1.6.0", + "@opentelemetry/sdk-metrics": "0.32.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/sdk-trace-web": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/tracer-web" } diff --git a/examples/otlp-exporter-node/metrics.js b/examples/otlp-exporter-node/metrics.js index 049d8229ec6..f6c3efa55b5 100644 --- a/examples/otlp-exporter-node/metrics.js +++ b/examples/otlp-exporter-node/metrics.js @@ -4,7 +4,7 @@ const { DiagConsoleLogger, DiagLogLevel, diag } = require('@opentelemetry/api'); const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http'); // const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-grpc'); // const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto'); -const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics-base'); +const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); const { Resource } = require('@opentelemetry/resources'); const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions'); diff --git a/examples/otlp-exporter-node/package.json b/examples/otlp-exporter-node/package.json index 3ba7f67f8a7..21b27440d41 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.31.0", + "version": "0.32.0", "description": "Example of using @opentelemetry/collector-exporter in Node.js", "main": "index.js", "scripts": { @@ -29,18 +29,18 @@ }, "dependencies": { "@opentelemetry/api": "^1.1.0", - "@opentelemetry/api-metrics": "0.31.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/exporter-metrics-otlp-grpc": "0.31.0", - "@opentelemetry/exporter-metrics-otlp-http": "0.31.0", - "@opentelemetry/exporter-metrics-otlp-proto": "0.31.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.31.0", - "@opentelemetry/exporter-trace-otlp-http": "0.31.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-metrics-base": "0.31.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.32.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.32.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.32.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.32.0", + "@opentelemetry/exporter-trace-otlp-http": "0.32.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-metrics": "0.32.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/otlp-exporter-node" } diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index ca329878e31..377e37c9fad 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -6,19 +6,69 @@ All notable changes to experimental packages in this project will be documented ### :boom: Breaking Change +* Add `resourceDetectors` option to `NodeSDK` [#3210](https://github.com/open-telemetry/opentelemetry-js/issues/3210) + * `NodeSDK.detectResources()` function is no longer able to receive config as a parameter. + Instead, the detectors are passed to the constructor. + +* chore(metrics-sdk): clean up exports [#3197](https://github.com/open-telemetry/opentelemetry-js/pull/3197) @pichlermarc + * removes export for: + * `AccumulationRecord` + * `Aggregator` + * `AggregatorKind` + * `Accumulation` + * `createInstrumentDescriptor` + * `createInstrumentDescriptorWithView` + * `isDescriptorCompatibleWith` +* chore(api-metrics): clean up exports [#3198](https://github.com/open-telemetry/opentelemetry-js/pull/3198) @pichlermarc + * removes export for: + * `NOOP_COUNTER_METRIC` + * `NOOP_HISTOGRAM_METRIC` + * `NOOP_METER_PROVIDER` + * `NOOP_OBSERVABLE_COUNTER_METRIC` + * `NOOP_OBSERVABLE_GAUGE_METRIC` + * `NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC` + * `NOOP_UP_DOWN_COUNTER_METRIC` + * `NoopCounterMetric` + * `NoopHistogramMetric` + * `NoopMeter` + * `NoopMeterProvider` + * `NoopMetric` + * `NoopObservableCounterMetric` + * `NoopObservableGaugeMetric` + * `NoopObservableMetric` + * `NoopObservableUpDownCounterMetric` + * `NoopUpDownCounterMetric` + ### :rocket: (Enhancement) -* feature(add-console-metrics-exporter): add ConsoleMetricExporter [#3120](https://github.com/open-telemetry/opentelemetry-js/pull/3120) @weyert -* feature(prometheus-serialiser): export the unit block when unit is set in metric descriptor [#3066](https://github.com/open-telemetry/opentelemetry-js/pull/3041) @weyert +* Add `resourceDetectors` option to `NodeSDK` [#3210](https://github.com/open-telemetry/opentelemetry-js/issues/3210) ### :bug: (Bug Fix) -* fix(instrumentation-http): add `http.host` attribute before sending the request #3054 @cuichenli - ### :books: (Refine Doc) ### :house: (Internal) +## 0.32.0 + +### :boom: Breaking Change + +* Rename @opentelemetry/sdk-metrics-base package to @opentelemetry/sdk-metrics [#3162](https://github.com/open-telemetry/opentelemetry-js/pull/3162) @hectorhdzg + +### :rocket: (Enhancement) + +* feature(instrumentation-http): Add HTTP Server and Client duration Metrics in HTTP Node.js Instrumentation [#3149](https://github.com/open-telemetry/opentelemetry-js/pull/3149) @hectorhdzg +* fix(add-views-to-node-sdk): added the ability to define meter views in `NodeSDK` [#3066](https://github.com/open-telemetry/opentelemetry-js/pull/3124) @weyert +* feature(add-console-metrics-exporter): add ConsoleMetricExporter [#3120](https://github.com/open-telemetry/opentelemetry-js/pull/3120) @weyert +* feature(prometheus-serialiser): export the unit block when unit is set in metric descriptor [#3066](https://github.com/open-telemetry/opentelemetry-js/pull/3041) @weyert +* feat: support latest `@opentelemetry/api` [#3177](https://github.com/open-telemetry/opentelemetry-js/pull/3177) @dyladan +* feat(sdk-metrics-base): add per metric-reader aggregation support [#3153](https://github.com/open-telemetry/opentelemetry-js/pull/3153) @legendecas +* chore(deps): update prometheus example dependencies to 0.32 [#3126](https://github.com/open-telemetry/opentelemetry-js/pull/3216) @avzis + +### :bug: (Bug Fix) + +* fix(instrumentation-http): add `http.host` attribute before sending the request #3054 @cuichenli + ## 0.31.0 ### :boom: Breaking Change diff --git a/experimental/backwards-compatability/node14/package.json b/experimental/backwards-compatability/node14/package.json index 4a93b5f39ca..a9db91d167a 100644 --- a/experimental/backwards-compatability/node14/package.json +++ b/experimental/backwards-compatability/node14/package.json @@ -1,6 +1,6 @@ { "name": "backcompat-node14", - "version": "0.31.0", + "version": "0.32.0", "private": true, "description": "Backwards compatability app for node 14 types and the OpenTelemetry Node.js SDK", "main": "index.js", @@ -9,11 +9,11 @@ "peer-api-check": "node ../../../scripts/peer-api-check.js" }, "dependencies": { - "@opentelemetry/sdk-node": "0.31.0", - "@opentelemetry/sdk-trace-base": "1.5.0" + "@opentelemetry/sdk-node": "0.32.0", + "@opentelemetry/sdk-trace-base": "1.6.0" }, "devDependencies": { - "@types/node": "^14.0.0", + "@types/node": "14.18.25", "typescript": "4.4.4" }, "author": "OpenTelemetry Authors", diff --git a/experimental/backwards-compatability/node16/package.json b/experimental/backwards-compatability/node16/package.json index 9f9543d6690..f1ea4b4f77c 100644 --- a/experimental/backwards-compatability/node16/package.json +++ b/experimental/backwards-compatability/node16/package.json @@ -1,6 +1,6 @@ { "name": "backcompat-node16", - "version": "0.31.0", + "version": "0.32.0", "private": true, "description": "Backwards compatability app for node 16 types and the OpenTelemetry Node.js SDK", "main": "index.js", @@ -9,11 +9,11 @@ "peer-api-check": "node ../../../scripts/peer-api-check.js" }, "dependencies": { - "@opentelemetry/sdk-node": "0.31.0", - "@opentelemetry/sdk-trace-base": "1.5.0" + "@opentelemetry/sdk-node": "0.32.0", + "@opentelemetry/sdk-trace-base": "1.6.0" }, "devDependencies": { - "@types/node": "^16.0.0", + "@types/node": "16.11.52", "typescript": "4.4.4" }, "author": "OpenTelemetry Authors", diff --git a/experimental/examples/prometheus/README.md b/experimental/examples/prometheus/README.md index 7ebed957dbf..549db19535a 100644 --- a/experimental/examples/prometheus/README.md +++ b/experimental/examples/prometheus/README.md @@ -54,7 +54,7 @@ If you are using the default configurations, the prometheus client will be avail ## Useful links - For more information on OpenTelemetry, visit: -- For more information on OpenTelemetry metrics, visit: +- For more information on OpenTelemetry metrics, visit: - For more information on OpenTelemetry for Node.js, visit: ## LICENSE diff --git a/experimental/examples/prometheus/index.js b/experimental/examples/prometheus/index.js index 3394e404817..cd267db0198 100644 --- a/experimental/examples/prometheus/index.js +++ b/experimental/examples/prometheus/index.js @@ -1,7 +1,7 @@ 'use strict'; const { DiagConsoleLogger, DiagLogLevel, diag } = require('@opentelemetry/api'); -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); +const { MeterProvider } = require('@opentelemetry/sdk-metrics'); const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); // Optional and only needed to see the internal diagnostic logging (during development) diff --git a/experimental/examples/prometheus/package.json b/experimental/examples/prometheus/package.json index a3c5dbca516..9816279e53c 100644 --- a/experimental/examples/prometheus/package.json +++ b/experimental/examples/prometheus/package.json @@ -1,7 +1,7 @@ { "name": "prometheus-example", - "version": "0.28.0", - "description": "Example of using @opentelemetry/sdk-metrics-base and @opentelemetry/exporter-prometheus", + "version": "0.32.0", + "description": "Example of using @opentelemetry/sdk-metrics and @opentelemetry/exporter-prometheus", "main": "index.js", "scripts": { "start": "node index.js" @@ -10,7 +10,7 @@ "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.0.2", - "@opentelemetry/exporter-prometheus": "0.28.0", - "@opentelemetry/sdk-metrics-base": "0.28.0" + "@opentelemetry/exporter-prometheus": "0.32.0", + "@opentelemetry/sdk-metrics": "0.32.0" } } diff --git a/experimental/packages/exporter-trace-otlp-grpc/README.md b/experimental/packages/exporter-trace-otlp-grpc/README.md index 3893a9f4495..b03274b320c 100644 --- a/experimental/packages/exporter-trace-otlp-grpc/README.md +++ b/experimental/packages/exporter-trace-otlp-grpc/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides exporter for node to be used with OTLP (`grpc`) compatible receivers. Compatible with [opentelemetry-collector][opentelemetry-collector-url] versions `>=0.16 <=0.50`. diff --git a/experimental/packages/exporter-trace-otlp-grpc/package.json b/experimental/packages/exporter-trace-otlp-grpc/package.json index 0f6cb596193..7402f23557e 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry Collector Exporter allows user to send collected traces to the OpenTelemetry Collector", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -49,7 +49,7 @@ "devDependencies": { "@babel/core": "7.16.0", "@opentelemetry/api": "^1.0.0", - "@opentelemetry/otlp-exporter-base": "0.31.0", + "@opentelemetry/otlp-exporter-base": "0.32.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -69,11 +69,11 @@ "dependencies": { "@grpc/grpc-js": "^1.5.9", "@grpc/proto-loader": "^0.6.9", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.31.0", - "@opentelemetry/otlp-transformer": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.32.0", + "@opentelemetry/otlp-transformer": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-grpc" } diff --git a/experimental/packages/exporter-trace-otlp-http/README.md b/experimental/packages/exporter-trace-otlp-http/README.md index 448c8caf201..5afdf0d9e06 100644 --- a/experimental/packages/exporter-trace-otlp-http/README.md +++ b/experimental/packages/exporter-trace-otlp-http/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides exporter for web and node to be used with OTLP (`http/json`) compatible receivers. Compatible with [opentelemetry-collector][opentelemetry-collector-url] versions `>=0.48 <=0.50`. diff --git a/experimental/packages/exporter-trace-otlp-http/package.json b/experimental/packages/exporter-trace-otlp-http/package.json index 4a2a7f5a6ce..990f56cd428 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry Collector Trace Exporter allows user to send collected traces to the OpenTelemetry Collector", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -94,11 +94,11 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/otlp-exporter-base": "0.31.0", - "@opentelemetry/otlp-transformer": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/otlp-exporter-base": "0.32.0", + "@opentelemetry/otlp-transformer": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-http" } diff --git a/experimental/packages/exporter-trace-otlp-proto/README.md b/experimental/packages/exporter-trace-otlp-proto/README.md index 56551f92887..0338b4cd936 100644 --- a/experimental/packages/exporter-trace-otlp-proto/README.md +++ b/experimental/packages/exporter-trace-otlp-proto/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides exporter for node to be used with OTLP (`http/protobuf`) compatible receivers. Compatible with [opentelemetry-collector][opentelemetry-collector-url] versions `>=0.32 <=0.50`. diff --git a/experimental/packages/exporter-trace-otlp-proto/package.json b/experimental/packages/exporter-trace-otlp-proto/package.json index 0e791c0f373..41aff440c79 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry Collector Exporter allows user to send collected traces to the OpenTelemetry Collector using protobuf over HTTP", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -67,12 +67,12 @@ }, "dependencies": { "@grpc/proto-loader": "^0.6.9", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/otlp-exporter-base": "0.31.0", - "@opentelemetry/otlp-proto-exporter-base": "0.31.0", - "@opentelemetry/otlp-transformer": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/otlp-exporter-base": "0.32.0", + "@opentelemetry/otlp-proto-exporter-base": "0.32.0", + "@opentelemetry/otlp-transformer": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", "protobufjs": "^6.9.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-proto" diff --git a/experimental/packages/opentelemetry-api-metrics/README.md b/experimental/packages/opentelemetry-api-metrics/README.md index f922ed2e457..d9e8745ec7e 100644 --- a/experimental/packages/opentelemetry-api-metrics/README.md +++ b/experimental/packages/opentelemetry-api-metrics/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This package provides everything needed to interact with the unstable OpenTelemetry Metrics API, including all TypeScript interfaces, enums, and no-op implementations. It is intended for use both on the server and in the browser. ## Beta Software - Use at your own risk @@ -19,7 +21,7 @@ To get started you need to install the SDK and instrumentations, create a MeterP $ # Install metrics dependencies $ npm install \ @opentelemetry/api-metrics \ - @opentelemetry/sdk-metrics-base \ + @opentelemetry/sdk-metrics \ @opentelemetry/exporter-prometheus # add exporters as needed ``` @@ -35,15 +37,15 @@ To collect traces and metrics, you will have to tell the SDK where to export tel ```javascript const api = require("@opentelemetry/api-metrics"); -const { MeterProvider } = require("@opentelemetry/sdk-metrics-base"); +const { MeterProvider } = require("@opentelemetry/sdk-metrics"); const { PrometheusExporter } = require("@opentelemetry/exporter-prometheus"); -const meterProvider = new MeterProvider({ - // The Prometheus exporter runs an HTTP server which - // the Prometheus backend scrapes to collect metrics. - exporter: new PrometheusExporter({ startServer: true }), - interval: 1000, -}); +// The Prometheus exporter runs an HTTP server which the Prometheus backend +// scrapes to collect metrics. +const exporter = new PrometheusExporter({ startServer: true }); +// Creates MeterProvider and installs the exporter as a MetricReader +const meterProvider = new MeterProvider(); +meterProvider.addMetricReader(exporter); /** * Registering the provider with the API allows it to be discovered diff --git a/experimental/packages/opentelemetry-api-metrics/package.json b/experimental/packages/opentelemetry-api-metrics/package.json index fdc8f762201..a901850ee7c 100644 --- a/experimental/packages/opentelemetry-api-metrics/package.json +++ b/experimental/packages/opentelemetry-api-metrics/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/api-metrics", - "version": "0.31.0", + "version": "0.32.0", "description": "Public metrics API for OpenTelemetry", "main": "build/src/index.js", "module": "build/esm/index.js", diff --git a/experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts b/experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts index 317431096fc..69c25134493 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts @@ -114,11 +114,14 @@ export class NoopHistogramMetric extends NoopMetric implements Histogram { export class NoopObservableMetric { addCallback(_callback: ObservableCallback) {} + removeCallback(_callback: ObservableCallback) {} } export class NoopObservableCounterMetric extends NoopObservableMetric implements ObservableCounter {} + export class NoopObservableGaugeMetric extends NoopObservableMetric implements ObservableGauge {} + export class NoopObservableUpDownCounterMetric extends NoopObservableMetric implements ObservableUpDownCounter {} export const NOOP_METER = new NoopMeter(); @@ -132,3 +135,10 @@ export const NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric(); export const NOOP_OBSERVABLE_COUNTER_METRIC = new NoopObservableCounterMetric(); export const NOOP_OBSERVABLE_GAUGE_METRIC = new NoopObservableGaugeMetric(); export const NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC = new NoopObservableUpDownCounterMetric(); + +/** + * Create a no-op Meter + */ +export function createNoopMeter(): Meter { + return NOOP_METER; +} diff --git a/experimental/packages/opentelemetry-api-metrics/src/index.ts b/experimental/packages/opentelemetry-api-metrics/src/index.ts index e306e6c1ab9..5a59fe2d968 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/index.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/index.ts @@ -14,13 +14,41 @@ * limitations under the License. */ -export * from './NoopMeter'; -export * from './NoopMeterProvider'; -export * from './types/Meter'; -export * from './types/MeterProvider'; -export * from './types/Metric'; -export * from './types/ObservableResult'; +export { + createNoopMeter, +} from './NoopMeter'; + +export { + MeterOptions, + Meter, +} from './types/Meter'; + +export { + MeterProvider, +} from './types/MeterProvider'; + +export { + ValueType, + Counter, + Histogram, + MetricOptions, + Observable, + ObservableCounter, + ObservableGauge, + ObservableUpDownCounter, + UpDownCounter, + BatchObservableCallback, + MetricAttributes, + MetricAttributeValue, + ObservableCallback, +} from './types/Metric'; + +export { + BatchObservableResult, + ObservableResult, +} from './types/ObservableResult'; import { MetricsAPI } from './api/metrics'; + /** Entrypoint for metrics API */ export const metrics = MetricsAPI.getInstance(); diff --git a/experimental/packages/opentelemetry-api-metrics/test/api/api.test.ts b/experimental/packages/opentelemetry-api-metrics/test/api/api.test.ts index e9a837230ec..66278d6bc78 100644 --- a/experimental/packages/opentelemetry-api-metrics/test/api/api.test.ts +++ b/experimental/packages/opentelemetry-api-metrics/test/api/api.test.ts @@ -15,7 +15,10 @@ */ import * as assert from 'assert'; -import { metrics, NoopMeter, NoopMeterProvider } from '../../src'; +import { metrics } from '../../src'; +import { NoopMeter } from '../../src/NoopMeter'; +import { NoopMeterProvider } from '../../src/NoopMeterProvider'; + describe('API', () => { it('should expose a meter provider via getMeterProvider', () => { diff --git a/experimental/packages/opentelemetry-api-metrics/test/api/global.test.ts b/experimental/packages/opentelemetry-api-metrics/test/api/global.test.ts index 485c68c41a4..c48949a3e5c 100644 --- a/experimental/packages/opentelemetry-api-metrics/test/api/global.test.ts +++ b/experimental/packages/opentelemetry-api-metrics/test/api/global.test.ts @@ -16,7 +16,7 @@ import * as assert from 'assert'; import { _global, GLOBAL_METRICS_API_KEY } from '../../src/api/global-utils'; -import { NoopMeterProvider } from '../../src'; +import { NoopMeterProvider } from '../../src/NoopMeterProvider'; const api1 = require('../../src') as typeof import('../../src'); diff --git a/experimental/packages/opentelemetry-api-metrics/test/noop-implementations/noop-meter.test.ts b/experimental/packages/opentelemetry-api-metrics/test/noop-implementations/noop-meter.test.ts index 82f0e8b6beb..07395a925bc 100644 --- a/experimental/packages/opentelemetry-api-metrics/test/noop-implementations/noop-meter.test.ts +++ b/experimental/packages/opentelemetry-api-metrics/test/noop-implementations/noop-meter.test.ts @@ -17,14 +17,15 @@ import * as assert from 'assert'; import { NoopMeter, - NoopMeterProvider, NOOP_COUNTER_METRIC, NOOP_HISTOGRAM_METRIC, NOOP_OBSERVABLE_COUNTER_METRIC, NOOP_OBSERVABLE_GAUGE_METRIC, NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC, NOOP_UP_DOWN_COUNTER_METRIC, -} from '../../src'; + createNoopMeter, +} from '../../src/NoopMeter'; +import { NoopMeterProvider } from '../../src/NoopMeterProvider'; const attributes = {}; const options = { @@ -133,3 +134,9 @@ describe('NoopMeter', () => { meter.removeBatchObservableCallback(() => {}, []); }); }); + +describe('createNoopMeter', () => { + it('should return NoopMeter', () => { + assert.ok(createNoopMeter() instanceof NoopMeter); + }); +}); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md index e964db55985..02f25fc8554 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides exporter for node to be used with OTLP (`grpc`) compatible receivers. Compatible with [opentelemetry-collector][opentelemetry-collector-url] versions `>=0.16 <=0.53`. @@ -23,7 +25,7 @@ To see sample code and documentation for the traces exporter, as well as instruc The OTLPMetricsExporter in Node expects the URL to only be the hostname. It will not work with `/v1/metrics`. All options that work with trace also work with metrics. ```js -const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics-base'); +const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-grpc'); const collectorOptions = { // url is optional and can be omitted - default is http://localhost:4317 diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json index 96878925f2d..362fdae821a 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry Collector Metrics Exporter allows user to send collected metrics to the OpenTelemetry Collector", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -49,7 +49,7 @@ "devDependencies": { "@babel/core": "7.16.0", "@opentelemetry/api": "^1.0.0", - "@opentelemetry/api-metrics": "0.31.0", + "@opentelemetry/api-metrics": "0.32.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -69,12 +69,12 @@ "dependencies": { "@grpc/grpc-js": "^1.5.9", "@grpc/proto-loader": "^0.6.9", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/exporter-metrics-otlp-http": "0.31.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.31.0", - "@opentelemetry/otlp-transformer": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-metrics-base": "0.31.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.32.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.32.0", + "@opentelemetry/otlp-transformer": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-metrics": "0.32.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc" } 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 90c6ceb92b8..5f7d979fd30 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts @@ -19,7 +19,7 @@ import { OTLPMetricExporterBase, OTLPMetricExporterOptions } from '@opentelemetry/exporter-metrics-otlp-http'; -import { ResourceMetrics } from '@opentelemetry/sdk-metrics-base'; +import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { OTLPGRPCExporterConfigNode, OTLPGRPCExporterNodeBase, 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 3792c3e8dac..08a30aca3e0 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 @@ -33,7 +33,7 @@ import { mockHistogram, mockObservableGauge, setUp, shutdown, } from './metricsHelper'; -import { AggregationTemporality, ResourceMetrics } from '@opentelemetry/sdk-metrics-base'; +import { AggregationTemporality, ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { IExportMetricsServiceRequest, IResourceMetrics } from '@opentelemetry/otlp-transformer'; const metricsServiceProtoPath = @@ -214,13 +214,18 @@ const testOTLPMetricExporter = (params: TestParams) => assert.ok(exportedData, 'exportedData does not exist'); + // The order of the metrics is not guaranteed. + const counterIndex = exportedData[0].scopeMetrics[0].metrics.findIndex(it => it.name === 'int-counter'); + const observableIndex = exportedData[0].scopeMetrics[0].metrics.findIndex(it => it.name === 'double-observable-gauge'); + const histogramIndex = exportedData[0].scopeMetrics[0].metrics.findIndex(it => it.name === 'int-histogram'); + const resource = exportedData[0].resource; const counter = - exportedData[0].scopeMetrics[0].metrics[0]; + exportedData[0].scopeMetrics[0].metrics[counterIndex]; const observableGauge = - exportedData[0].scopeMetrics[0].metrics[1]; + exportedData[0].scopeMetrics[0].metrics[observableIndex]; const histogram = - exportedData[0].scopeMetrics[0].metrics[2]; + exportedData[0].scopeMetrics[0].metrics[histogramIndex]; ensureExportedCounterIsCorrect( counter, counter.sum?.dataPoints[0].timeUnixNano, diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts index 62376db7bae..0ca7df3226f 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts @@ -20,15 +20,20 @@ import * as assert from 'assert'; import * as grpc from '@grpc/grpc-js'; import { VERSION } from '@opentelemetry/core'; import { + Aggregation, AggregationTemporality, ExplicitBucketHistogramAggregation, MeterProvider, MetricReader, View, -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import { IKeyValue, IMetric, IResource } from '@opentelemetry/otlp-transformer'; class TestMetricReader extends MetricReader { + selectAggregation() { + return Aggregation.Default(); + } + selectAggregationTemporality() { return AggregationTemporality.CUMULATIVE; } diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json index 77f463edd10..b6a4e457480 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json @@ -22,7 +22,7 @@ "path": "../opentelemetry-exporter-metrics-otlp-http" }, { - "path": "../opentelemetry-sdk-metrics-base" + "path": "../opentelemetry-sdk-metrics" }, { "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 92ccfd51f10..28fa70613b0 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides exporter for web and node to be used with OTLP (`http/json`) compatible receivers. Compatible with [opentelemetry-collector][opentelemetry-collector-url] versions `>=0.52 <=0.53`. @@ -23,7 +25,7 @@ To see sample code and documentation for the traces exporter, visit the [Collect The OTLPMetricExporter in Web expects the endpoint to end in `/v1/metrics`. ```js -import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics-base'; +import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'; import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'; const collectorOptions = { url: '', // url is optional and can be omitted - default is http://localhost:4318/v1/metrics @@ -47,7 +49,7 @@ counter.add(10, { 'key': 'value' }); ## Metrics in Node ```js -const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics-base'); +const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http'); const collectorOptions = { url: '', // url is optional and can be omitted - default is http://localhost:4318/v1/metrics diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json index bb9df8cfc74..91a50f01250 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry Collector Metrics Exporter allows user to send collected metrics to the OpenTelemetry Collector", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -94,12 +94,12 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/api-metrics": "0.31.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/otlp-exporter-base": "0.31.0", - "@opentelemetry/otlp-transformer": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-metrics-base": "0.31.0" + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/otlp-exporter-base": "0.32.0", + "@opentelemetry/otlp-transformer": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-metrics": "0.32.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-http" } 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 059d44eeca6..b970a150d0e 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterBase.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterBase.ts @@ -21,7 +21,7 @@ import { InstrumentType, PushMetricExporter, ResourceMetrics -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import { defaultOptions, OTLPMetricExporterOptions } from './OTLPMetricExporterOptions'; import { OTLPExporterBase } from '@opentelemetry/otlp-exporter-base'; import { IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer'; diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterOptions.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterOptions.ts index a9f601992ff..986a85890b4 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterOptions.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/OTLPMetricExporterOptions.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { AggregationTemporality } from '@opentelemetry/sdk-metrics-base'; +import { AggregationTemporality } from '@opentelemetry/sdk-metrics'; import { OTLPExporterConfigBase } from '@opentelemetry/otlp-exporter-base'; export interface OTLPMetricExporterOptions extends OTLPExporterConfigBase { 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 e7aedd8d994..2a7b14d2192 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 @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ResourceMetrics } from '@opentelemetry/sdk-metrics-base'; +import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { baggageUtils, getEnv } from '@opentelemetry/core'; import { defaultOptions, OTLPMetricExporterOptions } from '../../OTLPMetricExporterOptions'; import { OTLPMetricExporterBase } from '../../OTLPMetricExporterBase'; 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 4652764f7d3..2008b88662f 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 @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ResourceMetrics } from '@opentelemetry/sdk-metrics-base'; +import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { getEnv, baggageUtils} from '@opentelemetry/core'; import { defaultOptions, OTLPMetricExporterOptions } from '../../OTLPMetricExporterOptions'; import { OTLPMetricExporterBase } from '../../OTLPMetricExporterBase'; 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 c76ca3ebdcd..166dbc4a81c 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 @@ -17,7 +17,7 @@ import { diag, DiagLogger, DiagLogLevel } from '@opentelemetry/api'; import { Counter, Histogram, } from '@opentelemetry/api-metrics'; import { ExportResultCode, hrTimeToNanoseconds } from '@opentelemetry/core'; -import { AggregationTemporality, ResourceMetrics, } from '@opentelemetry/sdk-metrics-base'; +import { AggregationTemporality, ResourceMetrics, } from '@opentelemetry/sdk-metrics'; import * as assert from 'assert'; import * as sinon from 'sinon'; import { OTLPMetricExporter } from '../../src/platform/browser'; @@ -99,6 +99,7 @@ describe('OTLPMetricExporter - web', () => { temporalityPreference: AggregationTemporality.CUMULATIVE }); }); + it('should successfully send metrics using sendBeacon', done => { collectorExporter.export(metrics, () => { }); @@ -109,16 +110,22 @@ describe('OTLPMetricExporter - web', () => { const blob: Blob = args[1]; const body = await blob.text(); const json = JSON.parse(body) as IExportMetricsServiceRequest; - const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[0]; - const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[1]; - const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[2]; + + // 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-gauge2'); + 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', "metric doesn't exist"); ensureCounterIsCorrect( metric1, - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].endTime), - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].startTime) + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime) ); @@ -128,8 +135,8 @@ describe('OTLPMetricExporter - web', () => { ); ensureObservableGaugeIsCorrect( metric2, - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].endTime), - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].startTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].endTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].startTime), 6, 'double-observable-gauge2' ); @@ -140,8 +147,8 @@ describe('OTLPMetricExporter - web', () => { ); ensureHistogramIsCorrect( metric3, - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].endTime), - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].startTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].startTime), [0, 100], [0, 2, 0] ); @@ -216,15 +223,20 @@ describe('OTLPMetricExporter - web', () => { const body = request.requestBody; const json = JSON.parse(body) as IExportMetricsServiceRequest; - const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[0]; - const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[1]; - const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[2]; + // 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-gauge2'); + 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', "metric doesn't exist"); ensureCounterIsCorrect( metric1, - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].endTime), - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].startTime) + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime) ); assert.ok( @@ -233,8 +245,8 @@ describe('OTLPMetricExporter - web', () => { ); ensureObservableGaugeIsCorrect( metric2, - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].endTime), - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].startTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].endTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].startTime), 6, 'double-observable-gauge2' ); @@ -245,8 +257,8 @@ describe('OTLPMetricExporter - web', () => { ); ensureHistogramIsCorrect( metric3, - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].endTime), - hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].startTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime), + hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].startTime), [0, 100], [0, 2, 0] ); 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 51b3b04a681..38c0b3bcc71 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 @@ -17,7 +17,7 @@ import { ExportResultCode } from '@opentelemetry/core'; import { ResourceMetrics, -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import * as assert from 'assert'; import * as sinon from 'sinon'; import { collect, mockCounter, mockObservableGauge, setUp, shutdown } from '../metricsHelper'; diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts index 90e4a39cd6d..8cb3811f810 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts @@ -27,12 +27,13 @@ import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; import { InstrumentationScope, VERSION } from '@opentelemetry/core'; import { + Aggregation, AggregationTemporality, ExplicitBucketHistogramAggregation, MeterProvider, MetricReader, View -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import { IExportMetricsServiceRequest, IKeyValue, @@ -57,6 +58,10 @@ class TestMetricReader extends MetricReader { return Promise.resolve(undefined); } + selectAggregation() { + return Aggregation.Default(); + } + selectAggregationTemporality() { return AggregationTemporality.CUMULATIVE; } 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 ddd4780b15c..77c50231536 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 @@ -41,7 +41,7 @@ import { HISTOGRAM_AGGREGATION_VIEW, } from '../metricsHelper'; import { MockedResponse } from './nodeHelpers'; -import { AggregationTemporality, ResourceMetrics } from '@opentelemetry/sdk-metrics-base'; +import { AggregationTemporality, ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { Stream, PassThrough } from 'stream'; import { OTLPExporterError, OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'; import { IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer'; @@ -288,29 +288,34 @@ describe('OTLPMetricExporter - node with json over http', () => { const responseBody = buff.toString(); const json = JSON.parse(responseBody) as IExportMetricsServiceRequest; - const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[0]; - const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[1]; - const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[2]; + // 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-gauge2'); + 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"); ensureCounterIsCorrect( metric1, - core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].endTime), - core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].startTime) + core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime), + core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime) ); assert.ok(typeof metric2 !== 'undefined', "observable gauge doesn't exist"); ensureObservableGaugeIsCorrect( metric2, - core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].endTime), - core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].startTime), + core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].endTime), + core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].startTime), 6, 'double-observable-gauge2' ); assert.ok(typeof metric3 !== 'undefined', "histogram doesn't exist"); ensureHistogramIsCorrect( metric3, - core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].endTime), - core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].startTime), + core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime), + core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].startTime), [0, 100], [0, 2, 0] ); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.json index 69019ed4090..132af2033a1 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.json @@ -19,7 +19,7 @@ "path": "../opentelemetry-api-metrics" }, { - "path": "../opentelemetry-sdk-metrics-base" + "path": "../opentelemetry-sdk-metrics" }, { "path": "../otlp-exporter-base" diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md index 9d7c8c0b2a0..1c1c115d481 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides exporter for node to be used with OTLP (`http/protobuf`) compatible receivers. Compatible with [opentelemetry-collector][opentelemetry-collector-url] versions `>=0.32 <=0.53`. @@ -21,7 +23,7 @@ To see sample code and documentation for the traces exporter, visit the [Collect ## Metrics in Node - PROTO over http ```js -const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics-base'); +const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto'); const collectorOptions = { url: '', // url is optional and can be omitted - default is http://localhost:4318/v1/metrics diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json index 296a5be5ffd..9723a58a552 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry Collector Metrics Exporter allows user to send collected metrics to the OpenTelemetry Collector using protobuf over HTTP", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -49,7 +49,7 @@ "devDependencies": { "@babel/core": "7.16.0", "@opentelemetry/api": "^1.0.0", - "@opentelemetry/api-metrics": "0.31.0", + "@opentelemetry/api-metrics": "0.32.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -68,13 +68,13 @@ }, "dependencies": { "@grpc/proto-loader": "0.6.9", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/exporter-metrics-otlp-http": "0.31.0", - "@opentelemetry/otlp-exporter-base": "0.31.0", - "@opentelemetry/otlp-proto-exporter-base": "0.31.0", - "@opentelemetry/otlp-transformer": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-metrics-base": "0.31.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.32.0", + "@opentelemetry/otlp-exporter-base": "0.32.0", + "@opentelemetry/otlp-proto-exporter-base": "0.32.0", + "@opentelemetry/otlp-transformer": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-metrics": "0.32.0", "protobufjs": "^6.9.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-metrics-otlp-proto" 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 925be74611f..dec361e522d 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts @@ -19,8 +19,8 @@ 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-base'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; +import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { OTLPMetricExporterBase } from '@opentelemetry/exporter-metrics-otlp-http'; import { OTLPExporterNodeConfigBase, 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 ad81bb5e6a7..8ff43fed7cc 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 @@ -32,7 +32,7 @@ import { mockObservableGauge, mockHistogram, collect, setUp, shutdown, } from './metricsHelper'; -import { AggregationTemporality, ResourceMetrics } from '@opentelemetry/sdk-metrics-base'; +import { AggregationTemporality, ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { OTLPMetricExporterOptions } from '@opentelemetry/exporter-metrics-otlp-http'; import { Stream, PassThrough } from 'stream'; import { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'; @@ -240,9 +240,14 @@ describe('OTLPMetricExporter - node with proto over http', () => { const data = ExportTraceServiceRequestProto.decode(buff); const json = data?.toJSON() as IExportMetricsServiceRequest; - const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[0]; - const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[1]; - const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[2]; + // 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( 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 06527896898..3a69427f90e 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts @@ -24,16 +24,21 @@ import { import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; import { + Aggregation, AggregationTemporality, ExplicitBucketHistogramAggregation, MeterProvider, MetricReader, View -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import { IExportMetricsServiceRequest, IKeyValue, IMetric } from '@opentelemetry/otlp-transformer'; import { Stream } from 'stream'; export class TestMetricReader extends MetricReader { + selectAggregation() { + return Aggregation.Default(); + } + selectAggregationTemporality() { return AggregationTemporality.CUMULATIVE; } diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json index 1023f08037d..be2921b2fd5 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json @@ -22,7 +22,7 @@ "path": "../opentelemetry-exporter-metrics-otlp-http" }, { - "path": "../opentelemetry-sdk-metrics-base" + "path": "../opentelemetry-sdk-metrics" }, { "path": "../otlp-exporter-base" diff --git a/experimental/packages/opentelemetry-exporter-prometheus/README.md b/experimental/packages/opentelemetry-exporter-prometheus/README.md index f16f8a19635..97ea063d3ca 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/README.md +++ b/experimental/packages/opentelemetry-exporter-prometheus/README.md @@ -3,14 +3,16 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] -The OpenTelemetry Prometheus Metrics Exporter allows the user to send collected [OpenTelemetry Metrics](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-metrics-base) to Prometheus. +**Note: This is an experimental package under active development. New releases may include breaking changes.** + +The OpenTelemetry Prometheus Metrics Exporter allows the user to send collected [OpenTelemetry Metrics](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-metrics) to Prometheus. [Prometheus](https://prometheus.io/) is a monitoring system that collects metrics, by scraping exposed endpoints at regular intervals, evaluating rule expressions. It can also trigger alerts if certain conditions are met. For assistance setting up Prometheus, [Click here](https://opencensus.io/codelabs/prometheus/#0) for a guided codelab. ## Installation ```bash -npm install --save @opentelemetry/sdk-metrics-base +npm install --save @opentelemetry/sdk-metrics npm install --save @opentelemetry/exporter-prometheus ``` @@ -20,17 +22,16 @@ Create & register the exporter on your application. ```js const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); +const { MeterProvider } = require('@opentelemetry/sdk-metrics'); // Add your port and startServer to the Prometheus options const options = {port: 9464, startServer: true}; const exporter = new PrometheusExporter(options); -// Register the exporter -const meter = new MeterProvider({ - exporter, - interval: 1000, -}).getMeter('example-prometheus'); +// Creates MeterProvider and installs the exporter as a MetricReader +const meterProvider = new MeterProvider(); +meterProvider.addMetricReader(exporter); +const meter = meterProvider.getMeter('example-prometheus'); // Now, start recording data const counter = meter.createCounter('metric_name', { diff --git a/experimental/packages/opentelemetry-exporter-prometheus/package.json b/experimental/packages/opentelemetry-exporter-prometheus/package.json index 6aac05d44f4..69e9dc9694c 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry Exporter Prometheus provides a metrics endpoint for Prometheus", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -59,9 +59,9 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/api-metrics": "0.31.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/sdk-metrics-base": "0.31.0" + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/sdk-metrics": "0.32.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-prometheus" } diff --git a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts index dd00bfee770..675472ec566 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts @@ -18,7 +18,7 @@ import { diag } from '@opentelemetry/api'; import { globalErrorHandler, } from '@opentelemetry/core'; -import { AggregationTemporality, MetricReader } from '@opentelemetry/sdk-metrics-base'; +import { Aggregation, AggregationTemporality, MetricReader } from '@opentelemetry/sdk-metrics'; import { createServer, IncomingMessage, Server, ServerResponse } from 'http'; import { ExporterConfig } from './export/types'; import { PrometheusSerializer } from './PrometheusSerializer'; @@ -90,6 +90,10 @@ export class PrometheusExporter extends MetricReader { } } + selectAggregation(): Aggregation { + return Aggregation.Default(); + } + selectAggregationTemporality(): AggregationTemporality { return AggregationTemporality.CUMULATIVE; } diff --git a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts index 3c4c127d31e..94144732ac2 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts @@ -23,7 +23,7 @@ import { MetricData, DataPoint, Histogram, -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import type { MetricAttributes, MetricAttributeValue diff --git a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts index 6439b57c2e7..080ac599e3f 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts @@ -15,9 +15,7 @@ */ import { Meter, ObservableResult } from '@opentelemetry/api-metrics'; -import { - MeterProvider, -} from '@opentelemetry/sdk-metrics-base'; +import { MeterProvider } from '@opentelemetry/sdk-metrics'; import * as assert from 'assert'; import * as sinon from 'sinon'; import * as http from 'http'; @@ -480,22 +478,19 @@ describe('PrometheusExporter', () => { let meter: Meter; let meterProvider: MeterProvider; let counter: Counter; - let exporter: PrometheusExporter | undefined; + let exporter: PrometheusExporter; - beforeEach(() => { + function setup(reader: PrometheusExporter) { meterProvider = new MeterProvider(); + meterProvider.addMetricReader(reader); + meter = meterProvider.getMeter('test-prometheus'); counter = meter.createCounter('counter'); counter.add(10, { key1: 'attributeValue1' }); - }); + } - afterEach(done => { - if (exporter) { - exporter.shutdown().then(done); - exporter = undefined; - } else { - done(); - } + afterEach(async () => { + await exporter.shutdown(); }); it('should use a configured name prefix', done => { @@ -504,7 +499,7 @@ describe('PrometheusExporter', () => { prefix: 'test_prefix', }, async () => { - meterProvider.addMetricReader(exporter!); + setup(exporter); http .get('http://localhost:9464/metrics', res => { res.on('data', chunk => { @@ -532,7 +527,7 @@ describe('PrometheusExporter', () => { port: 8080, }, async () => { - meterProvider.addMetricReader(exporter!); + setup(exporter); http .get('http://localhost:8080/metrics', res => { res.on('data', chunk => { @@ -560,7 +555,7 @@ describe('PrometheusExporter', () => { endpoint: '/test', }, async () => { - meterProvider.addMetricReader(exporter!); + setup(exporter); http .get('http://localhost:9464/test', res => { res.on('data', chunk => { @@ -588,7 +583,7 @@ describe('PrometheusExporter', () => { appendTimestamp: false, }, async () => { - meterProvider.addMetricReader(exporter!); + setup(exporter); http .get('http://localhost:9464/metrics', res => { res.on('data', chunk => { diff --git a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts index b0fc47ce2db..00e082a8612 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts @@ -17,6 +17,7 @@ import * as assert from 'assert'; import { MetricAttributes, UpDownCounter } from '@opentelemetry/api-metrics'; import { + Aggregation, AggregationTemporality, DataPoint, DataPointType, @@ -27,7 +28,7 @@ import { MetricReader, SumAggregation, View, -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import * as sinon from 'sinon'; import { PrometheusSerializer } from '../src'; import { mockedHrTimeMs, mockHrTime } from './util'; @@ -46,6 +47,10 @@ class TestMetricReader extends MetricReader { return AggregationTemporality.CUMULATIVE; } + selectAggregation() { + return Aggregation.Default(); + } + async onForceFlush() {} async onShutdown() {} diff --git a/experimental/packages/opentelemetry-exporter-prometheus/tsconfig.json b/experimental/packages/opentelemetry-exporter-prometheus/tsconfig.json index 362d404d694..b9a0327885e 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/tsconfig.json +++ b/experimental/packages/opentelemetry-exporter-prometheus/tsconfig.json @@ -16,7 +16,7 @@ "path": "../opentelemetry-api-metrics" }, { - "path": "../opentelemetry-sdk-metrics-base" + "path": "../opentelemetry-sdk-metrics" } ] } diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/README.md b/experimental/packages/opentelemetry-instrumentation-fetch/README.md index bf6719731ce..67ecbd6082a 100644 --- a/experimental/packages/opentelemetry-instrumentation-fetch/README.md +++ b/experimental/packages/opentelemetry-instrumentation-fetch/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides auto instrumentation for web using fetch. ## Installation diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/package.json b/experimental/packages/opentelemetry-instrumentation-fetch/package.json index f65a0c66151..d7e22f7f07c 100644 --- a/experimental/packages/opentelemetry-instrumentation-fetch/package.json +++ b/experimental/packages/opentelemetry-instrumentation-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-fetch", - "version": "0.31.0", + "version": "0.32.0", "description": "OpenTelemetry fetch automatic instrumentation package.", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -56,9 +56,9 @@ "devDependencies": { "@babel/core": "7.16.0", "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-zone": "1.5.0", - "@opentelemetry/propagator-b3": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", + "@opentelemetry/context-zone": "1.6.0", + "@opentelemetry/propagator-b3": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -87,10 +87,10 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/instrumentation": "0.31.0", - "@opentelemetry/sdk-trace-web": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/instrumentation": "0.32.0", + "@opentelemetry/sdk-trace-web": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-fetch" } diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/README.md b/experimental/packages/opentelemetry-instrumentation-grpc/README.md index 44d598fe142..16a5b22eae9 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/README.md +++ b/experimental/packages/opentelemetry-instrumentation-grpc/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides automatic instrumentation for [`grpc`](https://grpc.github.io/grpc/node/) and [`@grpc/grpc-js`](https://grpc.io/blog/grpc-js-1.0/). Currently, version [`1.x`](https://www.npmjs.com/package/grpc?activeTab=versions) of `grpc` and version [`1.x`](https://www.npmjs.com/package/@grpc/grpc-js?activeTab=versions) of `@grpc/grpc-js` is supported. For automatic instrumentation see the diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/package.json b/experimental/packages/opentelemetry-instrumentation-grpc/package.json index cc65f811308..31675724b9c 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/package.json +++ b/experimental/packages/opentelemetry-instrumentation-grpc/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-grpc", - "version": "0.31.0", + "version": "0.32.0", "description": "OpenTelemetry grpc automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -48,10 +48,10 @@ "@grpc/grpc-js": "1.5.9", "@grpc/proto-loader": "0.6.9", "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "1.5.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/sdk-trace-node": "1.5.0", + "@opentelemetry/context-async-hooks": "1.6.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/sdk-trace-node": "1.6.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/semver": "7.3.9", @@ -71,9 +71,9 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/api-metrics": "0.31.0", - "@opentelemetry/instrumentation": "0.31.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/instrumentation": "0.32.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-grpc" } diff --git a/experimental/packages/opentelemetry-instrumentation-http/README.md b/experimental/packages/opentelemetry-instrumentation-http/README.md index 4684adaa4ce..5973ceb7960 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/README.md +++ b/experimental/packages/opentelemetry-instrumentation-http/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides automatic instrumentation for [`http`](https://nodejs.org/api/http.html) and [`https`](https://nodejs.org/api/https.html). For automatic instrumentation see the diff --git a/experimental/packages/opentelemetry-instrumentation-http/package.json b/experimental/packages/opentelemetry-instrumentation-http/package.json index 44ba06a46b9..754414cf9f8 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/package.json +++ b/experimental/packages/opentelemetry-instrumentation-http/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-http", - "version": "0.31.0", + "version": "0.32.0", "description": "OpenTelemetry http/https automatic instrumentation package.", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -46,9 +46,9 @@ }, "devDependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/sdk-trace-node": "1.5.0", + "@opentelemetry/context-async-hooks": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/sdk-trace-node": "1.6.0", "@types/got": "9.6.12", "@types/mocha": "9.1.1", "@types/node": "18.6.5", @@ -66,7 +66,7 @@ "request-promise-native": "1.0.9", "rimraf": "3.0.2", "sinon": "14.0.0", - "superagent": "6.1.0", + "superagent": "8.0.0", "ts-mocha": "10.0.0", "typescript": "4.4.4" }, @@ -74,9 +74,11 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/instrumentation": "0.31.0", - "@opentelemetry/semantic-conventions": "1.5.0", + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/instrumentation": "0.32.0", + "@opentelemetry/sdk-metrics": "0.32.0", + "@opentelemetry/semantic-conventions": "1.6.0", "semver": "^7.3.5" }, "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 5459e1d26ff..a0e07a1e9f7 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts @@ -15,6 +15,7 @@ */ import { context, + HrTime, INVALID_SPAN_CONTEXT, propagation, ROOT_CONTEXT, @@ -25,7 +26,8 @@ import { SpanStatusCode, trace, } from '@opentelemetry/api'; -import { suppressTracing } from '@opentelemetry/core'; +import { Histogram, MeterProvider, MetricAttributes, ValueType } from '@opentelemetry/api-metrics'; +import { hrTime, hrTimeDuration, hrTimeToMilliseconds, suppressTracing } from '@opentelemetry/core'; import type * as http from 'http'; import type * as https from 'https'; import { Socket } from 'net'; @@ -58,6 +60,8 @@ export class HttpInstrumentation extends InstrumentationBase { private readonly _spanNotEnded: WeakSet = new WeakSet(); private readonly _version = process.versions.node; private _headerCapture; + private _httpServerDurationHistogram!: Histogram; + private _httpClientDurationHistogram!: Histogram; constructor(config?: HttpInstrumentationConfig) { super( @@ -65,8 +69,26 @@ export class HttpInstrumentation extends InstrumentationBase { VERSION, config ); - this._headerCapture = this._createHeaderCapture(); + this._updateMetricInstruments(); + } + + override setMeterProvider(meterProvider: MeterProvider) { + super.setMeterProvider(meterProvider); + this._updateMetricInstruments(); + } + + private _updateMetricInstruments() { + this._httpServerDurationHistogram = this.meter.createHistogram('http.server.duration', { + description: 'measures the duration of the inbound HTTP requests', + unit: 'ms', + valueType: ValueType.DOUBLE + }); + this._httpClientDurationHistogram = this.meter.createHistogram('http.client.duration', { + description: 'measures the duration of the outbound HTTP requests', + unit: 'ms', + valueType: ValueType.DOUBLE + }); } private _getConfig(): HttpInstrumentationConfig { @@ -272,11 +294,15 @@ export class HttpInstrumentation extends InstrumentationBase { * @param request The original request object. * @param options The arguments to the original function. * @param span representing the current operation + * @param startTime representing the start time of the request to calculate duration in Metric + * @param metricAttributes metric attributes */ private _traceClientRequest( request: http.ClientRequest, hostname: string, - span: Span + span: Span, + startTime: HrTime, + metricAttributes: MetricAttributes ): http.ClientRequest { if (this._getConfig().requestHook) { this._callRequestHook(span, request); @@ -294,6 +320,8 @@ export class HttpInstrumentation extends InstrumentationBase { response, ); span.setAttributes(responseAttributes); + metricAttributes = Object.assign(metricAttributes, utils.getOutgoingRequestMetricAttributesOnResponse(responseAttributes)); + if (this._getConfig().responseHook) { this._callResponseHook(span, response); } @@ -323,32 +351,32 @@ export class HttpInstrumentation extends InstrumentationBase { request, response ), - () => {}, + () => { }, true ); } - this._closeHttpSpan(span); + this._closeHttpSpan(span, SpanKind.CLIENT, startTime, metricAttributes); }); response.on('error', (error: Err) => { this._diag.debug('outgoingRequest on error()', error); utils.setSpanWithError(span, error); const code = utils.parseResponseStatus(SpanKind.CLIENT, response.statusCode); span.setStatus({ code, message: error.message }); - this._closeHttpSpan(span); + this._closeHttpSpan(span, SpanKind.CLIENT, startTime, metricAttributes); }); } ); request.on('close', () => { this._diag.debug('outgoingRequest on request close()'); if (!request.aborted) { - this._closeHttpSpan(span); + this._closeHttpSpan(span, SpanKind.CLIENT, startTime, metricAttributes); } }); request.on('error', (error: Err) => { this._diag.debug('outgoingRequest on request error()', error); utils.setSpanWithError(span, error); - this._closeHttpSpan(span); + this._closeHttpSpan(span, SpanKind.CLIENT, startTime, metricAttributes); }); this._diag.debug('http.ClientRequest return request'); @@ -404,18 +432,23 @@ export class HttpInstrumentation extends InstrumentationBase { const headers = request.headers; + const spanAttributes = utils.getIncomingRequestAttributes(request, { + component: component, + serverName: instrumentation._getConfig().serverName, + hookAttributes: instrumentation._callStartSpanHook( + request, + instrumentation._getConfig().startIncomingSpanHook + ), + }); + const spanOptions: SpanOptions = { kind: SpanKind.SERVER, - attributes: utils.getIncomingRequestAttributes(request, { - component: component, - serverName: instrumentation._getConfig().serverName, - hookAttributes: instrumentation._callStartSpanHook( - request, - instrumentation._getConfig().startIncomingSpanHook - ), - }), + attributes: spanAttributes, }; + const startTime = hrTime(); + let metricAttributes: MetricAttributes = utils.getIncomingRequestMetricAttributes(spanAttributes); + const ctx = propagation.extract(ROOT_CONTEXT, headers); const span = instrumentation._startHttpSpan( `${component.toLocaleUpperCase()} ${method}`, @@ -456,7 +489,7 @@ export class HttpInstrumentation extends InstrumentationBase { error => { if (error) { utils.setSpanWithError(span, error); - instrumentation._closeHttpSpan(span); + instrumentation._closeHttpSpan(span, SpanKind.SERVER, startTime, metricAttributes); throw error; } } @@ -466,6 +499,7 @@ export class HttpInstrumentation extends InstrumentationBase { request, response ); + metricAttributes = Object.assign(metricAttributes, utils.getIncomingRequestMetricAttributesOnResponse(attributes)); instrumentation._headerCapture.server.captureResponseHeaders(span, header => response.getHeader(header)); @@ -481,12 +515,12 @@ export class HttpInstrumentation extends InstrumentationBase { request, response ), - () => {}, + () => { }, true ); } - instrumentation._closeHttpSpan(span); + instrumentation._closeHttpSpan(span, SpanKind.SERVER, startTime, metricAttributes); return returned; }; @@ -495,7 +529,7 @@ export class HttpInstrumentation extends InstrumentationBase { error => { if (error) { utils.setSpanWithError(span, error); - instrumentation._closeHttpSpan(span); + instrumentation._closeHttpSpan(span, SpanKind.SERVER, startTime, metricAttributes); throw error; } } @@ -520,7 +554,7 @@ export class HttpInstrumentation extends InstrumentationBase { } const extraOptions = typeof args[0] === 'object' && - (typeof options === 'string' || options instanceof url.URL) + (typeof options === 'string' || options instanceof url.URL) ? (args.shift() as http.RequestOptions) : undefined; const { origin, pathname, method, optionsParsed } = utils.getRequestInfo( @@ -572,6 +606,9 @@ export class HttpInstrumentation extends InstrumentationBase { ), }); + const startTime = hrTime(); + const metricAttributes: MetricAttributes = utils.getOutgoingRequestMetricAttributes(attributes); + const spanOptions: SpanOptions = { kind: SpanKind.CLIENT, attributes, @@ -601,7 +638,7 @@ export class HttpInstrumentation extends InstrumentationBase { error => { if (error) { utils.setSpanWithError(span, error); - instrumentation._closeHttpSpan(span); + instrumentation._closeHttpSpan(span, SpanKind.CLIENT, startTime, metricAttributes); throw error; } } @@ -612,7 +649,9 @@ export class HttpInstrumentation extends InstrumentationBase { return instrumentation._traceClientRequest( request, hostname, - span + span, + startTime, + metricAttributes ); }); }; @@ -646,13 +685,21 @@ export class HttpInstrumentation extends InstrumentationBase { return span; } - private _closeHttpSpan(span: Span) { + private _closeHttpSpan(span: Span, spanKind: SpanKind, startTime: HrTime, metricAttributes: MetricAttributes) { if (!this._spanNotEnded.has(span)) { return; } span.end(); this._spanNotEnded.delete(span); + + // Record metrics + const duration = hrTimeToMilliseconds(hrTimeDuration(startTime, hrTime())); + if (spanKind === SpanKind.SERVER) { + this._httpServerDurationHistogram.record(duration, metricAttributes); + } else if (spanKind === SpanKind.CLIENT) { + this._httpClientDurationHistogram.record(duration, metricAttributes); + } } private _callResponseHook( @@ -661,7 +708,7 @@ export class HttpInstrumentation extends InstrumentationBase { ) { safeExecuteInTheMiddle( () => this._getConfig().responseHook!(span, response), - () => {}, + () => { }, true ); } @@ -672,7 +719,7 @@ export class HttpInstrumentation extends InstrumentationBase { ) { safeExecuteInTheMiddle( () => this._getConfig().requestHook!(span, request), - () => {}, + () => { }, true ); } @@ -681,7 +728,7 @@ export class HttpInstrumentation extends InstrumentationBase { request: http.IncomingMessage | http.RequestOptions, hookFunc: Function | undefined, ) { - if(typeof hookFunc === 'function'){ + if (typeof hookFunc === 'function') { return safeExecuteInTheMiddle( () => hookFunc(request), () => { }, diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts b/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts index f42f9955b32..e9e9b454683 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts @@ -35,6 +35,7 @@ import { getRPCMetadata, RPCType } from '@opentelemetry/core'; import * as url from 'url'; import { AttributeNames } from './enums/AttributeNames'; import { Err, IgnoreMatcher, ParsedRequestOptions } from './types'; +import { MetricAttributes } from '@opentelemetry/api-metrics'; /** * Get an absolute url @@ -299,7 +300,7 @@ export const extractHostnameAndPort = ( requestOptions: Pick ): { hostname: string, port: number | string } => { if (requestOptions.hostname && requestOptions.port) { - return {hostname: requestOptions.hostname, port: requestOptions.port}; + return { hostname: requestOptions.hostname, port: requestOptions.port }; } const matches = requestOptions.host?.match(/^([^:/ ]+)(:\d{1,5})?/) || null; const hostname = requestOptions.hostname || (matches === null ? 'localhost' : matches[1]); @@ -312,7 +313,7 @@ export const extractHostnameAndPort = ( port = requestOptions.protocol === 'https:' ? '443' : '80'; } } - return {hostname, port}; + return { hostname, port }; }; /** @@ -348,6 +349,20 @@ export const getOutgoingRequestAttributes = ( return Object.assign(attributes, options.hookAttributes); }; +/** + * Returns outgoing request Metric attributes scoped to the request data + * @param {SpanAttributes} spanAttributes the span attributes + */ +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. + return metricAttributes; +}; + /** * 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". @@ -392,6 +407,20 @@ export const getOutgoingRequestAttributesOnResponse = ( return Object.assign(attributes, httpKindAttributes); }; +/** + * Returns outgoing request Metric attributes scoped to the response data + * @param {SpanAttributes} spanAttributes the span attributes + */ +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]; + return metricAttributes; +}; + /** * Returns incoming request attributes scoped to the request data * @param {IncomingMessage} request the request object @@ -422,6 +451,7 @@ export const getIncomingRequestAttributes = ( [SemanticAttributes.HTTP_HOST]: host, [SemanticAttributes.NET_HOST_NAME]: hostname, [SemanticAttributes.HTTP_METHOD]: method, + [SemanticAttributes.HTTP_SCHEME]: options.component, }; if (typeof ips === 'string') { @@ -445,6 +475,23 @@ export const getIncomingRequestAttributes = ( return Object.assign(attributes, httpKindAttributes, options.hookAttributes); }; +/** + * Returns incoming request Metric attributes scoped to the request data + * @param {SpanAttributes} spanAttributes the span attributes + * @param {{ component: string }} options used to pass data needed to create attributes + */ +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. + return metricAttributes; +}; + /** * Returns incoming request attributes scoped to the response data * @param {(ServerResponse & { socket: Socket; })} response the response object @@ -475,6 +522,19 @@ export const getIncomingRequestAttributesOnResponse = ( return attributes; }; +/** + * Returns incoming request Metric attributes scoped to the request data + * @param {SpanAttributes} spanAttributes the span attributes + */ +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]; + return metricAttributes; +}; + export function headerCapture(type: 'request' | 'response', headers: string[]) { const normalizedHeaders = new Map(headers.map(header => [header.toLowerCase(), header.toLowerCase().replace(/-/g, '_')])); 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 44bedc3a1f4..bee473ed3d2 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 @@ -725,14 +725,16 @@ describe('HttpInstrumentation', () => { } }); - it("should have 1 ended span when request doesn't listening response", done => { + it("should have 1 ended client span when request doesn't listening response", done => { + // nock doesn't emit close event. nock.cleanAll(); nock.enableNetConnect(); - const req = http.request(`${protocol}://${hostname}/`); + + const req = http.request(`${protocol}://${hostname}:${serverPort}/`); req.on('close', () => { - const spans = memoryExporter.getFinishedSpans(); - const [span] = spans; + const spans = memoryExporter.getFinishedSpans().filter(it => it.kind === SpanKind.CLIENT); assert.strictEqual(spans.length, 1); + const [span] = spans; assert.ok(Object.keys(span.attributes).length > 6); done(); }); 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 new file mode 100644 index 00000000000..5ab046b45fd --- /dev/null +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts @@ -0,0 +1,103 @@ +/* + * 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 { + AggregationTemporality, + DataPointType, + InMemoryMetricExporter, + MeterProvider, + PeriodicExportingMetricReader, +} from '@opentelemetry/sdk-metrics'; +import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; +import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import * as assert from 'assert'; +import { HttpInstrumentation } from '../../src/http'; +import { httpRequest } from '../utils/httpRequest'; + +const instrumentation = new HttpInstrumentation(); +instrumentation.enable(); +instrumentation.disable(); + +import * as http from 'http'; + +let server: http.Server; +const serverPort = 22346; +const protocol = 'http'; +const hostname = 'localhost'; +const pathname = '/test'; +const tracerProvider = new NodeTracerProvider(); +const meterProvider = new MeterProvider(); +const metricsMemoryExporter = new InMemoryMetricExporter(AggregationTemporality.DELTA); +const metricReader = new PeriodicExportingMetricReader({ exporter: metricsMemoryExporter, exportIntervalMillis: 100 }); +meterProvider.addMetricReader(metricReader); +instrumentation.setTracerProvider(tracerProvider); +instrumentation.setMeterProvider(meterProvider); + + +describe('metrics', () => { + beforeEach(() => { + metricsMemoryExporter.reset(); + }); + + before(() => { + instrumentation.enable(); + server = http.createServer((request, response) => { + response.end('Test Server Response'); + }); + server.listen(serverPort); + }); + + after(() => { + server.close(); + instrumentation.disable(); + }); + + it('should add server/client duration metrics', async () => { + const requestCount = 3; + for (let i = 0; i < requestCount; i++) { + await httpRequest.get(`${protocol}://${hostname}:${serverPort}${pathname}`); + } + await new Promise(resolve => setTimeout(resolve, 300)); + const resourceMetrics = metricsMemoryExporter.getMetrics(); + const scopeMetrics = resourceMetrics[0].scopeMetrics; + assert.strictEqual(scopeMetrics.length, 1, 'scopeMetrics count'); + const metrics = scopeMetrics[0].metrics; + assert.strictEqual(metrics.length, 2, 'metrics count'); + assert.strictEqual(metrics[0].dataPointType, DataPointType.HISTOGRAM); + assert.strictEqual(metrics[0].descriptor.description, 'measures the duration of the inbound HTTP requests'); + assert.strictEqual(metrics[0].descriptor.name, 'http.server.duration'); + assert.strictEqual(metrics[0].descriptor.unit, 'ms'); + assert.strictEqual(metrics[0].dataPoints.length, 1); + assert.strictEqual((metrics[0].dataPoints[0].value as any).count, requestCount); + assert.strictEqual(metrics[0].dataPoints[0].attributes[SemanticAttributes.HTTP_SCHEME], 'http'); + assert.strictEqual(metrics[0].dataPoints[0].attributes[SemanticAttributes.HTTP_METHOD], 'GET'); + assert.strictEqual(metrics[0].dataPoints[0].attributes[SemanticAttributes.HTTP_FLAVOR], '1.1'); + assert.strictEqual(metrics[0].dataPoints[0].attributes[SemanticAttributes.NET_HOST_NAME], 'localhost'); + assert.strictEqual(metrics[0].dataPoints[0].attributes[SemanticAttributes.HTTP_STATUS_CODE], 200); + assert.strictEqual(metrics[0].dataPoints[0].attributes[SemanticAttributes.NET_HOST_PORT], 22346); + + assert.strictEqual(metrics[1].dataPointType, DataPointType.HISTOGRAM); + assert.strictEqual(metrics[1].descriptor.description, 'measures the duration of the outbound HTTP requests'); + assert.strictEqual(metrics[1].descriptor.name, 'http.client.duration'); + assert.strictEqual(metrics[1].descriptor.unit, 'ms'); + assert.strictEqual(metrics[1].dataPoints.length, 1); + assert.strictEqual((metrics[1].dataPoints[0].value as any).count, requestCount); + assert.strictEqual(metrics[1].dataPoints[0].attributes[SemanticAttributes.HTTP_METHOD], 'GET'); + assert.strictEqual(metrics[1].dataPoints[0].attributes[SemanticAttributes.NET_PEER_NAME], 'localhost'); + assert.strictEqual(metrics[1].dataPoints[0].attributes[SemanticAttributes.NET_PEER_PORT], 22346); + assert.strictEqual(metrics[1].dataPoints[0].attributes[SemanticAttributes.HTTP_STATUS_CODE], 200); + assert.strictEqual(metrics[1].dataPoints[0].attributes[SemanticAttributes.HTTP_FLAVOR], '1.1'); + }); +}); diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts b/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts index db0d0d1ea0f..3b9b1a402dd 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts @@ -125,7 +125,7 @@ export const assertSpan = ( validations.hostname, 'must be consistent (PEER_NAME and hostname)' ); - if(!validations.noNetPeer) { + if (!validations.noNetPeer) { assert.ok( span.attributes[SemanticAttributes.NET_PEER_IP], 'must have PEER_IP' @@ -178,6 +178,11 @@ export const assertSpan = ( 'must have HOST_IP' ); } + assert.strictEqual( + span.attributes[SemanticAttributes.HTTP_SCHEME], + validations.component, + ' must have http.scheme attribute' + ); assert.ok(typeof span.parentSpanId === 'string'); assert.ok(isValidSpanId(span.parentSpanId)); } else if (validations.reqHeaders) { diff --git a/experimental/packages/opentelemetry-instrumentation-http/tsconfig.json b/experimental/packages/opentelemetry-instrumentation-http/tsconfig.json index b883031b0f8..034c613b3e6 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/tsconfig.json +++ b/experimental/packages/opentelemetry-instrumentation-http/tsconfig.json @@ -24,8 +24,14 @@ { "path": "../../../packages/opentelemetry-semantic-conventions" }, + { + "path": "../opentelemetry-api-metrics" + }, { "path": "../opentelemetry-instrumentation" + }, + { + "path": "../opentelemetry-sdk-metrics" } ] } diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/README.md b/experimental/packages/opentelemetry-instrumentation-xml-http-request/README.md index bdd343d46cb..c02aa030d26 100644 --- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/README.md +++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides auto instrumentation for web using XMLHttpRequest . ## Installation diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json index e8b38a23325..78b43fda9ea 100644 --- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json +++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation-xml-http-request", - "version": "0.31.0", + "version": "0.32.0", "description": "OpenTelemetry XMLHttpRequest automatic instrumentation package.", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -56,9 +56,9 @@ "devDependencies": { "@babel/core": "7.16.0", "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-zone": "1.5.0", - "@opentelemetry/propagator-b3": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", + "@opentelemetry/context-zone": "1.6.0", + "@opentelemetry/propagator-b3": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -87,10 +87,10 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/instrumentation": "0.31.0", - "@opentelemetry/sdk-trace-web": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/instrumentation": "0.32.0", + "@opentelemetry/sdk-trace-web": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-xml-http-request" } diff --git a/experimental/packages/opentelemetry-instrumentation/README.md b/experimental/packages/opentelemetry-instrumentation/README.md index 834b5adc873..26e9f8c6962 100644 --- a/experimental/packages/opentelemetry-instrumentation/README.md +++ b/experimental/packages/opentelemetry-instrumentation/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + ## Installation ```bash diff --git a/experimental/packages/opentelemetry-instrumentation/package.json b/experimental/packages/opentelemetry-instrumentation/package.json index b448b1f7726..6fc1409a1f3 100644 --- a/experimental/packages/opentelemetry-instrumentation/package.json +++ b/experimental/packages/opentelemetry-instrumentation/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/instrumentation", - "version": "0.31.0", + "version": "0.32.0", "description": "Base class for node which OpenTelemetry instrumentation modules extend", "author": "OpenTelemetry Authors", "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation", @@ -68,7 +68,7 @@ "url": "https://github.com/open-telemetry/opentelemetry-js/issues" }, "dependencies": { - "@opentelemetry/api-metrics": "0.31.0", + "@opentelemetry/api-metrics": "0.32.0", "require-in-the-middle": "^5.0.3", "semver": "^7.3.2", "shimmer": "^1.2.1" diff --git a/experimental/packages/opentelemetry-instrumentation/test/common/autoLoader.test.ts b/experimental/packages/opentelemetry-instrumentation/test/common/autoLoader.test.ts index ff7971f66ac..c7bf2f6967d 100644 --- a/experimental/packages/opentelemetry-instrumentation/test/common/autoLoader.test.ts +++ b/experimental/packages/opentelemetry-instrumentation/test/common/autoLoader.test.ts @@ -15,16 +15,27 @@ */ import { Tracer, TracerProvider } from '@opentelemetry/api'; -import { NOOP_METER_PROVIDER } from '@opentelemetry/api-metrics'; import * as assert from 'assert'; import * as sinon from 'sinon'; import { InstrumentationBase, registerInstrumentations } from '../../src'; +import { + Meter, + MeterOptions, + MeterProvider, +} from '@opentelemetry/api-metrics'; class DummyTracerProvider implements TracerProvider { getTracer(name: string, version?: string): Tracer { throw new Error('not implemented'); } } + +class DummyMeterProvider implements MeterProvider { + getMeter(name: string, version?: string, options?: MeterOptions): Meter { + throw new Error('not implemented'); + } +} + class FooInstrumentation extends InstrumentationBase { init() { return []; @@ -50,14 +61,14 @@ describe('autoLoader', () => { let instrumentation: InstrumentationBase; let enableSpy: sinon.SinonSpy; let setTracerProviderSpy: sinon.SinonSpy; - let setsetMeterProvider: sinon.SinonSpy; + let setMeterProviderSpy: sinon.SinonSpy; const tracerProvider = new DummyTracerProvider(); - const meterProvider = NOOP_METER_PROVIDER; + const meterProvider = new DummyMeterProvider(); beforeEach(() => { instrumentation = new FooInstrumentation('foo', '1', {}); enableSpy = sinon.spy(instrumentation, 'enable'); setTracerProviderSpy = sinon.stub(instrumentation, 'setTracerProvider'); - setsetMeterProvider = sinon.stub(instrumentation, 'setMeterProvider'); + setMeterProviderSpy = sinon.stub(instrumentation, 'setMeterProvider'); unload = registerInstrumentations({ instrumentations: [instrumentation], tracerProvider, @@ -85,6 +96,7 @@ describe('autoLoader', () => { ); enableSpy = sinon.spy(instrumentation, 'enable'); setTracerProviderSpy = sinon.stub(instrumentation, 'setTracerProvider'); + setMeterProviderSpy = sinon.stub(instrumentation, 'setMeterProvider'); unload = registerInstrumentations({ instrumentations: [instrumentation], tracerProvider, @@ -104,9 +116,9 @@ describe('autoLoader', () => { }); it('should set MeterProvider', () => { - assert.strictEqual(setsetMeterProvider.callCount, 1); - assert.ok(setsetMeterProvider.lastCall.args[0] === meterProvider); - assert.strictEqual(setsetMeterProvider.lastCall.args.length, 1); + assert.strictEqual(setMeterProviderSpy.callCount, 1); + assert.ok(setMeterProviderSpy.lastCall.args[0] === meterProvider); + assert.strictEqual(setMeterProviderSpy.lastCall.args.length, 1); }); }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/index.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/index.ts deleted file mode 100644 index e9ad1ef4b94..00000000000 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/index.ts +++ /dev/null @@ -1,32 +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. - */ - -export { Sum, LastValue, Histogram } from './aggregator/types'; -export * from './export/AggregationTemporality'; -export * from './export/MetricData'; -export * from './export/MetricExporter'; -export * from './export/MetricProducer'; -export * from './export/MetricReader'; -export * from './export/PeriodicExportingMetricReader'; -export * from './export/InMemoryMetricExporter'; -export * from './export/ConsoleMetricExporter'; -export { InstrumentDescriptor, InstrumentType } from './InstrumentDescriptor'; -export * from './Meter'; -export * from './MeterProvider'; -export * from './ObservableResult'; -export { TimeoutError } from './utils'; -export * from './view/Aggregation'; -export * from './view/View'; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/MetricReader.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/MetricReader.test.ts deleted file mode 100644 index 1ee88df5d1a..00000000000 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/MetricReader.test.ts +++ /dev/null @@ -1,34 +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 { MeterProvider } from '../../src/MeterProvider'; -import { TestMetricReader } from './TestMetricReader'; - - -describe('MetricReader', () => { - describe('setMetricProducer', () => { - it('The SDK MUST NOT allow a MetricReader instance to be registered on more than one MeterProvider instance', () => { - const reader = new TestMetricReader(); - const meterProvider1 = new MeterProvider(); - const meterProvider2 = new MeterProvider(); - - meterProvider1.addMetricReader(reader); - assert.throws(() => meterProvider1.addMetricReader(reader), /MetricReader can not be bound to a MeterProvider again/); - assert.throws(() => meterProvider2.addMetricReader(reader), /MetricReader can not be bound to a MeterProvider again/); - }); - }); -}); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/.eslintignore b/experimental/packages/opentelemetry-sdk-metrics/.eslintignore similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/.eslintignore rename to experimental/packages/opentelemetry-sdk-metrics/.eslintignore diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/.eslintrc.js b/experimental/packages/opentelemetry-sdk-metrics/.eslintrc.js similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/.eslintrc.js rename to experimental/packages/opentelemetry-sdk-metrics/.eslintrc.js diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/.npmignore b/experimental/packages/opentelemetry-sdk-metrics/.npmignore similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/.npmignore rename to experimental/packages/opentelemetry-sdk-metrics/.npmignore diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/LICENSE b/experimental/packages/opentelemetry-sdk-metrics/LICENSE similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/LICENSE rename to experimental/packages/opentelemetry-sdk-metrics/LICENSE diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/README.md b/experimental/packages/opentelemetry-sdk-metrics/README.md similarity index 94% rename from experimental/packages/opentelemetry-sdk-metrics-base/README.md rename to experimental/packages/opentelemetry-sdk-metrics/README.md index 2d90184b6aa..044c3859130 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/README.md +++ b/experimental/packages/opentelemetry-sdk-metrics/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + OpenTelemetry metrics module contains the foundation for all metrics SDKs of [opentelemetry-js](https://github.com/open-telemetry/opentelemetry-js). Used standalone, this module provides methods for manual instrumentation of code, offering full control over recording metrics for client-side JavaScript (browser) and Node.js. @@ -13,7 +15,7 @@ It does **not** provide automated instrumentation of known libraries or host env ```bash npm install --save @opentelemetry/api-metrics -npm install --save @opentelemetry/sdk-metrics-base +npm install --save @opentelemetry/sdk-metrics ``` ## Usage @@ -22,7 +24,7 @@ The basic setup of the SDK can be seen as followings: ```js const opentelemetry = require('@opentelemetry/api-metrics'); -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); +const { MeterProvider } = require('@opentelemetry/sdk-metrics'); // To create an instrument, you first need to initialize the Meter provider. // NOTE: The default OpenTelemetry meter provider does not record any metric instruments. @@ -88,5 +90,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/LICENSE [license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat -[npm-url]: https://www.npmjs.com/package/@opentelemetry/sdk-metrics-base +[npm-url]: https://www.npmjs.com/package/@opentelemetry/sdk-metrics [npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fmetrics.svg diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/karma.conf.js b/experimental/packages/opentelemetry-sdk-metrics/karma.conf.js similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/karma.conf.js rename to experimental/packages/opentelemetry-sdk-metrics/karma.conf.js diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/package.json b/experimental/packages/opentelemetry-sdk-metrics/package.json similarity index 90% rename from experimental/packages/opentelemetry-sdk-metrics-base/package.json rename to experimental/packages/opentelemetry-sdk-metrics/package.json index 0e719042222..3d8cbb9a235 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/package.json +++ b/experimental/packages/opentelemetry-sdk-metrics/package.json @@ -1,6 +1,6 @@ { - "name": "@opentelemetry/sdk-metrics-base", - "version": "0.31.0", + "name": "@opentelemetry/sdk-metrics", + "version": "0.32.0", "description": "Work in progress OpenTelemetry metrics SDK", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -77,10 +77,10 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/api-metrics": "0.31.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/resources": "1.5.0", + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/resources": "1.6.0", "lodash.merge": "4.6.2" }, - "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-metrics-base" + "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-metrics" } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/InstrumentDescriptor.ts b/experimental/packages/opentelemetry-sdk-metrics/src/InstrumentDescriptor.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/InstrumentDescriptor.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/InstrumentDescriptor.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Instruments.ts b/experimental/packages/opentelemetry-sdk-metrics/src/Instruments.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/Instruments.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/Instruments.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts b/experimental/packages/opentelemetry-sdk-metrics/src/Meter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/Meter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts b/experimental/packages/opentelemetry-sdk-metrics/src/MeterProvider.ts similarity index 98% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/MeterProvider.ts index 003bb41a6b5..f8008d1c4be 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/MeterProvider.ts @@ -55,7 +55,7 @@ export class MeterProvider implements metrics.MeterProvider { // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#meter-creation if (this._shutdown) { api.diag.warn('A shutdown MeterProvider cannot provide a Meter'); - return metrics.NOOP_METER; + return metrics.createNoopMeter(); } return this._sharedState diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts b/experimental/packages/opentelemetry-sdk-metrics/src/ObservableResult.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/ObservableResult.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Drop.ts b/experimental/packages/opentelemetry-sdk-metrics/src/aggregator/Drop.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Drop.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/aggregator/Drop.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts b/experimental/packages/opentelemetry-sdk-metrics/src/aggregator/Histogram.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/aggregator/Histogram.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts b/experimental/packages/opentelemetry-sdk-metrics/src/aggregator/LastValue.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/aggregator/LastValue.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts b/experimental/packages/opentelemetry-sdk-metrics/src/aggregator/Sum.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/aggregator/Sum.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/index.ts b/experimental/packages/opentelemetry-sdk-metrics/src/aggregator/index.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/index.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/aggregator/index.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/types.ts b/experimental/packages/opentelemetry-sdk-metrics/src/aggregator/types.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/types.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/aggregator/types.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/AlignedHistogramBucketExemplarReservoir.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/AlignedHistogramBucketExemplarReservoir.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/AlignedHistogramBucketExemplarReservoir.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/AlignedHistogramBucketExemplarReservoir.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/AlwaysSampleExemplarFilter.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/AlwaysSampleExemplarFilter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/AlwaysSampleExemplarFilter.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/AlwaysSampleExemplarFilter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/Exemplar.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/Exemplar.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/Exemplar.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/Exemplar.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarFilter.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/ExemplarFilter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarFilter.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/ExemplarFilter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarReservoir.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/ExemplarReservoir.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarReservoir.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/ExemplarReservoir.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/NeverSampleExemplarFilter.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/NeverSampleExemplarFilter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/NeverSampleExemplarFilter.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/NeverSampleExemplarFilter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/SimpleFixedSizeExemplarReservoir.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/SimpleFixedSizeExemplarReservoir.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/SimpleFixedSizeExemplarReservoir.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/SimpleFixedSizeExemplarReservoir.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/WithTraceExemplarFilter.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/WithTraceExemplarFilter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/WithTraceExemplarFilter.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/WithTraceExemplarFilter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/index.ts b/experimental/packages/opentelemetry-sdk-metrics/src/exemplar/index.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/index.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/exemplar/index.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics/src/export/AggregationSelector.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/AggregationSelector.ts new file mode 100644 index 00000000000..8a372d0e74d --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics/src/export/AggregationSelector.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 { InstrumentType } from '../InstrumentDescriptor'; +import { Aggregation } from '../view/Aggregation'; +import { AggregationTemporality } from './AggregationTemporality'; + +/** + * Aggregation selector based on metric instrument types. + */ +export type AggregationSelector = (instrumentType: InstrumentType) => Aggregation; + +/** + * Aggregation temporality selector based on metric instrument types. + */ +export type AggregationTemporalitySelector = (instrumentType: InstrumentType) => AggregationTemporality; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/AggregationTemporality.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/AggregationTemporality.ts similarity index 82% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/export/AggregationTemporality.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/export/AggregationTemporality.ts index 0b936714722..6cc6d1231bf 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/AggregationTemporality.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/export/AggregationTemporality.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { InstrumentType } from '../InstrumentDescriptor'; - /** * AggregationTemporality indicates the way additive quantities are expressed. */ @@ -23,5 +21,3 @@ export enum AggregationTemporality { DELTA, CUMULATIVE, } - -export type AggregationTemporalitySelector = (instrumentType: InstrumentType) => AggregationTemporality; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/ConsoleMetricExporter.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/ConsoleMetricExporter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/export/ConsoleMetricExporter.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/export/ConsoleMetricExporter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/InMemoryMetricExporter.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/InMemoryMetricExporter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/export/InMemoryMetricExporter.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/export/InMemoryMetricExporter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricData.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/MetricData.ts similarity index 99% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricData.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/export/MetricData.ts index 36e031e2d31..f31c748e0ba 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricData.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/export/MetricData.ts @@ -25,7 +25,7 @@ import { Histogram } from '../aggregator/types'; /** * Basic metric data fields. */ -export interface BaseMetricData { +interface BaseMetricData { readonly descriptor: InstrumentDescriptor; readonly aggregationTemporality: AggregationTemporality; /** diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricExporter.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/MetricExporter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricExporter.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/export/MetricExporter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricProducer.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/MetricProducer.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricProducer.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/export/MetricProducer.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/MetricReader.ts similarity index 95% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/export/MetricReader.ts index 35d86c5d943..3037384fcf9 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/export/MetricReader.ts @@ -21,6 +21,7 @@ import { CollectionResult } from './MetricData'; import { callWithTimeout } from '../utils'; import { InstrumentType } from '../InstrumentDescriptor'; import { CollectionOptions, ForceFlushOptions, ShutdownOptions } from '../types'; +import { Aggregation } from '../view/Aggregation'; /** * A registered reader of metrics that, when linked to a {@link MetricProducer}, offers global @@ -46,6 +47,12 @@ export abstract class MetricReader { this.onInitialized(); } + /** + * Select the {@link Aggregation} for the given {@link InstrumentType} for this + * reader. + */ + abstract selectAggregation(instrumentType: InstrumentType): Aggregation; + /** * Select the {@link AggregationTemporality} for the given * {@link InstrumentType} for this reader. diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics/src/export/PeriodicExportingMetricReader.ts similarity index 78% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/export/PeriodicExportingMetricReader.ts index 3e188c02931..4d2206cda00 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/export/PeriodicExportingMetricReader.ts @@ -25,25 +25,43 @@ import { AggregationTemporality } from './AggregationTemporality'; import { InstrumentType } from '../InstrumentDescriptor'; import { PushMetricExporter } from './MetricExporter'; import { callWithTimeout, TimeoutError } from '../utils'; +import { Aggregation } from '../view/Aggregation'; +import { AggregationSelector } from './AggregationSelector'; export type PeriodicExportingMetricReaderOptions = { - exporter: PushMetricExporter - exportIntervalMillis?: number, - exportTimeoutMillis?: number + /** + * Aggregation selector based on metric instrument types. If no views are + * configured for a metric instrument, a per-metric-reader aggregation is + * selected with this selector. + */ + aggregationSelector?: AggregationSelector; + /** + * The backing exporter for the metric reader. + */ + exporter: PushMetricExporter; + /** + * An internal milliseconds for the metric reader to initiate metric + * collection. + */ + exportIntervalMillis?: number; + /** + * Milliseconds for the async observable callback to timeout. + */ + exportTimeoutMillis?: number; }; +const DEFAULT_AGGREGATION_SELECTOR: AggregationSelector = Aggregation.Default; + /** * {@link MetricReader} which collects metrics based on a user-configurable time interval, and passes the metrics to * the configured {@link MetricExporter} */ export class PeriodicExportingMetricReader extends MetricReader { private _interval?: ReturnType; - private _exporter: PushMetricExporter; - private readonly _exportInterval: number; - private readonly _exportTimeout: number; + private readonly _aggregationSelector: AggregationSelector; constructor(options: PeriodicExportingMetricReaderOptions) { super(); @@ -65,6 +83,7 @@ export class PeriodicExportingMetricReader extends MetricReader { this._exportInterval = options.exportIntervalMillis ?? 60000; this._exportTimeout = options.exportTimeoutMillis ?? 30000; this._exporter = options.exporter; + this._aggregationSelector = options.aggregationSelector ?? DEFAULT_AGGREGATION_SELECTOR; } private async _runOnce(): Promise { @@ -119,6 +138,13 @@ export class PeriodicExportingMetricReader extends MetricReader { await this._exporter.shutdown(); } + /** + * @inheritdoc + */ + selectAggregation(instrumentType: InstrumentType): Aggregation { + return this._aggregationSelector(instrumentType); + } + /** * @inheritdoc */ diff --git a/experimental/packages/opentelemetry-sdk-metrics/src/index.ts b/experimental/packages/opentelemetry-sdk-metrics/src/index.ts new file mode 100644 index 00000000000..e5e1ab6ed2a --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics/src/index.ts @@ -0,0 +1,96 @@ +/* + * 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 { + Sum, + LastValue, + Histogram, +} from './aggregator/types'; + +export { + AggregationSelector, + AggregationTemporalitySelector, +} from './export/AggregationSelector'; + +export { + AggregationTemporality, +} from './export/AggregationTemporality'; + +export { + DataPoint, + DataPointType, + SumMetricData, + GaugeMetricData, + HistogramMetricData, + ResourceMetrics, + ScopeMetrics, + MetricData, + CollectionResult, +} from './export/MetricData'; + +export { + PushMetricExporter, +} from './export/MetricExporter'; + +export { + MetricReader, +} from './export/MetricReader'; + +export { + PeriodicExportingMetricReader, + PeriodicExportingMetricReaderOptions, +} from './export/PeriodicExportingMetricReader'; + +export { + InMemoryMetricExporter, +} from './export/InMemoryMetricExporter'; + +export { + ConsoleMetricExporter, +} from './export/ConsoleMetricExporter'; + +export { + InstrumentDescriptor, + InstrumentType, +} from './InstrumentDescriptor'; + +export { + Meter, +} from './Meter'; + +export { + MeterProvider, + MeterProviderOptions, +} from './MeterProvider'; + +export { + DefaultAggregation, + ExplicitBucketHistogramAggregation, + DropAggregation, + HistogramAggregation, + LastValueAggregation, + SumAggregation, + Aggregation +} from './view/Aggregation'; + +export { + View, + ViewOptions, +} from './view/View'; + +export { + TimeoutError +} from './utils'; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/AsyncMetricStorage.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/AsyncMetricStorage.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/DeltaMetricProcessor.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/DeltaMetricProcessor.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/DeltaMetricProcessor.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/DeltaMetricProcessor.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/HashMap.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/HashMap.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/HashMap.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/HashMap.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/MeterProviderSharedState.ts similarity index 79% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/MeterProviderSharedState.ts index 87fe540ee56..a63f53d51dc 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/state/MeterProviderSharedState.ts @@ -16,10 +16,11 @@ import { InstrumentationScope } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; +import { Aggregation, InstrumentType } from '..'; import { instrumentationScopeId } from '../utils'; import { ViewRegistry } from '../view/ViewRegistry'; import { MeterSharedState } from './MeterSharedState'; -import { MetricCollector } from './MetricCollector'; +import { MetricCollector, MetricCollectorHandle } from './MetricCollector'; /** * An internal record for shared meter provider states. @@ -42,4 +43,12 @@ export class MeterProviderSharedState { } return meterSharedState; } + + selectAggregations(instrumentType: InstrumentType) { + const result: [MetricCollectorHandle, Aggregation][] = []; + for (const collector of this.metricCollectors) { + result.push([collector, collector.selectAggregation(instrumentType)]); + } + return result; + } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/MeterSharedState.ts similarity index 59% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/MeterSharedState.ts index ed96aca444a..4ddc0b89328 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterSharedState.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/state/MeterSharedState.ts @@ -20,7 +20,7 @@ import { MetricCollectOptions } from '../export/MetricProducer'; import { ScopeMetrics } from '../export/MetricData'; import { createInstrumentDescriptorWithView, InstrumentDescriptor } from '../InstrumentDescriptor'; import { Meter } from '../Meter'; -import { isNotNullish } from '../utils'; +import { isNotNullish, Maybe } from '../utils'; import { AsyncMetricStorage } from './AsyncMetricStorage'; import { MeterProviderSharedState } from './MeterProviderSharedState'; import { MetricCollectorHandle } from './MetricCollector'; @@ -28,12 +28,15 @@ import { MetricStorageRegistry } from './MetricStorageRegistry'; import { MultiMetricStorage } from './MultiWritableMetricStorage'; import { ObservableRegistry } from './ObservableRegistry'; import { SyncMetricStorage } from './SyncMetricStorage'; +import { Accumulation, Aggregator } from '../aggregator/types'; +import { AttributesProcessor } from '../view/AttributesProcessor'; +import { MetricStorage } from './MetricStorage'; /** * An internal record for shared meter provider states. */ export class MeterSharedState { - private _metricStorageRegistry = new MetricStorageRegistry(); + metricStorageRegistry = new MetricStorageRegistry(); observableRegistry = new ObservableRegistry(); meter: Meter; @@ -42,15 +45,8 @@ export class MeterSharedState { } registerMetricStorage(descriptor: InstrumentDescriptor) { - const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationScope); - const storages = views - .map(view => { - const viewDescriptor = createInstrumentDescriptorWithView(view, descriptor); - const aggregator = view.aggregation.createAggregator(viewDescriptor); - const storage = new SyncMetricStorage(viewDescriptor, aggregator, view.attributesProcessor); - return this._metricStorageRegistry.register(storage); - }) - .filter(isNotNullish); + const storages = this._registerMetricStorage(descriptor, SyncMetricStorage); + if (storages.length === 1) { return storages[0]; } @@ -58,15 +54,8 @@ export class MeterSharedState { } registerAsyncMetricStorage(descriptor: InstrumentDescriptor) { - const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationScope); - const storages = views - .map(view => { - const viewDescriptor = createInstrumentDescriptorWithView(view, descriptor); - const aggregator = view.aggregation.createAggregator(viewDescriptor); - const viewStorage = new AsyncMetricStorage(viewDescriptor, aggregator, view.attributesProcessor); - return this._metricStorageRegistry.register(viewStorage); - }) - .filter(isNotNullish); + const storages = this._registerMetricStorage(descriptor, AsyncMetricStorage); + return storages; } @@ -81,7 +70,7 @@ export class MeterSharedState { * 2. Collect metric result for the collector. */ const errors = await this.observableRegistry.observe(collectionTime, options?.timeoutMillis); - const metricDataList = Array.from(this._metricStorageRegistry.getStorages()) + const metricDataList = Array.from(this.metricStorageRegistry.getStorages(collector)) .map(metricStorage => { return metricStorage.collect( collector, @@ -98,9 +87,49 @@ export class MeterSharedState { errors, }; } + + private _registerMetricStorage>(descriptor: InstrumentDescriptor, MetricStorageType: MetricStorageType): R[] { + const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationScope); + let storages = views + .map(view => { + const viewDescriptor = createInstrumentDescriptorWithView(view, descriptor); + const compatibleStorage = this.metricStorageRegistry.findOrUpdateCompatibleStorage(viewDescriptor); + if (compatibleStorage != null) { + return compatibleStorage; + } + const aggregator = view.aggregation.createAggregator(viewDescriptor); + const viewStorage = new MetricStorageType(viewDescriptor, aggregator, view.attributesProcessor) as R; + this.metricStorageRegistry.register(viewStorage); + return viewStorage; + }); + + // Fallback to the per-collector aggregations if no view is configured for the instrument. + if (storages.length === 0) { + const perCollectorAggregations = this._meterProviderSharedState.selectAggregations(descriptor.type); + const collectorStorages = perCollectorAggregations.map(([collector, aggregation]) => { + const compatibleStorage = this.metricStorageRegistry.findOrUpdateCompatibleCollectorStorage(collector, descriptor); + if (compatibleStorage != null) { + return compatibleStorage; + } + const aggregator = aggregation.createAggregator(descriptor); + const storage = new MetricStorageType(descriptor, aggregator, AttributesProcessor.Noop()) as R; + this.metricStorageRegistry.registerForCollector(collector, storage); + return storage; + }); + storages = storages.concat(collectorStorages); + } + + return storages; + } } interface ScopeMetricsResult { scopeMetrics: ScopeMetrics; errors: unknown[]; } + +interface MetricStorageConstructor { + new (instrumentDescriptor: InstrumentDescriptor, + aggregator: Aggregator>, + attributesProcessor: AttributesProcessor): MetricStorage; +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/MetricCollector.ts similarity index 95% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/MetricCollector.ts index 066106e47d4..fbffc2f0605 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/state/MetricCollector.ts @@ -15,7 +15,7 @@ */ import { hrTime } from '@opentelemetry/core'; -import { AggregationTemporalitySelector } from '../export/AggregationTemporality'; +import { AggregationTemporalitySelector } from '../export/AggregationSelector'; import { CollectionResult } from '../export/MetricData'; import { MetricProducer, MetricCollectOptions } from '../export/MetricProducer'; import { MetricReader } from '../export/MetricReader'; @@ -65,6 +65,10 @@ export class MetricCollector implements MetricProducer { selectAggregationTemporality(instrumentType: InstrumentType) { return this._metricReader.selectAggregationTemporality(instrumentType); } + + selectAggregation(instrumentType: InstrumentType) { + return this._metricReader.selectAggregation(instrumentType); + } } /** diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/MetricStorage.ts similarity index 96% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorage.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/MetricStorage.ts index 8e24da668ab..f69a00daa45 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorage.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/state/MetricStorage.ts @@ -41,7 +41,7 @@ export abstract class MetricStorage { collectionTime: HrTime, ): Maybe; - getInstrumentDescriptor(): InstrumentDescriptor{ + getInstrumentDescriptor(): Readonly { return this._instrumentDescriptor; } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorageRegistry.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/MetricStorageRegistry.ts similarity index 51% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorageRegistry.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/MetricStorageRegistry.ts index 1a930cacb05..c65a1dd7b2a 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricStorageRegistry.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/state/MetricStorageRegistry.ts @@ -15,40 +15,93 @@ */ import { MetricStorage } from './MetricStorage'; -import { isDescriptorCompatibleWith } from '../InstrumentDescriptor'; +import { InstrumentDescriptor, isDescriptorCompatibleWith } from '../InstrumentDescriptor'; import * as api from '@opentelemetry/api'; -import { Maybe } from '../utils'; import { getConflictResolutionRecipe, getIncompatibilityDetails } from '../view/RegistrationConflicts'; +import { MetricCollectorHandle } from './MetricCollector'; + +type StorageMap = Map; /** * Internal class for storing {@link MetricStorage} */ export class MetricStorageRegistry { - private readonly _metricStorageRegistry = new Map(); + private readonly _sharedRegistry: StorageMap = new Map(); + private readonly _perCollectorRegistry = new Map(); static create(){ return new MetricStorageRegistry(); } - getStorages(): MetricStorage[] { + getStorages(collector: MetricCollectorHandle): MetricStorage[] { let storages: MetricStorage[] = []; - for (const metricStorages of this._metricStorageRegistry.values()) { + for (const metricStorages of this._sharedRegistry.values()) { storages = storages.concat(metricStorages); } + const perCollectorStorages = this._perCollectorRegistry.get(collector); + if (perCollectorStorages != null) { + for (const metricStorages of perCollectorStorages.values()) { + storages = storages.concat(metricStorages); + } + } + return storages; } - register(storage: T): Maybe { - const expectedDescriptor = storage.getInstrumentDescriptor(); - const existingStorages = this._metricStorageRegistry.get(expectedDescriptor.name); + register(storage: MetricStorage) { + this._registerStorage(storage, this._sharedRegistry); + } + + registerForCollector(collector: MetricCollectorHandle, storage: MetricStorage) { + let storageMap = this._perCollectorRegistry.get(collector); + if (storageMap == null) { + storageMap = new Map(); + this._perCollectorRegistry.set(collector, storageMap); + } + this._registerStorage(storage, storageMap); + } + + findOrUpdateCompatibleStorage(expectedDescriptor: InstrumentDescriptor): T | null { + const storages = this._sharedRegistry.get(expectedDescriptor.name); + if (storages === undefined) { + return null; + } + + // If the descriptor is compatible, the type of their metric storage + // (either SyncMetricStorage or AsyncMetricStorage) must be compatible. + return this._findOrUpdateCompatibleStorage(expectedDescriptor, storages); + } - // Add storage if it does not exist. - if (existingStorages === undefined) { - this._metricStorageRegistry.set(expectedDescriptor.name, [storage]); - return storage; + findOrUpdateCompatibleCollectorStorage(collector: MetricCollectorHandle, expectedDescriptor: InstrumentDescriptor): T | null { + const storageMap = this._perCollectorRegistry.get(collector); + if (storageMap === undefined) { + return null; } + const storages = this._sharedRegistry.get(expectedDescriptor.name); + if (storages === undefined) { + return null; + } + + // If the descriptor is compatible, the type of their metric storage + // (either SyncMetricStorage or AsyncMetricStorage) must be compatible. + return this._findOrUpdateCompatibleStorage(expectedDescriptor, storages); + } + + private _registerStorage(storage: MetricStorage, storageMap: StorageMap) { + const descriptor = storage.getInstrumentDescriptor(); + const storages = storageMap.get(descriptor.name); + + if (storages === undefined) { + storageMap.set(descriptor.name, [storage]); + return; + } + + storages.push(storage); + } + + private _findOrUpdateCompatibleStorage(expectedDescriptor: InstrumentDescriptor, existingStorages: MetricStorage[]): T | null { let compatibleStorage = null; for (const existingStorage of existingStorages) { @@ -84,12 +137,6 @@ export class MetricStorageRegistry { } } - if (compatibleStorage != null) { - return compatibleStorage; - } - - // None of the storages were compatible, add the current one to the list. - existingStorages.push(storage); - return storage; + return compatibleStorage; } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MultiWritableMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/MultiWritableMetricStorage.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/MultiWritableMetricStorage.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/MultiWritableMetricStorage.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/ObservableRegistry.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/ObservableRegistry.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/ObservableRegistry.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/ObservableRegistry.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/SyncMetricStorage.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/SyncMetricStorage.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/TemporalMetricProcessor.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/TemporalMetricProcessor.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/WritableMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics/src/state/WritableMetricStorage.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/state/WritableMetricStorage.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/state/WritableMetricStorage.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/types.ts b/experimental/packages/opentelemetry-sdk-metrics/src/types.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/types.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/types.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/utils.ts b/experimental/packages/opentelemetry-sdk-metrics/src/utils.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/utils.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/utils.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/Aggregation.ts b/experimental/packages/opentelemetry-sdk-metrics/src/view/Aggregation.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/view/Aggregation.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/view/Aggregation.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/AttributesProcessor.ts b/experimental/packages/opentelemetry-sdk-metrics/src/view/AttributesProcessor.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/view/AttributesProcessor.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/view/AttributesProcessor.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/InstrumentSelector.ts b/experimental/packages/opentelemetry-sdk-metrics/src/view/InstrumentSelector.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/view/InstrumentSelector.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/view/InstrumentSelector.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/MeterSelector.ts b/experimental/packages/opentelemetry-sdk-metrics/src/view/MeterSelector.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/view/MeterSelector.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/view/MeterSelector.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/Predicate.ts b/experimental/packages/opentelemetry-sdk-metrics/src/view/Predicate.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/view/Predicate.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/view/Predicate.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/RegistrationConflicts.ts b/experimental/packages/opentelemetry-sdk-metrics/src/view/RegistrationConflicts.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/view/RegistrationConflicts.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/view/RegistrationConflicts.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/View.ts b/experimental/packages/opentelemetry-sdk-metrics/src/view/View.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/view/View.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/view/View.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/ViewRegistry.ts b/experimental/packages/opentelemetry-sdk-metrics/src/view/ViewRegistry.ts similarity index 92% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/view/ViewRegistry.ts rename to experimental/packages/opentelemetry-sdk-metrics/src/view/ViewRegistry.ts index 1a26387d10a..1dcaf7d22f2 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/ViewRegistry.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/src/view/ViewRegistry.ts @@ -21,9 +21,6 @@ import { MeterSelector } from './MeterSelector'; import { View } from './View'; export class ViewRegistry { - private static DEFAULT_VIEW = new View({ - instrumentName: '*' - }); private _registeredViews: View[] = []; addView(view: View) { @@ -37,9 +34,6 @@ export class ViewRegistry { this._matchMeter(registeredView.meterSelector, meter); }); - if (views.length === 0) { - return [ViewRegistry.DEFAULT_VIEW]; - } return views; } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarFilter.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/ExemplarFilter.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarFilter.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/ExemplarFilter.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarReservoir.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/ExemplarReservoir.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarReservoir.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/ExemplarReservoir.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/InstrumentDescriptor.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/InstrumentDescriptor.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/InstrumentDescriptor.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/InstrumentDescriptor.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/Instruments.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/Instruments.test.ts similarity index 98% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/Instruments.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/Instruments.test.ts index 2bb47be3b2d..772e268fa4a 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/Instruments.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/Instruments.test.ts @@ -19,7 +19,6 @@ import * as sinon from 'sinon'; import { InstrumentationScope } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; import { - AggregationTemporality, InstrumentDescriptor, InstrumentType, MeterProvider, @@ -28,7 +27,7 @@ import { DataPointType, Histogram } from '../src'; -import { TestMetricReader } from './export/TestMetricReader'; +import { TestDeltaMetricReader, TestMetricReader } from './export/TestMetricReader'; import { assertMetricData, assertDataPoint, @@ -654,9 +653,9 @@ function setup() { const meter = meterProvider.getMeter(defaultInstrumentationScope.name, defaultInstrumentationScope.version, { schemaUrl: defaultInstrumentationScope.schemaUrl, }); - const deltaReader = new TestMetricReader(() => AggregationTemporality.DELTA); + const deltaReader = new TestDeltaMetricReader(); meterProvider.addMetricReader(deltaReader); - const cumulativeReader = new TestMetricReader(() => AggregationTemporality.CUMULATIVE); + const cumulativeReader = new TestMetricReader(); meterProvider.addMetricReader(cumulativeReader); return { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/Meter.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/Meter.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/Meter.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/Meter.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/MeterProvider.test.ts similarity index 99% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/MeterProvider.test.ts index 3d7dc68c6a9..e8c42bf798b 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/MeterProvider.test.ts @@ -15,7 +15,6 @@ */ import * as assert from 'assert'; -import { NOOP_METER } from '@opentelemetry/api-metrics'; import { Meter, MeterProvider, InstrumentType, DataPointType } from '../src'; import { assertScopeMetrics, @@ -62,7 +61,8 @@ describe('MeterProvider', () => { const meterProvider = new MeterProvider(); meterProvider.shutdown(); const meter = meterProvider.getMeter('meter1', '1.0.0'); - assert.strictEqual(meter, NOOP_METER); + // returned tracer should be no-op, not instance of Meter (from SDK) + assert.ok(!(meter instanceof Meter)); }); it('get meter with same identity', async () => { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/ObservableResult.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/ObservableResult.test.ts similarity index 96% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/ObservableResult.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/ObservableResult.test.ts index f6a38ce4431..aaa97768b89 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/ObservableResult.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/ObservableResult.test.ts @@ -16,9 +16,12 @@ import { ValueType } from '@opentelemetry/api-metrics'; import * as assert from 'assert'; -import { BatchObservableResultImpl, InstrumentType } from '../src'; +import { InstrumentType } from '../src'; import { ObservableInstrument } from '../src/Instruments'; -import { ObservableResultImpl } from '../src/ObservableResult'; +import { + BatchObservableResultImpl, + ObservableResultImpl +} from '../src/ObservableResult'; import { ObservableRegistry } from '../src/state/ObservableRegistry'; import { commonAttributes, commonValues, defaultInstrumentDescriptor } from './util'; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Drop.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/aggregator/Drop.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Drop.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/aggregator/Drop.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Histogram.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/aggregator/Histogram.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Histogram.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/aggregator/Histogram.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/LastValue.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/aggregator/LastValue.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/LastValue.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/aggregator/LastValue.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Sum.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/aggregator/Sum.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Sum.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/aggregator/Sum.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/ConsoleMetricExporter.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/export/ConsoleMetricExporter.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/export/ConsoleMetricExporter.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/export/ConsoleMetricExporter.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/InMemoryMetricExporter.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/export/InMemoryMetricExporter.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/export/InMemoryMetricExporter.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/export/InMemoryMetricExporter.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics/test/export/MetricReader.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/export/MetricReader.test.ts new file mode 100644 index 00000000000..27a54d867ac --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics/test/export/MetricReader.test.ts @@ -0,0 +1,83 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as assert from 'assert'; +import * as sinon from 'sinon'; +import { MeterProvider } from '../../src/MeterProvider'; +import { assertRejects } from '../test-utils'; +import { emptyResourceMetrics, TestMetricProducer } from './TestMetricProducer'; +import { TestMetricReader } from './TestMetricReader'; + +describe('MetricReader', () => { + describe('setMetricProducer', () => { + it('The SDK MUST NOT allow a MetricReader instance to be registered on more than one MeterProvider instance', () => { + const reader = new TestMetricReader(); + const meterProvider1 = new MeterProvider(); + const meterProvider2 = new MeterProvider(); + + meterProvider1.addMetricReader(reader); + assert.throws(() => meterProvider1.addMetricReader(reader), /MetricReader can not be bound to a MeterProvider again/); + assert.throws(() => meterProvider2.addMetricReader(reader), /MetricReader can not be bound to a MeterProvider again/); + }); + }); + + describe('setMetricProducer', () => { + it('should initialize the metric reader', async () => { + const reader = new TestMetricReader(); + + reader.setMetricProducer(new TestMetricProducer()); + const result = await reader.collect(); + + assert.deepStrictEqual(result, { + resourceMetrics: emptyResourceMetrics, + errors: [], + }); + await reader.shutdown(); + }); + }); + + describe('collect', () => { + it('should throw on non-initialized instance', async () => { + const reader = new TestMetricReader(); + + await assertRejects(() => reader.collect(), /MetricReader is not bound to a MetricProducer/); + }); + + it('should return empty on shut-down instance', async () => { + const reader = new TestMetricReader(); + + reader.setMetricProducer(new TestMetricProducer()); + + await reader.shutdown(); + assertRejects(reader.collect(), /MetricReader is shutdown/); + }); + + it('should call MetricProduce.collect with timeout', async () => { + const reader = new TestMetricReader(); + const producer = new TestMetricProducer(); + reader.setMetricProducer(producer); + + const collectStub = sinon.stub(producer, 'collect'); + + await reader.collect({ timeoutMillis: 20 }); + assert(collectStub.calledOnce); + const args = collectStub.args[0]; + assert.deepStrictEqual(args, [{ timeoutMillis: 20 }]); + + await reader.shutdown(); + }); + }); +}); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/export/PeriodicExportingMetricReader.test.ts similarity index 85% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/export/PeriodicExportingMetricReader.test.ts index 21890024bf5..77489f1e233 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/export/PeriodicExportingMetricReader.test.ts @@ -17,14 +17,13 @@ import { PeriodicExportingMetricReader } from '../../src/export/PeriodicExportingMetricReader'; import { AggregationTemporality } from '../../src/export/AggregationTemporality'; import { InstrumentType, PushMetricExporter } from '../../src'; -import { CollectionResult, ResourceMetrics } from '../../src/export/MetricData'; +import { ResourceMetrics } from '../../src/export/MetricData'; import * as assert from 'assert'; import * as sinon from 'sinon'; -import { MetricProducer } from '../../src/export/MetricProducer'; import { TimeoutError } from '../../src/utils'; import { ExportResult, ExportResultCode } from '@opentelemetry/core'; import { assertRejects } from '../test-utils'; -import { defaultResource } from '../util'; +import { emptyResourceMetrics, TestMetricProducer } from './TestMetricProducer'; const MAX_32_BIT_INT = 2 ** 31 - 1; @@ -88,17 +87,6 @@ class TestDeltaMetricExporter extends TestMetricExporter { } } -const emptyResourceMetrics = { resource: defaultResource, scopeMetrics: [] }; - -class TestMetricProducer implements MetricProducer { - async collect(): Promise { - return { - resourceMetrics: { resource: defaultResource, scopeMetrics: [] }, - errors: [], - }; - } -} - describe('PeriodicExportingMetricReader', () => { afterEach(() => { sinon.restore(); @@ -364,53 +352,5 @@ describe('PeriodicExportingMetricReader', () => { await assertRejects(() => reader.shutdown(), /Error during forceFlush/); }); - }) - ; - - describe('collect', () => { - it('should throw on non-initialized instance', async () => { - const exporter = new TestMetricExporter(); - const reader = new PeriodicExportingMetricReader({ - exporter: exporter, - exportIntervalMillis: MAX_32_BIT_INT, - exportTimeoutMillis: 80, - }); - - await assertRejects(() => reader.collect(), /MetricReader is not bound to a MetricProducer/); - }); - - it('should return empty on shut-down instance', async () => { - const exporter = new TestMetricExporter(); - const reader = new PeriodicExportingMetricReader({ - exporter: exporter, - exportIntervalMillis: MAX_32_BIT_INT, - exportTimeoutMillis: 80, - }); - - reader.setMetricProducer(new TestMetricProducer()); - - await reader.shutdown(); - assertRejects(reader.collect(), /MetricReader is shutdown/); - }); - - it('should call MetricProduce.collect with timeout', async () => { - const exporter = new TestMetricExporter(); - const reader = new PeriodicExportingMetricReader({ - exporter: exporter, - exportIntervalMillis: MAX_32_BIT_INT, - exportTimeoutMillis: 80, - }); - const producer = new TestMetricProducer(); - reader.setMetricProducer(producer); - - const collectStub = sinon.stub(producer, 'collect'); - - await reader.collect({ timeoutMillis: 20 }); - assert(collectStub.calledOnce); - const args = collectStub.args[0]; - assert.deepStrictEqual(args, [{ timeoutMillis: 20 }]); - - await reader.shutdown(); - }); }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricExporter.ts b/experimental/packages/opentelemetry-sdk-metrics/test/export/TestMetricExporter.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricExporter.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/export/TestMetricExporter.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics/test/export/TestMetricProducer.ts b/experimental/packages/opentelemetry-sdk-metrics/test/export/TestMetricProducer.ts new file mode 100644 index 00000000000..cb1247ed00d --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics/test/export/TestMetricProducer.ts @@ -0,0 +1,30 @@ +/* + * 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 { CollectionResult } from '../../src/export/MetricData'; +import { MetricProducer } from '../../src/export/MetricProducer'; +import { defaultResource } from '../util'; + +export const emptyResourceMetrics = { resource: defaultResource, scopeMetrics: [] }; + +export class TestMetricProducer implements MetricProducer { + async collect(): Promise { + return { + resourceMetrics: { resource: defaultResource, scopeMetrics: [] }, + errors: [], + }; + } +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics/test/export/TestMetricReader.ts similarity index 62% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/export/TestMetricReader.ts index 4b02562c943..e708e1d2e00 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/export/TestMetricReader.ts @@ -15,6 +15,8 @@ */ import { + Aggregation, + AggregationSelector, AggregationTemporality, AggregationTemporalitySelector, InstrumentType, @@ -22,15 +24,22 @@ import { } from '../../src'; import { MetricCollector } from '../../src/state/MetricCollector'; +export interface TestMetricReaderOptions { + aggregationTemporalitySelector?: AggregationTemporalitySelector; + aggregationSelector?: AggregationSelector; +} + /** * A test metric reader that implements no-op onForceFlush() and onShutdown() handlers. */ export class TestMetricReader extends MetricReader { private _aggregationTemporalitySelector: AggregationTemporalitySelector; + private _aggregationSelector: AggregationSelector; - constructor(aggregationTemporalitySelector?: AggregationTemporalitySelector) { + constructor(options?: TestMetricReaderOptions) { super(); - this._aggregationTemporalitySelector = aggregationTemporalitySelector ?? (() => AggregationTemporality.CUMULATIVE); + this._aggregationTemporalitySelector = options?.aggregationTemporalitySelector ?? (() => AggregationTemporality.CUMULATIVE); + this._aggregationSelector = options?.aggregationSelector ?? Aggregation.Default; } protected onForceFlush(): Promise { @@ -45,7 +54,20 @@ export class TestMetricReader extends MetricReader { return this._aggregationTemporalitySelector(instrumentType); } + selectAggregation(instrumentType: InstrumentType) { + return this._aggregationSelector(instrumentType); + } + getMetricCollector(): MetricCollector { return this['_metricProducer'] as MetricCollector; } } + +export class TestDeltaMetricReader extends TestMetricReader { + constructor(options: TestMetricReaderOptions = {}) { + super({ + ...options, + aggregationTemporalitySelector: () => AggregationTemporality.DELTA, + }); + } +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/index-webpack.ts b/experimental/packages/opentelemetry-sdk-metrics/test/index-webpack.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/index-webpack.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/index-webpack.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/AsyncMetricStorage.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/AsyncMetricStorage.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/DeltaMetricProcessor.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/DeltaMetricProcessor.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/DeltaMetricProcessor.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/DeltaMetricProcessor.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/HashMap.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/HashMap.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/HashMap.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/HashMap.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/MeterSharedState.test.ts similarity index 60% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/MeterSharedState.test.ts index bacbe87e3f5..dc7651f83aa 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MeterSharedState.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/state/MeterSharedState.test.ts @@ -17,31 +17,140 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; import { - AggregationTemporality, Meter, MeterProvider, DataPointType, - CollectionResult, - View + View, + Aggregation, + MetricReader, + InstrumentType } from '../../src'; import { assertMetricData, defaultInstrumentationScope, defaultResource, sleep } from '../util'; -import { TestMetricReader } from '../export/TestMetricReader'; +import { TestDeltaMetricReader, TestMetricReader } from '../export/TestMetricReader'; import { MeterSharedState } from '../../src/state/MeterSharedState'; +import { CollectionResult } from '../../src/export/MetricData'; describe('MeterSharedState', () => { afterEach(() => { sinon.restore(); }); + describe('registerMetricStorage', () => { + function setupMeter(views?: View[], readers?: MetricReader[]) { + const meterProvider = new MeterProvider({ + resource: defaultResource, + views, + }); + readers?.forEach(reader => meterProvider.addMetricReader(reader)); + + const meter = meterProvider.getMeter('test-meter'); + + return { + meter, + meterSharedState: meterProvider['_sharedState'].getMeterSharedState({ name: 'test-meter' }), + collectors: Array.from(meterProvider['_sharedState'].metricCollectors), + }; + } + + it('should register metric storages with views', () => { + const reader = new TestMetricReader({ + aggregationSelector: () => { + throw new Error('should not be called'); + }, + }); + const { meter, meterSharedState, collectors } = setupMeter( + [ new View({ instrumentName: 'test-counter' }) ], + [reader], + ); + + meter.createCounter('test-counter'); + const metricStorages = meterSharedState.metricStorageRegistry.getStorages(collectors[0]); + + assert.strictEqual(metricStorages.length, 1); + assert.strictEqual(metricStorages[0].getInstrumentDescriptor().name, 'test-counter'); + }); + + it('should register metric storages with views', () => { + const reader = new TestMetricReader({ + aggregationSelector: () => { + throw new Error('should not be called'); + }, + }); + const { meter, meterSharedState, collectors } = setupMeter( + [ new View({ instrumentName: 'test-counter' }) ], + [reader], + ); + + meter.createCounter('test-counter'); + const metricStorages = meterSharedState.metricStorageRegistry.getStorages(collectors[0]); + + assert.strictEqual(metricStorages.length, 1); + assert.strictEqual(metricStorages[0].getInstrumentDescriptor().name, 'test-counter'); + }); + + it('should register metric storages with the collector', () => { + const reader = new TestMetricReader({ + aggregationSelector: (instrumentType: InstrumentType) => { + return Aggregation.Drop(); + }, + }); + const readerAggregationSelectorSpy = sinon.spy(reader, 'selectAggregation'); + + const { meter, meterSharedState, collectors } = setupMeter( + [], /** no views registered */ + [reader], + ); + + meter.createCounter('test-counter'); + const metricStorages = meterSharedState.metricStorageRegistry.getStorages(collectors[0]); + + // Should select aggregation with the metric reader. + assert.strictEqual(readerAggregationSelectorSpy.callCount, 1); + assert.strictEqual(metricStorages.length, 1); + assert.strictEqual(metricStorages[0].getInstrumentDescriptor().name, 'test-counter'); + }); + + it('should register metric storages with collectors', () => { + const reader = new TestMetricReader({ + aggregationSelector: (instrumentType: InstrumentType) => { + return Aggregation.Drop(); + }, + }); + const reader2 = new TestMetricReader({ + aggregationSelector: (instrumentType: InstrumentType) => { + return Aggregation.LastValue(); + }, + }); + + const { meter, meterSharedState, collectors } = setupMeter( + [], /** no views registered */ + [reader, reader2], + ); + + meter.createCounter('test-counter'); + const metricStorages = meterSharedState.metricStorageRegistry.getStorages(collectors[0]); + const metricStorages2 = meterSharedState.metricStorageRegistry.getStorages(collectors[1]); + + // Should select aggregation with the metric reader. + assert.strictEqual(metricStorages.length, 1); + assert.strictEqual(metricStorages[0].getInstrumentDescriptor().name, 'test-counter'); + + assert.strictEqual(metricStorages2.length, 1); + assert.strictEqual(metricStorages2[0].getInstrumentDescriptor().name, 'test-counter'); + + assert.notStrictEqual(metricStorages[0], metricStorages2[0], 'should create a distinct metric storage for each metric reader'); + }); + }); + describe('collect', () => { function setupInstruments(views?: View[]) { const meterProvider = new MeterProvider({ resource: defaultResource, views: views }); - const cumulativeReader = new TestMetricReader(() => AggregationTemporality.CUMULATIVE); + const cumulativeReader = new TestMetricReader(); meterProvider.addMetricReader(cumulativeReader); const cumulativeCollector = cumulativeReader.getMetricCollector(); - const deltaReader = new TestMetricReader(() => AggregationTemporality.DELTA); + const deltaReader = new TestDeltaMetricReader(); meterProvider.addMetricReader(deltaReader); const deltaCollector = deltaReader.getMetricCollector(); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/MetricCollector.test.ts similarity index 91% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/MetricCollector.test.ts index 77047d9f52b..6f316a11edb 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/state/MetricCollector.test.ts @@ -16,9 +16,9 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { MeterProvider, TimeoutError } from '../../src'; +import { MeterProvider } from '../../src'; +import { TimeoutError } from '../../src/utils'; import { DataPointType } from '../../src/export/MetricData'; -import { PushMetricExporter } from '../../src/export/MetricExporter'; import { MeterProviderSharedState } from '../../src/state/MeterProviderSharedState'; import { MetricCollector } from '../../src/state/MetricCollector'; import { @@ -29,8 +29,7 @@ import { ObservableCallbackDelegate, BatchObservableCallbackDelegate, } from '../util'; -import { TestMetricReader } from '../export/TestMetricReader'; -import { TestDeltaMetricExporter, TestMetricExporter } from '../export/TestMetricExporter'; +import { TestDeltaMetricReader, TestMetricReader } from '../export/TestMetricReader'; describe('MetricCollector', () => { afterEach(() => { @@ -40,20 +39,18 @@ describe('MetricCollector', () => { describe('constructor', () => { it('should construct MetricCollector without exceptions', () => { const meterProviderSharedState = new MeterProviderSharedState(defaultResource); - const exporters = [ new TestMetricExporter(), new TestDeltaMetricExporter() ]; - for (const exporter of exporters) { - const reader = new TestMetricReader(exporter.selectAggregationTemporality); + const readers = [ new TestMetricReader(), new TestDeltaMetricReader() ]; + for (const reader of readers) { assert.doesNotThrow(() => new MetricCollector(meterProviderSharedState, reader)); } }); }); describe('collect', () => { - - function setupInstruments(exporter: PushMetricExporter) { + function setupInstruments() { const meterProvider = new MeterProvider({ resource: defaultResource }); - const reader = new TestMetricReader(exporter.selectAggregationTemporality); + const reader = new TestMetricReader(); meterProvider.addMetricReader(reader); const metricCollector = reader.getMetricCollector(); @@ -66,8 +63,7 @@ describe('MetricCollector', () => { it('should collect sync metrics', async () => { /** preparing test instrumentations */ - const exporter = new TestMetricExporter(); - const { metricCollector, meter } = setupInstruments(exporter); + const { metricCollector, meter } = setupInstruments(); /** creating metric events */ const counter = meter.createCounter('counter1'); @@ -104,8 +100,7 @@ describe('MetricCollector', () => { it('should collect async metrics', async () => { /** preparing test instrumentations */ - const exporter = new TestMetricExporter(); - const { metricCollector, meter } = setupInstruments(exporter); + const { metricCollector, meter } = setupInstruments(); /** creating metric events */ /** observable */ @@ -163,8 +158,7 @@ describe('MetricCollector', () => { it('should collect observer metrics with timeout', async () => { sinon.useFakeTimers(); /** preparing test instrumentations */ - const exporter = new TestMetricExporter(); - const { metricCollector, meter } = setupInstruments(exporter); + const { metricCollector, meter } = setupInstruments(); /** creating metric events */ @@ -246,8 +240,7 @@ describe('MetricCollector', () => { it('should collect with throwing observable callbacks', async () => { /** preparing test instrumentations */ - const exporter = new TestMetricExporter(); - const { metricCollector, meter } = setupInstruments(exporter); + const { metricCollector, meter } = setupInstruments(); /** creating metric events */ const counter = meter.createCounter('counter1'); @@ -283,8 +276,7 @@ describe('MetricCollector', () => { it('should collect batch observer metrics with timeout', async () => { sinon.useFakeTimers(); /** preparing test instrumentations */ - const exporter = new TestMetricExporter(); - const { metricCollector, meter } = setupInstruments(exporter); + const { metricCollector, meter } = setupInstruments(); /** creating metric events */ @@ -366,8 +358,7 @@ describe('MetricCollector', () => { it('should collect with throwing batch observable callbacks', async () => { /** preparing test instrumentations */ - const exporter = new TestMetricExporter(); - const { metricCollector, meter } = setupInstruments(exporter); + const { metricCollector, meter } = setupInstruments(); /** creating metric events */ const counter = meter.createCounter('counter1'); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricStorageRegistry.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/MetricStorageRegistry.test.ts similarity index 58% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricStorageRegistry.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/MetricStorageRegistry.test.ts index e3defd2c924..fa8424b992b 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricStorageRegistry.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/state/MetricStorageRegistry.test.ts @@ -31,7 +31,8 @@ import { } from '../../src/view/RegistrationConflicts'; class TestMetricStorage extends MetricStorage { - collect(collector: MetricCollectorHandle, + collect( + collector: MetricCollectorHandle, collectors: MetricCollectorHandle[], collectionTime: HrTime, ): Maybe { @@ -50,8 +51,19 @@ describe('MetricStorageRegistry', () => { sinon.restore(); }); + const collectorHandle: MetricCollectorHandle = { + selectAggregationTemporality: () => { + throw new Error('should not be invoked'); + }, + }; + const collectorHandle2: MetricCollectorHandle = { + selectAggregationTemporality: () => { + throw new Error('should not be invoked'); + }, + }; + describe('register', () => { - it('should register MetricStorage if it does not exist', () => { + it('should register MetricStorage', () => { const registry = new MetricStorageRegistry(); const storage = new TestMetricStorage({ name: 'instrument', @@ -61,34 +73,65 @@ describe('MetricStorageRegistry', () => { valueType: ValueType.DOUBLE }); - const registeredStorage = registry.register(storage); - const registeredStorages = registry.getStorages(); + registry.register(storage); + const registeredStorages = registry.getStorages(collectorHandle); - // returned the same storage - assert.strictEqual(registeredStorage, storage); - // registered the actual storage + // registered the storage. assert.deepStrictEqual([storage], registeredStorages); - // no warning logs written - assert.strictEqual(spyLoggerWarn.args.length, 0); }); + }); - function testConflictingRegistration(existingDescriptor: InstrumentDescriptor, + describe('registerForCollector', () => { + it('should register MetricStorage for each collector', () => { + const registry = new MetricStorageRegistry(); + const storage = new TestMetricStorage({ + name: 'instrument', + type: InstrumentType.COUNTER, + description: 'description', + unit: '1', + valueType: ValueType.DOUBLE + }); + const storage2 = new TestMetricStorage({ + name: 'instrument2', + type: InstrumentType.COUNTER, + description: 'description', + unit: '1', + valueType: ValueType.DOUBLE + }); + + registry.registerForCollector(collectorHandle, storage); + registry.registerForCollector(collectorHandle2, storage); + registry.registerForCollector(collectorHandle2, storage2); + + assert.deepStrictEqual(registry.getStorages(collectorHandle), [storage]); + assert.deepStrictEqual(registry.getStorages(collectorHandle2), [storage, storage2]); + }); + }); + + describe('findOrUpdateCompatibleStorage', () => { + function testConflictingRegistration( + existingDescriptor: InstrumentDescriptor, otherDescriptor: InstrumentDescriptor, - expectedLog: string) { + expectedLog: string + ) { const registry = new MetricStorageRegistry(); const storage = new TestMetricStorage(existingDescriptor); const otherStorage = new TestMetricStorage(otherDescriptor); - assert.strictEqual(registry.register(storage), storage); - assert.strictEqual(registry.register(otherStorage), otherStorage); - const registeredStorages = registry.getStorages(); + assert.strictEqual(registry.findOrUpdateCompatibleStorage(existingDescriptor), null); + registry.register(storage); + assertLogNotCalled(); - // registered both storages - assert.deepStrictEqual([storage, otherStorage], registeredStorages); + assert.strictEqual(registry.findOrUpdateCompatibleStorage(otherDescriptor), null); // warned assertLogCalledOnce(); assertFirstLogContains(expectedLog); + registry.register(otherStorage); + + // registered both storages + const registeredStorages = registry.getStorages(collectorHandle); + assert.deepStrictEqual([storage, otherStorage], registeredStorages); } it('warn when instrument with same name and different type is already registered', () => { @@ -179,17 +222,14 @@ describe('MetricStorageRegistry', () => { const storage = new TestMetricStorage(existingDescriptor); const otherStorage = new TestMetricStorage(otherDescriptor); - // returns the first registered storage. - assert.strictEqual(registry.register(storage), storage); - // returns the original storage - assert.strictEqual(registry.register(otherStorage), storage); + // register the first storage. + assert.strictEqual(registry.findOrUpdateCompatibleStorage(existingDescriptor), null); + registry.register(storage); + // register the second storage. + assert.strictEqual(registry.findOrUpdateCompatibleStorage(otherDescriptor), storage); // original storage now has the updated (longer) description. assert.strictEqual(otherStorage.getInstrumentDescriptor().description, otherDescriptor.description); - const registeredStorages = registry.getStorages(); - - // only the original storage has been added - assert.deepStrictEqual([storage], registeredStorages); // log called exactly once assertLogCalledOnce(); // added resolution recipe to the log @@ -207,14 +247,9 @@ describe('MetricStorageRegistry', () => { }; const storage = new TestMetricStorage(descriptor); - const otherStorage = new TestMetricStorage(descriptor); - assert.strictEqual(registry.register(storage), storage); - assert.strictEqual(registry.register(otherStorage), storage); - const registeredStorages = registry.getStorages(); - - // registered the actual storage, but not more than that. - assert.deepStrictEqual([storage], registeredStorages); + registry.register(storage); + assert.strictEqual(registry.findOrUpdateCompatibleStorage(descriptor), storage); }); it('should return the existing instrument if a compatible sync instrument is already registered', () => { @@ -228,18 +263,15 @@ describe('MetricStorageRegistry', () => { }; const storage = new TestMetricStorage(descriptor); - const otherStorage = new TestMetricStorage(descriptor); registry.register(storage); - const previouslyRegisteredStorage = registry.register(otherStorage); - const registeredStorages = registry.getStorages(); - - // returned undefined - assert.strictEqual(previouslyRegisteredStorage, storage); - // registered the actual storage, but not more than that. - assert.deepStrictEqual([storage], registeredStorages); + assert.strictEqual(registry.findOrUpdateCompatibleStorage(descriptor), storage); }); + function assertLogNotCalled() { + assert.strictEqual(spyLoggerWarn.args.length, 0); + } + function assertLogCalledOnce() { assert.strictEqual(spyLoggerWarn.args.length, 1); } @@ -248,4 +280,63 @@ describe('MetricStorageRegistry', () => { assert.ok(spyLoggerWarn.args[0].includes(expectedString), 'Logs did not include: ' + expectedString); } }); + + describe('findOrUpdateCompatibleCollectorStorage', () => { + it('register conflicting metric storages for collector', () => { + const existingDescriptor = { + name: 'instrument', + type: InstrumentType.COUNTER, + description: 'description', + unit: '1', + valueType: ValueType.DOUBLE + }; + + const otherDescriptor = { + name: 'instrument', + type: InstrumentType.UP_DOWN_COUNTER, + description: 'description', + unit: '1', + valueType: ValueType.DOUBLE + }; + + const registry = new MetricStorageRegistry(); + + const storage = new TestMetricStorage(existingDescriptor); + const otherStorage = new TestMetricStorage(otherDescriptor); + + assert.strictEqual(registry.findOrUpdateCompatibleCollectorStorage(collectorHandle, existingDescriptor), null); + registry.registerForCollector(collectorHandle, storage); + + // Should not return an existing metric storage. + assert.strictEqual(registry.findOrUpdateCompatibleCollectorStorage(collectorHandle, otherDescriptor), null); + registry.registerForCollector(collectorHandle, otherStorage); + + // registered both storages + const registeredStorages = registry.getStorages(collectorHandle); + assert.deepStrictEqual([storage, otherStorage], registeredStorages); + }); + + it('register the same metric storage for each collector', () => { + const descriptor = { + name: 'instrument', + type: InstrumentType.COUNTER, + description: 'description', + unit: '1', + valueType: ValueType.DOUBLE + }; + const registry = new MetricStorageRegistry(); + + const storage = new TestMetricStorage(descriptor); + + assert.strictEqual(registry.findOrUpdateCompatibleCollectorStorage(collectorHandle, descriptor), null); + registry.registerForCollector(collectorHandle, storage); + + assert.strictEqual(registry.findOrUpdateCompatibleCollectorStorage(collectorHandle2, descriptor), null); + registry.registerForCollector(collectorHandle2, storage); + + // registered the storage for each collector + assert.deepStrictEqual(registry.getStorages(collectorHandle), [storage]); + assert.deepStrictEqual(registry.getStorages(collectorHandle2), [storage]); + }); + }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MultiWritableMetricStorage.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/MultiWritableMetricStorage.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/MultiWritableMetricStorage.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/MultiWritableMetricStorage.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/ObservableRegistry.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/ObservableRegistry.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/ObservableRegistry.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/ObservableRegistry.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/SyncMetricStorage.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/SyncMetricStorage.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/SyncMetricStorage.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/SyncMetricStorage.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/TemporalMetricProcessor.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/state/TemporalMetricProcessor.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/state/TemporalMetricProcessor.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/state/TemporalMetricProcessor.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/test-utils.ts b/experimental/packages/opentelemetry-sdk-metrics/test/test-utils.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/test-utils.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/test-utils.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts b/experimental/packages/opentelemetry-sdk-metrics/test/util.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/util.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/utils.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/utils.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/utils.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/utils.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/view/Aggregation.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/view/Aggregation.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/view/Aggregation.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/view/Aggregation.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/view/AttributesProcessor.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/view/AttributesProcessor.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/view/AttributesProcessor.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/view/AttributesProcessor.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/view/Predicate.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/view/Predicate.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/view/Predicate.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/view/Predicate.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/view/View.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/view/View.test.ts similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/view/View.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/view/View.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/view/ViewRegistry.test.ts b/experimental/packages/opentelemetry-sdk-metrics/test/view/ViewRegistry.test.ts similarity index 92% rename from experimental/packages/opentelemetry-sdk-metrics-base/test/view/ViewRegistry.test.ts rename to experimental/packages/opentelemetry-sdk-metrics/test/view/ViewRegistry.test.ts index a56d7b65e06..68f9f270723 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/view/ViewRegistry.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics/test/view/ViewRegistry.test.ts @@ -23,13 +23,6 @@ import { View } from '../../src'; describe('ViewRegistry', () => { describe('findViews', () => { - it('should return default view if no view registered', () => { - const registry = new ViewRegistry(); - const views = registry.findViews(defaultInstrumentDescriptor, defaultInstrumentationScope); - assert.strictEqual(views.length, 1); - assert.strictEqual(views[0], ViewRegistry['DEFAULT_VIEW']); - }); - describe('InstrumentSelector', () => { it('should match view with instrument name', () => { const registry = new ViewRegistry(); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/tsconfig.all.json b/experimental/packages/opentelemetry-sdk-metrics/tsconfig.all.json similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/tsconfig.all.json rename to experimental/packages/opentelemetry-sdk-metrics/tsconfig.all.json diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/tsconfig.esm.json b/experimental/packages/opentelemetry-sdk-metrics/tsconfig.esm.json similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/tsconfig.esm.json rename to experimental/packages/opentelemetry-sdk-metrics/tsconfig.esm.json diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/tsconfig.esnext.json b/experimental/packages/opentelemetry-sdk-metrics/tsconfig.esnext.json similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/tsconfig.esnext.json rename to experimental/packages/opentelemetry-sdk-metrics/tsconfig.esnext.json diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/tsconfig.json b/experimental/packages/opentelemetry-sdk-metrics/tsconfig.json similarity index 100% rename from experimental/packages/opentelemetry-sdk-metrics-base/tsconfig.json rename to experimental/packages/opentelemetry-sdk-metrics/tsconfig.json diff --git a/experimental/packages/opentelemetry-sdk-node/README.md b/experimental/packages/opentelemetry-sdk-node/README.md index a21de3c7411..008e8f5eee2 100644 --- a/experimental/packages/opentelemetry-sdk-node/README.md +++ b/experimental/packages/opentelemetry-sdk-node/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This package provides the full OpenTelemetry SDK for Node.js including tracing and metrics. ## Quick Start @@ -114,9 +116,14 @@ or configure each instrumentation individually. Configure a resource. Resources may also be detected by using the `autoDetectResources` method of the SDK. +### resourceDetectors + +Configure resource detectors. By default, the resource detectors are [envDetector, processDetector]. +NOTE: In order to enable the detection, the parameter `autoDetectResources` has to be `true`. + ### sampler -Configure a custom sampler. By default all traces will be sampled. +Configure a custom sampler. By default, all traces will be sampled. ### spanProcessor @@ -128,6 +135,10 @@ Configure a trace exporter. If an exporter OR span processor is not configured, Configure tracing parameters. These are the same trace parameters used to [configure a tracer](../../../packages/opentelemetry-sdk-trace-base/src/types.ts#L71). +### views + +Configure views of your instruments and accepts an array of [View](../opentelemetry-sdk-metrics-base/src/view/View.ts)-instances. The parameter can be used to configure the explicit bucket sizes of histogram metrics. + ### serviceName Configure the [service name](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service). diff --git a/experimental/packages/opentelemetry-sdk-node/package.json b/experimental/packages/opentelemetry-sdk-node/package.json index 316a8cd09e8..584183a5ddd 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry SDK for Node.js", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -44,21 +44,21 @@ "access": "public" }, "dependencies": { - "@opentelemetry/api-metrics": "0.31.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/instrumentation": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-metrics-base": "0.31.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/sdk-trace-node": "1.5.0" + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/instrumentation": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-metrics": "0.32.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/sdk-trace-node": "1.6.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", - "@opentelemetry/context-async-hooks": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", + "@opentelemetry/context-async-hooks": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/semver": "7.3.9", diff --git a/experimental/packages/opentelemetry-sdk-node/src/index.ts b/experimental/packages/opentelemetry-sdk-node/src/index.ts index 4d1783c45ed..d2461742083 100644 --- a/experimental/packages/opentelemetry-sdk-node/src/index.ts +++ b/experimental/packages/opentelemetry-sdk-node/src/index.ts @@ -17,7 +17,7 @@ export * as api from '@opentelemetry/api'; export * as contextBase from '@opentelemetry/api'; export * as core from '@opentelemetry/core'; -export * as metrics from '@opentelemetry/sdk-metrics-base'; +export * as metrics from '@opentelemetry/sdk-metrics'; export * as node from '@opentelemetry/sdk-trace-node'; export * as resources from '@opentelemetry/resources'; export * as tracing from '@opentelemetry/sdk-trace-base'; diff --git a/experimental/packages/opentelemetry-sdk-node/src/sdk.ts b/experimental/packages/opentelemetry-sdk-node/src/sdk.ts index f1f4815829e..11870ebf28e 100644 --- a/experimental/packages/opentelemetry-sdk-node/src/sdk.ts +++ b/experimental/packages/opentelemetry-sdk-node/src/sdk.ts @@ -21,13 +21,14 @@ import { registerInstrumentations } from '@opentelemetry/instrumentation'; import { + Detector, detectResources, envDetector, processDetector, Resource, ResourceDetectionConfig } from '@opentelemetry/resources'; -import { MeterProvider, MetricReader } from '@opentelemetry/sdk-metrics-base'; +import { MeterProvider, MetricReader, View } from '@opentelemetry/sdk-metrics'; import { BatchSpanProcessor, SpanProcessor @@ -37,6 +38,20 @@ import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' import { NodeSDKConfiguration } from './types'; /** This class represents everything needed to register a fully configured OpenTelemetry Node.js SDK */ + +export type MeterProviderConfig = { + /** + * Reference to the MetricReader instance by the NodeSDK + */ + reader?: MetricReader + /** + * Lists the views that should be passed when meterProvider + * + * Note: This is only getting used when NodeSDK is responsible for + * instantiated an instance of MeterProvider + */ + views?: View[] +}; export class NodeSDK { private _tracerProviderConfig?: { tracerConfig: NodeTracerConfig; @@ -44,10 +59,11 @@ export class NodeSDK { contextManager?: ContextManager; textMapPropagator?: TextMapPropagator; }; + private _meterProviderConfig?: MeterProviderConfig; private _instrumentations: InstrumentationOption[]; - private _metricReader?: MetricReader; private _resource: Resource; + private _resourceDetectors: Detector[]; private _autoDetectResources: boolean; @@ -60,6 +76,7 @@ export class NodeSDK { */ public constructor(configuration: Partial = {}) { this._resource = configuration.resource ?? new Resource({}); + this._resourceDetectors = configuration.resourceDetectors ?? [envDetector, processDetector]; this._serviceName = configuration.serviceName; @@ -87,8 +104,17 @@ export class NodeSDK { ); } - if (configuration.metricReader) { - this.configureMeterProvider(configuration.metricReader); + if (configuration.metricReader || configuration.views) { + const meterProviderConfig: MeterProviderConfig = {}; + if (configuration.metricReader) { + meterProviderConfig.reader = configuration.metricReader; + } + + if (configuration.views) { + meterProviderConfig.views = configuration.views; + } + + this.configureMeterProvider(meterProviderConfig); } let instrumentations: InstrumentationOption[] = []; @@ -114,17 +140,38 @@ export class NodeSDK { } /** Set configurations needed to register a MeterProvider */ - public configureMeterProvider(reader: MetricReader): void { - this._metricReader = reader; + 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; + } } /** Detect resource attributes */ - public async detectResources( - config?: ResourceDetectionConfig - ): Promise { + public async detectResources(): Promise { const internalConfig: ResourceDetectionConfig = { - detectors: [ envDetector, processDetector], - ...config, + detectors: this._resourceDetectors, }; this.addResource(await detectResources(internalConfig)); @@ -146,7 +193,7 @@ export class NodeSDK { this._resource = this._serviceName === undefined ? this._resource : this._resource.merge(new Resource( - {[SemanticResourceAttributes.SERVICE_NAME]: this._serviceName} + { [SemanticResourceAttributes.SERVICE_NAME]: this._serviceName } )); if (this._tracerProviderConfig) { @@ -164,12 +211,15 @@ export class NodeSDK { }); } - if (this._metricReader) { + if (this._meterProviderConfig) { const meterProvider = new MeterProvider({ resource: this._resource, + views: this._meterProviderConfig?.views ?? [], }); - meterProvider.addMetricReader(this._metricReader); + if (this._meterProviderConfig.reader) { + meterProvider.addMetricReader(this._meterProviderConfig.reader); + } this._meterProvider = meterProvider; diff --git a/experimental/packages/opentelemetry-sdk-node/src/types.ts b/experimental/packages/opentelemetry-sdk-node/src/types.ts index 705481174cc..722201f03f5 100644 --- a/experimental/packages/opentelemetry-sdk-node/src/types.ts +++ b/experimental/packages/opentelemetry-sdk-node/src/types.ts @@ -17,8 +17,8 @@ import type { ContextManager, SpanAttributes } from '@opentelemetry/api'; import { TextMapPropagator } from '@opentelemetry/api'; import { InstrumentationOption } from '@opentelemetry/instrumentation'; -import { Resource } from '@opentelemetry/resources'; -import { MetricReader } from '@opentelemetry/sdk-metrics-base'; +import { Detector, Resource } from '@opentelemetry/resources'; +import { MetricReader, View } from '@opentelemetry/sdk-metrics'; import { Sampler, SpanExporter, @@ -32,8 +32,10 @@ export interface NodeSDKConfiguration { defaultAttributes: SpanAttributes; textMapPropagator: TextMapPropagator; metricReader: MetricReader; + views: View[] instrumentations: InstrumentationOption[]; resource: Resource; + resourceDetectors: Detector[]; sampler: Sampler; serviceName?: string; spanProcessor: SpanProcessor; diff --git a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts index 217800c9c05..c1b0b90d567 100644 --- a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts +++ b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts @@ -22,13 +22,21 @@ import { diag, DiagLogLevel, } from '@opentelemetry/api'; -import { metrics, NoopMeterProvider } from '@opentelemetry/api-metrics'; +import { metrics } from '@opentelemetry/api-metrics'; import { AsyncHooksContextManager, AsyncLocalStorageContextManager, } from '@opentelemetry/context-async-hooks'; import { CompositePropagator } from '@opentelemetry/core'; -import { ConsoleMetricExporter, MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics-base'; +import { + AggregationTemporality, + ConsoleMetricExporter, + InMemoryMetricExporter, + InstrumentType, + MeterProvider, + PeriodicExportingMetricReader, + View, +} from '@opentelemetry/sdk-metrics'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import { assertServiceResource, @@ -41,7 +49,11 @@ import * as assert from 'assert'; import * as semver from 'semver'; import * as Sinon from 'sinon'; import { NodeSDK } from '../src'; -import { envDetector, processDetector } from '@opentelemetry/resources'; +import { + envDetector, + processDetector, + Resource +} from '@opentelemetry/resources'; const DefaultContextManager = semver.gte(process.version, '14.8.0') @@ -76,7 +88,7 @@ describe('Node SDK', () => { assert.strictEqual(propagation['_getGlobalPropagator'](), propagator, 'propagator should not change'); assert.strictEqual((trace.getTracerProvider() as ProxyTracerProvider).getDelegate(), delegate, 'tracer provider should not have changed'); - assert.ok(metrics.getMeterProvider() instanceof NoopMeterProvider); + assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider)); }); it('should register a tracer provider if an exporter is provided', async () => { @@ -87,7 +99,7 @@ describe('Node SDK', () => { await sdk.start(); - assert.ok(metrics.getMeterProvider() instanceof NoopMeterProvider); + assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider)); assert.ok( context['_getContextManager']().constructor.name === DefaultContextManager.name @@ -110,7 +122,7 @@ describe('Node SDK', () => { await sdk.start(); - assert.ok(metrics.getMeterProvider() instanceof NoopMeterProvider); + assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider)); assert.ok( context['_getContextManager']().constructor.name === DefaultContextManager.name @@ -147,6 +159,133 @@ describe('Node SDK', () => { }); }); + async function waitForNumberOfMetrics(exporter: InMemoryMetricExporter, numberOfMetrics: number): Promise { + if (numberOfMetrics <= 0) { + throw new Error('numberOfMetrics must be greater than or equal to 0'); + } + + let totalExports = 0; + while (totalExports < numberOfMetrics) { + await new Promise(resolve => setTimeout(resolve, 20)); + const exportedMetrics = exporter.getMetrics(); + totalExports = exportedMetrics.length; + } + } + + it('should register meter views when provided', async () => { + 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, + }); + + await sdk.start(); + + assert.strictEqual(context['_getContextManager'](), ctxManager, 'context manager should not change'); + assert.strictEqual(propagation['_getGlobalPropagator'](), propagator, 'propagator should not change'); + assert.strictEqual((trace.getTracerProvider() as ProxyTracerProvider).getDelegate(), delegate, 'tracer provider should not have changed'); + + const meterProvider = metrics.getMeterProvider() as MeterProvider; + assert.ok(meterProvider); + + const meter = meterProvider.getMeter('NodeSDKViews', '1.0.0'); + const counter = meter.createCounter('test_counter', { + description: 'a test description', + }); + counter.add(10); + + await waitForNumberOfMetrics(exporter, 1); + const exportedMetrics = exporter.getMetrics(); + const [firstExportedMetric] = exportedMetrics; + assert.ok(firstExportedMetric, 'should have one exported metric'); + const [firstScopeMetric] = firstExportedMetric.scopeMetrics; + assert.ok(firstScopeMetric, 'should have one scope metric'); + assert.ok(firstScopeMetric.scope.name === 'NodeSDKViews', 'scope should match created view'); + assert.ok(firstScopeMetric.metrics.length > 0, 'should have at least one metrics entry'); + const [firstMetricRecord] = firstScopeMetric.metrics; + assert.ok(firstMetricRecord.descriptor.name === 'test-view', 'should have renamed counter metric'); + + await sdk.shutdown(); + }); + + 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.'); + }); + }); + describe('detectResources', async () => { beforeEach(() => { process.env.OTEL_RESOURCE_ATTRIBUTES = @@ -157,19 +296,47 @@ describe('Node SDK', () => { delete process.env.OTEL_RESOURCE_ATTRIBUTES; }); - describe('with a buggy detector', () => { + describe('with a custom resource', () => { it('returns a merged resource', async () => { const sdk = new NodeSDK({ autoDetectResources: true, + resourceDetectors: [processDetector, { + async detect(): Promise { + return new Resource({'customAttr': 'someValue'}); + } + }, + envDetector] }); - await sdk.detectResources({ - detectors: [ processDetector, { + await sdk.detectResources(); + const resource = sdk['_resource']; + + assert.strictEqual( + resource.attributes['customAttr'], + 'someValue' + ); + + assertServiceResource(resource, { + instanceId: '627cc493', + name: 'my-service', + namespace: 'default', + version: '0.0.1', + }); + }); + }); + + describe('with a buggy detector', () => { + it('returns a merged resource', async () => { + const sdk = new NodeSDK({ + autoDetectResources: true, + resourceDetectors: [processDetector, { detect() { throw new Error('Buggy detector'); } }, - envDetector ] + envDetector] }); + + await sdk.detectResources(); const resource = sdk['_resource']; assertServiceResource(resource, { @@ -277,7 +444,7 @@ describe('Node SDK', () => { }); it('should configure service name via OTEL_SERVICE_NAME env var', async () => { - process.env.OTEL_SERVICE_NAME='env-set-name'; + process.env.OTEL_SERVICE_NAME = 'env-set-name'; const sdk = new NodeSDK(); await sdk.start(); @@ -290,7 +457,7 @@ describe('Node SDK', () => { }); it('should favor config set service name over OTEL_SERVICE_NAME env set service name', async () => { - process.env.OTEL_SERVICE_NAME='env-set-name'; + process.env.OTEL_SERVICE_NAME = 'env-set-name'; const sdk = new NodeSDK({ serviceName: 'config-set-name', }); diff --git a/experimental/packages/opentelemetry-sdk-node/tsconfig.json b/experimental/packages/opentelemetry-sdk-node/tsconfig.json index c0fe67144f2..8249dd1ce64 100644 --- a/experimental/packages/opentelemetry-sdk-node/tsconfig.json +++ b/experimental/packages/opentelemetry-sdk-node/tsconfig.json @@ -34,7 +34,7 @@ "path": "../opentelemetry-instrumentation" }, { - "path": "../opentelemetry-sdk-metrics-base" + "path": "../opentelemetry-sdk-metrics" } ] } diff --git a/experimental/packages/otlp-exporter-base/README.md b/experimental/packages/otlp-exporter-base/README.md index cdb8a26cdcb..f44387c4026 100644 --- a/experimental/packages/otlp-exporter-base/README.md +++ b/experimental/packages/otlp-exporter-base/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides a base exporter for web and node to be used with [opentelemetry-collector][opentelemetry-collector-url]. ## Installation diff --git a/experimental/packages/otlp-exporter-base/package.json b/experimental/packages/otlp-exporter-base/package.json index 17f8920fada..3cc6e7e75e8 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.31.0", + "version": "0.32.0", "description": "OpenTelemetry OTLP Exporter base (for internal use only)", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -61,7 +61,7 @@ "access": "public" }, "dependencies": { - "@opentelemetry/core": "1.5.0" + "@opentelemetry/core": "1.6.0" }, "devDependencies": { "@opentelemetry/api": "^1.0.0", diff --git a/experimental/packages/otlp-grpc-exporter-base/README.md b/experimental/packages/otlp-grpc-exporter-base/README.md index c55d7d2e2a0..ec6f495b9a2 100644 --- a/experimental/packages/otlp-grpc-exporter-base/README.md +++ b/experimental/packages/otlp-grpc-exporter-base/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides a gRPC exporter base for Node.js (browsers not supported) to be used with [opentelemetry-collector][opentelemetry-collector-url]. ## Installation diff --git a/experimental/packages/otlp-grpc-exporter-base/package.json b/experimental/packages/otlp-grpc-exporter-base/package.json index da8338b42ad..12ede6c9321 100644 --- a/experimental/packages/otlp-grpc-exporter-base/package.json +++ b/experimental/packages/otlp-grpc-exporter-base/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/otlp-grpc-exporter-base", - "version": "0.31.0", + "version": "0.32.0", "description": "OpenTelemetry OTLP-gRPC Exporter base (for internal use only)", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -51,9 +51,9 @@ "devDependencies": { "@babel/core": "7.16.0", "@opentelemetry/api": "^1.0.0", - "@opentelemetry/otlp-transformer": "0.31.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", + "@opentelemetry/otlp-transformer": "0.32.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -73,8 +73,8 @@ "dependencies": { "@grpc/grpc-js": "^1.5.9", "@grpc/proto-loader": "^0.6.9", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/otlp-exporter-base": "0.31.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/otlp-exporter-base": "0.32.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/otlp-grpc-exporter-base" } diff --git a/experimental/packages/otlp-proto-exporter-base/README.md b/experimental/packages/otlp-proto-exporter-base/README.md index adeffe39f42..ed9f0d679b6 100644 --- a/experimental/packages/otlp-proto-exporter-base/README.md +++ b/experimental/packages/otlp-proto-exporter-base/README.md @@ -3,6 +3,8 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] +**Note: This is an experimental package under active development. New releases may include breaking changes.** + This module provides a OTLP-http/protobuf exporter base for Node.js (browsers not supported) to be used with [opentelemetry-collector][opentelemetry-collector-url]. ## Installation diff --git a/experimental/packages/otlp-proto-exporter-base/package.json b/experimental/packages/otlp-proto-exporter-base/package.json index ca008a0843a..a9ae89dcec3 100644 --- a/experimental/packages/otlp-proto-exporter-base/package.json +++ b/experimental/packages/otlp-proto-exporter-base/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/otlp-proto-exporter-base", - "version": "0.31.0", + "version": "0.32.0", "description": "OpenTelemetry OTLP-HTTP-protobuf Exporter base (for internal use only)", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -52,7 +52,7 @@ "codecov": "3.8.3", "mocha": "10.0.0", "nyc": "15.1.0", - "protobufjs": "^6.9.0", + "protobufjs": "6.11.3", "rimraf": "3.0.2", "sinon": "14.0.0", "ts-loader": "8.4.0", @@ -64,8 +64,8 @@ }, "dependencies": { "@grpc/proto-loader": "^0.6.9", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/otlp-exporter-base": "0.31.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/otlp-exporter-base": "0.32.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/otlp-proto-exporter-base" } diff --git a/experimental/packages/otlp-transformer/README.md b/experimental/packages/otlp-transformer/README.md index fc5c13af9e1..e069aab559e 100644 --- a/experimental/packages/otlp-transformer/README.md +++ b/experimental/packages/otlp-transformer/README.md @@ -3,7 +3,9 @@ [![NPM Published Version][npm-img]][npm-url] [![Apache License][license-image]][license-image] -**NOTE: This package is intended for internal use only.** +**Note: This package is intended for internal use only.** + +**Note: This is an experimental package under active development. New releases may include breaking changes.** This package provides everything needed to serialize [OpenTelemetry SDK][sdk] traces and metrics into the [OpenTelemetry Protocol][otlp] format. diff --git a/experimental/packages/otlp-transformer/package.json b/experimental/packages/otlp-transformer/package.json index f01c07a101a..b15be78d137 100644 --- a/experimental/packages/otlp-transformer/package.json +++ b/experimental/packages/otlp-transformer/package.json @@ -4,7 +4,7 @@ "publishConfig": { "access": "public" }, - "version": "0.31.0", + "version": "0.32.0", "description": "Transform OpenTelemetry SDK data into OTLP", "module": "build/esm/index.js", "esnext": "build/esnext/index.js", @@ -52,10 +52,10 @@ "README.md" ], "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "@types/mocha": "9.1.1", "@types/webpack-env": "1.16.3", "codecov": "3.8.3", @@ -77,11 +77,11 @@ "webpack": "4.46.0" }, "dependencies": { - "@opentelemetry/api-metrics": "0.31.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-metrics-base": "0.31.0", - "@opentelemetry/sdk-trace-base": "1.5.0" + "@opentelemetry/api-metrics": "0.32.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-metrics": "0.32.0", + "@opentelemetry/sdk-trace-base": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/otlp-transformer" } diff --git a/experimental/packages/otlp-transformer/src/metrics/index.ts b/experimental/packages/otlp-transformer/src/metrics/index.ts index 28337c3cd41..26d910b1654 100644 --- a/experimental/packages/otlp-transformer/src/metrics/index.ts +++ b/experimental/packages/otlp-transformer/src/metrics/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { ResourceMetrics } from '@opentelemetry/sdk-metrics-base'; +import type { ResourceMetrics } from '@opentelemetry/sdk-metrics'; import type { IExportMetricsServiceRequest } from './types'; import { toResourceMetrics } from './internal'; diff --git a/experimental/packages/otlp-transformer/src/metrics/internal.ts b/experimental/packages/otlp-transformer/src/metrics/internal.ts index 17946ffc466..bc17b84976a 100644 --- a/experimental/packages/otlp-transformer/src/metrics/internal.ts +++ b/experimental/packages/otlp-transformer/src/metrics/internal.ts @@ -23,7 +23,7 @@ import { MetricData, ResourceMetrics, ScopeMetrics -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import { toAttributes } from '../common/internal'; import { EAggregationTemporality, diff --git a/experimental/packages/otlp-transformer/test/metrics.test.ts b/experimental/packages/otlp-transformer/test/metrics.test.ts index d188d4ea8b4..afb65d264a4 100644 --- a/experimental/packages/otlp-transformer/test/metrics.test.ts +++ b/experimental/packages/otlp-transformer/test/metrics.test.ts @@ -21,7 +21,7 @@ import { InstrumentType, MetricData, ResourceMetrics -} from '@opentelemetry/sdk-metrics-base'; +} from '@opentelemetry/sdk-metrics'; import * as assert from 'assert'; import { createExportMetricsServiceRequest } from '../src/metrics'; import { EAggregationTemporality } from '../src/metrics/types'; diff --git a/experimental/packages/otlp-transformer/tsconfig.json b/experimental/packages/otlp-transformer/tsconfig.json index 89cb53e4dea..a396bcb48fa 100644 --- a/experimental/packages/otlp-transformer/tsconfig.json +++ b/experimental/packages/otlp-transformer/tsconfig.json @@ -22,7 +22,7 @@ "path": "../opentelemetry-api-metrics" }, { - "path": "../opentelemetry-sdk-metrics-base" + "path": "../opentelemetry-sdk-metrics" } ] } diff --git a/integration-tests/propagation-validation-server/package.json b/integration-tests/propagation-validation-server/package.json index 4a49b677577..d937b351afe 100644 --- a/integration-tests/propagation-validation-server/package.json +++ b/integration-tests/propagation-validation-server/package.json @@ -1,6 +1,6 @@ { "name": "propagation-validation-server", - "version": "1.5.0", + "version": "1.6.0", "description": "server for w3c tests", "main": "validation_server.js", "private": true, @@ -12,9 +12,9 @@ }, "dependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/context-async-hooks": "1.5.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", + "@opentelemetry/context-async-hooks": "1.6.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", "axios": "0.24.0", "body-parser": "1.19.0", "express": "4.17.1" diff --git a/package.json b/package.json index b391e6c9fdd..59bc7ae95c9 100644 --- a/package.json +++ b/package.json @@ -50,12 +50,12 @@ "devDependencies": { "@typescript-eslint/eslint-plugin": "5.3.1", "@typescript-eslint/parser": "5.3.1", - "eslint": "7.32.0", + "eslint": "8.22.0", "eslint-plugin-header": "3.1.1", "eslint-plugin-node": "11.1.0", "gh-pages": "4.0.0", - "lerna": "3.22.1", - "lerna-changelog": "1.0.1", + "lerna": "5.4.3", + "lerna-changelog": "2.2.0", "linkinator": "3.0.3", "markdownlint-cli": "0.29.0", "semver": "7.3.5", diff --git a/packages/opentelemetry-context-async-hooks/package.json b/packages/opentelemetry-context-async-hooks/package.json index d72a000888f..cc06b47ca74 100644 --- a/packages/opentelemetry-context-async-hooks/package.json +++ b/packages/opentelemetry-context-async-hooks/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/context-async-hooks", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry AsyncHooks-based Context Manager", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -44,7 +44,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "codecov": "3.8.3", @@ -55,7 +55,7 @@ "typescript": "4.4.4" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-context-async-hooks" } diff --git a/packages/opentelemetry-context-zone-peer-dep/package.json b/packages/opentelemetry-context-zone-peer-dep/package.json index 827b3e869b1..e2fd07fe4b5 100644 --- a/packages/opentelemetry-context-zone-peer-dep/package.json +++ b/packages/opentelemetry-context-zone-peer-dep/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/context-zone-peer-dep", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Context Zone with peer dependency for zone.js", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -54,7 +54,7 @@ }, "devDependencies": { "@babel/core": "7.16.0", - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -81,7 +81,7 @@ "zone.js": "0.11.4" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "zone.js": "^0.10.2 || ^0.11.0" }, "sideEffects": false, diff --git a/packages/opentelemetry-context-zone/package.json b/packages/opentelemetry-context-zone/package.json index bac9ce7f4c4..d9d38cd4e52 100644 --- a/packages/opentelemetry-context-zone/package.json +++ b/packages/opentelemetry-context-zone/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/context-zone", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Context Zone", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -74,7 +74,7 @@ "webpack-merge": "5.8.0" }, "dependencies": { - "@opentelemetry/context-zone-peer-dep": "1.5.0", + "@opentelemetry/context-zone-peer-dep": "1.6.0", "zone.js": "^0.11.0" }, "sideEffects": true, diff --git a/packages/opentelemetry-core/package.json b/packages/opentelemetry-core/package.json index a5cd6192272..a5fab5ea21f 100644 --- a/packages/opentelemetry-core/package.json +++ b/packages/opentelemetry-core/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/core", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Core provides constants and utilities shared by all OpenTelemetry SDK packages.", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -64,7 +64,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -77,7 +77,7 @@ "karma-mocha": "2.0.1", "karma-spec-reporter": "0.0.32", "karma-webpack": "4.0.2", - "lerna": "3.22.1", + "lerna": "5.4.3", "mocha": "10.0.0", "nyc": "15.1.0", "rimraf": "3.0.2", @@ -88,10 +88,10 @@ "webpack": "4.46.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "dependencies": { - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-core" } diff --git a/packages/opentelemetry-core/src/platform/node/hex-to-base64.ts b/packages/opentelemetry-core/src/platform/node/hex-to-base64.ts index 9330aaa91f8..66d4ad0fe9c 100644 --- a/packages/opentelemetry-core/src/platform/node/hex-to-base64.ts +++ b/packages/opentelemetry-core/src/platform/node/hex-to-base64.ts @@ -13,14 +13,40 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +function intValue(charCode: number): number { + // 0-9 + if (charCode >= 48 && charCode <= 57) { + return charCode - 48; + } + + // a-f + if (charCode >= 97 && charCode <= 102) { + return charCode - 87; + } + + // A-F + return charCode - 55; +} + +const buf8 = Buffer.alloc(8); +const buf16 = Buffer.alloc(16); + export function hexToBase64(hexStr: string): string { - const hexStrLen = hexStr.length; - let hexAsciiCharsStr = ''; - for (let i = 0; i < hexStrLen; i += 2) { - const hexPair = hexStr.substring(i, i + 2); - const hexVal = parseInt(hexPair, 16); - hexAsciiCharsStr += String.fromCharCode(hexVal); + let buf; + if (hexStr.length === 16) { + buf = buf8; + } else if (hexStr.length === 32) { + buf = buf16; + } else { + buf = Buffer.alloc(hexStr.length / 2); + } + let offset = 0; + + for (let i = 0; i < hexStr.length; i += 2) { + const hi = intValue(hexStr.charCodeAt(i)); + const lo = intValue(hexStr.charCodeAt(i + 1)); + buf.writeUInt8((hi << 4) | lo, offset++); } - return Buffer.from(hexAsciiCharsStr, 'ascii').toString('base64'); + return buf.toString('base64'); } diff --git a/packages/opentelemetry-core/test/platform/hex-to-base64.test.ts b/packages/opentelemetry-core/test/platform/hex-to-base64.test.ts index 7f78ded3ef9..d73409fc099 100644 --- a/packages/opentelemetry-core/test/platform/hex-to-base64.test.ts +++ b/packages/opentelemetry-core/test/platform/hex-to-base64.test.ts @@ -20,8 +20,12 @@ import { hexToBase64 } from '../../src/platform'; describe('hexToBase64', () => { it('convert hex to base64', () => { const id1 = '7deb739e02e44ef2'; - const id2 = '46cef837b919a16ff26e608c8cf42c80'; + const id2 = '12abc034d567e89ff26e608c8cf42c80'; + const id3 = id2.toUpperCase(); assert.strictEqual(hexToBase64(id1), 'fetzngLkTvI='); - assert.strictEqual(hexToBase64(id2), 'Rs74N7kZoW/ybmCMjPQsgA=='); + assert.strictEqual(hexToBase64(id2), 'EqvANNVn6J/ybmCMjPQsgA=='); + assert.strictEqual(hexToBase64(id3), 'EqvANNVn6J/ybmCMjPQsgA=='); + // Don't use the preallocated path + assert.strictEqual(hexToBase64(id2.repeat(2)), 'EqvANNVn6J/ybmCMjPQsgBKrwDTVZ+if8m5gjIz0LIA='); }); }); diff --git a/packages/opentelemetry-exporter-jaeger/package.json b/packages/opentelemetry-exporter-jaeger/package.json index eb70b8517a6..15064eba8f6 100644 --- a/packages/opentelemetry-exporter-jaeger/package.json +++ b/packages/opentelemetry-exporter-jaeger/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/exporter-jaeger", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Exporter Jaeger allows user to send collected traces to Jaeger", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -45,7 +45,7 @@ }, "devDependencies": { "@opentelemetry/api": "^1.0.0", - "@opentelemetry/resources": "1.5.0", + "@opentelemetry/resources": "1.6.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -62,9 +62,9 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0", "jaeger-client": "^3.15.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-jaeger" diff --git a/packages/opentelemetry-exporter-zipkin/package.json b/packages/opentelemetry-exporter-zipkin/package.json index 845aed0df78..ed04d165b11 100644 --- a/packages/opentelemetry-exporter-zipkin/package.json +++ b/packages/opentelemetry-exporter-zipkin/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/exporter-zipkin", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Zipkin Exporter allows the user to send collected traces to Zipkin.", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -91,10 +91,10 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-zipkin" } diff --git a/packages/opentelemetry-propagator-b3/package.json b/packages/opentelemetry-propagator-b3/package.json index 805637b7d05..6b78e271fe1 100644 --- a/packages/opentelemetry-propagator-b3/package.json +++ b/packages/opentelemetry-propagator-b3/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/propagator-b3", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry B3 propagator provides context propagation for systems that are using the B3 header format", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -51,13 +51,13 @@ "access": "public" }, "dependencies": { - "@opentelemetry/core": "1.5.0" + "@opentelemetry/core": "1.6.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "codecov": "3.8.3", diff --git a/packages/opentelemetry-propagator-jaeger/package.json b/packages/opentelemetry-propagator-jaeger/package.json index a7b2d39f854..54b24fcf694 100644 --- a/packages/opentelemetry-propagator-jaeger/package.json +++ b/packages/opentelemetry-propagator-jaeger/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/propagator-jaeger", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Jaeger propagator provides HTTP header propagation for systems that are using Jaeger HTTP header format.", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -54,7 +54,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -77,10 +77,10 @@ "webpack": "4.46.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0" + "@opentelemetry/core": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-propagator-jaeger" } diff --git a/packages/opentelemetry-resources/package.json b/packages/opentelemetry-resources/package.json index 4eded5097f2..0e4d276c301 100644 --- a/packages/opentelemetry-resources/package.json +++ b/packages/opentelemetry-resources/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/resources", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry SDK resources", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -61,7 +61,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -86,11 +86,11 @@ "webpack-merge": "5.8.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-resources" } diff --git a/packages/opentelemetry-sdk-trace-base/package.json b/packages/opentelemetry-sdk-trace-base/package.json index d81cbfb9cc4..088904cc49e 100644 --- a/packages/opentelemetry-sdk-trace-base/package.json +++ b/packages/opentelemetry-sdk-trace-base/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/sdk-trace-base", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Tracing", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -64,7 +64,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/sinon": "10.0.13", @@ -88,12 +88,12 @@ "webpack": "4.46.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-base" } diff --git a/packages/opentelemetry-sdk-trace-node/package.json b/packages/opentelemetry-sdk-trace-node/package.json index 9066a3d1fe7..051fad0f9d1 100644 --- a/packages/opentelemetry-sdk-trace-node/package.json +++ b/packages/opentelemetry-sdk-trace-node/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/sdk-trace-node", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Node SDK provides automatic telemetry (tracing, metrics, etc) for Node.js applications", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -45,9 +45,9 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", - "@opentelemetry/resources": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", + "@opentelemetry/resources": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "@types/semver": "7.3.9", @@ -61,14 +61,14 @@ "typescript": "4.4.4" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "dependencies": { - "@opentelemetry/context-async-hooks": "1.5.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/propagator-b3": "1.5.0", - "@opentelemetry/propagator-jaeger": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", + "@opentelemetry/context-async-hooks": "1.6.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/propagator-b3": "1.6.0", + "@opentelemetry/propagator-jaeger": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", "semver": "^7.3.5" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node" diff --git a/packages/opentelemetry-sdk-trace-web/package.json b/packages/opentelemetry-sdk-trace-web/package.json index 421283f0d17..ade633dcf7a 100644 --- a/packages/opentelemetry-sdk-trace-web/package.json +++ b/packages/opentelemetry-sdk-trace-web/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/sdk-trace-web", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry Web Tracer", "main": "build/src/index.js", "module": "build/esm/index.js", @@ -56,10 +56,10 @@ }, "devDependencies": { "@babel/core": "7.16.0", - "@opentelemetry/api": ">=1.0.0 <1.2.0", - "@opentelemetry/context-zone": "1.5.0", - "@opentelemetry/propagator-b3": "1.5.0", - "@opentelemetry/resources": "1.5.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", + "@opentelemetry/context-zone": "1.6.0", + "@opentelemetry/propagator-b3": "1.6.0", + "@opentelemetry/resources": "1.6.0", "@types/jquery": "3.5.8", "@types/mocha": "9.1.1", "@types/node": "18.6.5", @@ -88,12 +88,12 @@ "webpack-merge": "5.8.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0" + "@opentelemetry/core": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-web" } diff --git a/packages/opentelemetry-semantic-conventions/package.json b/packages/opentelemetry-semantic-conventions/package.json index 82554158ae8..8d4953452a9 100644 --- a/packages/opentelemetry-semantic-conventions/package.json +++ b/packages/opentelemetry-semantic-conventions/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/semantic-conventions", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTelemetry semantic conventions", "main": "build/src/index.js", "module": "build/esm/index.js", diff --git a/packages/opentelemetry-shim-opentracing/package.json b/packages/opentelemetry-shim-opentracing/package.json index a78d22696e8..81ac9c3a662 100644 --- a/packages/opentelemetry-shim-opentracing/package.json +++ b/packages/opentelemetry-shim-opentracing/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/shim-opentracing", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenTracing to OpenTelemetry shim", "main": "build/src/index.js", "types": "build/src/index.d.ts", @@ -42,10 +42,10 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0", - "@opentelemetry/propagator-b3": "1.5.0", - "@opentelemetry/propagator-jaeger": "1.5.0", - "@opentelemetry/sdk-trace-base": "1.5.0", + "@opentelemetry/api": ">=1.0.0 <1.3.0", + "@opentelemetry/propagator-b3": "1.6.0", + "@opentelemetry/propagator-jaeger": "1.6.0", + "@opentelemetry/sdk-trace-base": "1.6.0", "@types/mocha": "9.1.1", "@types/node": "18.6.5", "codecov": "3.8.3", @@ -56,11 +56,11 @@ "typescript": "4.4.4" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.2.0" + "@opentelemetry/api": ">=1.0.0 <1.3.0" }, "dependencies": { - "@opentelemetry/core": "1.5.0", - "@opentelemetry/semantic-conventions": "1.5.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/semantic-conventions": "1.6.0", "opentracing": "^0.14.4" }, "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-shim-opentracing" diff --git a/packages/template/package.json b/packages/template/package.json index be638a87420..e34c60e5757 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/template", - "version": "1.5.0", + "version": "1.6.0", "private": true, "publishConfig": { "access": "restricted" diff --git a/selenium-tests/package.json b/selenium-tests/package.json index 5e350280ee0..a276f0e84cb 100644 --- a/selenium-tests/package.json +++ b/selenium-tests/package.json @@ -1,6 +1,6 @@ { "name": "@opentelemetry/selenium-tests", - "version": "1.5.0", + "version": "1.6.0", "private": true, "description": "OpenTelemetry Selenium Tests", "main": "index.js", @@ -56,16 +56,16 @@ "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/context-zone-peer-dep": "1.5.0", - "@opentelemetry/core": "1.5.0", - "@opentelemetry/exporter-trace-otlp-http": "0.31.0", - "@opentelemetry/exporter-zipkin": "1.5.0", - "@opentelemetry/instrumentation": "0.31.0", - "@opentelemetry/instrumentation-fetch": "0.31.0", - "@opentelemetry/instrumentation-xml-http-request": "0.31.0", - "@opentelemetry/sdk-metrics-base": "0.31.0", - "@opentelemetry/sdk-trace-base": "1.5.0", - "@opentelemetry/sdk-trace-web": "1.5.0", + "@opentelemetry/context-zone-peer-dep": "1.6.0", + "@opentelemetry/core": "1.6.0", + "@opentelemetry/exporter-trace-otlp-http": "0.32.0", + "@opentelemetry/exporter-zipkin": "1.6.0", + "@opentelemetry/instrumentation": "0.32.0", + "@opentelemetry/instrumentation-fetch": "0.32.0", + "@opentelemetry/instrumentation-xml-http-request": "0.32.0", + "@opentelemetry/sdk-metrics": "0.32.0", + "@opentelemetry/sdk-trace-base": "1.6.0", + "@opentelemetry/sdk-trace-web": "1.6.0", "zone.js": "0.11.4" } } diff --git a/tsconfig.json b/tsconfig.json index d5872dfc602..cdbf4c42722 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -128,7 +128,7 @@ "path": "experimental/packages/opentelemetry-instrumentation" }, { - "path": "experimental/packages/opentelemetry-sdk-metrics-base" + "path": "experimental/packages/opentelemetry-sdk-metrics" }, { "path": "experimental/packages/opentelemetry-sdk-node"