diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1d576cc70d..554b4ebfee 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,8 +15,29 @@ Before creating a pull request, please make sure: ## Which problem is this PR solving? -- +Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. + +Fixes # (issue) ## Short description of the changes -- +## Type of change + +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +## How Has This Been Tested? + +Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration + +- [ ] Test A + +## Checklist: + +- [ ] Followed the style guidelines of this project +- [ ] Unit tests have been added +- [ ] Documentation has been updated diff --git a/.github/workflows/peer-api.yaml b/.github/workflows/peer-api.yaml index 2917235bc3..f4f1731ea9 100644 --- a/.github/workflows/peer-api.yaml +++ b/.github/workflows/peer-api.yaml @@ -18,9 +18,13 @@ jobs: - name: Install lerna run: npm install -g lerna + - name: Install semver + run: npm install semver + - name: Check API dependency semantics (stable) - run: lerna exec --ignore propagation-validation-server "node ../../scripts/peer-api-check.js" + working-directory: packages + run: lerna exec --ignore propagation-validation-server --ignore propagation-validation-server --ignore @opentelemetry/selenium-tests "node ../../scripts/peer-api-check.js" - name: Check API dependency semantics (experimental) working-directory: experimental - run: lerna exec --ignore propagation-validation-server "node ../../../scripts/peer-api-check.js" + run: lerna exec --ignore propagation-validation-server --ignore @opentelemetry/selenium-tests "node ../../../scripts/peer-api-check.js" diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 6352235f8b..4cc9daca63 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -35,7 +35,7 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' run: | npm install --ignore-scripts - npx lerna bootstrap --no-ci --hoist --nohoist='zone.js' + npx lerna bootstrap --no-ci --hoist --nohoist='zone.js' --ignore @opentelemetry/selenium-tests - name: Build 🔧 run: | @@ -111,7 +111,7 @@ jobs: working-directory: experimental run: | npm install --ignore-scripts - npx lerna bootstrap --no-ci --hoist --nohoist='zone.js' + npx lerna bootstrap --no-ci --hoist --nohoist='zone.js' --ignore @opentelemetry/selenium-tests - name: Build 🔧 working-directory: experimental diff --git a/.gitmodules b/.gitmodules index ac506a776f..278e2d9a57 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,12 @@ -[submodule "experimental/packages/opentelemetry-exporter-otlp-proto/protos"] - path = experimental/packages/opentelemetry-exporter-otlp-proto/protos +[submodule "experimental/packages/opentelemetry-exporter-trace-otlp-proto/protos"] + path = experimental/packages/opentelemetry-exporter-trace-otlp-proto/protos url = https://github.com/open-telemetry/opentelemetry-proto.git -[submodule "experimental/packages/opentelemetry-exporter-otlp-grpc/protos"] - path = experimental/packages/opentelemetry-exporter-otlp-grpc/protos +[submodule "experimental/packages/opentelemetry-exporter-trace-otlp-grpc/protos"] + path = experimental/packages/opentelemetry-exporter-trace-otlp-grpc/protos + url = https://github.com/open-telemetry/opentelemetry-proto.git +[submodule "experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/protos"] + path = experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/protos + url = https://github.com/open-telemetry/opentelemetry-proto.git +[submodule "experimental/packages/opentelemetry-exporter-metrics-otlp-proto/protos"] + path = experimental/packages/opentelemetry-exporter-metrics-otlp-proto/protos url = https://github.com/open-telemetry/opentelemetry-proto.git diff --git a/README.md b/README.md index d5e2f0d917..ab729fc636 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ---

- Getting Started + Getting Started   •   API Reference   •   @@ -49,7 +49,7 @@ This is the JavaScript version of [OpenTelemetry](https://opentelemetry.io/), a | API Version | Core version | Experimental Packages | Contrib Version | | ----------- |--------------| --------------------- |-------------------------| -| 1.0.x | 1.x | 0.26.x | ------ | +| 1.0.x | 1.x | 0.26.x | 0.26.x | | 1.0.x | 0.26.x | ----- | ------ | | 1.0.x | 0.25.x | ----- | ------ | | 1.0.x | 0.24.x | ----- | 0.24.x | @@ -131,7 +131,7 @@ process.on('SIGTERM', () => { node -r ./tracing.js app.js ``` -The above example will emit auto-instrumented telemetry about your Node.js application to the console. For a more in-depth example, see the [Getting Started Guide](https://github.com/open-telemetry/opentelemetry-js/blob/main/getting-started/README.md). For more information about automatic instrumentation see [@opentelemetry/sdk-trace-node][otel-node], which provides auto-instrumentation for Node.js applications. If the automatic instrumentation does not suit your needs, or you would like to create manual traces, see [@opentelemetry/sdk-trace-base][otel-tracing] +The above example will emit auto-instrumented telemetry about your Node.js application to the console. For a more in-depth example, see the [Getting Started Guide](https://opentelemetry.io/docs/js/getting-started/). For more information about automatic instrumentation see [@opentelemetry/sdk-trace-node][otel-node], which provides auto-instrumentation for Node.js applications. If the automatic instrumentation does not suit your needs, or you would like to create manual traces, see [@opentelemetry/sdk-trace-base][otel-tracing] ### Library Author @@ -286,6 +286,35 @@ To request automatic tracing support for a module not on this list, please [file ## Upgrade guidelines +### 0.26.x to 0.27.x + +Metric and trace exporters are split into separate packages: + +- `@opentelemetry/exporter-otlp-http` => `@opentelemetry/exporter-trace-otlp-http` and `@opentelemetry/exporter-metrics-otlp-http` +- `@opentelemetry/exporter-otlp-grpc` => `@opentelemetry/exporter-trace-otlp-grpc` and `@opentelemetry/exporter-metrics-otlp-grpc` +- `@opentelemetry/exporter-otlp-proto` => `@opentelemetry/exporter-trace-otlp-proto` and `@opentelemetry/exporter-metrics-otlp-proto` + +Metric types are renamed: + +- `@openetelemetry/api-metrics` + - `Meter` + - `createValueRecorder` => `createHistogram` + - `createValueObserver` => `createObservableGauge` + - `createSumObserver` => `createObservableCounter` + - `createUpDownSumObserver` => `createObservableUpDownCounter` + - `ValueRecorder` => `Histogram` + - `ValueObserver` => `ObservableGauge` + - `SumObserver` => `ObservableCounter` + - `UpDownSumObserver` => `ObservableUpDownCounter` + - `ObserverResult` => `ObservableResult` + - `Observation.observer` => `Observation.observable` +- `@opentelemetry/sdk-metrics-base` + - `MetricKind` + - `VALUE_RECORDER` => `HISTOGRAM` + - `SUM_OBSERVER` => `OBSERVABLE_COUNTER` + - `UP_DOWN_SUM_OBSERVER` => `OBSERVABLE_UP_DOWN_COUNTER` + - `VALUE_OBSERVER` => `OBSERVABLE_GAUGE` + ### 0.25.x to 1.x.y Collector exporter packages and types are renamed: @@ -308,6 +337,9 @@ Collector exporter packages and types are renamed: - `CollectorExporterNodeBase` => `OTLPExporterNodeBase` - `CollectorMetricExporter` => `OTLPMetricExporter` - `CollectorTraceExporter` => `OTLPTraceExporter` +- W3C propagators in @opentelemetry/core were renamed + - `HttpTraceContextPropagator` -> `W3CTraceContextPropagator` + - `HttpBaggagePropagator` -> `W3CBaggagePropagator` ### 0.24.x to 0.25.x @@ -317,9 +349,6 @@ Collector exporter packages and types are renamed: - @opentelemetry/web -> @opentelemetry/sdk-trace-web - @opentelemetry/metrics -> @opentelemetry/sdk-metrics-base - @opentelemetry/node-sdk -> @opentelemetry/sdk-node -- W3C propagators in @opentelemetry/core were renamed - - `HttpTraceContextPropagator` -> `W3CTraceContextPropagator` - - `W3CBaggagePropagator` -> `W3CBaggagePropagator` ### 0.23.x to 0.24.x @@ -507,13 +536,13 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [docs]: https://open-telemetry.github.io/opentelemetry-js [compliance-matrix]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md -[otel-metrics]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-metrics-base +[otel-metrics]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-metrics-base [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/packages/opentelemetry-instrumentation-fetch -[otel-instrumentation-grpc]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-instrumentation-grpc -[otel-instrumentation-http]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-instrumentation-http -[otel-instrumentation-xml-http-request]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-instrumentation-xml-http-request +[otel-instrumentation-fetch]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-fetch +[otel-instrumentation-grpc]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-grpc +[otel-instrumentation-http]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http +[otel-instrumentation-xml-http-request]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-xml-http-request [otel-shim-opentracing]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-shim-opentracing [otel-tracing]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-base @@ -522,16 +551,16 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [otel-core]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-core [generate-api-documentation]: https://github.com/open-telemetry/opentelemetry-js/blob/main/CONTRIBUTING.md#generating-api-documentation -[otel-contrib-instrumentation-dns]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-dns -[otel-contrib-instrumentation-ioredis]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-ioredis -[otel-contrib-instrumentation-mongodb]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-mongodb -[otel-contrib-instrumentation-mysql]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-mysql -[otel-contrib-instrumentation-pg]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-pg -[otel-contrib-instrumentation-redis]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-redis -[otel-contrib-instrumentation-express]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-express -[otel-contrib-instrumentation-user-interaction]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/web/opentelemetry-instrumentation-user-interaction -[otel-contrib-instrumentation-document-load]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/web/opentelemetry-instrumentation-document-load -[otel-contrib-instrumentation-hapi]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-hapi -[otel-contrib-instrumentation-koa]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/master/plugins/node/opentelemetry-instrumentation-koa +[otel-contrib-instrumentation-dns]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-dns +[otel-contrib-instrumentation-ioredis]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-ioredis +[otel-contrib-instrumentation-mongodb]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mongodb +[otel-contrib-instrumentation-mysql]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-mysql +[otel-contrib-instrumentation-pg]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-pg +[otel-contrib-instrumentation-redis]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-redis +[otel-contrib-instrumentation-express]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-express +[otel-contrib-instrumentation-user-interaction]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/web/opentelemetry-instrumentation-user-interaction +[otel-contrib-instrumentation-document-load]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/web/opentelemetry-instrumentation-document-load +[otel-contrib-instrumentation-hapi]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-hapi +[otel-contrib-instrumentation-koa]: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-koa [spec-versioning]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md diff --git a/doc/processor-api.md b/doc/processor-api.md index b3abbcdecc..944834b038 100644 --- a/doc/processor-api.md +++ b/doc/processor-api.md @@ -138,7 +138,7 @@ const meter = new MeterProvider({ interval: 1000, }).getMeter('example-custom-processor'); -const requestsLatency = meter.createValueRecorder('requests', { +const requestsLatency = meter.createHistogram('requests', { monotonic: true, description: 'Average latency' }); diff --git a/examples/metrics/metrics/observer.js b/examples/metrics/metrics/observer.js index def56d872b..a2ad804e2c 100644 --- a/examples/metrics/metrics/observer.js +++ b/examples/metrics/metrics/observer.js @@ -21,72 +21,18 @@ const exporter = new PrometheusExporter( const meter = new MeterProvider({ exporter, interval: 2000, -}).getMeter('example-observer'); +}).getMeter('example-meter'); -meter.createValueObserver('cpu_core_usage', { - description: 'Example of a sync value observer with callback', -}, async (observerResult) => { // this callback is called once per each interval +meter.createObservableGauge('cpu_core_usage', { + description: 'Example of a sync observable gauge with callback', +}, async (observableResult) => { // this callback is called once per each interval await new Promise((resolve) => { - setTimeout(()=> {resolve()}, 50); + setTimeout(() => { resolve(); }, 50); }); - observerResult.observe(getRandomValue(), { core: '1' }); - observerResult.observe(getRandomValue(), { core: '2' }); + observableResult.observe(getRandomValue(), { core: '1' }); + observableResult.observe(getRandomValue(), { core: '2' }); }); -// no callback as they will be updated in batch observer -const tempMetric = meter.createValueObserver('cpu_temp_per_app', { - description: 'Example of sync value observer used with async batch observer', -}); - -// no callback as they will be updated in batch observer -const cpuUsageMetric = meter.createValueObserver('cpu_usage_per_app', { - description: 'Example of sync value observer used with async batch observer', -}); - -meter.createBatchObserver((observerBatchResult) => { - Promise.all([ - someAsyncMetrics(), - // simulate waiting - new Promise((resolve, reject) => { - setTimeout(resolve, 300); - }), - ]).then(([apps, waiting]) => { - apps.forEach(app => { - observerBatchResult.observe({ app: app.name, core: '1' }, [ - tempMetric.observation(app.core1.temp), - cpuUsageMetric.observation(app.core1.usage), - ]); - observerBatchResult.observe({ app: app.name, core: '2' }, [ - tempMetric.observation(app.core2.temp), - cpuUsageMetric.observation(app.core2.usage), - ]); - }); - }); - }, { - maxTimeoutUpdateMS: 500, - }, -); - -function someAsyncMetrics() { - return new Promise((resolve) => { - setTimeout(() => { - const stats = [ - { - name: 'app1', - core1: { usage: getRandomValue(), temp: getRandomValue() * 100 }, - core2: { usage: getRandomValue(), temp: getRandomValue() * 100 }, - }, - { - name: 'app2', - core1: { usage: getRandomValue(), temp: getRandomValue() * 100 }, - core2: { usage: getRandomValue(), temp: getRandomValue() * 100 }, - }, - ]; - resolve(stats); - }, 200); - }); -} - function getRandomValue() { return Math.random(); } diff --git a/examples/otlp-exporter-node/metrics.js b/examples/otlp-exporter-node/metrics.js index e0065aa697..cb90169405 100644 --- a/examples/otlp-exporter-node/metrics.js +++ b/examples/otlp-exporter-node/metrics.js @@ -31,14 +31,14 @@ const upDownCounter = meter.createUpDownCounter('test_up_down_counter', { description: 'Example of a UpDownCounter', }); -const recorder = meter.createValueRecorder('test_value_recorder', { - description: 'Example of a ValueRecorder', +const histogram = meter.createHistogram('test_histogram', { + description: 'Example of a Histogram', }); const labels = { pid: process.pid, environment: 'staging' }; setInterval(() => { - requestCounter.bind(labels).add(1); - upDownCounter.bind(labels).add(Math.random() > 0.5 ? 1 : -1); - recorder.bind(labels).record(Math.random()); + requestCounter.add(1, labels); + upDownCounter.add(Math.random() > 0.5 ? 1 : -1, labels); + histogram.record(Math.random(), labels); }, 1000); diff --git a/examples/prometheus/index.js b/examples/prometheus/index.js index e486c2701e..ea3f2e6882 100644 --- a/examples/prometheus/index.js +++ b/examples/prometheus/index.js @@ -30,6 +30,6 @@ const upDownCounter = meter.createUpDownCounter('test_up_down_counter', { const labels = { pid: process.pid, environment: 'staging' }; setInterval(() => { - requestCounter.bind(labels).add(1); - upDownCounter.bind(labels).add(Math.random() > 0.5 ? 1 : -1); + requestCounter.add(1, labels); + upDownCounter.add(Math.random() > 0.5 ? 1 : -1, labels); }, 1000); diff --git a/examples/tracer-web/examples/metrics/index.js b/examples/tracer-web/examples/metrics/index.js index 53d6ac6a07..e067e30c7e 100644 --- a/examples/tracer-web/examples/metrics/index.js +++ b/examples/tracer-web/examples/metrics/index.js @@ -41,8 +41,8 @@ function startMetrics() { const labels = { pid: process.pid, environment: 'staging' }; interval = setInterval(() => { - requestCounter.bind(labels).add(1); - upDownCounter.bind(labels).add(Math.random() > 0.5 ? 1 : -1); + requestCounter.add(1, labels); + upDownCounter.add(Math.random() > 0.5 ? 1 : -1, labels); }, 1000); } diff --git a/experimental/packages/opentelemetry-api-metrics/package.json b/experimental/packages/opentelemetry-api-metrics/package.json index 5cb9e1503b..cb99f06016 100644 --- a/experimental/packages/opentelemetry-api-metrics/package.json +++ b/experimental/packages/opentelemetry-api-metrics/package.json @@ -54,17 +54,13 @@ "publishConfig": { "access": "public" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.2" - }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/webpack-env": "1.16.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", diff --git a/experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts b/experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts index 6e0fd5bd20..a5568b545d 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/NoopMeter.ts @@ -14,25 +14,19 @@ * limitations under the License. */ -import { BatchObserverResult } from './types/BatchObserverResult'; import { Meter } from './types/Meter'; import { MetricOptions, - UnboundMetric, - Labels, + Attributes, Counter, - ValueRecorder, - ValueObserver, + Histogram, + ObservableGauge, UpDownCounter, - BaseObserver, - UpDownSumObserver, + ObservableBase, + ObservableCounter, + ObservableUpDownCounter, } from './types/Metric'; -import { - BoundValueRecorder, - BoundCounter, - BoundBaseObserver, -} from './types/BoundInstrument'; -import { ObserverResult } from './types/ObserverResult'; +import { ObservableResult } from './types/ObservableResult'; import { Observation } from './types/Observation'; /** @@ -43,12 +37,12 @@ export class NoopMeter implements Meter { constructor() {} /** - * Returns constant noop value recorder. + * Returns a constant noop histogram. * @param name the name of the metric. * @param [options] the metric options. */ - createValueRecorder(_name: string, _options?: MetricOptions): ValueRecorder { - return NOOP_VALUE_RECORDER_METRIC; + createHistogram(_name: string, _options?: MetricOptions): Histogram { + return NOOP_HISTOGRAM_METRIC; } /** @@ -66,162 +60,83 @@ export class NoopMeter implements Meter { * @param [options] the metric options. */ createUpDownCounter(_name: string, _options?: MetricOptions): UpDownCounter { - return NOOP_COUNTER_METRIC; + return NOOP_UP_DOWN_COUNTER_METRIC; } /** - * Returns constant noop value observer. + * Returns a constant noop observable gauge. * @param name the name of the metric. * @param [options] the metric options. - * @param [callback] the value observer callback + * @param [callback] the observable gauge callback */ - createValueObserver( + createObservableGauge( _name: string, _options?: MetricOptions, - _callback?: (observerResult: ObserverResult) => void - ): ValueObserver { - return NOOP_VALUE_OBSERVER_METRIC; + _callback?: (observableResult: ObservableResult) => void + ): ObservableGauge { + return NOOP_OBSERVABLE_GAUGE_METRIC; } /** - * Returns constant noop sum observer. + * Returns a constant noop observable counter. * @param name the name of the metric. * @param [options] the metric options. - * @param [callback] the sum observer callback + * @param [callback] the observable counter callback */ - createSumObserver( + createObservableCounter( _name: string, _options?: MetricOptions, - _callback?: (observerResult: ObserverResult) => void - ): ValueObserver { - return NOOP_SUM_OBSERVER_METRIC; + _callback?: (observableResult: ObservableResult) => void + ): ObservableCounter { + return NOOP_OBSERVABLE_COUNTER_METRIC; } /** - * Returns constant noop up down sum observer. + * Returns a constant noop up down observable counter. * @param name the name of the metric. * @param [options] the metric options. - * @param [callback] the up down sum observer callback + * @param [callback] the up down observable counter callback */ - createUpDownSumObserver( + createObservableUpDownCounter( _name: string, _options?: MetricOptions, - _callback?: (observerResult: ObserverResult) => void - ): UpDownSumObserver { - return NOOP_UP_DOWN_SUM_OBSERVER_METRIC; - } - - /** - * Returns constant noop batch observer. - * @param name the name of the metric. - * @param callback the batch observer callback - */ - createBatchObserver( - _callback: (batchObserverResult: BatchObserverResult) => void - ): NoopBatchObserver { - return NOOP_BATCH_OBSERVER; + _callback?: (observableResult: ObservableResult) => void + ): ObservableUpDownCounter { + return NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC; } } -export class NoopMetric implements UnboundMetric { - private readonly _instrument: T; - - constructor(instrument: T) { - this._instrument = instrument; - } - - /** - * Returns a Bound Instrument associated with specified Labels. - * It is recommended to keep a reference to the Bound Instrument instead of - * always calling this method for every operations. - * @param labels key-values pairs that are associated with a specific metric - * that you want to record. - */ - bind(_labels: Labels): T { - return this._instrument; - } - - /** - * Removes the Binding from the metric, if it is present. - * @param labels key-values pairs that are associated with a specific metric. - */ - unbind(_labels: Labels): void { - return; - } +export class NoopMetric {} - /** - * Clears all timeseries from the Metric. - */ - clear(): void { - return; - } +export class NoopCounterMetric extends NoopMetric implements Counter { + add(_value: number, _attributes: Attributes): void {} } -export class NoopCounterMetric - extends NoopMetric - implements Counter { - add(value: number, labels: Labels): void { - this.bind(labels).add(value); - } +export class NoopUpDownCounterMetric extends NoopMetric implements UpDownCounter { + add(_value: number, _attributes: Attributes): void {} } -export class NoopValueRecorderMetric - extends NoopMetric - implements ValueRecorder { - record(value: number, labels: Labels): void { - this.bind(labels).record(value); - } +export class NoopHistogramMetric extends NoopMetric implements Histogram { + record(_value: number, _attributes: Attributes): void {} } -export class NoopBaseObserverMetric - extends NoopMetric - implements BaseObserver { +export class NoopObservableBaseMetric extends NoopMetric implements ObservableBase { observation(): Observation { return { - observer: this as BaseObserver, + observable: this as ObservableBase, value: 0, }; } } -export class NoopBatchObserver {} - -export class NoopBoundCounter implements BoundCounter { - add(_value: number): void { - return; - } -} - -export class NoopBoundValueRecorder implements BoundValueRecorder { - record(_value: number, _baggage?: unknown, _spanContext?: unknown): void { - return; - } -} - -export class NoopBoundBaseObserver implements BoundBaseObserver { - update(_value: number): void {} -} - export const NOOP_METER = new NoopMeter(); -export const NOOP_BOUND_COUNTER = new NoopBoundCounter(); -export const NOOP_COUNTER_METRIC = new NoopCounterMetric(NOOP_BOUND_COUNTER); - -export const NOOP_BOUND_VALUE_RECORDER = new NoopBoundValueRecorder(); -export const NOOP_VALUE_RECORDER_METRIC = new NoopValueRecorderMetric( - NOOP_BOUND_VALUE_RECORDER -); - -export const NOOP_BOUND_BASE_OBSERVER = new NoopBoundBaseObserver(); -export const NOOP_VALUE_OBSERVER_METRIC = new NoopBaseObserverMetric( - NOOP_BOUND_BASE_OBSERVER -); - -export const NOOP_UP_DOWN_SUM_OBSERVER_METRIC = new NoopBaseObserverMetric( - NOOP_BOUND_BASE_OBSERVER -); -export const NOOP_SUM_OBSERVER_METRIC = new NoopBaseObserverMetric( - NOOP_BOUND_BASE_OBSERVER -); +// Synchronous instruments +export const NOOP_COUNTER_METRIC = new NoopCounterMetric(); +export const NOOP_HISTOGRAM_METRIC = new NoopHistogramMetric(); +export const NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric(); -export const NOOP_BATCH_OBSERVER = new NoopBatchObserver(); +// Asynchronous instruments +export const NOOP_OBSERVABLE_COUNTER_METRIC = new NoopObservableBaseMetric(); +export const NOOP_OBSERVABLE_GAUGE_METRIC = new NoopObservableBaseMetric(); +export const NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC = new NoopObservableBaseMetric(); diff --git a/experimental/packages/opentelemetry-api-metrics/src/NoopMeterProvider.ts b/experimental/packages/opentelemetry-api-metrics/src/NoopMeterProvider.ts index 2cc737960e..97628d7122 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/NoopMeterProvider.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/NoopMeterProvider.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Meter } from './types/Meter'; +import { Meter, MeterOptions } from './types/Meter'; import { MeterProvider } from './types/MeterProvider'; import { NOOP_METER } from './NoopMeter'; @@ -23,7 +23,7 @@ import { NOOP_METER } from './NoopMeter'; * for all calls to `getMeter` */ export class NoopMeterProvider implements MeterProvider { - getMeter(_name?: string, _version?: string): Meter { + getMeter(_name: string, _version?: string, _options?: MeterOptions): Meter { return NOOP_METER; } } diff --git a/experimental/packages/opentelemetry-api-metrics/src/api/global-utils.ts b/experimental/packages/opentelemetry-api-metrics/src/api/global-utils.ts index a23f76396d..e371d5165d 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/api/global-utils.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/api/global-utils.ts @@ -52,4 +52,4 @@ export function makeGetter( * version. If the global API is not compatible with the API package * attempting to get it, a NOOP API implementation will be returned. */ -export const API_BACKWARDS_COMPATIBILITY_VERSION = 3; +export const API_BACKWARDS_COMPATIBILITY_VERSION = 4; diff --git a/experimental/packages/opentelemetry-api-metrics/src/api/metrics.ts b/experimental/packages/opentelemetry-api-metrics/src/api/metrics.ts index 079fc952e4..3e5fb6015a 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/api/metrics.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/api/metrics.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Meter } from '../types/Meter'; +import { Meter, MeterOptions } from '../types/Meter'; import { MeterProvider } from '../types/MeterProvider'; import { NOOP_METER_PROVIDER } from '../NoopMeterProvider'; import { @@ -73,8 +73,8 @@ export class MetricsAPI { /** * Returns a meter from the global meter provider. */ - public getMeter(name: string, version?: string): Meter { - return this.getMeterProvider().getMeter(name, version); + public getMeter(name: string, version?: string, options?: MeterOptions): Meter { + return this.getMeterProvider().getMeter(name, version, options); } /** Remove the global meter provider */ diff --git a/experimental/packages/opentelemetry-api-metrics/src/index.ts b/experimental/packages/opentelemetry-api-metrics/src/index.ts index de39eb0821..ffdac63125 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/index.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/index.ts @@ -16,13 +16,11 @@ export * from './NoopMeter'; export * from './NoopMeterProvider'; -export * from './types/BatchObserverResult'; -export * from './types/BoundInstrument'; export * from './types/Meter'; export * from './types/MeterProvider'; export * from './types/Metric'; export * from './types/Observation'; -export * from './types/ObserverResult'; +export * from './types/ObservableResult'; import { MetricsAPI } from './api/metrics'; /** Entrypoint for metrics API */ diff --git a/experimental/packages/opentelemetry-api-metrics/src/platform/browser/globalThis.ts b/experimental/packages/opentelemetry-api-metrics/src/platform/browser/globalThis.ts index 34a8254b88..693547b7c2 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/platform/browser/globalThis.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/platform/browser/globalThis.ts @@ -14,6 +14,22 @@ * limitations under the License. */ +// Updates to this file should also be replicated to @opentelemetry/api and +// @opentelemetry/core too. + +/** + * - globalThis (New standard) + * - self (Will return the current window instance for supported browsers) + * - window (fallback for older browser implementations) + * - global (NodeJS implementation) + * - (When all else fails) + */ + /** only globals that common to node and browsers are allowed */ // eslint-disable-next-line node/no-unsupported-features/es-builtins, no-undef -export const _globalThis = typeof globalThis === 'object' ? globalThis : window; +export const _globalThis: typeof globalThis = + typeof globalThis === 'object' ? globalThis : + typeof self === 'object' ? self : + typeof window === 'object' ? window : + typeof global === 'object' ? global : + {} as typeof globalThis; diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/BatchObserverResult.ts b/experimental/packages/opentelemetry-api-metrics/src/types/BatchObserverResult.ts deleted file mode 100644 index bae99eb866..0000000000 --- a/experimental/packages/opentelemetry-api-metrics/src/types/BatchObserverResult.ts +++ /dev/null @@ -1,31 +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 { Labels } from './Metric'; -import { Observation } from './Observation'; - -/** - * Interface that is being used in callback function for Observer Metric - * for batch - */ -export interface BatchObserverResult { - /** - * Used to observe (update) observations for certain labels - * @param labels - * @param observations - */ - observe(labels: Labels, observations: Observation[]): void; -} diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/BoundInstrument.ts b/experimental/packages/opentelemetry-api-metrics/src/types/BoundInstrument.ts deleted file mode 100644 index 0d5554771e..0000000000 --- a/experimental/packages/opentelemetry-api-metrics/src/types/BoundInstrument.ts +++ /dev/null @@ -1,38 +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. - */ - -/** An Instrument for Counter Metric. */ -export interface BoundCounter { - /** - * Adds the given value to the current value. Values cannot be negative. - * @param value the value to add. - */ - add(value: number): void; -} - -/** ValueRecorder to report instantaneous measurement of a value. */ -export interface BoundValueRecorder { - /** - * Records the given value to this value recorder. - * @param value to record. - */ - record(value: number): void; -} - -/** An Instrument for Base Observer */ -export interface BoundBaseObserver { - update(value: number): void; -} diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts b/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts index 27428f2554..ce4d57a4f8 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/types/Meter.ts @@ -14,33 +14,41 @@ * limitations under the License. */ -import { BatchObserverResult } from './BatchObserverResult'; import { MetricOptions, Counter, - ValueRecorder, - ValueObserver, - BatchObserverOptions, + Histogram, + ObservableGauge, UpDownCounter, - SumObserver, - UpDownSumObserver, + ObservableCounter, + ObservableUpDownCounter, } from './Metric'; -import { ObserverResult } from './ObserverResult'; +import { ObservableResult } from './ObservableResult'; + +/** + * An interface describes additional metadata of a meter. + */ +export interface MeterOptions { + /** + * The schemaUrl of the meter or instrumentation library + */ + schemaUrl?: string; +} /** * An interface to allow the recording metrics. * * {@link Metric}s are used for recording pre-defined aggregation (`Counter`), - * or raw values (`ValueRecorder`) in which the aggregation and labels + * or raw values (`Histogram`) in which the aggregation and attributes * for the exported metric are deferred. */ export interface Meter { /** - * Creates and returns a new `ValueRecorder`. + * Creates and returns a new `Histogram`. * @param name the name of the metric. * @param [options] the metric options. */ - createValueRecorder(name: string, options?: MetricOptions): ValueRecorder; + createHistogram(name: string, options?: MetricOptions): Histogram; /** * Creates a new `Counter` metric. Generally, this kind of metric when the @@ -71,49 +79,38 @@ export interface Meter { createUpDownCounter(name: string, options?: MetricOptions): UpDownCounter; /** - * Creates a new `ValueObserver` metric. + * Creates a new `ObservableGauge` metric. * @param name the name of the metric. * @param [options] the metric options. - * @param [callback] the observer callback + * @param [callback] the observable callback */ - createValueObserver( + createObservableGauge( name: string, options?: MetricOptions, - callback?: (observerResult: ObserverResult) => void - ): ValueObserver; + callback?: (observableResult: ObservableResult) => void + ): ObservableGauge; /** - * Creates a new `SumObserver` metric. + * Creates a new `ObservableCounter` metric. * @param name the name of the metric. * @param [options] the metric options. - * @param [callback] the observer callback + * @param [callback] the observable callback */ - createSumObserver( + createObservableCounter( name: string, options?: MetricOptions, - callback?: (observerResult: ObserverResult) => void - ): SumObserver; + callback?: (observableResult: ObservableResult) => void + ): ObservableCounter; /** - * Creates a new `UpDownSumObserver` metric. + * Creates a new `ObservableUpDownCounter` metric. * @param name the name of the metric. * @param [options] the metric options. - * @param [callback] the observer callback + * @param [callback] the observable callback */ - createUpDownSumObserver( + createObservableUpDownCounter( name: string, options?: MetricOptions, - callback?: (observerResult: ObserverResult) => void - ): UpDownSumObserver; - - /** - * Creates a new `BatchObserver`, can be used to update many metrics - * at the same time and when operations needs to be async - * @param callback the batch observer callback - * @param [options] the batch observer options. - */ - createBatchObserver( - callback: (batchObserverResult: BatchObserverResult) => void, - options?: BatchObserverOptions - ): void; + callback?: (observableResult: ObservableResult) => void + ): ObservableUpDownCounter; } diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/MeterProvider.ts b/experimental/packages/opentelemetry-api-metrics/src/types/MeterProvider.ts index 981218ad59..448f10b17b 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/types/MeterProvider.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/types/MeterProvider.ts @@ -14,19 +14,20 @@ * limitations under the License. */ -import { Meter } from './Meter'; +import { Meter, MeterOptions } from './Meter'; /** * A registry for creating named {@link Meter}s. */ export interface MeterProvider { /** - * Returns a Meter, creating one if one with the given name and version is - * not already created. + * Returns a Meter, creating one if one with the given name, version, and + * schemaUrl pair is not already created. * * @param name The name of the meter or instrumentation library. * @param version The version of the meter or instrumentation library. + * @param options The options of the meter or instrumentation library. * @returns Meter A Meter with the given name and version */ - getMeter(name: string, version?: string): Meter; + getMeter(name: string, version?: string, options?: MeterOptions): Meter; } diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/Metric.ts b/experimental/packages/opentelemetry-api-metrics/src/types/Metric.ts index aebbc46246..3ba86d3e87 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/types/Metric.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/types/Metric.ts @@ -15,10 +15,8 @@ */ import { - BoundBaseObserver, - BoundCounter, - BoundValueRecorder, -} from './BoundInstrument'; + Observation, +} from './Observation'; /** * Options needed for metric creation @@ -39,8 +37,8 @@ export interface MetricOptions { */ unit?: string; - /** The map of constant labels for the Metric. */ - constantLabels?: Map; + /** The map of constant attributes for the Metric. */ + constantAttributes?: Map; /** * Indicates the metric is a verbose metric that is disabled by default @@ -65,13 +63,6 @@ export interface MetricOptions { aggregationTemporality?: AggregationTemporality; } -export interface BatchObserverOptions { - /** - * Indicates how long the batch metric should wait to update before cancel - */ - maxTimeoutUpdateMS?: number; -} - /** The Type of value. It describes how the data is reported. */ export enum ValueType { INT, @@ -85,38 +76,6 @@ export enum AggregationTemporality { AGGREGATION_TEMPORALITY_CUMULATIVE, } -/** - * Metric represents a base class for different types of metric - * pre aggregations. - */ -export interface Metric { - /** - * Clears all bound instruments from the Metric. - */ - clear(): void; -} - -/** - * UnboundMetric represents a base class for different types of metric - * pre aggregations without label value bound yet. - */ -export interface UnboundMetric extends Metric { - /** - * Returns a Instrument associated with specified Labels. - * It is recommended to keep a reference to the Instrument instead of always - * calling this method for every operations. - * @param labels key-values pairs that are associated with a specific metric - * that you want to record. - */ - bind(labels: Labels): T; - - /** - * Removes the Instrument from the metric, if it is present. - * @param labels key-values pairs that are associated with a specific metric. - */ - unbind(labels: Labels): void; -} - /** * Counter is the most common synchronous instrument. This instrument supports * an `Add(increment)` function for reporting a sum, and is restricted to @@ -132,47 +91,45 @@ export interface UnboundMetric extends Metric { *
  • count the number of 5xx errors.
  • *
      */ -export interface Counter extends UnboundMetric { +export interface Counter { /** - * Adds the given value to the current value. Values cannot be negative. + * Increment value of counter by the input. Inputs may not be negative. */ - add(value: number, labels?: Labels): void; + add(value: number, attributes?: Attributes): void; } -export interface UpDownCounter extends UnboundMetric { +export interface UpDownCounter { /** - * Adds the given value to the current value. Values can be negative. + * Increment value of counter by the input. Inputs may be negative. */ - add(value: number, labels?: Labels): void; + add(value: number, attributes?: Attributes): void; } -export interface ValueRecorder extends UnboundMetric { +export interface Histogram { /** - * Records the given value to this value recorder. + * Records the given value to this histogram. */ - record(value: number, labels?: Labels): void; + record(value: number, attributes?: Attributes): void; } -/** Base interface for the Observer metrics. */ -export interface BaseObserver extends UnboundMetric { +/** Base interface for the Observable metrics. */ +export interface ObservableBase { observation: ( - value: number - ) => { - value: number; - observer: BaseObserver; - }; + value: number, + attributes?: Attributes, + ) => Observation; } -/** Base interface for the ValueObserver metrics. */ -export type ValueObserver = BaseObserver; +/** Base interface for the ObservableGauge metrics. */ +export type ObservableGauge = ObservableBase; -/** Base interface for the UpDownSumObserver metrics. */ -export type UpDownSumObserver = BaseObserver; +/** Base interface for the ObservableUpDownCounter metrics. */ +export type ObservableUpDownCounter = ObservableBase; -/** Base interface for the SumObserver metrics. */ -export type SumObserver = BaseObserver; +/** Base interface for the ObservableCounter metrics. */ +export type ObservableCounter = ObservableBase; /** * key-value pairs passed by the user. */ -export type Labels = { [key: string]: string }; +export type Attributes = { [key: string]: string }; diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/ObserverResult.ts b/experimental/packages/opentelemetry-api-metrics/src/types/ObservableResult.ts similarity index 75% rename from experimental/packages/opentelemetry-api-metrics/src/types/ObserverResult.ts rename to experimental/packages/opentelemetry-api-metrics/src/types/ObservableResult.ts index 7792483ad1..74f71d4acc 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/types/ObserverResult.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/types/ObservableResult.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import { Labels } from './Metric'; +import { Attributes } from './Metric'; /** - * Interface that is being used in callback function for Observer Metric + * Interface that is being used in callback function for Observable Metric */ -export interface ObserverResult { - observe(value: number, labels: Labels): void; +export interface ObservableResult { + observe(value: number, attributes: Attributes): void; } diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/Observation.ts b/experimental/packages/opentelemetry-api-metrics/src/types/Observation.ts index d36f48fb71..1e805f3689 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/types/Observation.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/types/Observation.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import { BaseObserver } from './Metric'; +import { ObservableBase } from './Metric'; /** - * Interface for updating value of certain value observer + * Interface for updating value of certain observable */ export interface Observation { - observer: BaseObserver; + observable: ObservableBase; value: number; } 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 cbfe044a9f..4d5fced1f9 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,44 +17,38 @@ import * as assert from 'assert'; import { NoopMeterProvider, - NOOP_BOUND_COUNTER, - NOOP_BOUND_VALUE_RECORDER, NOOP_COUNTER_METRIC, - NOOP_VALUE_RECORDER_METRIC, + NOOP_HISTOGRAM_METRIC, } from '../../src'; describe('NoopMeter', () => { it('should not crash', () => { const meter = new NoopMeterProvider().getMeter('test-noop'); const counter = meter.createCounter('some-name'); - const labels = {}; + const attributes = {}; // ensure NoopMetric does not crash. - counter.bind(labels).add(1); - counter.unbind(labels); + counter.add(1, attributes); // ensure the correct noop const is returned assert.strictEqual(counter, NOOP_COUNTER_METRIC); - assert.strictEqual(counter.bind(labels), NOOP_BOUND_COUNTER); - counter.clear(); - const valueRecorder = meter.createValueRecorder('some-name'); - valueRecorder.bind(labels).record(1); + const histogram = meter.createHistogram('some-name'); + histogram.record(1, attributes); // ensure the correct noop const is returned - assert.strictEqual(valueRecorder, NOOP_VALUE_RECORDER_METRIC); - assert.strictEqual(valueRecorder.bind(labels), NOOP_BOUND_VALUE_RECORDER); + assert.strictEqual(histogram, NOOP_HISTOGRAM_METRIC); const options = { component: 'tests', description: 'the testing package', }; - const valueRecorderWithOptions = meter.createValueRecorder( + const histogramWithOptions = meter.createHistogram( 'some-name', options ); - assert.strictEqual(valueRecorderWithOptions, NOOP_VALUE_RECORDER_METRIC); + assert.strictEqual(histogramWithOptions, NOOP_HISTOGRAM_METRIC); const counterWithOptions = meter.createCounter('some-name', options); assert.strictEqual(counterWithOptions, NOOP_COUNTER_METRIC); }); diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/.eslintignore b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/.eslintignore similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/.eslintignore rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/.eslintignore diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/.eslintrc.js b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/.eslintrc.js similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/.eslintrc.js rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/.eslintrc.js diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/.npmignore b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/.npmignore similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/.npmignore rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/.npmignore diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/LICENSE b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/LICENSE similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/LICENSE rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/LICENSE diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md new file mode 100644 index 0000000000..007c36f86f --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/README.md @@ -0,0 +1,77 @@ +# OpenTelemetry Collector Metrics Exporter for node with grpc + +[![NPM Published Version][npm-img]][npm-url] +[![dependencies][dependencies-image]][dependencies-url] +[![devDependencies][devDependencies-image]][devDependencies-url] +[![Apache License][license-image]][license-image] + +This module provides exporter for web and node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.25.0**. + +## Installation + +```bash +npm install --save @opentelemetry/exporter-metrics-otlp-grpc +``` + +## Service Name + +The OpenTelemetry Collector Exporter does not have a service name configuration. +In order to set the service name, use the `service.name` resource attribute as prescribed in the [OpenTelemetry Resource Semantic Conventions][semconv-resource-service-name]. +To see sample code and documentation for the traces exporter, as well as instructions for using TLS, visit the [Collector Trace Exporter for web and node][trace-exporter-url]. + +## Metrics in Node - GRPC + +The OTLPTraceExporter 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 } = require('@opentelemetry/sdk-metrics-base'); +const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-grpc'); +const collectorOptions = { + // url is optional and can be omitted - default is grpc://localhost:4317 + url: 'grpc://:', +}; +const exporter = new OTLPMetricExporter(collectorOptions); + +// Register the exporter +const provider = new MeterProvider({ + exporter, + interval: 60000, +}) +['SIGINT', 'SIGTERM'].forEach(signal => { + process.on(signal, () => provider.shutdown().catch(console.error)); +}); + +// Now, start recording data +const meter = provider.getMeter('example-meter'); +const counter = meter.createCounter('metric_name'); +counter.add(10, { 'key': 'value' }); +``` + +## Running opentelemetry-collector locally to see the metrics + +1. Go to examples/otlp-exporter-node +2. run `npm run docker:start` +3. Open page at `http://localhost:9411/zipkin/` to observe the metrics + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us in [GitHub Discussions][discussions-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions +[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-grpc +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-grpc +[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-grpc&type=dev +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-grpc&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-grpc +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-metrics-otlp-grpc.svg +[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector +[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service +[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-trace-otlp-grpc diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json new file mode 100644 index 0000000000..53bbf31bb7 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json @@ -0,0 +1,79 @@ +{ + "name": "@opentelemetry/exporter-metrics-otlp-grpc", + "version": "0.26.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", + "repository": "open-telemetry/opentelemetry-js", + "scripts": { + "compile": "tsc --build", + "clean": "tsc --build --clean", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "postcompile": "npm run submodule && npm run protos:copy", + "protos:copy": "cpx protos/opentelemetry/**/*.* build/protos/opentelemetry", + "submodule": "git submodule sync --recursive && git submodule update --init --recursive", + "tdd": "npm run test -- --watch-extensions ts --watch", + "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", + "version": "node ../../../scripts/version-update.js", + "watch": "npm run protos:copy && tsc -w", + "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "prewatch": "npm run precompile" + }, + "keywords": [ + "opentelemetry", + "nodejs", + "grpc", + "tracing", + "profiling", + "metrics", + "stats" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.js.map", + "build/src/**/*.d.ts", + "build/protos/**/*.proto", + "doc", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@babel/core": "7.15.0", + "@opentelemetry/api": "^1.0.3", + "@opentelemetry/api-metrics": "0.26.0", + "@types/mocha": "8.2.3", + "@types/node": "14.17.11", + "@types/sinon": "10.0.2", + "codecov": "3.8.3", + "cpx": "1.5.0", + "mocha": "7.2.0", + "nyc": "15.1.0", + "rimraf": "3.0.2", + "sinon": "12.0.1", + "ts-loader": "8.3.0", + "ts-mocha": "8.0.0", + "typescript": "4.3.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.3" + }, + "dependencies": { + "@grpc/grpc-js": "^1.3.7", + "@grpc/proto-loader": "^0.6.4", + "@opentelemetry/core": "1.0.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.26.0", + "@opentelemetry/exporter-trace-otlp-http": "0.26.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.26.0", + "@opentelemetry/sdk-metrics-base": "0.26.0", + "@opentelemetry/resources": "1.0.0" + } +} diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/protos b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/protos similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/protos rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/protos diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts similarity index 84% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPMetricExporter.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts index a914c299cd..1816992850 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts @@ -14,15 +14,16 @@ * limitations under the License. */ -import { - otlpTypes, - toOTLPExportMetricServiceRequest, -} from '@opentelemetry/exporter-otlp-http'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; +import { toOTLPExportMetricServiceRequest } from '@opentelemetry/exporter-metrics-otlp-http' import { MetricRecord, MetricExporter } from '@opentelemetry/sdk-metrics-base'; -import { OTLPExporterConfigNode, ServiceClientType } from './types'; -import { OTLPExporterNodeBase } from './OTLPExporterNodeBase'; +import { + OTLPExporterConfigNode, + OTLPExporterNodeBase, + ServiceClientType, + validateAndNormalizeUrl +} from '@opentelemetry/exporter-trace-otlp-grpc'; import { baggageUtils, getEnv } from '@opentelemetry/core'; -import { validateAndNormalizeUrl } from './util'; import { Metadata } from '@grpc/grpc-js'; const DEFAULT_COLLECTOR_URL = 'localhost:4317'; @@ -58,7 +59,7 @@ export class OTLPMetricExporter ); } - getDefaultUrl(config: OTLPExporterConfigNode) { + getDefaultUrl(config: OTLPExporterConfigNode): string { return typeof config.url === 'string' ? validateAndNormalizeUrl(config.url) : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0 @@ -68,7 +69,7 @@ export class OTLPMetricExporter : DEFAULT_COLLECTOR_URL; } - getServiceClientType() { + getServiceClientType(): ServiceClientType { return ServiceClientType.METRICS; } diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/index.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/index.ts similarity index 94% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/index.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/index.ts index d54490a7ea..7b73804ce4 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/index.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -export * from './OTLPTraceExporter'; export * from './OTLPMetricExporter'; diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/submodule.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/submodule.md new file mode 100644 index 0000000000..4985e69dad --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/submodule.md @@ -0,0 +1,45 @@ +# Important + +**Submodule is always pointing to certain revision number. So updating the submodule repo will not have impact on your code. +Knowing this if you want to change the submodule to point to a different version (when for example proto has changed) here is how to do it:** + +## Updating submodule to point to certain revision number + +1. Make sure you are in the same folder as this instruction + +2. Update your submodules by running this command + + ```shell script + git submodule sync --recursive + git submodule update --init --recursive + ``` + +3. Find the commit SHA which you want to update to and copy it (the long one) + +4. Enter a submodule directory from this directory + + ```shell script + cd protos + ``` + +5. Updates files in the submodule tree to given commit: + + ```shell script + git checkout -q + ``` + +6. Return to the main directory: + + ```shell script + cd ../ + ``` + +7. Please run `git status` you should see something like `Head detached at`. This is correct, go to next step + +8. Now thing which is very important. You have to commit this to apply these changes + + ```shell script + git commit -am "chore: updating submodule for opentelemetry-proto" + ``` + +9. If you look now at git log you will notice that the folder `protos` has been changed and it will show what was the previous sha and what is current one. diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts similarity index 89% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPMetricExporter.test.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts index 86b8e1cef3..569bd2e500 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts @@ -17,11 +17,11 @@ import * as protoLoader from '@grpc/proto-loader'; import { Counter, - ValueObserver, - ValueRecorder, + ObservableGauge, + Histogram, } from '@opentelemetry/api-metrics'; import { diag } from '@opentelemetry/api'; -import { otlpTypes } from '@opentelemetry/exporter-otlp-http'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import * as metrics from '@opentelemetry/sdk-metrics-base'; import * as assert from 'assert'; import * as fs from 'fs'; @@ -31,14 +31,14 @@ import * as sinon from 'sinon'; import { OTLPMetricExporter } from '../src'; import { ensureExportedCounterIsCorrect, - ensureExportedObserverIsCorrect, - ensureExportedValueRecorderIsCorrect, + ensureExportedObservableGaugeIsCorrect, + ensureExportedHistogramIsCorrect, ensureMetadataIsCorrect, ensureResourceIsCorrect, mockCounter, - mockObserver, - mockValueRecorder, -} from './helper'; + mockObservableGauge, + mockHistogram, +} from './metricsHelper'; const metricsServiceProtoPath = 'opentelemetry/proto/collector/metrics/v1/metrics_service.proto'; @@ -140,21 +140,21 @@ const testOTLPMetricExporter = (params: TestParams) => metrics = []; const counter: metrics.Metric & Counter = mockCounter(); - const observer: metrics.Metric & - ValueObserver = mockObserver(observerResult => { - observerResult.observe(3, {}); - observerResult.observe(6, {}); + const observableGauge: metrics.Metric & + ObservableGauge = mockObservableGauge(observableResult => { + observableResult.observe(3, {}); + observableResult.observe(6, {}); }); - const recorder: metrics.Metric & - ValueRecorder = mockValueRecorder(); + const histogram: metrics.Metric & + Histogram = mockHistogram(); counter.add(1); - recorder.record(7); - recorder.record(14); + histogram.record(7); + histogram.record(14); metrics.push((await counter.getMetricRecord())[0]); - metrics.push((await observer.getMetricRecord())[0]); - metrics.push((await recorder.getMetricRecord())[0]); + metrics.push((await observableGauge.getMetricRecord())[0]); + metrics.push((await histogram.getMetricRecord())[0]); }); afterEach(() => { @@ -203,21 +203,21 @@ const testOTLPMetricExporter = (params: TestParams) => resource = exportedData[0].resource; const counter = exportedData[0].instrumentationLibraryMetrics[0].metrics[0]; - const observer = + const observableGauge = exportedData[0].instrumentationLibraryMetrics[0].metrics[1]; - const recorder = + const histogram = exportedData[0].instrumentationLibraryMetrics[0].metrics[2]; ensureExportedCounterIsCorrect( counter, counter.intSum?.dataPoints[0].timeUnixNano ); - ensureExportedObserverIsCorrect( - observer, - observer.doubleGauge?.dataPoints[0].timeUnixNano + ensureExportedObservableGaugeIsCorrect( + observableGauge, + observableGauge.doubleGauge?.dataPoints[0].timeUnixNano ); - ensureExportedValueRecorderIsCorrect( - recorder, - recorder.intHistogram?.dataPoints[0].timeUnixNano, + ensureExportedHistogramIsCorrect( + histogram, + histogram.intHistogram?.dataPoints[0].timeUnixNano, [0, 100], ['0', '2', '0'] ); diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/ca.crt b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/ca.crt rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/ca.key b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/ca.key rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/ca.key diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/client.crt b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/client.crt rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/client.csr b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.csr similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/client.csr rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.csr diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/client.key b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/client.key rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/client.key diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/regenerate.sh b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/regenerate.sh similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/regenerate.sh rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/regenerate.sh diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/server.crt b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/server.crt rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/server.csr b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.csr similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/server.csr rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.csr diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/server.key b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/certs/server.key rename to experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/certs/server.key diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts new file mode 100644 index 0000000000..7fd582968d --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts @@ -0,0 +1,251 @@ +/* + * 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 { + Counter, + ObservableResult, + ObservableGauge, + Histogram, + ValueType, +} from '@opentelemetry/api-metrics'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; +import * as metrics from '@opentelemetry/sdk-metrics-base'; +import { Resource } from '@opentelemetry/resources'; +import * as assert from 'assert'; +import * as grpc from '@grpc/grpc-js'; +import { VERSION } from '@opentelemetry/core'; + +const meterProvider = new metrics.MeterProvider({ + interval: 30000, + resource: new Resource({ + service: 'ui', + version: 1, + cost: 112.12, + }), +}); + +const meter = meterProvider.getMeter('default', '0.0.1'); + +export function mockCounter(): metrics.Metric & Counter { + const name = 'int-counter'; + const metric = + meter['_metrics'].get(name) || + meter.createCounter(name, { + description: 'sample counter description', + valueType: ValueType.INT, + }); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockObservableGauge( + callback: (observableResult: ObservableResult) => void +): metrics.Metric & ObservableGauge { + const name = 'double-observable-gauge'; + const metric = + meter['_metrics'].get(name) || + meter.createObservableGauge( + name, + { + description: 'sample observable gauge description', + valueType: ValueType.DOUBLE, + }, + callback + ); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockHistogram(): metrics.Metric & + Histogram { + const name = 'int-histogram'; + const metric = + meter['_metrics'].get(name) || + meter.createHistogram(name, { + description: 'sample histogram description', + valueType: ValueType.INT, + boundaries: [0, 100], + }); + metric.clear(); + metric.bind({}); + return metric; +} + +export function ensureExportedAttributesAreCorrect( + attributes: otlpTypes.opentelemetryProto.common.v1.KeyValue[] +) { + assert.deepStrictEqual( + attributes, + [ + { + key: 'component', + value: { + stringValue: 'document-load', + value: 'stringValue', + }, + }, + ], + 'exported attributes are incorrect' + ); +} + +export function ensureExportedCounterIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time?: number +) { + assert.deepStrictEqual(metric, { + name: 'int-counter', + description: 'sample counter description', + unit: '1', + data: 'intSum', + intSum: { + dataPoints: [ + { + labels: [], + exemplars: [], + value: '1', + startTimeUnixNano: '1592602232694000128', + timeUnixNano: String(time), + }, + ], + isMonotonic: true, + aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', + }, + }); +} + +export function ensureExportedObservableGaugeIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time?: number +) { + assert.deepStrictEqual(metric, { + name: 'double-observable-gauge', + description: 'sample observable gauge description', + unit: '1', + data: 'doubleGauge', + doubleGauge: { + dataPoints: [ + { + labels: [], + exemplars: [], + value: 6, + startTimeUnixNano: '1592602232694000128', + timeUnixNano: String(time), + }, + ], + }, + }); +} + +export function ensureExportedHistogramIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time?: number, + explicitBounds: number[] = [Infinity], + bucketCounts: string[] = ['2', '0'] +) { + assert.deepStrictEqual(metric, { + name: 'int-histogram', + description: 'sample histogram description', + unit: '1', + data: 'intHistogram', + intHistogram: { + dataPoints: [ + { + labels: [], + exemplars: [], + sum: '21', + count: '2', + startTimeUnixNano: '1592602232694000128', + timeUnixNano: String(time), + bucketCounts, + explicitBounds, + }, + ], + aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', + }, + }); +} + +export function ensureResourceIsCorrect( + resource: otlpTypes.opentelemetryProto.resource.v1.Resource +) { + assert.deepStrictEqual(resource, { + attributes: [ + { + 'key': 'service.name', + 'value': { + 'stringValue': `unknown_service:${process.argv0}`, + 'value': 'stringValue' + } + }, + { + 'key': 'telemetry.sdk.language', + 'value': { + 'stringValue': 'nodejs', + 'value': 'stringValue' + } + }, + { + 'key': 'telemetry.sdk.name', + 'value': { + 'stringValue': 'opentelemetry', + 'value': 'stringValue' + } + }, + { + 'key': 'telemetry.sdk.version', + 'value': { + 'stringValue': VERSION, + 'value': 'stringValue' + } + }, + { + key: 'service', + value: { + stringValue: 'ui', + value: 'stringValue', + }, + }, + { + key: 'version', + value: { + intValue: '1', + value: 'intValue', + }, + }, + { + key: 'cost', + value: { + doubleValue: 112.12, + value: 'doubleValue', + }, + }, + ], + droppedAttributesCount: 0, + }); +} + +export function ensureMetadataIsCorrect( + actual: grpc.Metadata, + expected: grpc.Metadata +) { + //ignore user agent + expected.remove('user-agent'); + actual.remove('user-agent'); + assert.deepStrictEqual(actual.getMap(), expected.getMap()); +} diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json new file mode 100644 index 0000000000..948abef3ce --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "build" + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ], + "references": [ + { + "path": "../opentelemetry-api-metrics" + } + ] +} diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/.eslintignore b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/.eslintignore similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/.eslintignore rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/.eslintignore diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/.eslintrc.js b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/.eslintrc.js similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/.eslintrc.js rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/.eslintrc.js diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/.npmignore b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/.npmignore similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/.npmignore rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/.npmignore diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/LICENSE b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/LICENSE similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/LICENSE rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/LICENSE diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md new file mode 100644 index 0000000000..791d1acb10 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/README.md @@ -0,0 +1,131 @@ +# OpenTelemetry Collector Metrics Exporter for web and node + +[![NPM Published Version][npm-img]][npm-url] +[![dependencies][dependencies-image]][dependencies-url] +[![devDependencies][devDependencies-image]][devDependencies-url] +[![Apache License][license-image]][license-image] + +This module provides exporter for web and node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.25.0**. + +## Installation + +```bash +npm install --save @opentelemetry/exporter-metrics-otlp-http +``` + +## Service Name + +The OpenTelemetry Collector Metrics Exporter does not have a service name configuration. +In order to set the service name, use the `service.name` resource attribute as prescribed in the [OpenTelemetry Resource Semantic Conventions][semconv-resource-service-name]. +To see sample code and documentation for the traces exporter, visit the [Collector Trace Exporter for web and node][trace-exporter-url]. + +## Metrics in Web + +The OTLPMetricExporter in Web expects the endpoint to end in `/v1/metrics`. + +```js +import { MeterProvider } from '@opentelemetry/sdk-metrics-base'; +import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'; +const collectorOptions = { + url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/metrics + headers: {}, // an optional object containing custom headers to be sent with each request + concurrencyLimit: 1, // an optional limit on pending requests +}; +const exporter = new OTLPMetricExporter(collectorOptions); + +// Register the exporter +const meter = new MeterProvider({ + exporter, + interval: 60000, +}).getMeter('example-meter'); + +// Now, start recording data +const counter = meter.createCounter('metric_name'); +counter.add(10, { 'key': 'value' }); + +``` + +## Metrics in Node + +```js +const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); +const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http'); +const collectorOptions = { + url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/metrics + concurrencyLimit: 1, // an optional limit on pending requests +}; +const exporter = new OTLPMetricExporter(collectorOptions); + +// Register the exporter +const meter = new MeterProvider({ + exporter, + interval: 60000, +}).getMeter('example-meter'); + +// Now, start recording data +const counter = meter.createCounter('metric_name'); +counter.add(10, { 'key': 'value' }); + +``` + +## GRPC + +For exporting metrics with GRPC please check [exporter-metrics-otlp-grpc][npm-url-grpc] + +## PROTOBUF + +For exporting metrics with PROTOBUF please check [exporter-metrics-otlp-proto][npm-url-proto] + +## Configuration options as environment variables + +Instead of providing options to `OTLPMetricExporter` and `OTLPTraceExporter` explicitly, environment variables may be provided instead. + +```sh +OTEL_EXPORTER_OTLP_ENDPOINT=https://localhost:4317 +# this will automatically append the version and signal path +# e.g. https://localhost:4317/v1/traces for `OTLPTraceExporter` and https://localhost:4317/v1/metrics for `OTLPMetricExporter` +``` + +If the trace and metric exporter endpoints have different providers, the env var for per-signal endpoints are available to use + +```sh +OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://trace-service:4317/v1/traces +OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://metric-service:4317/v1/metrics +# version and signal needs to be explicit +``` + +> The per-signal endpoints take precedence and overrides `OTEL_EXPORTER_OTLP_ENDPOINT` + +For more details, see [OpenTelemetry Specification on Protocol Exporter][opentelemetry-spec-protocol-exporter]. + +## Running opentelemetry-collector locally to see the metrics + +1. Go to examples/otlp-exporter-node +2. run `npm run docker:start` +3. Open page at `http://localhost:9411/zipkin/` to observe the metrics + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us in [GitHub Discussions][discussions-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions +[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-http +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-http +[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-http&type=dev +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-http&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-http +[npm-url-grpc]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-grpc +[npm-url-proto]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-proto +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-metrics-otlp-http.svg +[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector +[opentelemetry-spec-protocol-exporter]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options +[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service +[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-trace-otlp-http diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/karma.conf.js b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/karma.conf.js similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/karma.conf.js rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/karma.conf.js diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json new file mode 100644 index 0000000000..6e72458872 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json @@ -0,0 +1,95 @@ +{ + "name": "@opentelemetry/exporter-metrics-otlp-http", + "version": "0.26.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", + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js", + "browser": { + "./src/platform/index.ts": "./src/platform/browser/index.ts", + "./build/esm/platform/index.js": "./build/esm/platform/browser/index.js", + "./build/src/platform/index.js": "./build/src/platform/browser/index.js" + }, + "scripts": { + "compile": "tsc --build tsconfig.json tsconfig.esm.json", + "clean": "tsc --build --clean tsconfig.json tsconfig.esm.json", + "codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "tdd": "npm run test -- --watch-extensions ts --watch", + "tdd:browser": "karma start", + "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'", + "test:browser": "nyc karma start --single-run", + "version": "node ../../../scripts/version-update.js", + "watch": "tsc --build --watch tsconfig.json tsconfig.esm.json", + "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "prewatch": "npm run precompile" + }, + "keywords": [ + "opentelemetry", + "nodejs", + "browser", + "tracing", + "profiling", + "metrics", + "stats" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + }, + "files": [ + "build/esm/**/*.js", + "build/esm/**/*.js.map", + "build/esm/**/*.d.ts", + "build/src/**/*.js", + "build/src/**/*.js.map", + "build/src/**/*.d.ts", + "doc", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@opentelemetry/api": "^1.0.3", + "@babel/core": "7.15.0", + "@types/mocha": "8.2.3", + "@types/node": "14.17.11", + "@types/sinon": "10.0.2", + "@types/webpack-env": "1.16.2", + "babel-loader": "8.2.2", + "codecov": "3.8.3", + "cpx": "1.5.0", + "istanbul-instrumenter-loader": "3.0.1", + "karma": "6.3.7", + "karma-chrome-launcher": "3.1.0", + "karma-coverage-istanbul-reporter": "3.0.3", + "karma-mocha": "2.0.1", + "karma-spec-reporter": "0.0.32", + "karma-webpack": "4.0.2", + "mocha": "7.2.0", + "nyc": "15.1.0", + "rimraf": "3.0.2", + "sinon": "12.0.1", + "ts-loader": "8.3.0", + "ts-mocha": "8.0.0", + "typescript": "4.3.5", + "webpack": "4.46.0", + "webpack-cli": "4.8.0", + "webpack-merge": "5.8.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.3" + }, + "dependencies": { + "@opentelemetry/api-metrics": "0.26.0", + "@opentelemetry/core": "1.0.0", + "@opentelemetry/exporter-trace-otlp-http": "0.26.0", + "@opentelemetry/resources": "1.0.0", + "@opentelemetry/sdk-metrics-base": "0.26.0" + } +} diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/index.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/index.ts new file mode 100644 index 0000000000..f4e0549034 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './platform'; +export { toOTLPExportMetricServiceRequest } from './transformMetrics'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts similarity index 86% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/OTLPMetricExporter.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts index 7d3840f4c3..b19eb0070b 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts @@ -15,12 +15,9 @@ */ import { MetricRecord, MetricExporter } from '@opentelemetry/sdk-metrics-base'; -import { OTLPExporterConfigBase } from '../../types'; -import * as otlpTypes from '../../types'; -import { OTLPExporterBrowserBase } from './OTLPExporterBrowserBase'; +import { OTLPExporterBrowserBase, otlpTypes, appendResourcePathToUrlIfNotPresent } from '@opentelemetry/exporter-trace-otlp-http'; import { toOTLPExportMetricServiceRequest } from '../../transformMetrics'; import { getEnv, baggageUtils } from '@opentelemetry/core'; -import { appendResourcePathToUrlIfNotPresent } from '../../util'; const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics'; const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`; @@ -37,7 +34,7 @@ export class OTLPMetricExporter // Converts time to nanoseconds private readonly _startTime = new Date().getTime() * 1000000; - constructor(config: OTLPExporterConfigBase = {}) { + constructor(config: otlpTypes.OTLPExporterConfigBase = {}) { super(config); this._headers = Object.assign( this._headers, @@ -57,7 +54,7 @@ export class OTLPMetricExporter ); } - getDefaultUrl(config: OTLPExporterConfigBase): string { + getDefaultUrl(config: otlpTypes.OTLPExporterConfigBase): string { return typeof config.url === 'string' ? config.url : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0 diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/src/index.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/index.ts similarity index 94% rename from experimental/packages/opentelemetry-exporter-otlp-proto/src/index.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/index.ts index d54490a7ea..7b73804ce4 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/src/index.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -export * from './OTLPTraceExporter'; export * from './OTLPMetricExporter'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/index.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/index.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/index.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/index.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts similarity index 90% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/OTLPMetricExporter.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts index 5d3b645591..05bf6af767 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts @@ -15,12 +15,14 @@ */ import { MetricRecord, MetricExporter } from '@opentelemetry/sdk-metrics-base'; -import * as otlpTypes from '../../types'; -import { OTLPExporterNodeConfigBase } from './types'; -import { OTLPExporterNodeBase } from './OTLPExporterNodeBase'; +import { + OTLPExporterNodeBase, + OTLPExporterNodeConfigBase, + otlpTypes, + appendResourcePathToUrlIfNotPresent +} from '@opentelemetry/exporter-trace-otlp-http'; import { toOTLPExportMetricServiceRequest } from '../../transformMetrics'; import { getEnv, baggageUtils } from '@opentelemetry/core'; -import { appendResourcePathToUrlIfNotPresent } from '../../util'; const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics'; const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`; diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/index.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/index.ts similarity index 94% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/src/index.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/index.ts index d54490a7ea..7b73804ce4 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/index.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -export * from './OTLPTraceExporter'; export * from './OTLPMetricExporter'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/transformMetrics.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/transformMetrics.ts similarity index 82% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/transformMetrics.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/transformMetrics.ts index cc0f580883..b63947c28b 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/src/transformMetrics.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/transformMetrics.ts @@ -15,7 +15,7 @@ */ import { SpanAttributes, HrTime } from '@opentelemetry/api'; -import { Labels, ValueType } from '@opentelemetry/api-metrics'; +import { Attributes as Labels, ValueType } from '@opentelemetry/api-metrics'; import * as core from '@opentelemetry/core'; import { AggregatorKind, @@ -24,9 +24,7 @@ import { MetricRecord, } from '@opentelemetry/sdk-metrics-base'; import { Resource } from '@opentelemetry/resources'; -import { OTLPExporterBase } from './OTLPExporterBase'; -import { toCollectorResource } from './transform'; -import { OTLPExporterConfigBase, opentelemetryProto } from './types'; +import { OTLPExporterBase, otlpTypes, toCollectorResource } from '@opentelemetry/exporter-trace-otlp-http'; /** * Converts labels @@ -34,7 +32,7 @@ import { OTLPExporterConfigBase, opentelemetryProto } from './types'; */ export function toCollectorLabels( labels: Labels -): opentelemetryProto.common.v1.StringKeyValue[] { +): otlpTypes.opentelemetryProto.common.v1.StringKeyValue[] { return Object.entries(labels).map(([key, value]) => { return { key, value: String(value) }; }); @@ -46,9 +44,9 @@ export function toCollectorLabels( */ export function toAggregationTemporality( metric: MetricRecord -): opentelemetryProto.metrics.v1.AggregationTemporality { - if (metric.descriptor.metricKind === MetricKind.VALUE_OBSERVER) { - return opentelemetryProto.metrics.v1.AggregationTemporality +): otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality { + if (metric.descriptor.metricKind === MetricKind.OBSERVABLE_GAUGE) { + return otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality .AGGREGATION_TEMPORALITY_UNSPECIFIED; } @@ -56,16 +54,16 @@ export function toAggregationTemporality( } /** - * Returns an DataPoint which can have integers or doublle values + * Returns an DataPoint which can have integers or double values * @param metric * @param startTime */ export function toDataPoint( metric: MetricRecord, startTime: number -): opentelemetryProto.metrics.v1.DataPoint { +): otlpTypes.opentelemetryProto.metrics.v1.DataPoint { return { - labels: toCollectorLabels(metric.labels), + labels: toCollectorLabels(metric.attributes), value: metric.aggregator.toPoint().value as number, startTimeUnixNano: startTime, timeUnixNano: core.hrTimeToNanoseconds( @@ -82,13 +80,13 @@ export function toDataPoint( export function toHistogramPoint( metric: MetricRecord, startTime: number -): opentelemetryProto.metrics.v1.HistogramDataPoint { +): otlpTypes.opentelemetryProto.metrics.v1.HistogramDataPoint { const { value, timestamp } = metric.aggregator.toPoint() as { value: Histogram; timestamp: HrTime; }; return { - labels: toCollectorLabels(metric.labels), + labels: toCollectorLabels(metric.attributes), sum: value.sum, count: value.count, startTimeUnixNano: startTime, @@ -106,8 +104,8 @@ export function toHistogramPoint( export function toCollectorMetric( metric: MetricRecord, startTime: number -): opentelemetryProto.metrics.v1.Metric { - const metricCollector: opentelemetryProto.metrics.v1.Metric = { +): otlpTypes.opentelemetryProto.metrics.v1.Metric { + const metricCollector: otlpTypes.opentelemetryProto.metrics.v1.Metric = { name: metric.descriptor.name, description: metric.descriptor.description, unit: metric.descriptor.unit, @@ -115,14 +113,14 @@ export function toCollectorMetric( if ( metric.aggregator.kind === AggregatorKind.SUM || - metric.descriptor.metricKind === MetricKind.SUM_OBSERVER || - metric.descriptor.metricKind === MetricKind.UP_DOWN_SUM_OBSERVER + metric.descriptor.metricKind === MetricKind.OBSERVABLE_COUNTER || + metric.descriptor.metricKind === MetricKind.OBSERVABLE_UP_DOWN_COUNTER ) { const result = { dataPoints: [toDataPoint(metric, startTime)], isMonotonic: metric.descriptor.metricKind === MetricKind.COUNTER || - metric.descriptor.metricKind === MetricKind.SUM_OBSERVER, + metric.descriptor.metricKind === MetricKind.OBSERVABLE_COUNTER, aggregationTemporality: toAggregationTemporality(metric), }; if (metric.descriptor.valueType === ValueType.INT) { @@ -161,16 +159,16 @@ export function toCollectorMetric( * @param collectorMetricExporterBase */ export function toOTLPExportMetricServiceRequest< - T extends OTLPExporterConfigBase + T extends otlpTypes.OTLPExporterConfigBase >( metrics: MetricRecord[], startTime: number, collectorExporterBase: OTLPExporterBase< T, MetricRecord, - opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest + otlpTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest > -): opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest { +): otlpTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest { const groupedMetrics: Map< Resource, Map @@ -224,7 +222,7 @@ function toCollectorInstrumentationLibraryMetrics( instrumentationLibrary: core.InstrumentationLibrary, metrics: MetricRecord[], startTime: number -): opentelemetryProto.metrics.v1.InstrumentationLibraryMetrics { +): otlpTypes.opentelemetryProto.metrics.v1.InstrumentationLibraryMetrics { return { metrics: metrics.map(metric => toCollectorMetric(metric, startTime)), instrumentationLibrary, @@ -243,7 +241,7 @@ function toCollectorResourceMetrics( >, baseAttributes: SpanAttributes, startTime: number -): opentelemetryProto.metrics.v1.ResourceMetrics[] { +): otlpTypes.opentelemetryProto.metrics.v1.ResourceMetrics[] { return Array.from(groupedMetrics, ([resource, libMetrics]) => { return { resource: toCollectorResource(resource, baseAttributes), diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/browser/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts similarity index 92% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/browser/CollectorMetricExporter.test.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts index 34463695c8..ed31149691 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/browser/CollectorMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts @@ -17,33 +17,32 @@ import { diag } from '@opentelemetry/api'; import { Counter, - ValueObserver, - ValueRecorder, + ObservableGauge, + Histogram, } from '@opentelemetry/api-metrics'; import { ExportResultCode, hrTimeToNanoseconds } from '@opentelemetry/core'; import { BoundCounter, - BoundObserver, - BoundValueRecorder, + BoundObservable, + BoundHistogram, Metric, MetricRecord, } from '@opentelemetry/sdk-metrics-base'; import * as assert from 'assert'; import * as sinon from 'sinon'; import { OTLPMetricExporter } from '../../src/platform/browser/index'; -import * as otlpTypes from '../../src/types'; -import { OTLPExporterConfigBase } from '../../src/types'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import { ensureCounterIsCorrect, ensureExportMetricsServiceRequestIsSet, ensureHeadersContain, - ensureObserverIsCorrect, - ensureValueRecorderIsCorrect, + ensureObservableGaugeIsCorrect, + ensureHistogramIsCorrect, ensureWebResourceIsCorrect, mockCounter, - mockObserver, - mockValueRecorder, -} from '../helper'; + mockObservableGauge, + mockHistogram, +} from '../metricsHelper'; describe('OTLPMetricExporter - web', () => { let collectorExporter: OTLPMetricExporter; @@ -57,22 +56,22 @@ describe('OTLPMetricExporter - web', () => { stubBeacon = sinon.stub(navigator, 'sendBeacon'); metrics = []; const counter: Metric & Counter = mockCounter(); - const observer: Metric & ValueObserver = mockObserver( - observerResult => { - observerResult.observe(3, {}); - observerResult.observe(6, {}); + const observableGauge: Metric & ObservableGauge = mockObservableGauge( + observableResult => { + observableResult.observe(3, {}); + observableResult.observe(6, {}); }, - 'double-observer2' + 'double-observable-gauge2' ); - const recorder: Metric & - ValueRecorder = mockValueRecorder(); + const histogram: Metric & + Histogram = mockHistogram(); counter.add(1); - recorder.record(7); - recorder.record(14); + histogram.record(7); + histogram.record(14); metrics.push((await counter.getMetricRecord())[0]); - metrics.push((await observer.getMetricRecord())[0]); - metrics.push((await recorder.getMetricRecord())[0]); + metrics.push((await observableGauge.getMetricRecord())[0]); + metrics.push((await histogram.getMetricRecord())[0]); }); afterEach(() => { @@ -121,11 +120,11 @@ describe('OTLPMetricExporter - web', () => { "second metric doesn't exist" ); if (metric2) { - ensureObserverIsCorrect( + ensureObservableGaugeIsCorrect( metric2, hrTimeToNanoseconds(metrics[1].aggregator.toPoint().timestamp), 6, - 'double-observer2' + 'double-observable-gauge2' ); } @@ -134,7 +133,7 @@ describe('OTLPMetricExporter - web', () => { "third metric doesn't exist" ); if (metric3) { - ensureValueRecorderIsCorrect( + ensureHistogramIsCorrect( metric3, hrTimeToNanoseconds(metrics[2].aggregator.toPoint().timestamp), [0, 100], @@ -234,11 +233,11 @@ describe('OTLPMetricExporter - web', () => { "second metric doesn't exist" ); if (metric2) { - ensureObserverIsCorrect( + ensureObservableGaugeIsCorrect( metric2, hrTimeToNanoseconds(metrics[1].aggregator.toPoint().timestamp), 6, - 'double-observer2' + 'double-observable-gauge2' ); } @@ -247,7 +246,7 @@ describe('OTLPMetricExporter - web', () => { "third metric doesn't exist" ); if (metric3) { - ensureValueRecorderIsCorrect( + ensureHistogramIsCorrect( metric3, hrTimeToNanoseconds(metrics[2].aggregator.toPoint().timestamp), [0, 100], @@ -321,7 +320,7 @@ describe('OTLPMetricExporter - web', () => { foo: 'bar', bar: 'baz', }; - let collectorExporterConfig: OTLPExporterConfigBase; + let collectorExporterConfig: otlpTypes.OTLPExporterConfigBase; beforeEach(() => { collectorExporterConfig = { diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/browser/index-webpack.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/index-webpack.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/browser/index-webpack.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/index-webpack.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/CollectorMetricExporter.test.ts similarity index 89% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/common/CollectorMetricExporter.test.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/CollectorMetricExporter.test.ts index 119702c683..91b678d2a2 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/CollectorMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/CollectorMetricExporter.test.ts @@ -14,22 +14,20 @@ * limitations under the License. */ -import { Counter, ValueObserver } from '@opentelemetry/api-metrics'; +import { Counter, ObservableGauge } from '@opentelemetry/api-metrics'; import { ExportResultCode } from '@opentelemetry/core'; import { BoundCounter, - BoundObserver, + BoundObservable, Metric, MetricRecord, } from '@opentelemetry/sdk-metrics-base'; import * as assert from 'assert'; import * as sinon from 'sinon'; -import { OTLPExporterBase } from '../../src/OTLPExporterBase'; -import * as otlpTypes from '../../src/types'; -import { OTLPExporterConfigBase } from '../../src/types'; -import { mockCounter, mockObserver } from '../helper'; +import { OTLPExporterBase, otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; +import { mockCounter, mockObservableGauge } from '../metricsHelper'; -type CollectorExporterConfig = OTLPExporterConfigBase; +type CollectorExporterConfig = otlpTypes.OTLPExporterConfigBase; class OTLPMetricExporter extends OTLPExporterBase< CollectorExporterConfig, MetricRecord, @@ -70,17 +68,17 @@ describe('OTLPMetricExporter - common', () => { collectorExporter = new OTLPMetricExporter(collectorExporterConfig); metrics = []; const counter: Metric & Counter = mockCounter(); - const observer: Metric & ValueObserver = mockObserver( - observerResult => { - observerResult.observe(3, {}); - observerResult.observe(6, {}); + const observableGauge: Metric & ObservableGauge = mockObservableGauge( + observableResult => { + observableResult.observe(3, {}); + observableResult.observe(6, {}); }, - 'double-observer3' + 'double-observable-gauge3' ); counter.add(1); metrics.push((await counter.getMetricRecord())[0]); - metrics.push((await observer.getMetricRecord())[0]); + metrics.push((await observableGauge.getMetricRecord())[0]); }); it('should create an instance', () => { diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/transformMetrics.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/transformMetrics.test.ts similarity index 60% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/common/transformMetrics.test.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/transformMetrics.test.ts index e94a6cf71d..3169c02c80 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/transformMetrics.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/common/transformMetrics.test.ts @@ -15,16 +15,16 @@ */ import { Counter, - SumObserver, - UpDownSumObserver, - ValueObserver, - ValueRecorder, + ObservableCounter, + ObservableUpDownCounter, + ObservableGauge, + Histogram, } from '@opentelemetry/api-metrics'; import { hrTimeToNanoseconds } from '@opentelemetry/core'; import { BoundCounter, - BoundObserver, - BoundValueRecorder, + BoundObservable, + BoundHistogram, Metric, SumAggregator, } from '@opentelemetry/sdk-metrics-base'; @@ -34,30 +34,30 @@ import * as transform from '../../src/transformMetrics'; import { ensureCounterIsCorrect, ensureDoubleCounterIsCorrect, - ensureObserverIsCorrect, - ensureSumObserverIsCorrect, - ensureUpDownSumObserverIsCorrect, - ensureValueRecorderIsCorrect, + ensureObservableGaugeIsCorrect, + ensureObservableCounterIsCorrect, + ensureObservableUpDownCounterIsCorrect, + ensureHistogramIsCorrect, mockCounter, mockDoubleCounter, mockedInstrumentationLibraries, mockedResources, - mockObserver, - mockSumObserver, - mockUpDownSumObserver, - mockValueRecorder, + mockObservableGauge, + mockObservableCounter, + mockObservableUpDownCounter, + mockHistogram, multiInstrumentationLibraryMetricsGet, multiResourceMetricsGet, -} from '../helper'; +} from '../metricsHelper'; describe('transformMetrics', () => { describe('toCollectorMetric', async () => { let counter: Metric & Counter; let doubleCounter: Metric & Counter; - let observer: Metric & ValueObserver; - let sumObserver: Metric & SumObserver; - let upDownSumObserver: Metric & UpDownSumObserver; - let recorder: Metric & ValueRecorder; + let observableGauge: Metric & ObservableGauge; + let observableCounter: Metric & ObservableCounter; + let observableUpDownCounter: Metric & ObservableUpDownCounter; + let histogram: Metric & Histogram; beforeEach(() => { counter = mockCounter(); doubleCounter = mockDoubleCounter(); @@ -72,22 +72,22 @@ describe('transformMetrics', () => { return -1; } - observer = mockObserver(observerResult => { + observableGauge = mockObservableGauge(observableResult => { count1++; - observerResult.observe(getValue(count1), {}); + observableResult.observe(getValue(count1), {}); }); - sumObserver = mockSumObserver(observerResult => { + observableCounter = mockObservableCounter(observableResult => { count2++; - observerResult.observe(getValue(count2), {}); + observableResult.observe(getValue(count2), {}); }); - upDownSumObserver = mockUpDownSumObserver(observerResult => { + observableUpDownCounter = mockObservableUpDownCounter(observableResult => { count3++; - observerResult.observe(getValue(count3), {}); + observableResult.observe(getValue(count3), {}); }); - recorder = mockValueRecorder(); + histogram = mockHistogram(); // Counter counter.add(1); @@ -95,9 +95,9 @@ describe('transformMetrics', () => { // Double Counter doubleCounter.add(8); - // ValueRecorder - recorder.record(7); - recorder.record(14); + // Histogram + histogram.record(7); + histogram.record(14); }); it('should convert metric', async () => { @@ -113,52 +113,52 @@ describe('transformMetrics', () => { hrTimeToNanoseconds(doubleCounterMetric.aggregator.toPoint().timestamp) ); - await observer.getMetricRecord(); - await observer.getMetricRecord(); - const observerMetric = (await observer.getMetricRecord())[0]; - ensureObserverIsCorrect( - transform.toCollectorMetric(observerMetric, 1592602232694000000), - hrTimeToNanoseconds(observerMetric.aggregator.toPoint().timestamp), + await observableGauge.getMetricRecord(); + await observableGauge.getMetricRecord(); + const observableGaugeMetric = (await observableGauge.getMetricRecord())[0]; + ensureObservableGaugeIsCorrect( + transform.toCollectorMetric(observableGaugeMetric, 1592602232694000000), + hrTimeToNanoseconds(observableGaugeMetric.aggregator.toPoint().timestamp), -1 ); // collect 3 times - await sumObserver.getMetricRecord(); - await sumObserver.getMetricRecord(); - const sumObserverMetric = (await sumObserver.getMetricRecord())[0]; - ensureSumObserverIsCorrect( - transform.toCollectorMetric(sumObserverMetric, 1592602232694000000), - hrTimeToNanoseconds(sumObserverMetric.aggregator.toPoint().timestamp), + await observableCounter.getMetricRecord(); + await observableCounter.getMetricRecord(); + const observableCounterMetric = (await observableCounter.getMetricRecord())[0]; + ensureObservableCounterIsCorrect( + transform.toCollectorMetric(observableCounterMetric, 1592602232694000000), + hrTimeToNanoseconds(observableCounterMetric.aggregator.toPoint().timestamp), 3 ); // collect 3 times - await upDownSumObserver.getMetricRecord(); - await upDownSumObserver.getMetricRecord(); - const upDownSumObserverMetric = ( - await upDownSumObserver.getMetricRecord() + await observableUpDownCounter.getMetricRecord(); + await observableUpDownCounter.getMetricRecord(); + const observableUpDownCounterMetric = ( + await observableUpDownCounter.getMetricRecord() )[0]; - ensureUpDownSumObserverIsCorrect( + ensureObservableUpDownCounterIsCorrect( transform.toCollectorMetric( - upDownSumObserverMetric, + observableUpDownCounterMetric, 1592602232694000000 ), hrTimeToNanoseconds( - upDownSumObserverMetric.aggregator.toPoint().timestamp + observableUpDownCounterMetric.aggregator.toPoint().timestamp ), -1 ); - const recorderMetric = (await recorder.getMetricRecord())[0]; - ensureValueRecorderIsCorrect( - transform.toCollectorMetric(recorderMetric, 1592602232694000000), - hrTimeToNanoseconds(recorderMetric.aggregator.toPoint().timestamp), + const histogramMetric = (await histogram.getMetricRecord())[0]; + ensureHistogramIsCorrect( + transform.toCollectorMetric(histogramMetric, 1592602232694000000), + hrTimeToNanoseconds(histogramMetric.aggregator.toPoint().timestamp), [0, 100], [0, 2, 0] ); }); - it('should convert metric labels value to string', () => { + it('should convert metric attributes value to string', () => { const metric = transform.toCollectorMetric( { descriptor: { @@ -168,7 +168,7 @@ describe('transformMetrics', () => { metricKind: 0, valueType: 0, }, - labels: { foo: (1 as unknown) as string }, + attributes: { foo: (1 as unknown) as string }, aggregator: new SumAggregator(), resource: new Resource({}), aggregationTemporality: 0, @@ -186,8 +186,8 @@ describe('transformMetrics', () => { const [resource1, resource2] = mockedResources; const [library] = mockedInstrumentationLibraries; const [metric1, metric2, metric3] = multiResourceMetricsGet( - observerResult => { - observerResult.observe(1, {}); + observableResult => { + observableResult.observe(1, {}); } ); @@ -197,8 +197,8 @@ describe('transformMetrics', () => { ]); const result = transform.groupMetricsByResourceAndLibrary( - multiResourceMetricsGet(observerResult => { - observerResult.observe(1, {}); + multiResourceMetricsGet(observableResult => { + observableResult.observe(1, {}); }) ); @@ -212,7 +212,7 @@ describe('transformMetrics', () => { metric1, metric2, metric3, - ] = multiInstrumentationLibraryMetricsGet(observerResult => {}); + ] = multiInstrumentationLibraryMetricsGet(observableResult => {}); const expected = new Map([ [ resource, @@ -224,7 +224,7 @@ describe('transformMetrics', () => { ]); const result = transform.groupMetricsByResourceAndLibrary( - multiInstrumentationLibraryMetricsGet(observerResult => {}) + multiInstrumentationLibraryMetricsGet(observableResult => {}) ); assert.deepStrictEqual(result, expected); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts new file mode 100644 index 0000000000..830be337f0 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts @@ -0,0 +1,448 @@ +/* + * 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 { + Counter, + ObservableResult, + ObservableCounter, + ObservableUpDownCounter, + ObservableGauge, + Histogram, + ValueType, +} from '@opentelemetry/api-metrics'; +import { InstrumentationLibrary, VERSION } from '@opentelemetry/core'; +import * as metrics from '@opentelemetry/sdk-metrics-base'; +import { Resource } from '@opentelemetry/resources'; +import * as assert from 'assert'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; + +const meterProvider = new metrics.MeterProvider({ + interval: 30000, + resource: new Resource({ + service: 'ui', + version: 1, + cost: 112.12, + }), +}); + +const meter = meterProvider.getMeter('default', '0.0.1'); + +if (typeof Buffer === 'undefined') { + (window as any).Buffer = { + from: function (arr: []) { + return new Uint8Array(arr); + }, + }; +} + +export function mockCounter(): metrics.Metric & Counter { + const name = 'int-counter'; + const metric = + meter['_metrics'].get(name) || + meter.createCounter(name, { + description: 'sample counter description', + valueType: ValueType.INT, + }); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockDoubleCounter(): metrics.Metric & + Counter { + const name = 'double-counter'; + const metric = + meter['_metrics'].get(name) || + meter.createCounter(name, { + description: 'sample counter description', + valueType: ValueType.DOUBLE, + }); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockObservableGauge( + callback: (observableResult: ObservableResult) => unknown, + name = 'double-observable-gauge' +): metrics.Metric & ObservableGauge { + const metric = + meter['_metrics'].get(name) || + meter.createObservableGauge( + name, + { + description: 'sample observable gauge description', + valueType: ValueType.DOUBLE, + }, + callback + ); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockObservableCounter( + callback: (observableResult: ObservableResult) => unknown, + name = 'double-observable-counter' +): metrics.Metric & ObservableCounter { + const metric = + meter['_metrics'].get(name) || + meter.createObservableCounter( + name, + { + description: 'sample observable counter description', + valueType: ValueType.DOUBLE, + }, + callback + ); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockObservableUpDownCounter( + callback: (observableResult: ObservableResult) => unknown, + name = 'double-up-down-observable-counter' +): metrics.Metric & ObservableUpDownCounter { + const metric = + meter['_metrics'].get(name) || + meter.createObservableUpDownCounter( + name, + { + description: 'sample observable up down counter description', + valueType: ValueType.DOUBLE, + }, + callback + ); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockHistogram(): metrics.Metric & + Histogram { + const name = 'int-histogram'; + const metric = + meter['_metrics'].get(name) || + meter.createHistogram(name, { + description: 'sample histogram description', + valueType: ValueType.INT, + boundaries: [0, 100], + }); + metric.clear(); + metric.bind({}); + return metric; +} + +export const mockedResources: Resource[] = [ + new Resource({ name: 'resource 1' }), + new Resource({ name: 'resource 2' }), +]; + +export const mockedInstrumentationLibraries: InstrumentationLibrary[] = [ + { + name: 'lib1', + version: '0.0.1', + }, + { + name: 'lib2', + version: '0.0.2', + }, +]; + +export const multiResourceMetricsGet = function ( + callback: (observableResult: ObservableResult) => unknown +): any[] { + return [ + { + ...mockCounter(), + resource: mockedResources[0], + instrumentationLibrary: mockedInstrumentationLibraries[0], + }, + { + ...mockObservableGauge(callback), + resource: mockedResources[1], + instrumentationLibrary: mockedInstrumentationLibraries[0], + }, + { + ...mockCounter(), + resource: mockedResources[0], + instrumentationLibrary: mockedInstrumentationLibraries[0], + }, + ]; +}; + +export const multiInstrumentationLibraryMetricsGet = function ( + callback: (observableResult: ObservableResult) => unknown +): any[] { + return [ + { + ...mockCounter(), + resource: mockedResources[0], + instrumentationLibrary: mockedInstrumentationLibraries[0], + }, + { + ...mockObservableGauge(callback), + resource: mockedResources[0], + instrumentationLibrary: mockedInstrumentationLibraries[1], + }, + { + ...mockCounter(), + resource: mockedResources[0], + instrumentationLibrary: mockedInstrumentationLibraries[0], + }, + ]; +}; + +export function ensureAttributesAreCorrect( + attributes: otlpTypes.opentelemetryProto.common.v1.KeyValue[] +) { + assert.deepStrictEqual( + attributes, + [ + { + key: 'component', + value: { + stringValue: 'document-load', + }, + }, + ], + 'attributes are incorrect' + ); +} + +export function ensureWebResourceIsCorrect( + resource: otlpTypes.opentelemetryProto.resource.v1.Resource +) { + assert.strictEqual(resource.attributes.length, 7); + assert.strictEqual(resource.attributes[0].key, 'service.name'); + assert.strictEqual(resource.attributes[0].value.stringValue, 'unknown_service'); + assert.strictEqual(resource.attributes[1].key, 'telemetry.sdk.language'); + assert.strictEqual(resource.attributes[1].value.stringValue, 'webjs'); + assert.strictEqual(resource.attributes[2].key, 'telemetry.sdk.name'); + assert.strictEqual(resource.attributes[2].value.stringValue, 'opentelemetry'); + assert.strictEqual(resource.attributes[3].key, 'telemetry.sdk.version'); + assert.strictEqual(resource.attributes[3].value.stringValue, VERSION); + assert.strictEqual(resource.attributes[4].key, 'service'); + assert.strictEqual(resource.attributes[4].value.stringValue, 'ui'); + assert.strictEqual(resource.attributes[5].key, 'version'); + assert.strictEqual(resource.attributes[5].value.intValue, 1); + assert.strictEqual(resource.attributes[6].key, 'cost'); + assert.strictEqual(resource.attributes[6].value.doubleValue, 112.12); + assert.strictEqual(resource.droppedAttributesCount, 0); +} + +export function ensureCounterIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time: number +) { + assert.deepStrictEqual(metric, { + name: 'int-counter', + description: 'sample counter description', + unit: '1', + intSum: { + dataPoints: [ + { + labels: [], + value: 1, + startTimeUnixNano: 1592602232694000000, + timeUnixNano: time, + }, + ], + isMonotonic: true, + aggregationTemporality: + otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality + .AGGREGATION_TEMPORALITY_CUMULATIVE, + }, + }); +} + +export function ensureDoubleCounterIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time: number +) { + assert.deepStrictEqual(metric, { + name: 'double-counter', + description: 'sample counter description', + unit: '1', + doubleSum: { + dataPoints: [ + { + labels: [], + value: 8, + startTimeUnixNano: 1592602232694000000, + timeUnixNano: time, + }, + ], + isMonotonic: true, + aggregationTemporality: + otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality + .AGGREGATION_TEMPORALITY_CUMULATIVE, + }, + }); +} + +export function ensureObservableGaugeIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time: number, + value: number, + name = 'double-observable-gauge' +) { + assert.deepStrictEqual(metric, { + name, + description: 'sample observable gauge description', + unit: '1', + doubleGauge: { + dataPoints: [ + { + labels: [], + value, + startTimeUnixNano: 1592602232694000000, + timeUnixNano: time, + }, + ], + }, + }); +} + +export function ensureObservableCounterIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time: number, + value: number, + name = 'double-observable-counter' +) { + assert.deepStrictEqual(metric, { + name, + description: 'sample observable counter description', + unit: '1', + doubleSum: { + isMonotonic: true, + dataPoints: [ + { + labels: [], + value, + startTimeUnixNano: 1592602232694000000, + timeUnixNano: time, + }, + ], + aggregationTemporality: + otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality + .AGGREGATION_TEMPORALITY_CUMULATIVE, + }, + }); +} + +export function ensureObservableUpDownCounterIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time: number, + value: number, + name = 'double-up-down-observable-counter' +) { + assert.deepStrictEqual(metric, { + name, + description: 'sample observable up down counter description', + unit: '1', + doubleSum: { + isMonotonic: false, + dataPoints: [ + { + labels: [], + value, + startTimeUnixNano: 1592602232694000000, + timeUnixNano: time, + }, + ], + aggregationTemporality: + otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality + .AGGREGATION_TEMPORALITY_CUMULATIVE, + }, + }); +} + +export function ensureHistogramIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time: number, + explicitBounds: (number | null)[] = [Infinity], + bucketCounts: number[] = [2, 0] +) { + assert.deepStrictEqual(metric, { + name: 'int-histogram', + description: 'sample histogram description', + unit: '1', + intHistogram: { + dataPoints: [ + { + labels: [], + sum: 21, + count: 2, + startTimeUnixNano: 1592602232694000000, + timeUnixNano: time, + bucketCounts, + explicitBounds, + }, + ], + aggregationTemporality: + otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality + .AGGREGATION_TEMPORALITY_CUMULATIVE, + }, + }); +} + +export function ensureExportMetricsServiceRequestIsSet( + json: otlpTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest +) { + const resourceMetrics = json.resourceMetrics; + assert.strictEqual( + resourceMetrics.length, + 1, + 'resourceMetrics has incorrect length' + ); + + const resource = resourceMetrics[0].resource; + assert.strictEqual(!!resource, true, 'resource is missing'); + + const instrumentationLibraryMetrics = + resourceMetrics[0].instrumentationLibraryMetrics; + assert.strictEqual( + instrumentationLibraryMetrics && instrumentationLibraryMetrics.length, + 1, + 'instrumentationLibraryMetrics is missing' + ); + + const instrumentationLibrary = + instrumentationLibraryMetrics[0].instrumentationLibrary; + assert.strictEqual( + !!instrumentationLibrary, + true, + 'instrumentationLibrary is missing' + ); + + const metrics = resourceMetrics[0].instrumentationLibraryMetrics[0].metrics; + assert.strictEqual(metrics.length, 3, 'Metrics are missing'); +} + +export function ensureHeadersContain( + actual: { [key: string]: string }, + expected: { [key: string]: string } +) { + Object.entries(expected).forEach(([k, v]) => { + assert.strictEqual( + v, + actual[k], + `Expected ${actual} to contain ${k}: ${v}` + ); + }); +} diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/node/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts similarity index 91% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/node/CollectorMetricExporter.test.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts index 4937ef3737..f0beecd795 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/node/CollectorMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts @@ -17,14 +17,14 @@ import { diag } from '@opentelemetry/api'; import { Counter, - ValueObserver, - ValueRecorder, + ObservableGauge, + Histogram, } from '@opentelemetry/api-metrics'; import * as core from '@opentelemetry/core'; import { BoundCounter, - BoundObserver, - BoundValueRecorder, + BoundObservable, + BoundHistogram, Metric, MetricRecord, } from '@opentelemetry/sdk-metrics-base'; @@ -32,19 +32,18 @@ import * as assert from 'assert'; import * as http from 'http'; import * as sinon from 'sinon'; import { - OTLPExporterNodeConfigBase, OTLPMetricExporter, } from '../../src/platform/node'; -import * as otlpTypes from '../../src/types'; +import { OTLPExporterNodeConfigBase, otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import { ensureCounterIsCorrect, ensureExportMetricsServiceRequestIsSet, - ensureObserverIsCorrect, - ensureValueRecorderIsCorrect, + ensureObservableGaugeIsCorrect, + ensureHistogramIsCorrect, mockCounter, - mockObserver, - mockValueRecorder, -} from '../helper'; + mockObservableGauge, + mockHistogram, +} from '../metricsHelper'; import { MockedResponse } from './nodeHelpers'; const fakeRequest = { @@ -149,21 +148,21 @@ describe('OTLPMetricExporter - node with json over http', () => { }); metrics = []; const counter: Metric & Counter = mockCounter(); - const observer: Metric & ValueObserver = mockObserver( - observerResult => { - observerResult.observe(6, {}); + const observableGauge: Metric & ObservableGauge = mockObservableGauge( + observableResult => { + observableResult.observe(6, {}); }, - 'double-observer2' + 'double-observable-gauge2' ); - const recorder: Metric & - ValueRecorder = mockValueRecorder(); + const histogram: Metric & + Histogram = mockHistogram(); counter.add(1); - recorder.record(7); - recorder.record(14); + histogram.record(7); + histogram.record(14); metrics.push((await counter.getMetricRecord())[0]); - metrics.push((await observer.getMetricRecord())[0]); - metrics.push((await recorder.getMetricRecord())[0]); + metrics.push((await observableGauge.getMetricRecord())[0]); + metrics.push((await histogram.getMetricRecord())[0]); }); it('should open the connection', done => { @@ -224,15 +223,15 @@ describe('OTLPMetricExporter - node with json over http', () => { metric1, core.hrTimeToNanoseconds(metrics[0].aggregator.toPoint().timestamp) ); - assert.ok(typeof metric2 !== 'undefined', "observer doesn't exist"); - ensureObserverIsCorrect( + assert.ok(typeof metric2 !== 'undefined', "observable gauge doesn't exist"); + ensureObservableGaugeIsCorrect( metric2, core.hrTimeToNanoseconds(metrics[1].aggregator.toPoint().timestamp), 6, - 'double-observer2' + 'double-observable-gauge2' ); assert.ok(typeof metric3 !== 'undefined', "histogram doesn't exist"); - ensureValueRecorderIsCorrect( + ensureHistogramIsCorrect( metric3, core.hrTimeToNanoseconds(metrics[2].aggregator.toPoint().timestamp), [0, 100], diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/node/nodeHelpers.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/nodeHelpers.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/node/nodeHelpers.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/nodeHelpers.ts diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.esm.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.esm.json new file mode 100644 index 0000000000..379f547a46 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.esm.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.base.esm.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build/esm", + "tsBuildInfoFile": "build/esm/tsconfig.esm.tsbuildinfo" + }, + "include": [ + "src/**/*.ts" + ] +} diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.json new file mode 100644 index 0000000000..ed9d0830bd --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "build" + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ] +} diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/.eslintignore b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/.eslintignore similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/.eslintignore rename to experimental/packages/opentelemetry-exporter-metrics-otlp-proto/.eslintignore diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/.eslintrc.js b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/.eslintrc.js similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/.eslintrc.js rename to experimental/packages/opentelemetry-exporter-metrics-otlp-proto/.eslintrc.js diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/.npmignore b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/.npmignore similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/.npmignore rename to experimental/packages/opentelemetry-exporter-metrics-otlp-proto/.npmignore diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/LICENSE b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/LICENSE similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/LICENSE rename to experimental/packages/opentelemetry-exporter-metrics-otlp-proto/LICENSE diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md new file mode 100644 index 0000000000..efcfa521ca --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/README.md @@ -0,0 +1,71 @@ +# OpenTelemetry Collector Metrics Exporter for node with protobuf + +[![NPM Published Version][npm-img]][npm-url] +[![dependencies][dependencies-image]][dependencies-url] +[![devDependencies][devDependencies-image]][devDependencies-url] +[![Apache License][license-image]][license-image] + +This module provides exporter for node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.25.0**. + +## Installation + +```bash +npm install --save @opentelemetry/exporter-metrics-otlp-proto +``` + +## Service Name + +The OpenTelemetry Collector Exporter does not have a service name configuration. +In order to set the service name, use the `service.name` resource attribute as prescribed in the [OpenTelemetry Resource Semantic Conventions][semconv-resource-service-name]. +To see sample code and documentation for the traces exporter, visit the [Collector Trace Exporter for web and node][trace-exporter-url]. + +## Metrics in Node - PROTO over http + +```js +const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); +const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-proto'); +const collectorOptions = { + url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/metrics +}; +const exporter = new OTLPMetricExporter(collectorOptions); + +// Register the exporter +const meter = new MeterProvider({ + exporter, + interval: 60000, +}).getMeter('example-meter'); + +// Now, start recording data +const counter = meter.createCounter('metric_name'); +counter.add(10, { 'key': 'value' }); + +``` + +## Running opentelemetry-collector locally to see the metrics + +1. Go to examples/otlp-exporter-node +2. run `npm run docker:start` +3. Open page at `http://localhost:9411/zipkin/` to observe the metrics + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us in [GitHub Discussions][discussions-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions +[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-proto +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-proto +[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-proto&type=dev +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=experimental%2Fpackages%2Fopentelemetry-exporter-metrics-otlp-proto&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-metrics-otlp-proto +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-metrics-otlp-proto.svg +[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector +[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service +[trace-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-trace-otlp-http diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json new file mode 100644 index 0000000000..ff27c37db1 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json @@ -0,0 +1,79 @@ +{ + "name": "@opentelemetry/exporter-metrics-otlp-proto", + "version": "0.26.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", + "repository": "open-telemetry/opentelemetry-js", + "scripts": { + "compile": "tsc --build", + "clean": "tsc --build --clean", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "postcompile": "npm run submodule && npm run protos:copy", + "protos:copy": "cpx protos/opentelemetry/**/*.* build/protos/opentelemetry", + "submodule": "git submodule sync --recursive && git submodule update --init --recursive", + "tdd": "npm run test -- --watch-extensions ts --watch", + "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", + "version": "node ../../../scripts/version-update.js", + "watch": "npm run protos:copy && tsc -w", + "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "prewatch": "npm run precompile" + }, + "keywords": [ + "opentelemetry", + "nodejs", + "protobuf", + "tracing", + "profiling", + "metrics", + "stats" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.js.map", + "build/src/**/*.d.ts", + "build/protos/**/*.proto", + "doc", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@opentelemetry/api": "^1.0.3", + "@babel/core": "7.15.0", + "@opentelemetry/api-metrics": "0.26.0", + "@types/mocha": "8.2.3", + "@types/node": "14.17.11", + "@types/sinon": "10.0.2", + "codecov": "3.8.3", + "cpx": "1.5.0", + "mocha": "7.2.0", + "nyc": "15.1.0", + "rimraf": "3.0.2", + "sinon": "12.0.1", + "ts-loader": "8.3.0", + "ts-mocha": "8.0.0", + "typescript": "4.3.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.3" + }, + "dependencies": { + "@grpc/proto-loader": "^0.6.4", + "@opentelemetry/core": "1.0.0", + "@opentelemetry/exporter-trace-otlp-http": "0.26.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.26.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.26.0", + "@opentelemetry/sdk-metrics-base": "0.26.0", + "@opentelemetry/resources": "1.0.0", + "protobufjs": "^6.9.0" + } +} diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/protos b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/protos similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/protos rename to experimental/packages/opentelemetry-exporter-metrics-otlp-proto/protos diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts similarity index 90% rename from experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPMetricExporter.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts index bd1bc75c17..9bbbfa6c66 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts @@ -16,13 +16,12 @@ import { otlpTypes, - toOTLPExportMetricServiceRequest, OTLPExporterNodeConfigBase, appendResourcePathToUrlIfNotPresent, -} from '@opentelemetry/exporter-otlp-http'; +} from '@opentelemetry/exporter-trace-otlp-http'; +import { toOTLPExportMetricServiceRequest } from '@opentelemetry/exporter-metrics-otlp-http'; import { MetricRecord, MetricExporter } from '@opentelemetry/sdk-metrics-base'; -import { ServiceClientType } from './types'; -import { OTLPExporterNodeBase } from './OTLPExporterNodeBase'; +import { ServiceClientType, OTLPExporterNodeBase } from '@opentelemetry/exporter-trace-otlp-proto'; import { getEnv, baggageUtils } from '@opentelemetry/core'; const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics'; diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/index.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/index.ts new file mode 100644 index 0000000000..7b73804ce4 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/index.ts @@ -0,0 +1,17 @@ +/* + * 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 * from './OTLPMetricExporter'; diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/submodule.md b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/submodule.md new file mode 100644 index 0000000000..bbbca131ad --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/submodule.md @@ -0,0 +1,45 @@ +# Important + +**Submodule is always pointing to certain revision number. So updating the submodule repo will not have impact on your code. +Knowing this if you want to change the submodule to point to a different version (when for example proto has changed) here is how to do it:** + +## Updating submodule to point to certain revision number + +1. Make sure you are in the same folder as this instruction + +2. Update your submodules by running this command + + ```shell script + git submodule sync --recursive + git submodule update --init --recursive + ``` + +3. Find the SHA which you want to update to and copy it (the long one) + +4. Enter a submodule directory from this directory + + ```shell script + cd protos + ``` + +5. Updates files in the submodule tree to given commit: + + ```shell script + git checkout -q + ``` + +6. Return to the main directory: + + ```shell script + cd ../ + ``` + +7. Please run `git status` you should see something like `Head detached at`. This is correct, go to next step + +8. Now thing which is very important. You have to commit this to apply these changes + + ```shell script + git commit -am "chore: updating submodule for opentelemetry-proto" + ``` + +9. If you look now at git log you will notice that the folder `protos` has been changed and it will show what was the previous sha and what is current one. diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/OTLPMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts similarity index 89% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/OTLPMetricExporter.test.ts rename to experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts index 17716f0887..831b66780e 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/test/OTLPMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts @@ -17,30 +17,31 @@ import { diag } from '@opentelemetry/api'; import { Counter, - ValueObserver, - ValueRecorder, + ObservableGauge, + Histogram, } from '@opentelemetry/api-metrics'; import { ExportResultCode } from '@opentelemetry/core'; import { OTLPExporterNodeConfigBase, otlpTypes, -} from '@opentelemetry/exporter-otlp-http'; +} from '@opentelemetry/exporter-trace-otlp-http'; +import { getExportRequestProto } from '@opentelemetry/exporter-trace-otlp-proto'; import * as metrics from '@opentelemetry/sdk-metrics-base'; import * as assert from 'assert'; import * as http from 'http'; import * as sinon from 'sinon'; import { OTLPMetricExporter } from '../src'; -import { getExportRequestProto } from '../src/util'; + import { ensureExportedCounterIsCorrect, - ensureExportedObserverIsCorrect, - ensureExportedValueRecorderIsCorrect, + ensureExportedObservableGaugeIsCorrect, + ensureExportedHistogramIsCorrect, ensureExportMetricsServiceRequestIsSet, mockCounter, MockedResponse, - mockObserver, - mockValueRecorder, -} from './helper'; + mockObservableGauge, + mockHistogram, +} from './metricsHelper'; const fakeRequest = { end: function () {}, @@ -121,21 +122,21 @@ describe('OTLPMetricExporter - node with proto over http', () => { metrics = []; const counter: metrics.Metric & Counter = mockCounter(); - const observer: metrics.Metric & - ValueObserver = mockObserver(observerResult => { - observerResult.observe(3, {}); - observerResult.observe(6, {}); + const observableGauge: metrics.Metric & + ObservableGauge = mockObservableGauge(observableResult => { + observableResult.observe(3, {}); + observableResult.observe(6, {}); }); - const recorder: metrics.Metric & - ValueRecorder = mockValueRecorder(); + const histogram: metrics.Metric & + Histogram = mockHistogram(); counter.add(1); - recorder.record(7); - recorder.record(14); + histogram.record(7); + histogram.record(14); metrics.push((await counter.getMetricRecord())[0]); - metrics.push((await observer.getMetricRecord())[0]); - metrics.push((await recorder.getMetricRecord())[0]); + metrics.push((await observableGauge.getMetricRecord())[0]); + metrics.push((await histogram.getMetricRecord())[0]); }); afterEach(() => { sinon.restore(); @@ -197,8 +198,8 @@ describe('OTLPMetricExporter - node with proto over http', () => { metric1, metric1.intSum?.dataPoints[0].timeUnixNano ); - assert.ok(typeof metric2 !== 'undefined', "observer doesn't exist"); - ensureExportedObserverIsCorrect( + assert.ok(typeof metric2 !== 'undefined', "observable gauge doesn't exist"); + ensureExportedObservableGaugeIsCorrect( metric2, metric2.doubleGauge?.dataPoints[0].timeUnixNano ); @@ -206,7 +207,7 @@ describe('OTLPMetricExporter - node with proto over http', () => { typeof metric3 !== 'undefined', "value recorder doesn't exist" ); - ensureExportedValueRecorderIsCorrect( + ensureExportedHistogramIsCorrect( metric3, metric3.intHistogram?.dataPoints[0].timeUnixNano, [0, 100], diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts new file mode 100644 index 0000000000..b400f76a33 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts @@ -0,0 +1,223 @@ +/* + * 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 { + Counter, + ObservableResult, + ObservableGauge, + Histogram, + ValueType, +} from '@opentelemetry/api-metrics'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; +import * as metrics from '@opentelemetry/sdk-metrics-base'; +import { Resource } from '@opentelemetry/resources'; +import * as assert from 'assert'; +import { Stream } from 'stream'; + +const meterProvider = new metrics.MeterProvider({ + interval: 30000, + resource: new Resource({ + service: 'ui', + version: 1, + cost: 112.12, + }), +}); + +const meter = meterProvider.getMeter('default', '0.0.1'); + +export function mockCounter(): metrics.Metric & Counter { + const name = 'int-counter'; + const metric = + meter['_metrics'].get(name) || + meter.createCounter(name, { + description: 'sample counter description', + valueType: ValueType.INT, + }); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockObservableGauge( + callback: (observableResult: ObservableResult) => void +): metrics.Metric & ObservableGauge { + const name = 'double-observable-gauge'; + const metric = + meter['_metrics'].get(name) || + meter.createObservableGauge( + name, + { + description: 'sample observable gauge description', + valueType: ValueType.DOUBLE, + }, + callback + ); + metric.clear(); + metric.bind({}); + return metric; +} + +export function mockHistogram(): metrics.Metric & + Histogram { + const name = 'int-histogram'; + const metric = + meter['_metrics'].get(name) || + meter.createHistogram(name, { + description: 'sample histogram description', + valueType: ValueType.INT, + boundaries: [0, 100], + }); + metric.clear(); + metric.bind({}); + return metric; +} + +export function ensureProtoAttributesAreCorrect( + attributes: otlpTypes.opentelemetryProto.common.v1.KeyValue[] +) { + assert.deepStrictEqual( + attributes, + [ + { + key: 'component', + value: { + stringValue: 'document-load', + }, + }, + ], + 'attributes are incorrect' + ); +} + +export function ensureExportedCounterIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time?: number +) { + assert.deepStrictEqual(metric, { + name: 'int-counter', + description: 'sample counter description', + unit: '1', + intSum: { + dataPoints: [ + { + value: '1', + startTimeUnixNano: '1592602232694000128', + timeUnixNano: String(time), + }, + ], + isMonotonic: true, + aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', + }, + }); +} + +export function ensureExportedObservableGaugeIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time?: number +) { + assert.deepStrictEqual(metric, { + name: 'double-observable-gauge', + description: 'sample observable gauge description', + unit: '1', + doubleGauge: { + dataPoints: [ + { + value: 6, + startTimeUnixNano: '1592602232694000128', + timeUnixNano: String(time), + }, + ], + }, + }); +} + +export function ensureExportedHistogramIsCorrect( + metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, + time?: number, + explicitBounds: number[] = [Infinity], + bucketCounts: string[] = ['2', '0'] +) { + assert.deepStrictEqual(metric, { + name: 'int-histogram', + description: 'sample histogram description', + unit: '1', + intHistogram: { + dataPoints: [ + { + sum: '21', + count: '2', + startTimeUnixNano: '1592602232694000128', + timeUnixNano: time, + bucketCounts, + explicitBounds, + }, + ], + aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', + }, + }); +} + +export function ensureExportMetricsServiceRequestIsSet( + json: otlpTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest +) { + const resourceMetrics = json.resourceMetrics; + assert.strictEqual( + resourceMetrics.length, + 1, + 'resourceMetrics has incorrect length' + ); + + const resource = resourceMetrics[0].resource; + assert.strictEqual(!!resource, true, 'resource is missing'); + + const instrumentationLibraryMetrics = + resourceMetrics[0].instrumentationLibraryMetrics; + assert.strictEqual( + instrumentationLibraryMetrics && instrumentationLibraryMetrics.length, + 1, + 'instrumentationLibraryMetrics is missing' + ); + + const instrumentationLibrary = + instrumentationLibraryMetrics[0].instrumentationLibrary; + assert.strictEqual( + !!instrumentationLibrary, + true, + 'instrumentationLibrary is missing' + ); + + const metrics = resourceMetrics[0].instrumentationLibraryMetrics[0].metrics; + assert.strictEqual(metrics.length, 3, 'Metrics are missing'); +} + +export class MockedResponse extends Stream { + constructor(private _code: number, private _msg?: string) { + super(); + } + + send(data: string) { + this.emit('data', data); + this.emit('end'); + } + + get statusCode() { + return this._code; + } + + get statusMessage() { + return this._msg; + } +} diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json new file mode 100644 index 0000000000..03a463d637 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "build" + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ], + "references": [ + { + "path": "../opentelemetry-sdk-metrics-base" + }, + { + "path": "../opentelemetry-exporter-metrics-otlp-http" + } + ] +} diff --git a/experimental/packages/opentelemetry-exporter-prometheus/README.md b/experimental/packages/opentelemetry-exporter-prometheus/README.md index 95ad498edf..9d401c0e62 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/README.md +++ b/experimental/packages/opentelemetry-exporter-prometheus/README.md @@ -40,11 +40,6 @@ const counter = meter.createCounter('metric_name', { }); counter.add(10, { pid: process.pid }); -// Record data using Instrument: It is recommended to keep a reference to the Bound Instrument instead of -// always calling `bind()` method for every operations. -const boundCounter = counter.bind({ pid: process.pid }); -boundCounter.add(10); - // .. some other work ``` diff --git a/experimental/packages/opentelemetry-exporter-prometheus/package.json b/experimental/packages/opentelemetry-exporter-prometheus/package.json index a8af029d50..0ddfd28e68 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/package.json +++ b/experimental/packages/opentelemetry-exporter-prometheus/package.json @@ -41,7 +41,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", @@ -49,12 +49,12 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@opentelemetry/api-metrics": "0.26.0", diff --git a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusLabelsBatcher.ts b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusAttributesBatcher.ts similarity index 90% rename from experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusLabelsBatcher.ts rename to experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusAttributesBatcher.ts index d04e87f532..1ac7bb5ac9 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusLabelsBatcher.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusAttributesBatcher.ts @@ -26,7 +26,7 @@ interface BatcherCheckpoint { records: Map; } -export class PrometheusLabelsBatcher { +export class PrometheusAttributesBatcher { private _batchMap = new Map(); get hasMetric(): boolean { @@ -45,10 +45,10 @@ export class PrometheusLabelsBatcher { this._batchMap.set(name, item); } const recordMap = item.records; - const labels = Object.keys(record.labels) - .map(k => `${k}=${record.labels[k]}`) + const attributes = Object.keys(record.attributes) + .map(k => `${k}=${record.attributes[k]}`) .join(','); - recordMap.set(labels, record); + recordMap.set(attributes, record); } checkPointSet(): PrometheusCheckpoint[] { diff --git a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts index 35c1de5bd9..807b7a6636 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusExporter.ts @@ -25,7 +25,7 @@ import { createServer, IncomingMessage, Server, ServerResponse } from 'http'; import * as url from 'url'; import { ExporterConfig } from './export/types'; import { PrometheusSerializer } from './PrometheusSerializer'; -import { PrometheusLabelsBatcher } from './PrometheusLabelsBatcher'; +import { PrometheusAttributesBatcher } from './PrometheusAttributesBatcher'; export class PrometheusExporter implements MetricExporter { static readonly DEFAULT_OPTIONS = { @@ -43,10 +43,10 @@ export class PrometheusExporter implements MetricExporter { private readonly _prefix?: string; private readonly _appendTimestamp: boolean; private _serializer: PrometheusSerializer; - private _batcher = new PrometheusLabelsBatcher(); + private _batcher = new PrometheusAttributesBatcher(); // This will be required when histogram is implemented. Leaving here so it is not forgotten - // Histogram cannot have a label named 'le' + // Histogram cannot have a attribute named 'le' // private static readonly RESERVED_HISTOGRAM_LABEL = 'le'; /** @@ -68,7 +68,8 @@ export class PrometheusExporter implements MetricExporter { typeof config.appendTimestamp === 'boolean' ? config.appendTimestamp : PrometheusExporter.DEFAULT_OPTIONS.appendTimestamp; - this._server = createServer(this._requestHandler); + // unref to prevent prometheus exporter from holding the process open on exit + this._server = createServer(this._requestHandler).unref(); this._serializer = new PrometheusSerializer( this._prefix, this._appendTimestamp diff --git a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts index e62ba0478a..c08943cffa 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts @@ -19,7 +19,7 @@ import { MetricKind, } from '@opentelemetry/sdk-metrics-base'; import { PrometheusCheckpoint } from './types'; -import { Labels } from '@opentelemetry/api-metrics'; +import { Attributes } from '@opentelemetry/api-metrics'; import { hrTimeToMilliseconds } from '@opentelemetry/core'; type PrometheusDataTypeLiteral = @@ -33,7 +33,7 @@ function escapeString(str: string) { return str.replace(/\\/g, '\\\\').replace(/\n/g, '\\n'); } -function escapeLabelValue(str: string) { +function escapeAttributeValue(str: string) { if (typeof str !== 'string') { str = String(str); } @@ -45,7 +45,7 @@ const invalidCharacterRegex = /[^a-z0-9_]/gi; * Ensures metric names are valid Prometheus metric names by removing * characters allowed by OpenTelemetry but disallowed by Prometheus. * - * https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels + * https://prometheus.io/docs/concepts/data_model/#metric-names-and-attributes * * 1. Names must match `[a-zA-Z_:][a-zA-Z0-9_:]*` * @@ -106,11 +106,11 @@ function toPrometheusType( case AggregatorKind.SUM: if ( metricKind === MetricKind.COUNTER || - metricKind === MetricKind.SUM_OBSERVER + metricKind === MetricKind.OBSERVABLE_COUNTER ) { return 'counter'; } - /** MetricKind.UP_DOWN_COUNTER and MetricKind.UP_DOWN_SUM_OBSERVER */ + /** MetricKind.UP_DOWN_COUNTER and MetricKind.OBSERVABLE_UP_DOWN_COUNTER */ return 'gauge'; case AggregatorKind.LAST_VALUE: return 'gauge'; @@ -123,33 +123,33 @@ function toPrometheusType( function stringify( metricName: string, - labels: Labels, + attributes: Attributes, value: number, timestamp?: number, - additionalLabels?: Labels + additionalAttributes?: Attributes ) { - let hasLabel = false; - let labelsStr = ''; + let hasAttribute = false; + let attributesStr = ''; - for (const [key, val] of Object.entries(labels)) { - const sanitizedLabelName = sanitizePrometheusMetricName(key); - hasLabel = true; - labelsStr += `${ - labelsStr.length > 0 ? ',' : '' - }${sanitizedLabelName}="${escapeLabelValue(val)}"`; + for (const [key, val] of Object.entries(attributes)) { + const sanitizedAttributeName = sanitizePrometheusMetricName(key); + hasAttribute = true; + attributesStr += `${ + attributesStr.length > 0 ? ',' : '' + }${sanitizedAttributeName}="${escapeAttributeValue(val)}"`; } - if (additionalLabels) { - for (const [key, val] of Object.entries(additionalLabels)) { - const sanitizedLabelName = sanitizePrometheusMetricName(key); - hasLabel = true; - labelsStr += `${ - labelsStr.length > 0 ? ',' : '' - }${sanitizedLabelName}="${escapeLabelValue(val)}"`; + if (additionalAttributes) { + for (const [key, val] of Object.entries(additionalAttributes)) { + const sanitizedAttributeName = sanitizePrometheusMetricName(key); + hasAttribute = true; + attributesStr += `${ + attributesStr.length > 0 ? ',' : '' + }${sanitizedAttributeName}="${escapeAttributeValue(val)}"`; } } - if (hasLabel) { - metricName += `{${labelsStr}}`; + if (hasAttribute) { + metricName += `{${attributesStr}}`; } return `${metricName} ${valueString(value)}${ @@ -219,7 +219,7 @@ export class PrometheusSerializer { const timestamp = hrTimeToMilliseconds(hrtime); results += stringify( name, - record.labels, + record.attributes, value, this._appendTimestamp ? timestamp : undefined, undefined @@ -233,7 +233,7 @@ export class PrometheusSerializer { for (const key of ['count', 'sum'] as ('count' | 'sum')[]) { results += stringify( name + '_' + key, - record.labels, + record.attributes, value[key], this._appendTimestamp ? timestamp : undefined, undefined @@ -260,7 +260,7 @@ export class PrometheusSerializer { } results += stringify( name + '_bucket', - record.labels, + record.attributes, cumulativeSum, this._appendTimestamp ? timestamp : undefined, { diff --git a/experimental/packages/opentelemetry-exporter-prometheus/test/ExactProcessor.ts b/experimental/packages/opentelemetry-exporter-prometheus/test/ExactProcessor.ts index 6330e93eb5..f69b716ad4 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/test/ExactProcessor.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/test/ExactProcessor.ts @@ -41,9 +41,9 @@ export class ExactProcessor extends Processor { } process(record: MetricRecord): void { - const labels = Object.keys(record.labels) - .map(k => `${k}=${record.labels[k]}`) + const attributes = Object.keys(record.attributes) + .map(k => `${k}=${record.attributes[k]}`) .join(','); - this._batchMap.set(record.descriptor.name + labels, record); + this._batchMap.set(record.descriptor.name + attributes, record); } } diff --git a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts index 11d0090861..8808c092ee 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusExporter.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ObserverResult } from '@opentelemetry/api-metrics'; +import { ObservableResult } from '@opentelemetry/api-metrics'; import { CounterMetric, SumAggregator, @@ -36,6 +36,7 @@ describe('PrometheusExporter', () => { mockAggregator(HistogramAggregator); afterEach(() => { + sinon.restore(); delete process.env.OTEL_EXPORTER_PROMETHEUS_HOST; delete process.env.OTEL_EXPORTER_PROMETHEUS_PORT; }); @@ -116,6 +117,16 @@ describe('PrometheusExporter', () => { ); }); + it('should unref the server to allow graceful termination', () => { + const mockServer = sinon.createStubInstance(http.Server); + const createStub = sinon.stub(http, 'createServer'); + createStub.returns((mockServer as any) as http.Server); + const exporter = new PrometheusExporter({}, async () => { + await exporter.shutdown(); + }); + sinon.assert.calledOnce(mockServer.unref); + }); + it('should listen on environmentally set host and port', () => { process.env.OTEL_EXPORTER_PROMETHEUS_HOST = '127.0.0.1'; process.env.OTEL_EXPORTER_PROMETHEUS_PORT = '1234'; @@ -216,10 +227,9 @@ describe('PrometheusExporter', () => { exporter = new PrometheusExporter({}, () => { meterProvider = new MeterProvider({ interval: Math.pow(2, 31) - 1, - }); - meter = meterProvider.getMeter('test-prometheus', '1', { exporter, }); + meter = meterProvider.getMeter('test-prometheus', '1'); done(); }); }); @@ -233,15 +243,14 @@ describe('PrometheusExporter', () => { description: 'a test description', }); - const boundCounter = counter.bind({ key1: 'labelValue1' }); - boundCounter.add(10); + counter.add(10, { key1: 'attributeValue1' }); meter.collect().then(() => { exporter.export(meter.getProcessor().checkPointSet(), () => { // TODO: Remove this special case once the PR is ready. // This is to test the special case where counters are destroyed // and recreated in the exporter in order to get around prom-client's // aggregation and use ours. - boundCounter.add(10); + counter.add(10, { key1: 'attributeValue1' }); exporter.export(meter.getProcessor().checkPointSet(), () => { http .get('http://localhost:9464/metrics', res => { @@ -257,7 +266,7 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(lines, [ '# HELP counter_total a test description', '# TYPE counter_total counter', - `counter_total{key1="labelValue1"} 20 ${mockedHrTimeMs}`, + `counter_total{key1="attributeValue1"} 20 ${mockedHrTimeMs}`, '', ]); @@ -270,18 +279,18 @@ describe('PrometheusExporter', () => { }); }); - it('should export an observer aggregation', done => { + it('should export an observable gauge aggregation', done => { function getCpuUsage() { return 0.999; } - meter.createValueObserver( - 'metric_observer', + meter.createObservableGauge( + 'metric_observable_gauge', { description: 'a test description', }, - (observerResult: ObserverResult) => { - observerResult.observe(getCpuUsage(), { + (observableResult: ObservableResult) => { + observableResult.observe(getCpuUsage(), { pid: String(123), core: '1', }); @@ -298,9 +307,9 @@ describe('PrometheusExporter', () => { const lines = body.split('\n'); assert.deepStrictEqual(lines, [ - '# HELP metric_observer a test description', - '# TYPE metric_observer gauge', - `metric_observer{pid="123",core="1"} 0.999 ${mockedHrTimeMs}`, + '# HELP metric_observable_gauge a test description', + '# TYPE metric_observable_gauge gauge', + `metric_observable_gauge{pid="123",core="1"} 0.999 ${mockedHrTimeMs}`, '', ]); done(); @@ -312,13 +321,13 @@ describe('PrometheusExporter', () => { }); }); - it('should export multiple labels', done => { + it('should export multiple attributes', done => { const counter = meter.createCounter('counter_total', { description: 'a test description', }) as CounterMetric; - counter.bind({ counterKey1: 'labelValue1' }).add(10); - counter.bind({ counterKey1: 'labelValue2' }).add(20); + counter.add(10, { counterKey1: 'attributeValue1' }); + counter.add(20, { counterKey1: 'attributeValue2' }); meter.collect().then(() => { exporter.export(meter.getProcessor().checkPointSet(), () => { http @@ -330,8 +339,8 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(lines, [ '# HELP counter_total a test description', '# TYPE counter_total counter', - `counter_total{counterKey1="labelValue1"} 10 ${mockedHrTimeMs}`, - `counter_total{counterKey1="labelValue2"} 20 ${mockedHrTimeMs}`, + `counter_total{counterKey1="attributeValue1"} 10 ${mockedHrTimeMs}`, + `counter_total{counterKey1="attributeValue2"} 20 ${mockedHrTimeMs}`, '', ]); @@ -343,34 +352,24 @@ describe('PrometheusExporter', () => { }); }); - it('should export multiple labels on manual shutdown', done => { + it('should export multiple attributes on manual shutdown', done => { const counter = meter.createCounter('counter_total', { description: 'a test description', }) as CounterMetric; - counter.bind({ counterKey1: 'labelValue1' }).add(10); - counter.bind({ counterKey1: 'labelValue2' }).add(20); - counter.bind({ counterKey1: 'labelValue3' }).add(30); + counter.add(10, { counterKey1: 'attributeValue1' }); + counter.add(20, { counterKey1: 'attributeValue2' }); + counter.add(30, { counterKey1: 'attributeValue3' }); meterProvider.shutdown().then(() => { + // exporter has been shut down along with meter provider. http .get('http://localhost:9464/metrics', res => { - res.on('data', chunk => { - const body = chunk.toString(); - const lines = body.split('\n'); - - assert.deepStrictEqual(lines, [ - '# HELP counter_total a test description', - '# TYPE counter_total counter', - `counter_total{counterKey1="labelValue1"} 10 ${mockedHrTimeMs}`, - `counter_total{counterKey1="labelValue2"} 20 ${mockedHrTimeMs}`, - `counter_total{counterKey1="labelValue3"} 30 ${mockedHrTimeMs}`, - '', - ]); - - done(); - }); + errorHandler(done)(new Error('unreachable')); }) - .on('error', errorHandler(done)); + .on('error', err => { + assert(`${err}`.match('ECONNREFUSED')); + done(); + }); }); }); @@ -394,8 +393,7 @@ describe('PrometheusExporter', () => { it('should add a description if missing', done => { const counter = meter.createCounter('counter_total'); - const boundCounter = counter.bind({ key1: 'labelValue1' }); - boundCounter.add(10); + counter.add(10, { key1: 'attributeValue1' }); meter.collect().then(() => { exporter.export(meter.getProcessor().checkPointSet(), () => { http @@ -407,7 +405,7 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(lines, [ '# HELP counter_total description missing', '# TYPE counter_total counter', - `counter_total{key1="labelValue1"} 10 ${mockedHrTimeMs}`, + `counter_total{key1="attributeValue1"} 10 ${mockedHrTimeMs}`, '', ]); @@ -421,8 +419,8 @@ describe('PrometheusExporter', () => { it('should sanitize names', done => { const counter = meter.createCounter('counter.bad-name'); - const boundCounter = counter.bind({ key1: 'labelValue1' }); - boundCounter.add(10); + + counter.add(10, { key1: 'attributeValue1' }); meter.collect().then(() => { exporter.export(meter.getProcessor().checkPointSet(), () => { http @@ -434,7 +432,7 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(lines, [ '# HELP counter_bad_name_total description missing', '# TYPE counter_bad_name_total counter', - `counter_bad_name_total{key1="labelValue1"} 10 ${mockedHrTimeMs}`, + `counter_bad_name_total{key1="attributeValue1"} 10 ${mockedHrTimeMs}`, '', ]); @@ -451,7 +449,7 @@ describe('PrometheusExporter', () => { description: 'a test description', }); - counter.bind({ key1: 'labelValue1' }).add(20); + counter.add(20, { key1: 'attributeValue1' }); meter.collect().then(() => { exporter.export(meter.getProcessor().checkPointSet(), () => { http @@ -460,7 +458,7 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(chunk.toString().split('\n'), [ '# HELP counter a test description', '# TYPE counter gauge', - `counter{key1="labelValue1"} 20 ${mockedHrTimeMs}`, + `counter{key1="attributeValue1"} 20 ${mockedHrTimeMs}`, '', ]); @@ -472,19 +470,19 @@ describe('PrometheusExporter', () => { }); }); - it('should export a SumObserver as a counter', done => { + it('should export an ObservableCounter as a counter', done => { function getValue() { return 20; } - meter.createSumObserver( - 'sum_observer', + meter.createObservableCounter( + 'metric_observable_counter', { description: 'a test description', }, - (observerResult: ObserverResult) => { - observerResult.observe(getValue(), { - key1: 'labelValue1', + (observableResult: ObservableResult) => { + observableResult.observe(getValue(), { + key1: 'attributeValue1', }); } ); @@ -498,9 +496,9 @@ describe('PrometheusExporter', () => { const lines = body.split('\n'); assert.deepStrictEqual(lines, [ - '# HELP sum_observer a test description', - '# TYPE sum_observer gauge', - `sum_observer{key1="labelValue1"} 20 ${mockedHrTimeMs}`, + '# HELP metric_observable_counter a test description', + '# TYPE metric_observable_counter gauge', + `metric_observable_counter{key1="attributeValue1"} 20 ${mockedHrTimeMs}`, '', ]); }); @@ -512,19 +510,19 @@ describe('PrometheusExporter', () => { }); }); - it('should export a UpDownSumObserver as a gauge', done => { + it('should export an ObservableUpDownCounter as a gauge', done => { function getValue() { return 20; } - meter.createUpDownSumObserver( - 'updown_observer', + meter.createObservableUpDownCounter( + 'metric_observable_up_down_counter', { description: 'a test description', }, - (observerResult: ObserverResult) => { - observerResult.observe(getValue(), { - key1: 'labelValue1', + (observableResult: ObservableResult) => { + observableResult.observe(getValue(), { + key1: 'attributeValue1', }); } ); @@ -538,9 +536,9 @@ describe('PrometheusExporter', () => { const lines = body.split('\n'); assert.deepStrictEqual(lines, [ - '# HELP updown_observer a test description', - '# TYPE updown_observer gauge', - `updown_observer{key1="labelValue1"} 20 ${mockedHrTimeMs}`, + '# HELP metric_observable_up_down_counter a test description', + '# TYPE metric_observable_up_down_counter gauge', + `metric_observable_up_down_counter{key1="attributeValue1"} 20 ${mockedHrTimeMs}`, '', ]); }); @@ -552,12 +550,12 @@ describe('PrometheusExporter', () => { }); }); - it('should export a ValueRecorder as a summary', done => { - const valueRecorder = meter.createValueRecorder('value_recorder', { + it('should export a Histogram as a summary', done => { + const histogram = meter.createHistogram('test_histogram', { description: 'a test description', }); - valueRecorder.bind({ key1: 'labelValue1' }).record(20); + histogram.record(20, { key1: 'attributeValue1' }); meter.collect().then(() => { exporter.export(meter.getProcessor().checkPointSet(), () => { @@ -568,11 +566,11 @@ describe('PrometheusExporter', () => { const lines = body.split('\n'); assert.deepStrictEqual(lines, [ - '# HELP value_recorder a test description', - '# TYPE value_recorder histogram', - `value_recorder_count{key1="labelValue1"} 1 ${mockedHrTimeMs}`, - `value_recorder_sum{key1="labelValue1"} 20 ${mockedHrTimeMs}`, - `value_recorder_bucket{key1="labelValue1",le="+Inf"} 1 ${mockedHrTimeMs}`, + '# HELP test_histogram a test description', + '# TYPE test_histogram histogram', + `test_histogram_count{key1="attributeValue1"} 1 ${mockedHrTimeMs}`, + `test_histogram_sum{key1="attributeValue1"} 20 ${mockedHrTimeMs}`, + `test_histogram_bucket{key1="attributeValue1",le="+Inf"} 1 ${mockedHrTimeMs}`, '', ]); @@ -593,7 +591,7 @@ describe('PrometheusExporter', () => { beforeEach(() => { meter = new MeterProvider().getMeter('test-prometheus'); counter = meter.createCounter('counter') as CounterMetric; - counter.bind({ key1: 'labelValue1' }).add(10); + counter.add(10, { key1: 'attributeValue1' }); }); afterEach(done => { @@ -622,7 +620,7 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(lines, [ '# HELP test_prefix_counter_total description missing', '# TYPE test_prefix_counter_total counter', - `test_prefix_counter_total{key1="labelValue1"} 10 ${mockedHrTimeMs}`, + `test_prefix_counter_total{key1="attributeValue1"} 10 ${mockedHrTimeMs}`, '', ]); @@ -652,7 +650,7 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(lines, [ '# HELP counter_total description missing', '# TYPE counter_total counter', - `counter_total{key1="labelValue1"} 10 ${mockedHrTimeMs}`, + `counter_total{key1="attributeValue1"} 10 ${mockedHrTimeMs}`, '', ]); @@ -682,7 +680,7 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(lines, [ '# HELP counter_total description missing', '# TYPE counter_total counter', - `counter_total{key1="labelValue1"} 10 ${mockedHrTimeMs}`, + `counter_total{key1="attributeValue1"} 10 ${mockedHrTimeMs}`, '', ]); @@ -712,7 +710,7 @@ describe('PrometheusExporter', () => { assert.deepStrictEqual(lines, [ '# HELP counter_total description missing', '# TYPE counter_total counter', - 'counter_total{key1="labelValue1"} 10', + 'counter_total{key1="attributeValue1"} 10', '', ]); diff --git a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusLabelsBatcher.test.ts b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusLabelsBatcher.test.ts index 6e0a0d38c6..0f1f00f370 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusLabelsBatcher.test.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusLabelsBatcher.test.ts @@ -14,14 +14,14 @@ * limitations under the License. */ import * as assert from 'assert'; -import { PrometheusLabelsBatcher } from '../src/PrometheusLabelsBatcher'; +import { PrometheusAttributesBatcher } from '../src/PrometheusAttributesBatcher'; import { CounterMetric, AggregatorKind, MeterProvider, Meter, } from '@opentelemetry/sdk-metrics-base'; -import { Labels } from '@opentelemetry/api-metrics'; +import { Attributes } from '@opentelemetry/api-metrics'; describe('PrometheusBatcher', () => { let meter: Meter; @@ -31,17 +31,17 @@ describe('PrometheusBatcher', () => { describe('constructor', () => { it('should construct a batcher', () => { - const batcher = new PrometheusLabelsBatcher(); - assert(batcher instanceof PrometheusLabelsBatcher); + const batcher = new PrometheusAttributesBatcher(); + assert(batcher instanceof PrometheusAttributesBatcher); }); }); describe('process', () => { it('should aggregate metric records with same metric name', async () => { - const batcher = new PrometheusLabelsBatcher(); + const batcher = new PrometheusAttributesBatcher(); const counter = meter.createCounter('test_counter') as CounterMetric; - counter.bind({ val: '1' }).add(1); - counter.bind({ val: '2' }).add(1); + counter.add(1, { val: '1' }); + counter.add(1, { val: '2' }); const records = await counter.getMetricRecord(); records.forEach(it => batcher.process(it)); @@ -53,20 +53,20 @@ describe('PrometheusBatcher', () => { assert.strictEqual(checkPointSet[0].records.length, 2); }); - it('should recognize identical labels with different key-insertion order', async () => { - const batcher = new PrometheusLabelsBatcher(); + it('should recognize identical attributes with different key-insertion order', async () => { + const batcher = new PrometheusAttributesBatcher(); const counter = meter.createCounter('test_counter') as CounterMetric; - const label1: Labels = {}; - label1.key1 = '1'; - label1.key2 = '2'; + const attribute1: Attributes = {}; + attribute1.key1 = '1'; + attribute1.key2 = '2'; - const label2: Labels = {}; - label2.key2 = '2'; - label2.key1 = '1'; + const attribute2: Attributes = {}; + attribute2.key2 = '2'; + attribute2.key1 = '1'; - counter.bind(label1).add(1); - counter.bind(label2).add(1); + counter.bind(attribute1).add(1); + counter.bind(attribute2).add(1); const records = await counter.getMetricRecord(); records.forEach(it => batcher.process(it)); diff --git a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts index 4934ebb788..865353b116 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts @@ -19,19 +19,19 @@ import { LastValueAggregator, MeterProvider, CounterMetric, - ValueRecorderMetric, + HistogramMetric, UpDownCounterMetric, - ValueObserverMetric, + ObservableGaugeMetric, } from '@opentelemetry/sdk-metrics-base'; import { diag, DiagLogLevel } from '@opentelemetry/api'; import * as assert from 'assert'; -import { Labels } from '@opentelemetry/api-metrics'; +import { Attributes } from '@opentelemetry/api-metrics'; import { PrometheusSerializer } from '../src/PrometheusSerializer'; -import { PrometheusLabelsBatcher } from '../src/PrometheusLabelsBatcher'; +import { PrometheusAttributesBatcher } from '../src/PrometheusAttributesBatcher'; import { ExactProcessor } from './ExactProcessor'; import { mockedHrTimeMs, mockAggregator } from './util'; -const labels = { +const attributes = { foo1: 'bar1', foo2: 'bar2', }; @@ -55,7 +55,7 @@ describe('PrometheusSerializer', () => { processor: new ExactProcessor(SumAggregator), }).getMeter('test'); const counter = meter.createCounter('test_total') as CounterMetric; - counter.bind(labels).add(1); + counter.add(1, attributes); const records = await counter.getMetricRecord(); const record = records[0]; @@ -77,7 +77,7 @@ describe('PrometheusSerializer', () => { processor: new ExactProcessor(SumAggregator), }).getMeter('test'); const counter = meter.createCounter('test_total') as CounterMetric; - counter.bind(labels).add(1); + counter.add(1, attributes); const records = await counter.getMetricRecord(); const record = records[0]; @@ -99,15 +99,15 @@ describe('PrometheusSerializer', () => { const meter = new MeterProvider({ processor: new ExactProcessor(LastValueAggregator), }).getMeter('test'); - const observer = meter.createValueObserver( + const observableGauge = meter.createObservableGauge( 'test', {}, - observerResult => { - observerResult.observe(1, labels); + observableResult => { + observableResult.observe(1, attributes); } - ) as ValueObserverMetric; + ) as ObservableGaugeMetric; await meter.collect(); - const records = await observer.getMetricRecord(); + const records = await observableGauge.getMetricRecord(); const record = records[0]; const result = serializer.serializeRecord( @@ -126,15 +126,15 @@ describe('PrometheusSerializer', () => { const meter = new MeterProvider({ processor: new ExactProcessor(LastValueAggregator), }).getMeter('test'); - const observer = meter.createValueObserver( + const observableGauge = meter.createObservableGauge( 'test', {}, - observerResult => { - observerResult.observe(1, labels); + observableResult => { + observableResult.observe(1, attributes); } - ) as ValueObserverMetric; + ) as ObservableGaugeMetric; await meter.collect(); - const records = await observer.getMetricRecord(); + const records = await observableGauge.getMetricRecord(); const record = records[0]; const result = serializer.serializeRecord( @@ -153,13 +153,13 @@ describe('PrometheusSerializer', () => { const processor = new ExactProcessor(HistogramAggregator, [1, 10, 100]); const meter = new MeterProvider({ processor }).getMeter('test'); - const recorder = meter.createValueRecorder('test', { + const histogram = meter.createHistogram('test', { description: 'foobar', - }) as ValueRecorderMetric; + }) as HistogramMetric; - recorder.bind(labels).record(5); + histogram.record(5, attributes); - const records = await recorder.getMetricRecord(); + const records = await histogram.getMetricRecord(); const record = records[0]; const result = serializer.serializeRecord( @@ -181,13 +181,13 @@ describe('PrometheusSerializer', () => { const serializer = new PrometheusSerializer(); const meter = new MeterProvider().getMeter('test'); - const recorder = meter.createValueRecorder('test', { + const histogram = meter.createHistogram('test', { description: 'foobar', boundaries: [1, 10, 100], - }) as ValueRecorderMetric; - recorder.bind(labels).record(5); + }) as HistogramMetric; + histogram.record(5, attributes); - const records = await recorder.getMetricRecord(); + const records = await histogram.getMetricRecord(); const record = records[0]; const result = serializer.serializeRecord( @@ -210,12 +210,12 @@ describe('PrometheusSerializer', () => { const processor = new ExactProcessor(HistogramAggregator, [1, 10, 100]); const meter = new MeterProvider({ processor }).getMeter('test'); - const recorder = meter.createValueRecorder('test', { + const histogram = meter.createHistogram('test', { description: 'foobar', - }) as ValueRecorderMetric; - recorder.bind(labels).record(5); + }) as HistogramMetric; + histogram.record(5, attributes); - const records = await recorder.getMetricRecord(); + const records = await histogram.getMetricRecord(); const record = records[0]; const result = serializer.serializeRecord( @@ -245,12 +245,12 @@ describe('PrometheusSerializer', () => { const meter = new MeterProvider({ processor: new ExactProcessor(SumAggregator), }).getMeter('test'); - const processor = new PrometheusLabelsBatcher(); + const processor = new PrometheusAttributesBatcher(); const counter = meter.createCounter('test_total', { description: 'foobar', }) as CounterMetric; - counter.bind({ val: '1' }).add(1); - counter.bind({ val: '2' }).add(1); + counter.add(1, { val: '1' }); + counter.add(1, { val: '2' }); const records = await counter.getMetricRecord(); records.forEach(it => processor.process(it)); @@ -272,12 +272,12 @@ describe('PrometheusSerializer', () => { const meter = new MeterProvider({ processor: new ExactProcessor(SumAggregator), }).getMeter('test'); - const processor = new PrometheusLabelsBatcher(); + const processor = new PrometheusAttributesBatcher(); const counter = meter.createCounter('test_total', { description: 'foobar', }) as CounterMetric; - counter.bind({ val: '1' }).add(1); - counter.bind({ val: '2' }).add(1); + counter.add(1, { val: '1' }); + counter.add(1, { val: '2' }); const records = await counter.getMetricRecord(); records.forEach(it => processor.process(it)); @@ -303,18 +303,18 @@ describe('PrometheusSerializer', () => { const meter = new MeterProvider({ processor: new ExactProcessor(LastValueAggregator), }).getMeter('test'); - const processor = new PrometheusLabelsBatcher(); - const observer = meter.createValueObserver( + const processor = new PrometheusAttributesBatcher(); + const observableGauge = meter.createObservableGauge( 'test', { description: 'foobar', }, - observerResult => { - observerResult.observe(1, labels); + observableResult => { + observableResult.observe(1, attributes); } - ) as ValueObserverMetric; + ) as ObservableGaugeMetric; await meter.collect(); - const records = await observer.getMetricRecord(); + const records = await observableGauge.getMetricRecord(); records.forEach(it => processor.process(it)); const checkPointSet = processor.checkPointSet(); @@ -336,19 +336,19 @@ describe('PrometheusSerializer', () => { const processor = new ExactProcessor(HistogramAggregator, [1, 10, 100]); const meter = new MeterProvider({ processor }).getMeter('test'); - const recorder = meter.createValueRecorder('test', { + const histogram = meter.createHistogram('test', { description: 'foobar', - }) as ValueRecorderMetric; - recorder.bind({ val: '1' }).record(5); - recorder.bind({ val: '1' }).record(50); - recorder.bind({ val: '1' }).record(120); + }) as HistogramMetric; + histogram.record(5, { val: '1' }); + histogram.record(50, { val: '1' }); + histogram.record(120, { val: '1' }); - recorder.bind({ val: '2' }).record(5); + histogram.record(5, { val: '2' }); - const records = await recorder.getMetricRecord(); - const labelBatcher = new PrometheusLabelsBatcher(); - records.forEach(it => labelBatcher.process(it)); - const checkPointSet = labelBatcher.checkPointSet(); + const records = await histogram.getMetricRecord(); + const attributeBatcher = new PrometheusAttributesBatcher(); + records.forEach(it => attributeBatcher.process(it)); + const checkPointSet = attributeBatcher.checkPointSet(); const result = serializer.serialize(checkPointSet); assert.strictEqual( @@ -382,7 +382,7 @@ describe('PrometheusSerializer', () => { processor: new ExactProcessor(SumAggregator), }).getMeter('test'); const counter = meter.createCounter('test') as CounterMetric; - counter.bind({}).add(1); + counter.add(1); const records = await counter.getMetricRecord(); const record = records[0]; @@ -410,7 +410,7 @@ describe('PrometheusSerializer', () => { processor: new ExactProcessor(SumAggregator), }).getMeter('test'); const counter = meter.createCounter('test_total') as CounterMetric; - counter.bind({}).add(1); + counter.add(1); const records = await counter.getMetricRecord(); const record = records[0]; @@ -425,14 +425,14 @@ describe('PrometheusSerializer', () => { describe('with SumAggregator', () => { mockAggregator(SumAggregator); - it('should serialize records without labels', async () => { + it('should serialize records without attributes', async () => { const serializer = new PrometheusSerializer(); const meter = new MeterProvider({ processor: new ExactProcessor(SumAggregator), }).getMeter('test'); const counter = meter.createCounter('test_total') as CounterMetric; - counter.bind({}).add(1); + counter.add(1); const records = await counter.getMetricRecord(); const record = records[0]; @@ -444,21 +444,19 @@ describe('PrometheusSerializer', () => { assert.strictEqual(result, `test_total 1 ${mockedHrTimeMs}\n`); }); - it('should serialize non-string label values', async () => { + it('should serialize non-string attribute values', async () => { const serializer = new PrometheusSerializer(); const meter = new MeterProvider({ processor: new ExactProcessor(SumAggregator), }).getMeter('test'); const counter = meter.createCounter('test_total') as CounterMetric; - counter - .bind(({ - object: {}, - NaN: NaN, - null: null, - undefined: undefined, - } as unknown) as Labels) - .add(1); + counter.add(1, ({ + object: {}, + NaN: NaN, + null: null, + undefined: undefined, + } as unknown) as Attributes); const records = await counter.getMetricRecord(); const record = records[0]; @@ -487,7 +485,7 @@ describe('PrometheusSerializer', () => { const counter = meter.createUpDownCounter( 'test' ) as UpDownCounterMetric; - counter.bind(labels).add(esac[0]); + counter.add(esac[0], attributes); const records = await counter.getMetricRecord(); const record = records[0]; @@ -502,23 +500,21 @@ describe('PrometheusSerializer', () => { } }); - it('should escape backslash (\\), double-quote ("), and line feed (\\n) in label values', async () => { + it('should escape backslash (\\), double-quote ("), and line feed (\\n) in attribute values', async () => { const serializer = new PrometheusSerializer(); const meter = new MeterProvider({ processor: new ExactProcessor(SumAggregator), }).getMeter('test'); const counter = meter.createCounter('test_total') as CounterMetric; - counter - .bind(({ - backslash: '\u005c', // \ => \\ (\u005c\u005c) - doubleQuote: '\u0022', // " => \" (\u005c\u0022) - lineFeed: '\u000a', // ↵ => \n (\u005c\u006e) - backslashN: '\u005c\u006e', // \n => \\n (\u005c\u005c\u006e) - backslashDoubleQuote: '\u005c\u0022', // \" => \\\" (\u005c\u005c\u005c\u0022) - backslashLineFeed: '\u005c\u000a', // \↵ => \\\n (\u005c\u005c\u005c\u006e) - } as unknown) as Labels) - .add(1); + counter.add(1, ({ + backslash: '\u005c', // \ => \\ (\u005c\u005c) + doubleQuote: '\u0022', // " => \" (\u005c\u0022) + lineFeed: '\u000a', // ↵ => \n (\u005c\u006e) + backslashN: '\u005c\u006e', // \n => \\n (\u005c\u005c\u006e) + backslashDoubleQuote: '\u005c\u0022', // \" => \\\" (\u005c\u005c\u005c\u0022) + backslashLineFeed: '\u005c\u000a', // \↵ => \\\n (\u005c\u005c\u005c\u006e) + } as unknown) as Attributes); const records = await counter.getMetricRecord(); const record = records[0]; @@ -539,21 +535,19 @@ describe('PrometheusSerializer', () => { ); }); - it('should sanitize label names', async () => { + it('should sanitize attribute names', async () => { const serializer = new PrometheusSerializer(); const meter = new MeterProvider({ processor: new ExactProcessor(SumAggregator), }).getMeter('test_total'); const counter = meter.createCounter('test') as CounterMetric; - // if you try to use a label name like account-id prometheus will complain + // if you try to use a attribute name like account-id prometheus will complain // with an error like: // error while linting: text format parsing error in line 282: expected '=' after label name, found '-' - counter - .bind(({ - 'account-id': '123456', - } as unknown) as Labels) - .add(1); + counter.add(1, ({ + 'account-id': '123456', + } as unknown) as Attributes); const records = await counter.getMetricRecord(); const record = records[0]; diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.eslintignore b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.eslintignore @@ -0,0 +1 @@ +build diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.eslintrc.js b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.eslintrc.js new file mode 100644 index 0000000000..3ed0fbeba3 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + "env": { + "mocha": true, + "commonjs": true, + "node": true, + }, + ...require('../../../eslint.config.js') +} diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.npmignore b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.npmignore new file mode 100644 index 0000000000..9505ba9450 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/.npmignore @@ -0,0 +1,4 @@ +/bin +/coverage +/doc +/test diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/LICENSE b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/README.md b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/README.md similarity index 81% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/README.md rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/README.md index 1ef2a34732..f434da04ea 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/README.md +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/README.md @@ -10,13 +10,14 @@ This module provides exporter for web and node to be used with [opentelemetry-co ## Installation ```bash -npm install --save @opentelemetry/exporter-otlp-grpc +npm install --save @opentelemetry/exporter-trace-otlp-grpc ``` ## Service Name The OpenTelemetry Collector Exporter does not have a service name configuration. In order to set the service name, use the `service.name` resource attribute as prescribed in the [OpenTelemetry Resource Semantic Conventions][semconv-resource-service-name]. +To see documentation and sample code for the metric exporter, see the [exporter-metrics-otlp-grpc package][metrics-exporter-url] ## Traces in Node - GRPC @@ -24,7 +25,7 @@ The OTLPTraceExporter in Node expects the URL to only be the hostname. It will n ```js const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base'); -const { OTLPTraceExporter } = require('@opentelemetry/exporter-otlp-grpc'); +const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc'); const collectorOptions = { // url is optional and can be omitted - default is grpc://localhost:4317 @@ -48,7 +49,7 @@ const fs = require('fs'); const grpc = require('@grpc/grpc-js'); const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base'); -const { OTLPTraceExporter } = require('@opentelemetry/exporter-otlp-grpc'); +const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc'); const collectorOptions = { // url is optional and can be omitted - default is grpc://localhost:4317 @@ -84,7 +85,7 @@ The exporter can be configured to send custom metadata with each request as in t const grpc = require('@grpc/grpc-js'); const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base'); -const { OTLPTraceExporter } = require('@opentelemetry/exporter-otlp-grpc'); +const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc'); const metadata = new grpc.Metadata(); // For instance, an API key or access token might go here. @@ -108,34 +109,6 @@ provider.register(); Note, that this will only work if TLS is also configured on the server. -## Metrics in Node - GRPC - -The OTLPTraceExporter 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 } = require('@opentelemetry/sdk-metrics-base'); -const { OTLPMetricExporter } = require('@opentelemetry/exporter-otlp-grpc'); -const collectorOptions = { - // url is optional and can be omitted - default is grpc://localhost:4317 - url: 'grpc://:', -}; -const exporter = new OTLPMetricExporter(collectorOptions); - -// Register the exporter -const provider = new MeterProvider({ - exporter, - interval: 60000, -}) -['SIGINT', 'SIGTERM'].forEach(signal => { - process.on(signal, () => provider.shutdown().catch(console.error)); -}); - -// Now, start recording data -const meter = provider.getMeter('example-meter'); -const counter = meter.createCounter('metric_name'); -counter.add(10, { 'key': 'value' }); -``` - ## Running opentelemetry-collector locally to see the traces 1. Go to examples/otlp-exporter-node @@ -155,11 +128,12 @@ 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 -[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-otlp-grpc -[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-otlp-grpc -[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-otlp-grpc&type=dev -[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-otlp-grpc&type=dev -[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-otlp-grpc -[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-collector-grpc.svg +[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-trace-otlp-grpc +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-trace-otlp-grpc +[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-trace-otlp-grpc&type=dev +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-trace-otlp-grpc&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-grpc +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-trace-otlp-grpc.svg [opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector [semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service +[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-metrics-otlp-grpc diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/package.json b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/package.json similarity index 87% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/package.json rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/package.json index 0e169d818b..b7e23ce3a3 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/package.json +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/package.json @@ -1,5 +1,5 @@ { - "name": "@opentelemetry/exporter-otlp-grpc", + "name": "@opentelemetry/exporter-trace-otlp-grpc", "version": "0.26.0", "description": "OpenTelemetry Collector Exporter allows user to send collected traces to the OpenTelemetry Collector", "main": "build/src/index.js", @@ -48,8 +48,7 @@ }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", - "@opentelemetry/api-metrics": "0.26.0", + "@opentelemetry/api": "^1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", @@ -58,21 +57,20 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@grpc/grpc-js": "^1.3.7", "@grpc/proto-loader": "^0.6.4", "@opentelemetry/core": "1.0.0", - "@opentelemetry/exporter-otlp-http": "0.26.0", + "@opentelemetry/exporter-trace-otlp-http": "0.26.0", "@opentelemetry/resources": "1.0.0", - "@opentelemetry/sdk-metrics-base": "0.26.0", "@opentelemetry/sdk-trace-base": "1.0.0" } } diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/protos b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/protos new file mode 160000 index 0000000000..59c488bfb8 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/protos @@ -0,0 +1 @@ +Subproject commit 59c488bfb8fb6d0458ad6425758b70259ff4a2bd diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPExporterNodeBase.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/OTLPExporterNodeBase.ts similarity index 98% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPExporterNodeBase.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/OTLPExporterNodeBase.ts index 895ee3fa28..0c516865bd 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPExporterNodeBase.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/OTLPExporterNodeBase.ts @@ -18,7 +18,7 @@ import { diag } from '@opentelemetry/api'; import { OTLPExporterBase, otlpTypes, -} from '@opentelemetry/exporter-otlp-http'; +} from '@opentelemetry/exporter-trace-otlp-http'; import { Metadata } from '@grpc/grpc-js'; import { OTLPExporterConfigNode, diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPTraceExporter.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts similarity index 97% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPTraceExporter.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts index 828a7067d7..252a752a6d 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/OTLPTraceExporter.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts @@ -19,7 +19,7 @@ import { OTLPExporterNodeBase } from './OTLPExporterNodeBase'; import { otlpTypes, toOTLPExportTraceServiceRequest, -} from '@opentelemetry/exporter-otlp-http'; +} from '@opentelemetry/exporter-trace-otlp-http'; import { OTLPExporterConfigNode, ServiceClientType } from './types'; import { baggageUtils, getEnv } from '@opentelemetry/core'; import { validateAndNormalizeUrl } from './util'; diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/index.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/index.ts new file mode 100644 index 0000000000..34975b3ed5 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './OTLPExporterNodeBase'; +export * from './OTLPTraceExporter'; +export { ServiceClientType, OTLPExporterConfigNode } from './types'; +export { validateAndNormalizeUrl } from './util'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/types.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/types.ts similarity index 95% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/src/types.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/types.ts index da10ea415d..e9513819e7 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/types.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { otlpTypes } from '@opentelemetry/exporter-otlp-http'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import * as grpc from '@grpc/grpc-js'; /** diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/util.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/util.ts similarity index 98% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/src/util.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/util.ts index 1e2e480383..e0021ce896 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/src/util.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/src/util.ts @@ -18,7 +18,7 @@ import * as grpc from '@grpc/grpc-js'; import * as protoLoader from '@grpc/proto-loader'; import { diag } from '@opentelemetry/api'; import { globalErrorHandler } from '@opentelemetry/core'; -import { otlpTypes } from '@opentelemetry/exporter-otlp-http'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import * as path from 'path'; import { OTLPExporterNodeBase } from './OTLPExporterNodeBase'; import { URL } from 'url'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/submodule.md b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/submodule.md similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/submodule.md rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/submodule.md diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPExporterNodeBase.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/OTLPExporterNodeBase.test.ts similarity index 97% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPExporterNodeBase.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/OTLPExporterNodeBase.test.ts index f52f212f37..dbe6c6b406 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPExporterNodeBase.test.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/OTLPExporterNodeBase.test.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import { otlpTypes } from '@opentelemetry/exporter-otlp-http'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; import { OTLPExporterNodeBase } from '../src/OTLPExporterNodeBase'; import { OTLPExporterConfigNode, ServiceClientType } from '../src/types'; -import { mockedReadableSpan } from './helper'; +import { mockedReadableSpan } from './traceHelper'; class MockCollectorExporter extends OTLPExporterNodeBase< ReadableSpan, diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPTraceExporter.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/OTLPTraceExporter.test.ts similarity index 98% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPTraceExporter.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/OTLPTraceExporter.test.ts index 2014308967..2d17bf9f78 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/OTLPTraceExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/OTLPTraceExporter.test.ts @@ -15,7 +15,7 @@ */ import * as protoLoader from '@grpc/proto-loader'; -import { otlpTypes } from '@opentelemetry/exporter-otlp-http'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import { diag } from '@opentelemetry/api'; import { BasicTracerProvider, @@ -34,7 +34,7 @@ import { ensureMetadataIsCorrect, ensureResourceIsCorrect, mockedReadableSpan, -} from './helper'; +} from './traceHelper'; const traceServiceProtoPath = 'opentelemetry/proto/collector/trace/v1/trace_service.proto'; diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/ca.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/ca.crt new file mode 100644 index 0000000000..b6db7d0dd2 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/ca.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFozCCA4ugAwIBAgIUCdllngMpqYtsqRCpqdXxPZiSbGEwDQYJKoZIhvcNAQEL +BQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQHDBFPcGVuVGVs +ZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9vdDENMAsGA1UECwwEVGVzdDELMAkGA1UE +AwwCY2EwHhcNMjEwNjA3MjAyNzMyWhcNMjIwNjA3MjAyNzMyWjBhMQswCQYDVQQG +EwJDTDELMAkGA1UECAwCUk0xGjAYBgNVBAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0w +CwYDVQQKDARSb290MQ0wCwYDVQQLDARUZXN0MQswCQYDVQQDDAJjYTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKS4d8790qpxSOMAMNSxlvFxZvxZKih5 +BjKDefa3sPL8iSOZ12mSZyWqPifjU+fnb3PDLWJPEFYQiwpyMctlXoXo5qiDm1D5 +mLZPTc7/qbiyu33YZHW+iE23GiOQBfvgKHTqh2+ejWs9h/txlWlQuKm0NEDPnA2P +kHiIjudSkWCT1w0WOnlJXd/9CWq6gW0nCTeOmwGYaY7T/i1W500qQyv5j1xHrJCu +m9amRzZEc1I4L2XF8Lnz2vDuEEs2W1vjcO++sXODlSC78dIyGnDWxGuK+V7dhccB +jj/Q5V96CMUoY7RGl18hwn/MSkzmWghsQFkfYWw1Xvez8/IWh7AlEtB/hDn2Dqw7 +lr6lvn1cOUmhHAgYV+v/0gWFN482qi3OaR0z2cCdmfSxRlxhtrq0jH7B3dW5YXcf +ke9e4gh7P980HWeHPwanBlV7BAsPxJY7N+je1LsjHVkwv2OnpkAzGQqJycOzPAzn +tib/lxmhBYVV4eWhCKvLrDqkgp5J3Cp99wIovW6TEfg2PJG4jZI9PKztPQb/OHZp +995oEAG8lmgcCA6kpvwVvle/m3wXj4eKQ1U0mQLGfJja2ripSBk7aAlr7qxWbvjv +4kxe5dJPMRmVB3PRZvnNilfM78Pbn+du0X8TiSwXeG5Og8uSvGwBzQNeW0EZ//b0 +fHNgQlyp4OL9AgMBAAGjUzBRMB0GA1UdDgQWBBSsdECnQyhXkgqyNWFlhkSGlUJd +MzAfBgNVHSMEGDAWgBSsdECnQyhXkgqyNWFlhkSGlUJdMzAPBgNVHRMBAf8EBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAAfgD6lqyOyEOfGMAhtb5OVLpn5hG6WLfd +wyjIYzMNW5DScV9hrgB1ycfA9OIqBECWY3zP76X41KVI0siu7qg3bkaPM2qh7sbO +LXYCkDHNYF69Tlf0JR+Wpr740DIqoITcZRLy+/FMFWij9tNAsY1EcLrSYuiEd8/L +OanlD9AaA3fL1pOsfiNM7Ec6nUFl537+yNFGxU+Q9T7EMb/ypz/FwN3/zBbO0xdk +ZqPh/jDETKorBH87QnFRidmK5DiXRwh323+l+cWEEe79ssGzLBcLr+rzOvDH0qbo +fLBWkRbBtAcRGJAgM0F9dLG4/hQisELobNSCZ4aITHmr1J6MFiVxaaEvIXQ94zgj +xVtAv2Fp4lvpJWMjk/iKc8IR56VkvK6bui7BYEFc+DmtJLw0ryFZDD1wEzbQ5Gzl +W7JBC3vR8zQPo7kVl99BKAsNLhC+tCGdbLLOJROyFWHai/bkcRPHOLOMY1/lM/Wf +rlIcc46pSIOzlsxnlrDzoQihjtg3SrNBkPaRaJE12WFHYELHBX+65HRGlkaXnxaY +HOqPN6NiHVB0i5C4+l0M7JdOx2kEYVQiprm4kBiM3BNMdRpThn4Vt12TnEyq/Cyz +khz4FAMw/ytbEWMxFvEQJdOK1vjmPHAMDSFXiixeklVUD5Th/9so4kRTu97j8fq/ +T0JDHso8+A== +-----END CERTIFICATE----- diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/ca.key b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/ca.key new file mode 100644 index 0000000000..3a12f603d4 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/ca.key @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,723F7ADBF5E86DF0 + +laGpuVd6ib17eYFGAvuWCFodT4OxvWQVpvjXVEqfqoJw3x//SbS/J9GQXULJHanh +FZGagPYhv3cQjW5n8hSxFADCq09he3sN+IV6FOzQ5JzJZEQtb5jqfc23n0o2y1Sx +Xw2TOBuzzLB9NFnkTgZt0hUJW9wrqYhDLXXmwwdJb78OsFmgzlBCVrcXtZKiLK7F +4gKvMKSD/pS4INKmwHlAdNqssMyk0Snon7odLD9yTrTYVqIabytj7ZQi8Mxg/EZC +mkffRhMS591DYU86CE38of6UbSc7AXdfvpYZ+G3phIUwE+BxaDOL1RX/h04LcDjE +43R8ccI1akW3EGO0FvTr1jn4EsDv/kuYLVmC7fhuYroSBGLIdt89aEuRxBkLsn/Y +WJv/VviXlmO13wAi/kPrwPQk8GpBO73Yw367+iaHNsWihZ8qBYBjiqQyR59Tymwy +yLtTA8yhFCDwMwWLbB5NGVFuMmLGKUHvFvcXnEdK0RGJr5uu8cV/FAGpGMld3g84 +VY7srpocRLecTqQ5cfm8TZfcilIbTtpexqN97RicDdI+KjmYBVmWMOwrzzALFuKA +jVIgx6K32XOVE72gAsSWvTUpb8R6XAuc0WHHeqNr9w7NEC0+Y73YmKamqgCQSSAM +y9yeK6DaoroinOxRjGy8ygi6rg47+L0qEkiKzRICAqynfSMbJCidvRHf1lTuNmP1 +uLweRroiSXAcmCSnU0SelhcKM7DxzNIk5qlnnpI2WOp1lYmYjZH50ktD1FQ7nX06 +RlXUnhDZ6uWwyBWd+gP3/u8F6167tyFd4JXKVoEVklofyVbyzMZ+juSdcddjrtEz +qh+EESi0Z9YcV0yO0L5oV9Pd9hhR2j4hcRgoYZydjSRcZ5w619urHu5kmKLaExbE +Uy9RQl5GT3LRaFMyiMJv4MaN6lmbWfUi/ho5Isif8H/KHa72BzOe5HL9QCPBWD3r +GJyNH6Yjt6CpovhK2/LbwpAXfApX3WxGaskrgxEccBWu9jPwyvmkip65f0PEub+2 +vgK/3It7wqpR/FbJ56qmM2FIzTXAC2FqZ8yKlgRjGId3HqqsYo0BSmEtGFbiI8A0 +Snt+txyVPdl1gMDOAdvcpJrn5cB1ehmd/YcyvWaNN+9haA3BgAeS68KPm9Ilgu+I +r7FVPccKDUPXZJv7GIG7XJG0nPDjThNXsFr1zA6gLkFBAGy2ahKfXIBG9a0Adhqy +/weY23Tsq2pmz5f6xPtWoAm/bOEhz+DWV2Okb4uV+5PYTVBm1hT8GuiKqzTh6anB +1ZaJukt4HAyxqHM92Htqw5jEoMpChUT9iJyG9XrIyOTE9ygnVm4m55kEOBLeKeVS +r3g09bxqPtpj9IQeAlnCig8VA7JAvedmoVw+OzG+ywvgG2zGY+vraNey3ZvDow8w +maHXJlJKyE/uGHiHTPnL/k1yqUrbbgKHOddZfYCij0LsZ20OcMp4znm+UeIFGu32 +n7UhNqlmA9XEzKuQNNBR3VuaRu6poBNjjQkj3hCA2rJ2EAcWbPXrELUw7zjMR1+i +eawlOSv2OOuOhONan+hJB+W4W85E6b+isW/WFE0QTKGnhChGjNpZ/CPdv0P8hhUb +fYeTABv11gaIMvvLcDnPAE7jiTUk+SKVUj0JyaHKHjc53Ioy0ZKjnWJLlIJc/lzy +wVxfSM4GVu+PVAPTHqu92z7+2tGFZHYdstkKokA4FCAm7GJujI04CCemNzdbiqRs +sIxJk6/90XpMF5/nISErobs7LsbWL4jRfZUgKluklbAwFs14OICxcnyeNAsZawlc +LGykIfP1Qpim+yqKQuUAzOFHC00+kb2DzLm3f2n7vfaaf/4EwpWT9kuRPM9cziD0 +irc3vwCMtOrWQ8lp2TByOQ56Xh7ozsxvIw/RTISWp/0NkYvVfc53YPSEV/IUVy6H +bBQ18A+sb0Nj/3sJ8Qd3wnCt5W267CQwVDeoU+RJsrcqSaKpdg6lNJjZGzlLXzkq +n4wRv9y1wqXye0R6OgN9ly66UCkCH+kO8pMTJH49v7DA69BfwOgxQw2ey0/lsKqW +yoUctxN6J6t4GKyoslMB5KjT2FJY1DPcTxRiZwqbZwpDN5Lbw2JwbjX7RwYgJSsU +uuXb8pSr0T8kPC5QL3DzH3K6E4l9vaOqp6+VCBZ/lgtisNYkEIfepUYwg1cDo45X +J84XJjeju/MPxJ3sViBzyMhChUya8DdoovBeLnnFYDClUD1kV/L9hsQumc/uKF+t +a8xtoW7NdCSlwzr5YzRsrqybQGyWxMT7yGA4rh5nykaHp5YjoT3hT9evhOCbLpaC +HpoQqXRXx4Nc322AgiFmnemc3WrUu33PQdULue0FZFwf/GtDHUEbszHiCnlnUTrX +SIi/QJCUpV23UeU37lKTbDu85La81CAkN7I9DFsUZ7D0Kl+h3du4UL/ez5adPm/k +vu1TlONUUF8QTSWokeyrfr3GsjytpLBt/yni+VtT4DMXoPqJ5OjQanTbA5vIi/LG +rj5AYDZru1tR58FZBmErY6tgJ7Z9LgWL8vmNtDJha5NElEGqeQoBo2czvSUSnblS +Bdb0O1sqMGxpfjAPiwU3ErzkARMcYlTO4t2IAxPH+3arIGhcF/DCWtHnSCkJokj7 +S9ckrTYvNK7ROz3BTA8D48UF/XX/C/gBkdhFZcqgOI+VlCtexi6pUqakKicy96hw +QbBwh06/zl95YyCEqd2cUY18zrfwkc7L/1oLaeW6n50IVvt0MffI0k0r42zgBK0T +g0EAswdX6/0PrZ7bfJiRHf+HeqT30EPvXch7wLv7Vx68wMFaYKcPzFqQ4nBH3rOF +5Nhj0EpV+C0W/XMewfJEADbwE5XiTYY+2eYMU8kBa49+vjwXM7fkYLZOFfAZmVRQ +84JRgL8HG4gXmVo2YcbviRdNuw4y2LCyfhJ9NwuWW6Ly0uKiGRaVKP1JAEmIJmcX +SnG3rM0bJsRnDtBBURioN0whl64LS3BwsPWL3OOsjesBIBNkoDA10OukTzjnLc6A +RYAfgPrG1eSsjitMFYdSBX8wvrQDCpxyItIamMf8IlsgBMt/WlFeGOJ9wxxa26lb +PxLNlhSpj3PU6rA4NDKvxkr2IEJ0MEcDnFnQkyBPlWY6a6jSQ+WSQkzBLU9soZ/2 +-----END RSA PRIVATE KEY----- diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.crt new file mode 100644 index 0000000000..cbd324625f --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFPzCCAycCAQEwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNV +BAgMAlJNMRowGAYDVQQHDBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9v +dDENMAsGA1UECwwEVGVzdDELMAkGA1UEAwwCY2EwHhcNMjEwNjA3MjAyNzMzWhcN +MjIwNjA3MjAyNzMzWjBqMQswCQYDVQQGEwJDTDELMAkGA1UECAwCUk0xGjAYBgNV +BAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQKDARUZXN0MQ8wDQYDVQQLDAZD +bGllbnQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMBc1F9O8OcCu8xspnN1MNwccUZCx+lsh1F50T5D0INmxz3rXxin +TkM+QjFsJ09iF8MmgouI+yxmTayMlW733dUc/XQ9cV9GRwWVlF1RnoYp7mXVwMnz +o80s7CGWc+geliqeLUgzGIoq4bGTp1eEeB2KGJ/w8E2bTLs5a6B0pHhQuVXZ+Pq0 +E0Uzl2wPc+WwjeZyGRU4PbWzX6bN+R05Pfxq8PXhJ6Jnt0j8pNoF/XU6mOIYQyQb +THEKR8qB2SXo5+D1JOlRiofWtK4wsRH/wNm7j7tq75UezhOeqp6YU6MwGnea1loa +65K+DDG/rFyvxSlDS/53gjyKGSqYod8pevvytKjtUmw6xX5i5nFnf+wrKmMH6EDe +Hm63LReBv/CqCErYt4kV3NkdIuHmv7ZIdRfhDPdK8Q/kzAlRTX25wK/xWn5CqpSK +KCUwukEzccV266KU4sG63/4byv6zE62z8472P6u+OGSZlDxznL0BBg9iiHFYiopw +shBfFcszPCSOs1SO8XZH+6J5ypKBzBP7aAsyJflPHWGTUBACY9ZCU/7iwIF7YFPb +a/temVMLkg75oYGVow0Dlp55jQvrzMr7IaSBCxFUJEKf5u6GSNotJWmQdHYta5SH +Kj/rryFQV5qp9mBfia5DWnjHijFZTo+c/KLrgkmzfgbT4qVpnuxKahXNAgMBAAEw +DQYJKoZIhvcNAQELBQADggIBAA2nZTbaa9z/LTNJijf0clu4ULPG4RrqHgQ1q/Wh +NbrNemrxTJ+ZAwCR1gTv4oZe9NBd+V1pDXDQBid8mBTbttVrQCHdjgHFpQKNeyiK +nd2OI4awYiTvGbgDCMHAW/yf+XKCocuSkyNRnmfe8PihFD9wx6+kl6XCJuIkF3Vw +MGKEIrW2WLAARtBZeKV2yhtuVhkNm2TNFPfNrNtk2gdGO8TkX0orOllAENopR+GV +uffuLiIi9KWj9XP9T+6bdZbG2eMJX8wUNIIma54/3XN3RMi2iV9ZxW+F0j6d9ryo +j8pJJfpiW4qh6Eqi6HyvrzgdndKhkVYiIwbX5S60mqL+KcaPghX2goWexMW94QlQ +Re3/IvOAzGpu5fLn//y2tAaO9hDUsyoIJtXcFJKLbfM+mK/Bac2niEyBpr9Rzqur +N43Ga2pOsM4P/4YcAO6tvs5htvh2ala6UDXeEZV9Z1Bc5bOHAWNp13BfWE01iLNC +5rIu0XuVo1aa0FeVdJL6IpVeEwnkzDDt/9LKgp2K8w71VAtUSOg23AEYJu+GFr4D +y+0bahUiNETrFaiCsXQYa9HHFrqhA/PGOGpyq6GrBkJxWpzuL3rQQicpHzVIQEmb +3aCcIBdA2RQwQk7Z3YI2EuFMkHAElCXXZBulvxY6kl1n+2UwWRlocDMYZdkzI3+X +Tw8x +-----END CERTIFICATE----- diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.csr b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.csr new file mode 100644 index 0000000000..e5de7b1912 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.csr @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIErzCCApcCAQAwajELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQH +DBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEVGVzdDEPMA0GA1UECwwGQ2xp +ZW50MRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDAXNRfTvDnArvMbKZzdTDcHHFGQsfpbIdRedE+Q9CDZsc9618Yp05D +PkIxbCdPYhfDJoKLiPssZk2sjJVu993VHP10PXFfRkcFlZRdUZ6GKe5l1cDJ86PN +LOwhlnPoHpYqni1IMxiKKuGxk6dXhHgdihif8PBNm0y7OWugdKR4ULlV2fj6tBNF +M5dsD3PlsI3mchkVOD21s1+mzfkdOT38avD14SeiZ7dI/KTaBf11OpjiGEMkG0xx +CkfKgdkl6Ofg9STpUYqH1rSuMLER/8DZu4+7au+VHs4TnqqemFOjMBp3mtZaGuuS +vgwxv6xcr8UpQ0v+d4I8ihkqmKHfKXr78rSo7VJsOsV+YuZxZ3/sKypjB+hA3h5u +ty0Xgb/wqghK2LeJFdzZHSLh5r+2SHUX4Qz3SvEP5MwJUU19ucCv8Vp+QqqUiigl +MLpBM3HFduuilOLBut/+G8r+sxOts/OO9j+rvjhkmZQ8c5y9AQYPYohxWIqKcLIQ +XxXLMzwkjrNUjvF2R/uiecqSgcwT+2gLMiX5Tx1hk1AQAmPWQlP+4sCBe2BT22v7 +XplTC5IO+aGBlaMNA5aeeY0L68zK+yGkgQsRVCRCn+buhkjaLSVpkHR2LWuUhyo/ +668hUFeaqfZgX4muQ1p4x4oxWU6PnPyi64JJs34G0+KlaZ7sSmoVzQIDAQABoAAw +DQYJKoZIhvcNAQELBQADggIBAAtbvw2rrtnO5EeOF1Z+mJc9o3036liNbmCQTaC7 +Pf2yqo3Zk44L80R99sX5rDoq79MKEr//ED5C410EiCvzX42w330p7dasuoYRAwLw +YB0UwWnrKhm4SU20SC8zpnCUBL6K9lmXF2PJtkoMgFAnB8tIEc+DAr4hBIqh45vD +VgZ06GHH94/G6tIW3qNvi1mmvUYV0i6D3xBhcNAu6R/zopEYM3png24ZE2IlzZCX +x8hbYuMAqeQXSHQM9sKhXeb60GT8ns7d3P17S/TfpkTI7zRMkPhzsHC/Vp97xN/n +ojEEBY3MZJBPZj/q/buDfbp5x6H7/YxYdOKQKaGVWECGabISBcsg8NxaY++GKc+u +10C8O9KILRCJKGh8ze7chXx5n5+BPEoVVwhLn58eV7sOODvb4kZySUJHvFBb0ZM/ +7626K3443e5ZRkGXydvDIwPZgoiJ3L1L9+olL1cJ5rsRE6L5k6vPuJOeZITm4au2 +pE0THMHx/RjCMA1Lb/0BiDqbBHSh8hh+mHU7YXTq1Fxi2dSas0wAxcTBRs8TULsV +o57TmJqF+byiqwQvugyN7tndvWg9c+LDJHqitA5QC1GDXEi/bdjd7YeHRiL+ciVM +ZXXU9GT1O78O+84wbIDebahn8cifdGa7Kft7GftS3pCIyAjU9+eMXyT1JG3nssLr +4/ht +-----END CERTIFICATE REQUEST----- diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.key b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.key new file mode 100644 index 0000000000..9219944ca4 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/client.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAwFzUX07w5wK7zGymc3Uw3BxxRkLH6WyHUXnRPkPQg2bHPetf +GKdOQz5CMWwnT2IXwyaCi4j7LGZNrIyVbvfd1Rz9dD1xX0ZHBZWUXVGehinuZdXA +yfOjzSzsIZZz6B6WKp4tSDMYiirhsZOnV4R4HYoYn/DwTZtMuzlroHSkeFC5Vdn4 ++rQTRTOXbA9z5bCN5nIZFTg9tbNfps35HTk9/Grw9eEnome3SPyk2gX9dTqY4hhD +JBtMcQpHyoHZJejn4PUk6VGKh9a0rjCxEf/A2buPu2rvlR7OE56qnphTozAad5rW +Whrrkr4MMb+sXK/FKUNL/neCPIoZKpih3yl6+/K0qO1SbDrFfmLmcWd/7CsqYwfo +QN4ebrctF4G/8KoISti3iRXc2R0i4ea/tkh1F+EM90rxD+TMCVFNfbnAr/FafkKq +lIooJTC6QTNxxXbropTiwbrf/hvK/rMTrbPzjvY/q744ZJmUPHOcvQEGD2KIcViK +inCyEF8VyzM8JI6zVI7xdkf7onnKkoHME/toCzIl+U8dYZNQEAJj1kJT/uLAgXtg +U9tr+16ZUwuSDvmhgZWjDQOWnnmNC+vMyvshpIELEVQkQp/m7oZI2i0laZB0di1r +lIcqP+uvIVBXmqn2YF+JrkNaeMeKMVlOj5z8ouuCSbN+BtPipWme7EpqFc0CAwEA +AQKCAgBSCERY0KVTHotPxhXFrvhDJa34tInkNXAPgs+Eqg7FupLFCRbowJBThL1d +ri2lYMOZaVbKgoP6jzYYm2sug22KcG51n641XxbyfrNiiGf99uu/acRpWwlDeiDI +wgxztHd9fS76Vy/j3B2bSMhYPhmrHzUZH/qaXdv/C6GmL5fj5yjiP64524lMPZAZ +eQ2Hqh8ZYxbnQbCvR+tGixftKngQqNpRQM9SJsC202bJwzwvPensoUQgpbOXkTbE +WVNtI0GfYWt4RFm7TAiJMCKS9mobcCz/U78P7K8dFtDUCUnBkcX3s4QtsMU9Muao +YID0ldCSpCxIPFbB0nKhA64kKOBUylTnAjwfTKp6F/PPl/RLxT3xxHG8oTW9OWyD +3CjnG+EjLYnOypPKxVj8azs/K18AxyIOk+8imtqde9IHLV7OZC+jtKjTwqcVn0bi +rselH/S0NTdp1ksY2mfYQ1lkUMyfiohPMLSf6HJFZkpjWRICltLjpMbiNDuW7XdM +bUpE57yqXt1NSRqu1S8PaKI2qQQYotajdo2w4Ew511zwmtQwYI+TxaYvQI+Yl1tS +hU1sGJaCcojfKx0T/27SfKaKrjzGqebt4ag+LarZGvjVf4C7DiA6aw4zOGn8PMJl +1tr2GXx9hE9osrEgJP7VHw+6RlltDMjBqVvLa6oBDivBdBukAQKCAQEA/dG93DkQ +CeSdmWjGc1MTngLpERt/EAs2KJ+gGw37yRN/By3/Z52lVwfyzSfVxEZEWHzAj3rx +DGPsXTr7rEtyXISZdtloP0/nHQn1Tv0YoOpjKi8QsfirgghRwUYyXAcnFqEQsa24 +5BmsX4I7XE4+D2q+YdogmHVS69xMQWXpO13tS1RqE6VQ+XNTDAUgswKkB9PuwGP6 +21GASqrR9Gk/ZxBYJrp5Z6Qut3DkJSndZhraj5sInfi65DXPqSkw40ZsEmfrk/qs +fub+KTpyDknuKIOj66dFA7k1bbCm13mdjAzK/uoU7O4JfURijPxpo9GVjolqKeWr +M6LP5ITKa3J6QQKCAQEAwgPrCb4Tv1pizF4y2g1gB7KRpd4mpX5VG043BPh+hqyg +AoPkbt+iV2II9ye8/RwjiNSaoT+dRRrWXQyCIaDOnBJQLwgqPs0HPhzN++I6YL3n +In0uQLvNgyXCyf89xOFyixf5+PpXnItA5T5ciFi9yccY7zEG/91gC+GB1XQEkVmP +m8Vi6HUF14/jGEIjgeUTkFTXZdxS6kpP7p6sXyq6T2Q0a9KeVqBBP9XeBZZ03VSl +/PNyY4aq7x5HslfpMNAS44oNKQFSN+06NkYhjMFfDrrrb03VlwhbJas1sDjYi+rD +3ZeaMpwvxkUg//ApgiEXfffAaUQLGO09+jsl3azAjQKCAQBnpp5c72SQVa7SNgpM +kBGDxnZ9CPiDicCNKFqOkdBPlcmbGfqhyqv5dYJ+qxTNuVAxvog4T6FeSPP+QpcC +DjFefLva3/+FU1Dy990Ya50CIZVrZZrwwrbvPAx+2/a2xCj/Qbj6hhHp/F37BsjM +8hq/2vxyI0yKVecN8IGnd0Gef8XmrEtBSJJfu+ufDf0DfUGU/MQUBwArTgYQ998T +a2N76B3HewEXBOIbAVv5nTYPe0njuRD0yd0wUpVB5FNVjK2Xep6maIjGrff+yCJJ +mYFLRC7NjhpN4fVinPAVMFHZHmRLYzY2ZyKy6BlCr9VIE896TL1w7JxUUtmI3X14 +EWDBAoIBAQCn9TphKcLwse+72oSNTmzm3QjHngS42iAVTmXFENaAAitXYhS8gy+I +FF+Mj0NFnzmH9/2RQIAG1g/jZ7O0JwEWDaiKvrfLvDTb6ZXMy/Eb1OqmadZDxhFI +ysTRl/xCV6WQkoYdq6Ny6v6YNp9mjeRnLMwCLeBQWrYOMv/x6MkXh4ASKxPQB5ay +IWdIleElT0nbdgcusEi7eO+vtH+mt1eo6SeUfDYE6iDygVP+ZFzxSpmT3LEXRfru +nLkWxJIkZs0jXFy+Nd2WevEdESN0Nebz2o98wNX6NQqrFoeY8e1NW0SKrfaYf6vA +KhJCXwegFsO+kl9pAbXVs3QnD1Ndj3L1AoIBADUYFjD5y071ayhiunkwVekq4+wj +nbmqyaV5lWPU5XPBga6E3Tiah4Kt6C/LMSx3Q46jeEHTZOnCOr0KSk4BKf+WQaXN +4ueRdCWRIjdwxa37qCsg+MDf0iyHmnWp2y6IShhAwMC6konSqUkcez1ssqsChKt6 +dCxLeZEHuiFT6305E/xHZm/tWu9wbhhZecUElP+CyJ62GYtePzHKO+ZsdXywaiD4 +mZkq8ko6GIWkI7clasfdhjFqZ5GYA9Cv0OVQ6+MbFJnRPhCvz+iuAhAqXVE+nPhb +fSQOenyBtwtA3vRYYQR/2Z3xpydKzUiw1JcWf/etRwdtwpRfjEBTlzcQaHs= +-----END RSA PRIVATE KEY----- diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/regenerate.sh b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/regenerate.sh new file mode 100755 index 0000000000..e1f1af5b54 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/regenerate.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env sh +# +# Usage: regenerate.sh +# +# regenerate.sh regenerates certificates that are used to test gRPC with TLS +# Make sure you run it in test/certs directory. +# It also serves as a documentation on how existing certificates were generated. + +rm ca.crt ca.key client.crt client.csr client.key server.crt server.csr server.key + +openssl genrsa -nodes -des3 -out ca.key 4096 +openssl req -nodes -new -x509 -days 365 -key ca.key -out ca.crt -subj "/C=CL/ST=RM/L=OpenTelemetryTest/O=Root/OU=Test/CN=ca" + +openssl genrsa -nodes -des3 -out server.key 4096 +openssl req -nodes -new -key server.key -out server.csr -subj "/C=CL/ST=RM/L=OpenTelemetryTest/O=Test/OU=Server/CN=localhost" +openssl x509 -req -nodes -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt +openssl rsa -nodes -in server.key -out server.key + +openssl genrsa -nodes -des3 -out client.key 4096 +openssl req -nodes -new -key client.key -out client.csr -subj "/C=CL/ST=RM/L=OpenTelemetryTest/O=Test/OU=Client/CN=localhost" +openssl x509 -nodes -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt +openssl rsa -nodes -in client.key -out client.key diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.crt new file mode 100644 index 0000000000..09094e4526 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFPzCCAycCAQEwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQ0wxCzAJBgNV +BAgMAlJNMRowGAYDVQQHDBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEUm9v +dDENMAsGA1UECwwEVGVzdDELMAkGA1UEAwwCY2EwHhcNMjEwNjA3MjAyNzMyWhcN +MjIwNjA3MjAyNzMyWjBqMQswCQYDVQQGEwJDTDELMAkGA1UECAwCUk0xGjAYBgNV +BAcMEU9wZW5UZWxlbWV0cnlUZXN0MQ0wCwYDVQQKDARUZXN0MQ8wDQYDVQQLDAZT +ZXJ2ZXIxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBANaRv7jpdEedG0CQ/LoJEXuE32eZXzar45u05wq5CzqnUlYdHyx8 +cgCJJ44KThFXiOzgELFiiwjxmPo1CDLqGp8vEDHntvhxLhw/mFy/aa7YrCv1/1eX +0+cEvNUyoikjHKXECI7sV1ZVMrimGKXQNqRfub1JbJ+IzL+kp6MRtdA6GzxsU0Dg +Wwf7IQxtCQ4Tw3onJ3P3NZAkgz6zCVhOVkR7DuqGulzTQDa//mWwKQJie5wscURj +vLsJ0prS16Tc/5yXijwRjwx8ZEoDrJ5KszoMQwKIoLN7wHBo2r8/8RQsOGTVMJ1I +9kOkH3s9clswxCrnpzdNNmyIwTWaQ6CqpQpp0unGimF3VokanHhOhcpkWfzDArmU +jL4PIFBQBJvHIEKbuhZ4pUYL/6RtgEg2f3xVPe8s0hn/DzwJTgXqEX+TY7WvIKmH +0sMGZ9TZzWe9W64LM2/427+6pfgQOAJDHNLSYpmaa14R+630IMocdY6sj2hoZ9TK +8Ridqn+q+5kIpG/pP7bbzbzsotdzjNb6h7GBlsuyycoOfiP+C6Zs/yUZAAZEsSm0 +e4dXFCccurkXRL7cZJHC/agQhkkvcEP1TpmaygjbucME+h6H0G0St8yzBQwEJdkn +wNmfEhIdjmiX6u/fvPO6VJ5HBxgA5gONJlk+4EbiZTfl2rYauBFhloHzAgMBAAEw +DQYJKoZIhvcNAQELBQADggIBACIJLqVoH8oh8W0/0IF3sxH8LFsGByi0CUPo1JEB +1t3+FqyC7eFC9rDW12LfOKgiZl273OBpCHT8bx3OkoGZ4KwZsbsznyJv/X5OVYFH +5y5Lo8QNGWWMzXoK2JLlYJXZHMaJr5tTFOGqoIvC9C8ibLSAbL0MhtB9L5SvSxAm +mUOKZ/en7ZBepRex/s/rfCWYYTw2Ah02HZc8+H/J/aF3tvChI7Gx0anaSQxS48Ru +3eCaiaBEfoSGQvN9Jc+k1QJgJ4vZ8yi7ndl8pwW97YXo8Sg305ritqpnon+vemsV +rYoqHN+WV2/D0nqNu1AX8PldDvUYTfBtLfS7T5goN7abEIJCaTNmzU2ji0SqI9vJ +j4t9E9KcCKMshbciDrD7RPEPk3vogEDD3uygFwcPwUQfpCUFbRJOnTSH1oB/aUC4 +x9DnYSHBdDvaBmu0pBpoddJ+0pbw02P7YL9kPz5OnOAN06JP4McIYz5ytKoSt/m8 +Z7cUnvn7TRVNLuiapwpB0gtRmb9JY1q3pd63+X0SCaBEtUH+PWcRcS7eDsgMwEym +0CyANhCQYJjcKugIWLYtN/0/p2bIKcRmcH3iJiN2zZtP1AF6G7a4mp+21OynvFOc +3+ojTDGJxxD3uPtKEhJXRgYMOmfAEn3rgtoln1kkNYcd7f2EIulckwB2yeM1IMud +0le7 +-----END CERTIFICATE----- diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.csr b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.csr new file mode 100644 index 0000000000..bb61322340 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.csr @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIErzCCApcCAQAwajELMAkGA1UEBhMCQ0wxCzAJBgNVBAgMAlJNMRowGAYDVQQH +DBFPcGVuVGVsZW1ldHJ5VGVzdDENMAsGA1UECgwEVGVzdDEPMA0GA1UECwwGU2Vy +dmVyMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDWkb+46XRHnRtAkPy6CRF7hN9nmV82q+ObtOcKuQs6p1JWHR8sfHIA +iSeOCk4RV4js4BCxYosI8Zj6NQgy6hqfLxAx57b4cS4cP5hcv2mu2Kwr9f9Xl9Pn +BLzVMqIpIxylxAiO7FdWVTK4phil0DakX7m9SWyfiMy/pKejEbXQOhs8bFNA4FsH ++yEMbQkOE8N6Jydz9zWQJIM+swlYTlZEew7qhrpc00A2v/5lsCkCYnucLHFEY7y7 +CdKa0tek3P+cl4o8EY8MfGRKA6yeSrM6DEMCiKCze8BwaNq/P/EULDhk1TCdSPZD +pB97PXJbMMQq56c3TTZsiME1mkOgqqUKadLpxophd1aJGpx4ToXKZFn8wwK5lIy+ +DyBQUASbxyBCm7oWeKVGC/+kbYBINn98VT3vLNIZ/w88CU4F6hF/k2O1ryCph9LD +BmfU2c1nvVuuCzNv+Nu/uqX4EDgCQxzS0mKZmmteEfut9CDKHHWOrI9oaGfUyvEY +nap/qvuZCKRv6T+228287KLXc4zW+oexgZbLssnKDn4j/gumbP8lGQAGRLEptHuH +VxQnHLq5F0S+3GSRwv2oEIZJL3BD9U6ZmsoI27nDBPoeh9BtErfMswUMBCXZJ8DZ +nxISHY5ol+rv37zzulSeRwcYAOYDjSZZPuBG4mU35dq2GrgRYZaB8wIDAQABoAAw +DQYJKoZIhvcNAQELBQADggIBALQRbWtd7VIT7PI0g2TJY2nyFDZ+iNLlsqtlTQ+3 +9tDUNf911AyXGFBH2OaIg49UEl3Dn3ErAH6nZluZhRNjZRUYfE2dSEVYoeAA3SmE +FElARM1CX4dQUDnV++RLLRIKKGfcnwU+vSEWN4QfXs9qjI2UK80CBr6kPEt+bMfR +wUIax5HT1XLECoLph1rNza0h3WNk5ndEJMAt51U0JNAi6PwDF04ZfnX5E2RtiEjV ++3DPW1HYlX2hepkXVJPB568bbpmWLrmJsHjVZy4vmDoQi2bzS/QPsepgQ3aXxNel +vTxh0Or5SdIRRfNnP/Ov/aYjBxzkcKY83ADh7h1aqMOlUyFenHoMfTWnMYkeNY+1 +dOoLUS/ZNA6IH54UO7uY0uOcwCfRPYZzDxZI0IkjogX0aizixSs5duQx0ux3sUOo +a4zxMNPd89ppbCMZDS7biC7cOAsdDYXKcE5ijpc5CQXVo4/dA2xyfisRT7WUq9ay +vmQoYfMCAkGv47BVYhzASyPIXuFP2/HDbtnBvZ2aeSuMAwhHzj3vX9js2HGy7t2V +kj36LymQv+YBp9mV9/crSqy0DNFAYOWOuig0mQX/SPedGa4jf9v4OhANi+kzgxtQ +hBTcA0OtJyrVxesVGGK0YwaQIIZ8jwhsK3ljlZpOfVUflHl2/etME1DXtU37U9xA +fuw0 +-----END CERTIFICATE REQUEST----- diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.key b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.key new file mode 100644 index 0000000000..ddac188c23 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/certs/server.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEA1pG/uOl0R50bQJD8ugkRe4TfZ5lfNqvjm7TnCrkLOqdSVh0f +LHxyAIknjgpOEVeI7OAQsWKLCPGY+jUIMuoany8QMee2+HEuHD+YXL9prtisK/X/ +V5fT5wS81TKiKSMcpcQIjuxXVlUyuKYYpdA2pF+5vUlsn4jMv6SnoxG10DobPGxT +QOBbB/shDG0JDhPDeicnc/c1kCSDPrMJWE5WRHsO6oa6XNNANr/+ZbApAmJ7nCxx +RGO8uwnSmtLXpNz/nJeKPBGPDHxkSgOsnkqzOgxDAoigs3vAcGjavz/xFCw4ZNUw +nUj2Q6Qfez1yWzDEKuenN002bIjBNZpDoKqlCmnS6caKYXdWiRqceE6FymRZ/MMC +uZSMvg8gUFAEm8cgQpu6FnilRgv/pG2ASDZ/fFU97yzSGf8PPAlOBeoRf5Njta8g +qYfSwwZn1NnNZ71brgszb/jbv7ql+BA4AkMc0tJimZprXhH7rfQgyhx1jqyPaGhn +1MrxGJ2qf6r7mQikb+k/ttvNvOyi13OM1vqHsYGWy7LJyg5+I/4Lpmz/JRkABkSx +KbR7h1cUJxy6uRdEvtxkkcL9qBCGSS9wQ/VOmZrKCNu5wwT6HofQbRK3zLMFDAQl +2SfA2Z8SEh2OaJfq79+887pUnkcHGADmA40mWT7gRuJlN+Xathq4EWGWgfMCAwEA +AQKCAgAOCE4fi7T9Efs8R78fc4RfLZtmrRMbAjbKchRCEUP4vASYeSMWx7S08ENT ++LyOSck8pJKy5xzsotA8XMeCfOjszCkk+mBu8wfu9QHD3wjMVIM+BMKEOfuzug2X +a85LHm67MIzWvAIiNUQx6zrlbS6FpXUCOhEOheXOCrij436edY5ebz8qmQGbDgNl +SqQy9XvtOy5LWTl5icnDifXsfoMJy3p4QANkGrSyX/AFOnYUH9ixp/5oWJV5LfVG +Bs/vijx1QzvZHdTbHi9437CkUYJTI4YmXkUUN92n/FOB+m6LwTCW95JMVv80AUHF +z4jxCclqfOfkp/oNMwxfsw0FLuPIIcy0StssnTAXoOXDKzJm+nkVAqvIs+io6IuH +if+Ehng3N2uZFTD3LdJHDYQnLUJHR53WOdj5lUaqH0KHBFaz1bRyCjgNRbxR7psU +3CfbIhePFR3vw75LDFeEtDLOQuxTDuE+8M97RAta7oiPZjjiiY8qep+Z5MEdMpp9 +7L9ziqFntebz/H9y0QCxEIy99RbBc39WXt55sGknSs7cK6dWnAhNi8T2eFmgBMmX +t2JVYQ8ZDS92HsN40BRHEyUEpd8Dl9cDGDNQKGu0PpcwKA8S2liOVH45g99TelDv +hgc/vt15BFfdFz5zaWN3F5CEN7YaGr57OPTdeZJBxvZGIcg2QQKCAQEA/q7U/WCH +0yWNSE87JtrFfacRMAXtkX2b+AHZZM9F6iyOJnUYAuK5cUzbLCb3C0OQTwwluviy +md9oLddcI7ZPE1i2qhU1vhlvSRIpfJ+VoW2DNUKmkpAizlnEvvbSBkoNn1U8c2RK +WbyavfsFpZ8pVrkqAxjlHgO0zCOMvke2sUZrBietGMpGr08SnbZwFntQ/R9KVrT3 +oa9Aku5cDr1l2hm2GLuTG0ocnrlxV2NJ+gaCRcMAlboBfsIoE7bfn/Vt1Ea/UqrQ +Ym9ETc9fIjLC+FvIXBdY67mqjigyZI8DUee644eVONRblAv0j7JnpqxZl1mGyqiP +YiEvN4lFCkNhcQKCAQEA163Pw9HXOwaG7ofFCqpKu3OEvCc9/nA0S6eZHLh4RJkN +9FMt9Rmczb1doqK+Jnz+qoDCLTVNOARC1sQOTqzji1/yUUEAC5Hs8yZlSYuE0oqW +jA3hyc0PFm7H8OF5e2J68ZIX3PAi61ZuPuX7ApZSE2+ByHRLwcW7hJ1BkugwlPOP +nrlQZQiFJRtCykL1p3CwqLwzsv8qpu8o8hf50oT8kMs4olABE8CBoa4ufDrWe3ew +kN3Q1bmzf2x/RrlI7JptbT202zi8p86LuYAdJ+AC1dBJcoGKBjittrKS+Ps6YYjj +Z+haI6JEYZPHKJgWNmAWTQ+m66bFhFaI2G2wBqtnowKCAQAh7/An114iD8X01cH/ +GnXomYObz55pncBT2wM6ALjDTK6gh0fs0oN9io1GI+cVlCo9rlO0x4EdKfz65tC7 +XYbKAC9PGMZxj3gZ15a5qZZJzYsHZNtHend44dNq0v8HoYSRL81/XuTdcll4aWPG +PyBGEyR7By04w6uq7C3MCUhZ9RU727ugKwwiPjov0+i5xjLzl+DTDwhUfkLvkV2p +BSn2VyjBwPUIVObda76js3JfI9DmNOb2DLQ4TO0EO4EvEohRGiBShrp/8225pKF7 +sCH08F4Rj3bk6nfEu6yDY99AYc2wlheXXAzb/H/ZSh+vwRWrKl3g0XdRzzQ4hU0y +4emxAoIBAH2IhBJE09JeNTEmwxA3F/JNBWgCKzoqErYqIZsu34mF0DJyK6CqPLMf +Uh20PZrnS87vzJVFneFJ0aFxUaaHSJW5za9vdthFIjZQFcods7xbv85a0h2EBhEX +f7Z7dhrTsh1i3BLTjm+NyfNAJr5VwgXf9Bk5X1K0hTVl1mHsVUKNFP3cfKehsuVr +HY/eM1823wwHJsw7apbpQtrOC7F1iA+6yQboLAhUFt+FIzdZg7cvbgyTntaXFJvJ +CbefZouYQrK/pMGoH15IgNkCcXXhE6Vhay6DqVN/r9RT0emrSEq2wy2adsSg0M4+ +lj/RbbRObwyBXLVyRyqEt3fJOBhZsaMCggEBAIxcTLc4JPH/TxlFKTusALlR4CRG +XHDlTdMR4kWfsmWxWxocwcyGIshNpylox+MLzHw1JI4o5AyVrP8GD9Lzea2l649Y +vBLZjSan+ucJGkWnZPUG8sqo/Wg1mm2ZotQGfXmTaoOg9nN37YZvyDr3qgpQghZ2 +LhFNCaccJcoUZfW+snM9Q3Isiz6DmKfc92eq3goHfhmTInYq+b30Z9nO7nDV9oll +eeurRN0aCnfvRTAMoy17gt5/h9jg7w9kcbP6wyxixlBvTKQqxkBA1wfa2kBQ6TOK +JSldpu7eAHZ8IHEraQ70Drd/Qr77Witm59F5TX0Vxut7/A1dEjWuP9SY4do= +-----END RSA PRIVATE KEY----- diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/helper.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/traceHelper.ts similarity index 69% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/helper.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/traceHelper.ts index e77f0f1742..83578d3c12 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/helper.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/traceHelper.ts @@ -15,32 +15,13 @@ */ import { SpanStatusCode, TraceFlags } from '@opentelemetry/api'; -import { - Counter, - ObserverResult, - ValueObserver, - ValueRecorder, - ValueType, -} from '@opentelemetry/api-metrics'; -import { otlpTypes } from '@opentelemetry/exporter-otlp-http'; -import * as metrics from '@opentelemetry/sdk-metrics-base'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import { Resource } from '@opentelemetry/resources'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; import * as grpc from '@grpc/grpc-js'; import { VERSION } from '@opentelemetry/core'; -const meterProvider = new metrics.MeterProvider({ - interval: 30000, - resource: new Resource({ - service: 'ui', - version: 1, - cost: 112.12, - }), -}); - -const meter = meterProvider.getMeter('default', '0.0.1'); - const traceIdArr = [ 31, 16, @@ -62,53 +43,6 @@ const traceIdArr = [ const spanIdArr = [94, 16, 114, 97, 246, 79, 165, 62]; const parentIdArr = [120, 168, 145, 80, 152, 134, 67, 136]; -export function mockCounter(): metrics.Metric & Counter { - const name = 'int-counter'; - const metric = - meter['_metrics'].get(name) || - meter.createCounter(name, { - description: 'sample counter description', - valueType: ValueType.INT, - }); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockObserver( - callback: (observerResult: ObserverResult) => void -): metrics.Metric & ValueObserver { - const name = 'double-observer'; - const metric = - meter['_metrics'].get(name) || - meter.createValueObserver( - name, - { - description: 'sample observer description', - valueType: ValueType.DOUBLE, - }, - callback - ); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockValueRecorder(): metrics.Metric & - ValueRecorder { - const name = 'int-recorder'; - const metric = - meter['_metrics'].get(name) || - meter.createValueRecorder(name, { - description: 'sample recorder description', - valueType: ValueType.INT, - boundaries: [0, 100], - }); - metric.clear(); - metric.bind({}); - return metric; -} - export const mockedReadableSpan: ReadableSpan = { name: 'documentFetch', kind: 0, @@ -327,83 +261,6 @@ export function ensureExportedSpanIsCorrect( ); } -export function ensureExportedCounterIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time?: number -) { - assert.deepStrictEqual(metric, { - name: 'int-counter', - description: 'sample counter description', - unit: '1', - data: 'intSum', - intSum: { - dataPoints: [ - { - labels: [], - exemplars: [], - value: '1', - startTimeUnixNano: '1592602232694000128', - timeUnixNano: String(time), - }, - ], - isMonotonic: true, - aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', - }, - }); -} - -export function ensureExportedObserverIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time?: number -) { - assert.deepStrictEqual(metric, { - name: 'double-observer', - description: 'sample observer description', - unit: '1', - data: 'doubleGauge', - doubleGauge: { - dataPoints: [ - { - labels: [], - exemplars: [], - value: 6, - startTimeUnixNano: '1592602232694000128', - timeUnixNano: String(time), - }, - ], - }, - }); -} - -export function ensureExportedValueRecorderIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time?: number, - explicitBounds: number[] = [Infinity], - bucketCounts: string[] = ['2', '0'] -) { - assert.deepStrictEqual(metric, { - name: 'int-recorder', - description: 'sample recorder description', - unit: '1', - data: 'intHistogram', - intHistogram: { - dataPoints: [ - { - labels: [], - exemplars: [], - sum: '21', - count: '2', - startTimeUnixNano: '1592602232694000128', - timeUnixNano: String(time), - bucketCounts, - explicitBounds, - }, - ], - aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', - }, - }); -} - export function ensureResourceIsCorrect( resource: otlpTypes.opentelemetryProto.resource.v1.Resource ) { diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/test/util.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/util.test.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/test/util.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/test/util.test.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-grpc/tsconfig.json b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/tsconfig.json similarity index 85% rename from experimental/packages/opentelemetry-exporter-otlp-grpc/tsconfig.json rename to experimental/packages/opentelemetry-exporter-trace-otlp-grpc/tsconfig.json index caced6b4e8..13dc2e7744 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-grpc/tsconfig.json +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-grpc/tsconfig.json @@ -13,7 +13,7 @@ "path": "../opentelemetry-api-metrics" }, { - "path": "../opentelemetry-exporter-otlp-http" + "path": "../opentelemetry-exporter-trace-otlp-http" }, { "path": "../opentelemetry-sdk-metrics-base" diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/.eslintignore b/experimental/packages/opentelemetry-exporter-trace-otlp-http/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/.eslintignore @@ -0,0 +1 @@ +build diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/.eslintrc.js b/experimental/packages/opentelemetry-exporter-trace-otlp-http/.eslintrc.js new file mode 100644 index 0000000000..e41d9a9299 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + "env": { + "mocha": true, + "commonjs": true, + "node": true, + "browser": true + }, + ...require('../../../eslint.config.js') +} diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/.npmignore b/experimental/packages/opentelemetry-exporter-trace-otlp-http/.npmignore new file mode 100644 index 0000000000..9505ba9450 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/.npmignore @@ -0,0 +1,4 @@ +/bin +/coverage +/doc +/test diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/LICENSE b/experimental/packages/opentelemetry-exporter-trace-otlp-http/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/README.md b/experimental/packages/opentelemetry-exporter-trace-otlp-http/README.md similarity index 74% rename from experimental/packages/opentelemetry-exporter-otlp-http/README.md rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/README.md index 7aff40f464..f0f8853ef5 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/README.md +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/README.md @@ -10,13 +10,14 @@ This module provides exporter for web and node to be used with [opentelemetry-co ## Installation ```bash -npm install --save @opentelemetry/exporter-otlp-http +npm install --save @opentelemetry/exporter-trace-otlp-http ``` ## Service Name The OpenTelemetry Collector Exporter does not have a service name configuration. In order to set the service name, use the `service.name` resource attribute as prescribed in the [OpenTelemetry Resource Semantic Conventions][semconv-resource-service-name]. +To see documentation and sample code for the metric exporter, see the [exporter-metrics-otlp-http package][metrics-exporter-url] ## Traces in Web @@ -25,7 +26,7 @@ The OTLPTraceExporter in Web expects the endpoint to end in `/v1/traces`. ```js import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'; import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; -import { OTLPTraceExporter } from '@opentelemetry/exporter-otlp-http'; +import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; const collectorOptions = { url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/traces @@ -50,37 +51,11 @@ provider.register(); ``` -## Metrics in Web - -The OTLPMetricExporter in Web expects the endpoint to end in `/v1/metrics`. - -```js -import { MeterProvider } from '@opentelemetry/sdk-metrics-base'; -import { OTLPMetricExporter } from '@opentelemetry/exporter-otlp-http'; -const collectorOptions = { - url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/metrics - headers: {}, // an optional object containing custom headers to be sent with each request - concurrencyLimit: 1, // an optional limit on pending requests -}; -const exporter = new OTLPMetricExporter(collectorOptions); - -// Register the exporter -const meter = new MeterProvider({ - exporter, - interval: 60000, -}).getMeter('example-meter'); - -// Now, start recording data -const counter = meter.createCounter('metric_name'); -counter.add(10, { 'key': 'value' }); - -``` - ## Traces in Node - JSON over http ```js const { BasicTracerProvider, BatchSpanProcessor } = require('@opentelemetry/sdk-trace-base'); -const { OTLPTraceExporter } = require('@opentelemetry/exporter-otlp-http'); +const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http'); const collectorOptions = { url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/traces @@ -103,29 +78,6 @@ provider.register(); ``` -## Metrics in Node - -```js -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); -const { OTLPMetricExporter } = require('@opentelemetry/exporter-otlp-http'); -const collectorOptions = { - url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/metrics - concurrencyLimit: 1, // an optional limit on pending requests -}; -const exporter = new OTLPMetricExporter(collectorOptions); - -// Register the exporter -const meter = new MeterProvider({ - exporter, - interval: 60000, -}).getMeter('example-meter'); - -// Now, start recording data -const counter = meter.createCounter('metric_name'); -counter.add(10, { 'key': 'value' }); - -``` - ## GRPC For GRPC please check [npm-url-grpc] @@ -175,14 +127,15 @@ 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 -[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-otlp-http -[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-otlp-http -[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-otlp-http&type=dev -[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-otlp-http&type=dev -[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-otlp-http -[npm-url-grpc]: https://www.npmjs.com/package/@opentelemetry/exporter-otlp-grpc -[npm-url-proto]: https://www.npmjs.com/package/@opentelemetry/exporter-otlp-proto -[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-collector.svg +[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-trace-otlp-http +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-trace-otlp-http +[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-trace-otlp-http&type=dev +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-trace-otlp-http&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http +[npm-url-grpc]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-grpc +[npm-url-proto]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-trace-otlp-http.svg [opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector [opentelemetry-spec-protocol-exporter]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options [semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service +[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-metrics-otlp-http diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/karma.conf.js b/experimental/packages/opentelemetry-exporter-trace-otlp-http/karma.conf.js new file mode 100644 index 0000000000..4c60b54edb --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/karma.conf.js @@ -0,0 +1,26 @@ +/*! + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const karmaWebpackConfig = require('../../../karma.webpack'); +const karmaBaseConfig = require('../../../karma.base'); + +module.exports = (config) => { + config.set(Object.assign({}, karmaBaseConfig, { + webpack: karmaWebpackConfig, + files: ['test/browser/index-webpack.ts'], + preprocessors: { 'test/browser/index-webpack.ts': ['webpack'] } + })) +}; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/package.json b/experimental/packages/opentelemetry-exporter-trace-otlp-http/package.json similarity index 87% rename from experimental/packages/opentelemetry-exporter-otlp-http/package.json rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/package.json index 91399c51a8..99af715a2e 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/package.json +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/package.json @@ -1,7 +1,7 @@ { - "name": "@opentelemetry/exporter-otlp-http", + "name": "@opentelemetry/exporter-trace-otlp-http", "version": "0.26.0", - "description": "OpenTelemetry Collector Exporter allows user to send collected traces to the OpenTelemetry Collector", + "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", "types": "build/src/index.d.ts", @@ -56,7 +56,7 @@ }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", @@ -65,7 +65,7 @@ "codecov": "3.8.3", "cpx": "1.5.0", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -74,7 +74,7 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", @@ -83,13 +83,11 @@ "webpack-merge": "5.8.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { - "@opentelemetry/api-metrics": "0.26.0", "@opentelemetry/core": "1.0.0", "@opentelemetry/resources": "1.0.0", - "@opentelemetry/sdk-metrics-base": "0.26.0", "@opentelemetry/sdk-trace-base": "1.0.0" } } diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/OTLPExporterBase.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/OTLPExporterBase.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/OTLPExporterBase.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/OTLPExporterBase.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/index.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/index.ts similarity index 85% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/index.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/index.ts index 7b212c0399..bd025cd4d6 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/src/index.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/index.ts @@ -17,6 +17,5 @@ export * from './OTLPExporterBase'; export * from './platform'; export * as otlpTypes from './types'; -export { toOTLPExportTraceServiceRequest } from './transform'; -export { toOTLPExportMetricServiceRequest } from './transformMetrics'; +export { toCollectorResource, toOTLPExportTraceServiceRequest } from './transform'; export { appendResourcePathToUrlIfNotPresent } from './util'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/OTLPTraceExporter.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/OTLPTraceExporter.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/index.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/index.ts new file mode 100644 index 0000000000..6a322e976a --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './OTLPTraceExporter'; +export * from './OTLPExporterBrowserBase'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/util.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/util.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/browser/util.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/browser/util.ts diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/index.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/index.ts new file mode 100644 index 0000000000..a33b81cffb --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './node'; +export { OTLPExporterBrowserBase } from './browser'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/OTLPExporterNodeBase.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts similarity index 95% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/OTLPExporterNodeBase.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts index 03eb432b49..920f0ac043 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/OTLPExporterNodeBase.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts @@ -90,5 +90,7 @@ export abstract class OTLPExporterNodeBase< promise.then(popPromise, popPromise); } + // TODO: end gzip stream from util.ts if not undefined + // It should perhaps be a class member here instead of a variable in util.ts onShutdown(): void {} } diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/OTLPTraceExporter.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/OTLPTraceExporter.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/index.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/index.ts similarity index 95% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/index.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/index.ts index cfd5b2286d..ab18e724e0 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/index.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/index.ts @@ -15,7 +15,6 @@ */ export * from './OTLPTraceExporter'; -export * from './OTLPMetricExporter'; export * from './OTLPExporterNodeBase'; export * from './util'; export * from './types'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/types.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/types.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/types.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/types.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/util.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/util.ts similarity index 97% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/util.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/util.ts index 8c905c496d..0e40b585db 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/src/platform/node/util.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/platform/node/util.ts @@ -24,7 +24,7 @@ import { OTLPExporterNodeConfigBase } from '.'; import { diag } from '@opentelemetry/api'; import { CompressionAlgorithm } from './types'; -const gzip = zlib.createGzip(); +let gzip: zlib.Gzip | undefined; /** * Sends data using http @@ -83,6 +83,9 @@ export function sendWithHttp( switch (collector.compression) { case CompressionAlgorithm.GZIP: { + if (!gzip) { + gzip = zlib.createGzip(); + } req.setHeader('Content-Encoding', 'gzip'); const dataStream = readableFromBuffer(data); dataStream.on('error', onError) diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/transform.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/transform.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/transform.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/transform.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/types.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/types.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/types.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/types.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/src/util.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/src/util.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/src/util.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/src/util.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/browser/CollectorTraceExporter.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts similarity index 99% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/browser/CollectorTraceExporter.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts index 33cc33fff8..0a709a953f 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/browser/CollectorTraceExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts @@ -29,7 +29,7 @@ import { ensureWebResourceIsCorrect, ensureHeadersContain, mockedReadableSpan, -} from '../helper'; +} from '../traceHelper'; describe('OTLPTraceExporter - web', () => { let collectorTraceExporter: OTLPTraceExporter; diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/index-webpack.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/index-webpack.ts new file mode 100644 index 0000000000..99100a0f6e --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/index-webpack.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ +const testsContext = require.context('../browser', true, /test$/); +testsContext.keys().forEach(testsContext); + +const testsContextCommon = require.context('../common', true, /test$/); +testsContextCommon.keys().forEach(testsContextCommon); + +const srcContext = require.context('.', true, /src$/); +srcContext.keys().forEach(srcContext); diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/browser/util.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/util.test.ts similarity index 98% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/browser/util.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/util.test.ts index ecb6c4c801..c4cb185da1 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/browser/util.test.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/browser/util.test.ts @@ -16,7 +16,7 @@ import * as sinon from 'sinon'; import { sendWithXhr } from '../../src/platform/browser/util'; -import { ensureHeadersContain } from '../helper'; +import { ensureHeadersContain } from '../traceHelper'; describe('util - browser', () => { let server: any; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/ca.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/ca.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/ca.crt rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/ca.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/ca.key b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/ca.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/ca.key rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/ca.key diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/client.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/client.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/client.crt rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/client.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/client.csr b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/client.csr similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/client.csr rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/client.csr diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/client.key b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/client.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/client.key rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/client.key diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/regenerate.sh b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/regenerate.sh similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/regenerate.sh rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/regenerate.sh diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/server.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/server.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/server.crt rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/server.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/server.csr b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/server.csr similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/server.csr rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/server.csr diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/certs/server.key b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/server.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/certs/server.key rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/certs/server.key diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/CollectorTraceExporter.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/common/CollectorTraceExporter.test.ts similarity index 99% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/common/CollectorTraceExporter.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/common/CollectorTraceExporter.test.ts index f489a74906..945c059e5b 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/CollectorTraceExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/common/CollectorTraceExporter.test.ts @@ -20,7 +20,7 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; import { OTLPExporterBase } from '../../src/OTLPExporterBase'; import { OTLPExporterConfigBase } from '../../src/types'; -import { mockedReadableSpan } from '../helper'; +import { mockedReadableSpan } from '../traceHelper'; import * as otlpTypes from '../../src/types'; type CollectorExporterConfig = OTLPExporterConfigBase; diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/transform.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/common/transform.test.ts similarity index 99% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/common/transform.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/common/transform.test.ts index 0328aaea67..b2dfdf2145 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/transform.test.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/common/transform.test.ts @@ -25,7 +25,7 @@ import { mockedInstrumentationLibraries, multiResourceTrace, multiInstrumentationLibraryTrace, -} from '../helper'; +} from '../traceHelper'; import { Resource } from '@opentelemetry/resources'; describe('transform', () => { describe('toCollectorAttributes', () => { diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/common/utils.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/common/utils.test.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/common/utils.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/common/utils.test.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/node/CollectorTraceExporter.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts similarity index 99% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/node/CollectorTraceExporter.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts index 8988572b67..33c9559dc9 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/node/CollectorTraceExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts @@ -34,7 +34,7 @@ import { ensureExportTraceServiceRequestIsSet, ensureSpanIsCorrect, mockedReadableSpan, -} from '../helper'; +} from '../traceHelper'; let fakeRequest: PassThrough; diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/node/nodeHelpers.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/node/nodeHelpers.ts new file mode 100644 index 0000000000..1219f2d976 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/node/nodeHelpers.ts @@ -0,0 +1,36 @@ +/* + * 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 { Stream } from 'stream'; + +export class MockedResponse extends Stream { + constructor(private _code: number, private _msg?: string) { + super(); + } + + send(data: string) { + this.emit('data', data); + this.emit('end'); + } + + get statusCode() { + return this._code; + } + + get statusMessage() { + return this._msg; + } +} diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/test/helper.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/traceHelper.ts similarity index 56% rename from experimental/packages/opentelemetry-exporter-otlp-http/test/helper.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/test/traceHelper.ts index 8783906034..9975f05f3c 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-http/test/helper.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-http/test/traceHelper.ts @@ -15,34 +15,13 @@ */ import { SpanStatusCode, TraceFlags } from '@opentelemetry/api'; -import { - Counter, - ObserverResult, - SumObserver, - UpDownSumObserver, - ValueObserver, - ValueRecorder, - ValueType, -} from '@opentelemetry/api-metrics'; import { hexToBase64, InstrumentationLibrary, VERSION } from '@opentelemetry/core'; -import * as metrics from '@opentelemetry/sdk-metrics-base'; import { Resource } from '@opentelemetry/resources'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; import * as otlpTypes from '../src/types'; import { opentelemetryProto } from '../src/types'; -const meterProvider = new metrics.MeterProvider({ - interval: 30000, - resource: new Resource({ - service: 'ui', - version: 1, - cost: 112.12, - }), -}); - -const meter = meterProvider.getMeter('default', '0.0.1'); - if (typeof Buffer === 'undefined') { (window as any).Buffer = { from: function (arr: []) { @@ -51,105 +30,6 @@ if (typeof Buffer === 'undefined') { }; } -export function mockCounter(): metrics.Metric & Counter { - const name = 'int-counter'; - const metric = - meter['_metrics'].get(name) || - meter.createCounter(name, { - description: 'sample counter description', - valueType: ValueType.INT, - }); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockDoubleCounter(): metrics.Metric & - Counter { - const name = 'double-counter'; - const metric = - meter['_metrics'].get(name) || - meter.createCounter(name, { - description: 'sample counter description', - valueType: ValueType.DOUBLE, - }); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockObserver( - callback: (observerResult: ObserverResult) => unknown, - name = 'double-observer' -): metrics.Metric & ValueObserver { - const metric = - meter['_metrics'].get(name) || - meter.createValueObserver( - name, - { - description: 'sample observer description', - valueType: ValueType.DOUBLE, - }, - callback - ); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockSumObserver( - callback: (observerResult: ObserverResult) => unknown, - name = 'double-sum-observer' -): metrics.Metric & SumObserver { - const metric = - meter['_metrics'].get(name) || - meter.createSumObserver( - name, - { - description: 'sample sum observer description', - valueType: ValueType.DOUBLE, - }, - callback - ); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockUpDownSumObserver( - callback: (observerResult: ObserverResult) => unknown, - name = 'double-up-down-sum-observer' -): metrics.Metric & UpDownSumObserver { - const metric = - meter['_metrics'].get(name) || - meter.createUpDownSumObserver( - name, - { - description: 'sample up down sum observer description', - valueType: ValueType.DOUBLE, - }, - callback - ); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockValueRecorder(): metrics.Metric & - ValueRecorder { - const name = 'int-recorder'; - const metric = - meter['_metrics'].get(name) || - meter.createValueRecorder(name, { - description: 'sample recorder description', - valueType: ValueType.INT, - boundaries: [0, 100], - }); - metric.clear(); - metric.bind({}); - return metric; -} - const traceIdHex = '1f1008dc8e270e85c40a0d7c3939b278'; const spanIdHex = '5e107261f64fa53e'; const parentIdHex = '78a8915098864388'; @@ -312,50 +192,6 @@ export const multiResourceTrace: ReadableSpan[] = [ }, ]; -export const multiResourceMetricsGet = function ( - callback: (observerResult: ObserverResult) => unknown -): any[] { - return [ - { - ...mockCounter(), - resource: mockedResources[0], - instrumentationLibrary: mockedInstrumentationLibraries[0], - }, - { - ...mockObserver(callback), - resource: mockedResources[1], - instrumentationLibrary: mockedInstrumentationLibraries[0], - }, - { - ...mockCounter(), - resource: mockedResources[0], - instrumentationLibrary: mockedInstrumentationLibraries[0], - }, - ]; -}; - -export const multiInstrumentationLibraryMetricsGet = function ( - callback: (observerResult: ObserverResult) => unknown -): any[] { - return [ - { - ...mockCounter(), - resource: mockedResources[0], - instrumentationLibrary: mockedInstrumentationLibraries[0], - }, - { - ...mockObserver(callback), - resource: mockedResources[0], - instrumentationLibrary: mockedInstrumentationLibraries[1], - }, - { - ...mockCounter(), - resource: mockedResources[0], - instrumentationLibrary: mockedInstrumentationLibraries[0], - }, - ]; -}; - export const multiInstrumentationLibraryTrace: ReadableSpan[] = [ { ...basicTrace[0], @@ -551,162 +387,6 @@ export function ensureWebResourceIsCorrect( assert.strictEqual(resource.droppedAttributesCount, 0); } -export function ensureCounterIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time: number -) { - assert.deepStrictEqual(metric, { - name: 'int-counter', - description: 'sample counter description', - unit: '1', - intSum: { - dataPoints: [ - { - labels: [], - value: 1, - startTimeUnixNano: 1592602232694000000, - timeUnixNano: time, - }, - ], - isMonotonic: true, - aggregationTemporality: - otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality - .AGGREGATION_TEMPORALITY_CUMULATIVE, - }, - }); -} - -export function ensureDoubleCounterIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time: number -) { - assert.deepStrictEqual(metric, { - name: 'double-counter', - description: 'sample counter description', - unit: '1', - doubleSum: { - dataPoints: [ - { - labels: [], - value: 8, - startTimeUnixNano: 1592602232694000000, - timeUnixNano: time, - }, - ], - isMonotonic: true, - aggregationTemporality: - otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality - .AGGREGATION_TEMPORALITY_CUMULATIVE, - }, - }); -} - -export function ensureObserverIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time: number, - value: number, - name = 'double-observer' -) { - assert.deepStrictEqual(metric, { - name, - description: 'sample observer description', - unit: '1', - doubleGauge: { - dataPoints: [ - { - labels: [], - value, - startTimeUnixNano: 1592602232694000000, - timeUnixNano: time, - }, - ], - }, - }); -} - -export function ensureSumObserverIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time: number, - value: number, - name = 'double-sum-observer' -) { - assert.deepStrictEqual(metric, { - name, - description: 'sample sum observer description', - unit: '1', - doubleSum: { - isMonotonic: true, - dataPoints: [ - { - labels: [], - value, - startTimeUnixNano: 1592602232694000000, - timeUnixNano: time, - }, - ], - aggregationTemporality: - otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality - .AGGREGATION_TEMPORALITY_CUMULATIVE, - }, - }); -} - -export function ensureUpDownSumObserverIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time: number, - value: number, - name = 'double-up-down-sum-observer' -) { - assert.deepStrictEqual(metric, { - name, - description: 'sample up down sum observer description', - unit: '1', - doubleSum: { - isMonotonic: false, - dataPoints: [ - { - labels: [], - value, - startTimeUnixNano: 1592602232694000000, - timeUnixNano: time, - }, - ], - aggregationTemporality: - otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality - .AGGREGATION_TEMPORALITY_CUMULATIVE, - }, - }); -} - -export function ensureValueRecorderIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time: number, - explicitBounds: (number | null)[] = [Infinity], - bucketCounts: number[] = [2, 0] -) { - assert.deepStrictEqual(metric, { - name: 'int-recorder', - description: 'sample recorder description', - unit: '1', - intHistogram: { - dataPoints: [ - { - labels: [], - sum: 21, - count: 2, - startTimeUnixNano: 1592602232694000000, - timeUnixNano: time, - bucketCounts, - explicitBounds, - }, - ], - aggregationTemporality: - otlpTypes.opentelemetryProto.metrics.v1.AggregationTemporality - .AGGREGATION_TEMPORALITY_CUMULATIVE, - }, - }); -} - export function ensureExportTraceServiceRequestIsSet( json: otlpTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest ) { @@ -740,39 +420,6 @@ export function ensureExportTraceServiceRequestIsSet( assert.strictEqual(spans && spans.length, 1, 'spans are missing'); } -export function ensureExportMetricsServiceRequestIsSet( - json: otlpTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest -) { - const resourceMetrics = json.resourceMetrics; - assert.strictEqual( - resourceMetrics.length, - 1, - 'resourceMetrics has incorrect length' - ); - - const resource = resourceMetrics[0].resource; - assert.strictEqual(!!resource, true, 'resource is missing'); - - const instrumentationLibraryMetrics = - resourceMetrics[0].instrumentationLibraryMetrics; - assert.strictEqual( - instrumentationLibraryMetrics && instrumentationLibraryMetrics.length, - 1, - 'instrumentationLibraryMetrics is missing' - ); - - const instrumentationLibrary = - instrumentationLibraryMetrics[0].instrumentationLibrary; - assert.strictEqual( - !!instrumentationLibrary, - true, - 'instrumentationLibrary is missing' - ); - - const metrics = resourceMetrics[0].instrumentationLibraryMetrics[0].metrics; - assert.strictEqual(metrics.length, 3, 'Metrics are missing'); -} - export function ensureHeadersContain( actual: { [key: string]: string }, expected: { [key: string]: string } diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/tsconfig.esm.json b/experimental/packages/opentelemetry-exporter-trace-otlp-http/tsconfig.esm.json similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/tsconfig.esm.json rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/tsconfig.esm.json diff --git a/experimental/packages/opentelemetry-exporter-otlp-http/tsconfig.json b/experimental/packages/opentelemetry-exporter-trace-otlp-http/tsconfig.json similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-http/tsconfig.json rename to experimental/packages/opentelemetry-exporter-trace-otlp-http/tsconfig.json diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.eslintignore b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.eslintignore @@ -0,0 +1 @@ +build diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.eslintrc.js b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.eslintrc.js new file mode 100644 index 0000000000..3ed0fbeba3 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + "env": { + "mocha": true, + "commonjs": true, + "node": true, + }, + ...require('../../../eslint.config.js') +} diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.npmignore b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.npmignore new file mode 100644 index 0000000000..9505ba9450 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/.npmignore @@ -0,0 +1,4 @@ +/bin +/coverage +/doc +/test diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-proto/LICENSE b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/README.md b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/README.md similarity index 76% rename from experimental/packages/opentelemetry-exporter-otlp-proto/README.md rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/README.md index 55b14756ab..fa4f09a5b9 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/README.md +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/README.md @@ -10,19 +10,20 @@ This module provides exporter for node to be used with [opentelemetry-collector] ## Installation ```bash -npm install --save @opentelemetry/exporter-otlp-proto +npm install --save @opentelemetry/exporter-trace-otlp-proto ``` ## Service Name The OpenTelemetry Collector Exporter does not have a service name configuration. In order to set the service name, use the `service.name` resource attribute as prescribed in the [OpenTelemetry Resource Semantic Conventions][semconv-resource-service-name]. +To see documentation and sample code for the metric exporter, see the [exporter-metrics-otlp-proto package][metrics-exporter-url] ## Traces in Node - PROTO over http ```js const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base'); -const { OTLPTraceExporter } = require('@opentelemetry/exporter-otlp-proto'); +const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-proto'); const collectorOptions = { url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/traces @@ -39,28 +40,6 @@ provider.register(); ``` -## Metrics in Node - PROTO over http - -```js -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); -const { OTLPMetricExporter } = require('@opentelemetry/exporter-otlp-proto'); -const collectorOptions = { - url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/metrics -}; -const exporter = new OTLPMetricExporter(collectorOptions); - -// Register the exporter -const meter = new MeterProvider({ - exporter, - interval: 60000, -}).getMeter('example-meter'); - -// Now, start recording data -const counter = meter.createCounter('metric_name'); -counter.add(10, { 'key': 'value' }); - -``` - ## Running opentelemetry-collector locally to see the traces 1. Go to examples/otlp-exporter-node @@ -80,11 +59,12 @@ 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 -[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-otlp-proto -[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-otlp-proto -[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-otlp-proto&type=dev -[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-otlp-proto&type=dev -[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-otlp-proto -[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-collector-proto.svg +[dependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-trace-otlp-proto +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-trace-otlp-proto +[devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-exporter-trace-otlp-proto&type=dev +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-trace-otlp-proto&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-trace-otlp-proto.svg [opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector [semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service +[metrics-exporter-url]: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-metrics-otlp-proto diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/package.json b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/package.json similarity index 87% rename from experimental/packages/opentelemetry-exporter-otlp-proto/package.json rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/package.json index a8f7ff5afa..dd7476f8e1 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/package.json +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/package.json @@ -1,5 +1,5 @@ { - "name": "@opentelemetry/exporter-otlp-proto", + "name": "@opentelemetry/exporter-trace-otlp-proto", "version": "0.26.0", "description": "OpenTelemetry Collector Exporter allows user to send collected traces to the OpenTelemetry Collector using protobuf over HTTP", "main": "build/src/index.js", @@ -48,8 +48,7 @@ }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", - "@opentelemetry/api-metrics": "0.26.0", + "@opentelemetry/api": "^1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", @@ -58,20 +57,19 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@grpc/proto-loader": "^0.6.4", "@opentelemetry/core": "1.0.0", - "@opentelemetry/exporter-otlp-http": "0.26.0", + "@opentelemetry/exporter-trace-otlp-http": "0.26.0", "@opentelemetry/resources": "1.0.0", - "@opentelemetry/sdk-metrics-base": "0.26.0", "@opentelemetry/sdk-trace-base": "1.0.0", "protobufjs": "^6.9.0" } diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-proto/protos b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/protos new file mode 160000 index 0000000000..59c488bfb8 --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/protos @@ -0,0 +1 @@ +Subproject commit 59c488bfb8fb6d0458ad6425758b70259ff4a2bd diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPExporterNodeBase.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/OTLPExporterNodeBase.ts similarity index 98% rename from experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPExporterNodeBase.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/OTLPExporterNodeBase.ts index 5cb553a5c0..bebc831650 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPExporterNodeBase.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/OTLPExporterNodeBase.ts @@ -20,7 +20,7 @@ import { otlpTypes, OTLPExporterNodeConfigBase, CompressionAlgorithm, -} from '@opentelemetry/exporter-otlp-http'; +} from '@opentelemetry/exporter-trace-otlp-http'; import { ServiceClientType } from './types'; type SendFn = (collector: OTLPExporterNodeBase, diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPTraceExporter.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/OTLPTraceExporter.ts similarity index 97% rename from experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPTraceExporter.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/OTLPTraceExporter.ts index 1e2f8d7af4..b17e3c0633 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/src/OTLPTraceExporter.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/OTLPTraceExporter.ts @@ -21,7 +21,7 @@ import { toOTLPExportTraceServiceRequest, OTLPExporterNodeConfigBase, appendResourcePathToUrlIfNotPresent, -} from '@opentelemetry/exporter-otlp-http'; +} from '@opentelemetry/exporter-trace-otlp-http'; import { ServiceClientType } from './types'; import { getEnv, baggageUtils } from '@opentelemetry/core'; diff --git a/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/index.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/index.ts new file mode 100644 index 0000000000..bf4ab432ce --- /dev/null +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './OTLPTraceExporter'; +export * from './OTLPExporterNodeBase'; +export * from './types'; +export * from './util'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/src/types.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/types.ts similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/src/types.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/types.ts diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/src/util.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/util.ts similarity index 98% rename from experimental/packages/opentelemetry-exporter-otlp-proto/src/util.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/util.ts index d019afde80..007b35b56e 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/src/util.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/src/util.ts @@ -19,7 +19,7 @@ import { sendWithHttp, OTLPExporterNodeConfigBase, CompressionAlgorithm, -} from '@opentelemetry/exporter-otlp-http'; +} from '@opentelemetry/exporter-trace-otlp-http'; import * as path from 'path'; import { ServiceClientType } from './types'; diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/submodule.md b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/submodule.md similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/submodule.md rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/submodule.md diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/OTLPTraceExporter.test.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts similarity index 99% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/OTLPTraceExporter.test.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts index cf4676f9b5..67b8c17868 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/test/OTLPTraceExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts @@ -20,7 +20,7 @@ import { OTLPExporterNodeConfigBase, otlpTypes, CompressionAlgorithm, -} from '@opentelemetry/exporter-otlp-http'; +} from '@opentelemetry/exporter-trace-otlp-http'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; import * as http from 'http'; @@ -34,7 +34,7 @@ import { ensureProtoSpanIsCorrect, mockedReadableSpan, MockedResponse, -} from './helper'; +} from './traceHelper'; const fakeRequest = { end: function () { }, diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/ca.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/ca.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/ca.crt rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/ca.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/ca.key b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/ca.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/ca.key rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/ca.key diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/client.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/client.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/client.crt rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/client.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/client.csr b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/client.csr similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/client.csr rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/client.csr diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/client.key b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/client.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/client.key rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/client.key diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/regenerate.sh b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/regenerate.sh similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/regenerate.sh rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/regenerate.sh diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/server.crt b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/server.crt similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/server.crt rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/server.crt diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/server.csr b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/server.csr similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/server.csr rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/server.csr diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/server.key b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/server.key similarity index 100% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/certs/server.key rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/certs/server.key diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/test/helper.ts b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/traceHelper.ts similarity index 62% rename from experimental/packages/opentelemetry-exporter-otlp-proto/test/helper.ts rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/traceHelper.ts index f8b90b9fef..86ff5dc32c 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/test/helper.ts +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/test/traceHelper.ts @@ -15,79 +15,13 @@ */ import { SpanStatusCode, TraceFlags } from '@opentelemetry/api'; -import { - Counter, - ObserverResult, - ValueObserver, - ValueRecorder, - ValueType, -} from '@opentelemetry/api-metrics'; import { hexToBase64 } from '@opentelemetry/core'; -import { otlpTypes } from '@opentelemetry/exporter-otlp-http'; -import * as metrics from '@opentelemetry/sdk-metrics-base'; +import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; import { Resource } from '@opentelemetry/resources'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; import { Stream } from 'stream'; -const meterProvider = new metrics.MeterProvider({ - interval: 30000, - resource: new Resource({ - service: 'ui', - version: 1, - cost: 112.12, - }), -}); - -const meter = meterProvider.getMeter('default', '0.0.1'); - -export function mockCounter(): metrics.Metric & Counter { - const name = 'int-counter'; - const metric = - meter['_metrics'].get(name) || - meter.createCounter(name, { - description: 'sample counter description', - valueType: ValueType.INT, - }); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockObserver( - callback: (observerResult: ObserverResult) => void -): metrics.Metric & ValueObserver { - const name = 'double-observer'; - const metric = - meter['_metrics'].get(name) || - meter.createValueObserver( - name, - { - description: 'sample observer description', - valueType: ValueType.DOUBLE, - }, - callback - ); - metric.clear(); - metric.bind({}); - return metric; -} - -export function mockValueRecorder(): metrics.Metric & - ValueRecorder { - const name = 'int-recorder'; - const metric = - meter['_metrics'].get(name) || - meter.createValueRecorder(name, { - description: 'sample recorder description', - valueType: ValueType.INT, - boundaries: [0, 100], - }); - metric.clear(); - metric.bind({}); - return metric; -} - const traceIdHex = '1f1008dc8e270e85c40a0d7c3939b278'; const spanIdHex = '5e107261f64fa53e'; const parentIdHex = '78a8915098864388'; @@ -294,74 +228,6 @@ export function ensureProtoSpanIsCorrect( ); } -export function ensureExportedCounterIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time?: number -) { - assert.deepStrictEqual(metric, { - name: 'int-counter', - description: 'sample counter description', - unit: '1', - intSum: { - dataPoints: [ - { - value: '1', - startTimeUnixNano: '1592602232694000128', - timeUnixNano: String(time), - }, - ], - isMonotonic: true, - aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', - }, - }); -} - -export function ensureExportedObserverIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time?: number -) { - assert.deepStrictEqual(metric, { - name: 'double-observer', - description: 'sample observer description', - unit: '1', - doubleGauge: { - dataPoints: [ - { - value: 6, - startTimeUnixNano: '1592602232694000128', - timeUnixNano: String(time), - }, - ], - }, - }); -} - -export function ensureExportedValueRecorderIsCorrect( - metric: otlpTypes.opentelemetryProto.metrics.v1.Metric, - time?: number, - explicitBounds: number[] = [Infinity], - bucketCounts: string[] = ['2', '0'] -) { - assert.deepStrictEqual(metric, { - name: 'int-recorder', - description: 'sample recorder description', - unit: '1', - intHistogram: { - dataPoints: [ - { - sum: '21', - count: '2', - startTimeUnixNano: '1592602232694000128', - timeUnixNano: time, - bucketCounts, - explicitBounds, - }, - ], - aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', - }, - }); -} - export function ensureExportTraceServiceRequestIsSet( json: otlpTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest ) { @@ -395,39 +261,6 @@ export function ensureExportTraceServiceRequestIsSet( assert.strictEqual(spans && spans.length, 1, 'spans are missing'); } -export function ensureExportMetricsServiceRequestIsSet( - json: otlpTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest -) { - const resourceMetrics = json.resourceMetrics; - assert.strictEqual( - resourceMetrics.length, - 1, - 'resourceMetrics has incorrect length' - ); - - const resource = resourceMetrics[0].resource; - assert.strictEqual(!!resource, true, 'resource is missing'); - - const instrumentationLibraryMetrics = - resourceMetrics[0].instrumentationLibraryMetrics; - assert.strictEqual( - instrumentationLibraryMetrics && instrumentationLibraryMetrics.length, - 1, - 'instrumentationLibraryMetrics is missing' - ); - - const instrumentationLibrary = - instrumentationLibraryMetrics[0].instrumentationLibrary; - assert.strictEqual( - !!instrumentationLibrary, - true, - 'instrumentationLibrary is missing' - ); - - const metrics = resourceMetrics[0].instrumentationLibraryMetrics[0].metrics; - assert.strictEqual(metrics.length, 3, 'Metrics are missing'); -} - export class MockedResponse extends Stream { constructor(private _code: number, private _msg?: string) { super(); diff --git a/experimental/packages/opentelemetry-exporter-otlp-proto/tsconfig.json b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/tsconfig.json similarity index 85% rename from experimental/packages/opentelemetry-exporter-otlp-proto/tsconfig.json rename to experimental/packages/opentelemetry-exporter-trace-otlp-proto/tsconfig.json index caced6b4e8..13dc2e7744 100644 --- a/experimental/packages/opentelemetry-exporter-otlp-proto/tsconfig.json +++ b/experimental/packages/opentelemetry-exporter-trace-otlp-proto/tsconfig.json @@ -13,7 +13,7 @@ "path": "../opentelemetry-api-metrics" }, { - "path": "../opentelemetry-exporter-otlp-http" + "path": "../opentelemetry-exporter-trace-otlp-http" }, { "path": "../opentelemetry-sdk-metrics-base" diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/README.md b/experimental/packages/opentelemetry-instrumentation-fetch/README.md index 8e98c147f6..36e0af5488 100644 --- a/experimental/packages/opentelemetry-instrumentation-fetch/README.md +++ b/experimental/packages/opentelemetry-instrumentation-fetch/README.md @@ -66,7 +66,7 @@ Fetch instrumentation plugin has few options available to choose from. You can s | Options | Type | Description | | ------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------- | -| [`applyCustomAttributesOnSpan`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L47) | `HttpCustomAttributeFunction` | Function for adding custom attributes | +| [`applyCustomAttributesOnSpan`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L64) | `HttpCustomAttributeFunction` | Function for adding custom attributes | ## Useful links diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/package.json b/experimental/packages/opentelemetry-instrumentation-fetch/package.json index 40b652afb5..cda817c7b2 100644 --- a/experimental/packages/opentelemetry-instrumentation-fetch/package.json +++ b/experimental/packages/opentelemetry-instrumentation-fetch/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@opentelemetry/context-zone": "1.0.0", "@opentelemetry/propagator-b3": "1.0.0", "@opentelemetry/sdk-trace-base": "1.0.0", @@ -60,7 +60,7 @@ "babel-loader": "8.2.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -69,7 +69,7 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", @@ -78,7 +78,7 @@ "webpack-merge": "5.8.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts b/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts index a564b76f5a..1f762f429b 100644 --- a/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts +++ b/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts @@ -76,11 +76,11 @@ export class FetchInstrumentation extends InstrumentationBase< private _usedResources = new WeakSet(); private _tasksCount = 0; - constructor(config: FetchInstrumentationConfig = {}) { + constructor(config?: FetchInstrumentationConfig) { super( '@opentelemetry/instrumentation-fetch', VERSION, - Object.assign({}, config) + config ); } diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/README.md b/experimental/packages/opentelemetry-instrumentation-grpc/README.md index ebfc7d4ffc..04487f6bf1 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/README.md +++ b/experimental/packages/opentelemetry-instrumentation-grpc/README.md @@ -46,7 +46,7 @@ gRPC instrumentation accepts the following configuration: | Options | Type | Description | | ------- | ---- | ----------- | -| [`ignoreGrpcMethods`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-grpc/src/types.ts#L32) | `IgnoreMatcher[]` | gRPC instrumentation will not trace any methods that match anything in this list. You may pass a string (case-insensitive match), a `RegExp` object, or a filter function. | +| [`ignoreGrpcMethods`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-grpc/src/types.ts#L25) | `IgnoreMatcher[]` | gRPC instrumentation will not trace any methods that match anything in this list. You may pass a string (case-insensitive match), a `RegExp` object, or a filter function. | ## Useful links diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/package.json b/experimental/packages/opentelemetry-instrumentation-grpc/package.json index 158588b7fb..f5fb3fab66 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/package.json +++ b/experimental/packages/opentelemetry-instrumentation-grpc/package.json @@ -45,7 +45,7 @@ "devDependencies": { "@grpc/grpc-js": "1.3.7", "@grpc/proto-loader": "0.6.4", - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@opentelemetry/context-async-hooks": "1.0.0", "@opentelemetry/core": "1.0.0", "@opentelemetry/sdk-trace-base": "1.0.0", @@ -61,12 +61,12 @@ "nyc": "15.1.0", "rimraf": "3.0.2", "semver": "7.3.5", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@opentelemetry/api-metrics": "0.26.0", diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts index b2810cd104..5671d3a815 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts @@ -48,7 +48,7 @@ export function getMethodsToWrap( // For a method defined in .proto as "UnaryMethod" Object.entries(methods).forEach(([name, { originalName }]) => { - if (!_methodIsIgnored(name, this._config.ignoreGrpcMethods)) { + if (!_methodIsIgnored(name, this.getConfig().ignoreGrpcMethods)) { methodList.push(name); // adds camel case method name: "unaryMethod" if ( originalName && diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts index ba4f46e351..ce9777c68b 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts @@ -19,10 +19,7 @@ import { InstrumentationNodeModuleDefinition, isWrapped, } from '@opentelemetry/instrumentation'; -import { - InstrumentationBase, - InstrumentationConfig, -} from '@opentelemetry/instrumentation'; +import { InstrumentationBase } from '@opentelemetry/instrumentation'; import { GrpcInstrumentationConfig } from '../types'; import { ServerCallWithMeta, @@ -56,17 +53,11 @@ import { AttributeNames } from '../enums/AttributeNames'; export class GrpcJsInstrumentation extends InstrumentationBase { constructor( - protected override _config: GrpcInstrumentationConfig & InstrumentationConfig = {}, name: string, - version: string + version: string, + config?: GrpcInstrumentationConfig, ) { - super(name, version, _config); - } - - public override setConfig( - config: GrpcInstrumentationConfig & InstrumentationConfig = {} - ) { - this._config = Object.assign({}, config); + super(name, version, config); } init() { @@ -125,6 +116,10 @@ export class GrpcJsInstrumentation extends InstrumentationBase { ]; } + override getConfig(): GrpcInstrumentationConfig { + return super.getConfig(); + } + /** * Patch for grpc.Server.prototype.register(...) function. Provides auto-instrumentation for * client_stream, server_stream, bidi, unary server handler calls. @@ -134,7 +129,7 @@ export class GrpcJsInstrumentation extends InstrumentationBase { ) => ServerRegisterFunction { const instrumentation = this; return (originalRegister: ServerRegisterFunction) => { - const config = this._config; + const config = this.getConfig(); instrumentation._diag.debug('patched gRPC server'); return function register( this: grpcJs.Server, diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts index 18b649b95c..bf488028f0 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts @@ -19,7 +19,6 @@ import { InstrumentationNodeModuleDefinition, InstrumentationNodeModuleFile, InstrumentationBase, - InstrumentationConfig, isWrapped, } from '@opentelemetry/instrumentation'; import { @@ -55,17 +54,11 @@ export class GrpcNativeInstrumentation extends InstrumentationBase< typeof grpcTypes > { constructor( - protected override _config: GrpcInstrumentationConfig & InstrumentationConfig = {}, name: string, - version: string + version: string, + config?: GrpcInstrumentationConfig ) { - super(name, version, _config); - } - - public override setConfig( - config: GrpcInstrumentationConfig & InstrumentationConfig = {} - ) { - this._config = Object.assign({}, config); + super(name, version, config); } init() { @@ -107,6 +100,10 @@ export class GrpcNativeInstrumentation extends InstrumentationBase< ]; } + override getConfig(): GrpcInstrumentationConfig { + return super.getConfig(); + } + private _getInternalPatchs() { const onPatch = ( moduleExports: GrpcInternalClientTypes, @@ -268,7 +265,7 @@ export class GrpcNativeInstrumentation extends InstrumentationBase< // For a method defined in .proto as "UnaryMethod" Object.entries(methods).forEach(([name, { originalName }]) => { - if (!_methodIsIgnored(name, this._config.ignoreGrpcMethods)) { + if (!_methodIsIgnored(name, this.getConfig().ignoreGrpcMethods)) { methodList.push(name); // adds camel case method name: "unaryMethod" if ( originalName && diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/serverUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/serverUtils.ts index 5d88eeabcc..32f26ebd38 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/serverUtils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/serverUtils.ts @@ -131,6 +131,6 @@ export const shouldNotTraceServerCall = function ( const parsedName = name.split('/'); return _methodIsIgnored( parsedName[parsedName.length - 1] || name, - this._config.ignoreGrpcMethods + this.getConfig().ignoreGrpcMethods ); }; diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts index 0245f367d2..5ac237038a 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { InstrumentationConfig } from '@opentelemetry/instrumentation'; import { GrpcInstrumentationConfig } from './types'; import { VERSION } from './version'; import { GrpcNativeInstrumentation } from './grpc'; @@ -34,26 +33,23 @@ export class GrpcInstrumentation { public readonly instrumentationVersion: string = VERSION; constructor( - protected _config: GrpcInstrumentationConfig & InstrumentationConfig = {} + config?: GrpcInstrumentationConfig ) { this._grpcJsInstrumentation = new GrpcJsInstrumentation( - _config, this.instrumentationName, - this.instrumentationVersion + this.instrumentationVersion, + config ); this._grpcNativeInstrumentation = new GrpcNativeInstrumentation( - _config, this.instrumentationName, - this.instrumentationVersion + this.instrumentationVersion, + config ); } - public setConfig( - config: GrpcInstrumentationConfig & InstrumentationConfig = {} - ) { - this._config = Object.assign({}, config); - this._grpcJsInstrumentation.setConfig(this._config); - this._grpcNativeInstrumentation.setConfig(this._config); + public setConfig(config?: GrpcInstrumentationConfig) { + this._grpcJsInstrumentation.setConfig(config); + this._grpcNativeInstrumentation.setConfig(config); } /** @@ -61,8 +57,9 @@ export class GrpcInstrumentation { * Public reference to the protected BaseInstrumentation `_config` instance to be used by this * plugin's external helper functions */ - public getConfig() { - return this._config; + public getConfig(): GrpcInstrumentationConfig { + // grpcNative and grpcJs have their own config copy which should be identical so just pick one + return this._grpcJsInstrumentation.getConfig(); } init() { diff --git a/experimental/packages/opentelemetry-instrumentation-http/README.md b/experimental/packages/opentelemetry-instrumentation-http/README.md index 6d5fb9a073..9b1c579a3e 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/README.md +++ b/experimental/packages/opentelemetry-instrumentation-http/README.md @@ -47,17 +47,17 @@ Http instrumentation has few options available to choose from. You can set the f | Options | Type | Description | | ------- | ---- | ----------- | -| [`applyCustomAttributesOnSpan`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L91) | `HttpCustomAttributeFunction` | Function for adding custom attributes | -| [`requestHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#93) | `HttpRequestCustomAttributeFunction` | Function for adding custom attributes before request is handled | -| [`responseHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L95) | `HttpResponseCustomAttributeFunction` | Function for adding custom attributes before response is handled | -| [`startIncomingSpanHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L97) | `StartIncomingSpanCustomAttributeFunction` | Function for adding custom attributes before a span is started in incomingRequest | -| [`startOutgoingSpanHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L99) | `StartOutgoingSpanCustomAttributeFunction` | Function for adding custom attributes before a span is started in outgoingRequest | -| [`ignoreIncomingPaths`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L87) | `IgnoreMatcher[]` | Http instrumentation will not trace all incoming requests that match paths | -| [`ignoreOutgoingUrls`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L89) | `IgnoreMatcher[]` | Http instrumentation will not trace all outgoing requests that match urls | -| [`serverName`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L101) | `string` | The primary server name of the matched virtual host. | -| [`requireParentforOutgoingSpans`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L103) | Boolean | Require that is a parent span to create new span for outgoing requests. | -| [`requireParentforIncomingSpans`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L105) | Boolean | Require that is a parent span to create new span for incoming requests. | -| [`headersToSpanAttributes`](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-instrumentation-http/src/types.ts#L107) | `object` | List of case insensitive HTTP headers to convert to span attributes. Client (outgoing requests, incoming responses) and server (incoming requests, outgoing responses) headers will be converted to span attributes in the form of `http.{request\|response}.header.header_name`, e.g. `http.response.header.content_length` | +| [`applyCustomAttributesOnSpan`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L91) | `HttpCustomAttributeFunction` | Function for adding custom attributes | +| [`requestHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#93) | `HttpRequestCustomAttributeFunction` | Function for adding custom attributes before request is handled | +| [`responseHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L95) | `HttpResponseCustomAttributeFunction` | Function for adding custom attributes before response is handled | +| [`startIncomingSpanHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L97) | `StartIncomingSpanCustomAttributeFunction` | Function for adding custom attributes before a span is started in incomingRequest | +| [`startOutgoingSpanHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L99) | `StartOutgoingSpanCustomAttributeFunction` | Function for adding custom attributes before a span is started in outgoingRequest | +| [`ignoreIncomingPaths`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L87) | `IgnoreMatcher[]` | Http instrumentation will not trace all incoming requests that match paths | +| [`ignoreOutgoingUrls`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L89) | `IgnoreMatcher[]` | Http instrumentation will not trace all outgoing requests that match urls | +| [`serverName`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L101) | `string` | The primary server name of the matched virtual host. | +| [`requireParentforOutgoingSpans`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L103) | Boolean | Require that is a parent span to create new span for outgoing requests. | +| [`requireParentforIncomingSpans`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L105) | Boolean | Require that is a parent span to create new span for incoming requests. | +| [`headersToSpanAttributes`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L107) | `object` | List of case insensitive HTTP headers to convert to span attributes. Client (outgoing requests, incoming responses) and server (incoming requests, outgoing responses) headers will be converted to span attributes in the form of `http.{request\|response}.header.header_name`, e.g. `http.response.header.content_length` | ## Useful links diff --git a/experimental/packages/opentelemetry-instrumentation-http/package.json b/experimental/packages/opentelemetry-instrumentation-http/package.json index 41abcbab84..a71d1b4c6b 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/package.json +++ b/experimental/packages/opentelemetry-instrumentation-http/package.json @@ -43,7 +43,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@opentelemetry/context-async-hooks": "1.0.0", "@opentelemetry/sdk-trace-base": "1.0.0", "@opentelemetry/sdk-trace-node": "1.0.0", @@ -63,13 +63,13 @@ "request": "2.88.2", "request-promise-native": "1.0.9", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "superagent": "6.1.0", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts index 6c889b4066..e183d5e5e6 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts @@ -44,7 +44,6 @@ import * as utils from './utils'; import { VERSION } from './version'; import { InstrumentationBase, - InstrumentationConfig, InstrumentationNodeModuleDefinition, isWrapped, safeExecuteInTheMiddle, @@ -60,11 +59,11 @@ export class HttpInstrumentation extends InstrumentationBase { private readonly _version = process.versions.node; private _headerCapture; - constructor(config: HttpInstrumentationConfig & InstrumentationConfig = {}) { + constructor(config?: HttpInstrumentationConfig) { super( '@opentelemetry/instrumentation-http', VERSION, - Object.assign({}, config) + config ); this._headerCapture = this._createHeaderCapture(); @@ -74,8 +73,8 @@ export class HttpInstrumentation extends InstrumentationBase { return this._config; } - override setConfig(config: HttpInstrumentationConfig & InstrumentationConfig = {}): void { - this._config = Object.assign({}, config); + override setConfig(config?: HttpInstrumentationConfig): void { + super.setConfig(config); this._headerCapture = this._createHeaderCapture(); } diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json index 66d3c85f33..3e0a602215 100644 --- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json +++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@opentelemetry/context-zone": "1.0.0", "@opentelemetry/propagator-b3": "1.0.0", "@opentelemetry/sdk-trace-base": "1.0.0", @@ -60,7 +60,7 @@ "babel-loader": "8.2.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -69,7 +69,7 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", @@ -78,7 +78,7 @@ "webpack-merge": "5.8.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts b/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts index 09d8a0c588..1d0c9faac1 100644 --- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts +++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/src/xhr.ts @@ -57,13 +57,15 @@ export type XHRCustomAttributeFunction = ( */ export interface XMLHttpRequestInstrumentationConfig extends InstrumentationConfig { - // the number of timing resources is limited, after the limit - // (chrome 250, safari 150) the information is not collected anymore - // the only way to prevent that is to regularly clean the resources - // whenever it is possible, this is needed only when PerformanceObserver - // is not available + /** + * The number of timing resources is limited, after the limit + * (chrome 250, safari 150) the information is not collected anymore. + * The only way to prevent that is to regularly clean the resources + * whenever it is possible. This is needed only when PerformanceObserver + * is not available + */ clearTimingResources?: boolean; - // urls which should include trace headers when origin doesn't match + /** URLs which should include trace headers when origin doesn't match */ propagateTraceHeaderCorsUrls?: PropagateTraceHeaderCorsUrls; /** * URLs that partially match any regex in ignoreUrls will not be traced. @@ -87,13 +89,11 @@ export class XMLHttpRequestInstrumentation extends InstrumentationBase(); private _usedResources = new WeakSet(); - constructor( - config: XMLHttpRequestInstrumentationConfig & InstrumentationConfig = {} - ) { + constructor(config?: XMLHttpRequestInstrumentationConfig) { super( '@opentelemetry/instrumentation-xml-http-request', VERSION, - Object.assign({}, config) + config ); } diff --git a/experimental/packages/opentelemetry-instrumentation/package.json b/experimental/packages/opentelemetry-instrumentation/package.json index 7204d0e391..270172cfb4 100644 --- a/experimental/packages/opentelemetry-instrumentation/package.json +++ b/experimental/packages/opentelemetry-instrumentation/package.json @@ -67,11 +67,11 @@ "shimmer": "^1.2.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/semver": "7.3.8", @@ -82,7 +82,7 @@ "codecov": "3.8.3", "cpx": "1.5.0", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -91,7 +91,7 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", diff --git a/experimental/packages/opentelemetry-instrumentation/src/autoLoaderUtils.ts b/experimental/packages/opentelemetry-instrumentation/src/autoLoaderUtils.ts index e070fb3d10..6463f6cf27 100644 --- a/experimental/packages/opentelemetry-instrumentation/src/autoLoaderUtils.ts +++ b/experimental/packages/opentelemetry-instrumentation/src/autoLoaderUtils.ts @@ -62,7 +62,13 @@ export function enableInstrumentations( if (meterProvider) { instrumentation.setMeterProvider(meterProvider); } - instrumentation.enable(); + // instrumentations have been already enabled during creation + // so enable only if user prevented that by setting enabled to false + // this is to prevent double enabling but when calling register all + // instrumentations should be now enabled + if (!instrumentation.getConfig().enabled) { + instrumentation.enable(); + } } } diff --git a/experimental/packages/opentelemetry-instrumentation/test/common/autoLoader.test.ts b/experimental/packages/opentelemetry-instrumentation/test/common/autoLoader.test.ts index c378f83fe6..3cacd2cbb2 100644 --- a/experimental/packages/opentelemetry-instrumentation/test/common/autoLoader.test.ts +++ b/experimental/packages/opentelemetry-instrumentation/test/common/autoLoader.test.ts @@ -72,10 +72,30 @@ describe('autoLoader', () => { } }); - it('should enable instrumentation', () => { + it('should enable disabled instrumentation', () => { + if (typeof unload === 'function') { + unload(); + unload = undefined; + } + instrumentation = new FooInstrumentation( + 'foo', + '1', + { enabled: false } + ); + enableSpy = sinon.spy(instrumentation, 'enable'); + setTracerProviderSpy = sinon.stub(instrumentation, 'setTracerProvider'); + unload = registerInstrumentations({ + instrumentations: [instrumentation], + tracerProvider, + meterProvider, + }); assert.strictEqual(enableSpy.callCount, 1); }); + it('should NOT enable enabled instrumentation', () => { + assert.strictEqual(enableSpy.callCount, 0); + }); + it('should set TracerProvider', () => { assert.strictEqual(setTracerProviderSpy.callCount, 1); assert.ok(setTracerProviderSpy.lastCall.args[0] === tracerProvider); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/README.md b/experimental/packages/opentelemetry-sdk-metrics-base/README.md index 1761164b0f..8aabceac79 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/README.md +++ b/experimental/packages/opentelemetry-sdk-metrics-base/README.md @@ -36,12 +36,8 @@ const counter = meter.createCounter('metric_name', { description: 'Example of a counter' }); -const labels = { pid: process.pid }; - -// Create a BoundInstrument associated with specified label values. -const boundCounter = counter.bind(labels); -boundCounter.add(10); - +const attributes = { pid: process.pid }; +counter.add(10, attributes); ``` ### UpDownCounter @@ -65,15 +61,11 @@ const counter = meter.createUpDownCounter('metric_name', { description: 'Example of a UpDownCounter' }); -const labels = { pid: process.pid }; - -// Create a BoundInstrument associated with specified label values. -const boundCounter = counter.bind(labels); -boundCounter.add(Math.random() > 0.5 ? 1 : -1); - +const attributes = { pid: process.pid }; +counter.add(Math.random() > 0.5 ? 1 : -1, attributes); ``` -### Value Observer +### Observable Gauge Choose this kind of metric when only last value is important without worry about aggregation. The callback can be sync or async. @@ -85,11 +77,11 @@ const meter = new MeterProvider().getMeter('your-meter-name'); // async callback - for operation that needs to wait for value -meter.createValueObserver('your_metric_name', { - description: 'Example of an async observer with callback', -}, async (observerResult) => { +meter.createObservableGauge('your_metric_name', { + description: 'Example of an async observable gauge with callback', +}, async (observableResult) => { const value = await getAsyncValue(); - observerResult.observe(value, { label: '1' }); + observableResult.observe(value, { attribute: '1' }); }); function getAsyncValue() { @@ -101,11 +93,11 @@ function getAsyncValue() { } // sync callback in case you don't need to wait for value -meter.createValueObserver('your_metric_name', { - description: 'Example of a sync observer with callback', -}, (observerResult) => { - observerResult.observe(getRandomValue(), { label: '1' }); - observerResult.observe(getRandomValue(), { label: '2' }); +meter.createObservableGauge('your_metric_name', { + description: 'Example of a sync observable gauge with callback', +}, (observableResult) => { + observableResult.observe(getRandomValue(), { attribute: '1' }); + observableResult.observe(getRandomValue(), { attribute: '2' }); }); function getRandomValue() { @@ -113,7 +105,7 @@ function getRandomValue() { } ``` -### UpDownSumObserver +### ObservableUpDownCounter Choose this kind of metric when sum is important and you want to capture any value that starts at zero and rises or falls throughout the process lifetime. The callback can be sync or async. @@ -124,11 +116,11 @@ const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); const meter = new MeterProvider().getMeter('your-meter-name'); // async callback - for operation that needs to wait for value -meter.createUpDownSumObserver('your_metric_name', { - description: 'Example of an async observer with callback', -}, async (observerResult) => { +meter.createObservableUpDownCounter('your_metric_name', { + description: 'Example of an async observable up down counter with callback', +}, async (observableResult) => { const value = await getAsyncValue(); - observerResult.observe(value, { label: '1' }); + observableResult.observe(value, { attribute: '1' }); }); function getAsyncValue() { @@ -140,10 +132,10 @@ function getAsyncValue() { } // sync callback in case you don't need to wait for value -meter.createUpDownSumObserver('your_metric_name', { - description: 'Example of a sync observer with callback', -}, (observerResult) => { - observerResult.observe(getRandomValue(), { label: '1' }); +meter.createObservableUpDownCounter('your_metric_name', { + description: 'Example of a sync observable up down counter with callback', +}, (observableResult) => { + observableResult.observe(getRandomValue(), { attribute: '1' }); }); function getRandomValue() { @@ -152,7 +144,7 @@ function getRandomValue() { ``` -### Sum Observer +### Observable Counter Choose this kind of metric when collecting a sum that never decreases. The callback can be sync or async. @@ -163,11 +155,11 @@ const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); const meter = new MeterProvider().getMeter('your-meter-name'); // async callback in case you need to wait for values -meter.createSumObserver('example_metric', { - description: 'Example of an async sum observer with callback', -}, async (observerResult) => { +meter.createObservableCounter('example_metric', { + description: 'Example of an async observable counter with callback', +}, async (observableResult) => { const value = await getAsyncValue(); - observerResult.observe(value, { label: '1' }); + observableResult.observe(value, { attribute: '1' }); }); function getAsyncValue() { @@ -179,11 +171,11 @@ function getAsyncValue() { } // sync callback in case you don't need to wait for values -meter.createSumObserver('example_metric', { - description: 'Example of a sync sum observer with callback', -}, (observerResult) => { +meter.createObservableCounter('example_metric', { + description: 'Example of a sync observable counter with callback', +}, (observableResult) => { const value = getRandomValue(); - observerResult.observe(value, { label: '1' }); + observableResult.observe(value, { attribute: '1' }); }); function getRandomValue() { @@ -191,65 +183,11 @@ function getRandomValue() { } ``` -### Batch Observer - -Choose this kind of metric when you need to update multiple observers with the results of a single async calculation. - -```js -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); -const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); - -const exporter = new PrometheusExporter( - { - startServer: true, - }, - () => { - console.log('prometheus scrape endpoint: http://localhost:9464/metrics'); - }, -); - -const meter = new MeterProvider({ - exporter, - interval: 3000, -}).getMeter('example-observer'); - -const cpuUsageMetric = meter.createValueObserver('cpu_usage_per_app', { - description: 'CPU', -}); - -const MemUsageMetric = meter.createValueObserver('mem_usage_per_app', { - description: 'Memory', -}); - -meter.createBatchObserver((observerBatchResult) => { - getSomeAsyncMetrics().then(metrics => { - observerBatchResult.observe({ app: 'myApp' }, [ - cpuUsageMetric.observation(metrics.value1), - MemUsageMetric.observation(metrics.value2) - ]); - }); -}); - -function getSomeAsyncMetrics() { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve({ - value1: Math.random(), - value2: Math.random(), - }); - }, 100) - }); -} - -``` - -See [examples/prometheus](https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/prometheus) for a short example. - -### Value Recorder +### Histogram -`ValueRecorder` is a non-additive synchronous instrument useful for recording any non-additive number, positive or negative. -Values captured by `ValueRecorder.record(value)` are treated as individual events belonging to a distribution that is being summarized. -`ValueRecorder` should be chosen either when capturing measurements that do not contribute meaningfully to a sum, or when capturing numbers that are additive in nature, but where the distribution of individual increments is considered interesting. +`Histogram` is a non-additive synchronous instrument useful for recording any non-additive number, positive or negative. +Values captured by `Histogram.record(value)` are treated as individual events belonging to a distribution that is being summarized. +`Histogram` should be chosen either when capturing measurements that do not contribute meaningfully to a sum, or when capturing numbers that are additive in nature, but where the distribution of individual increments is considered interesting. ## Useful links @@ -269,4 +207,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-sdk-metrics-base&type=dev [devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-sdk-metrics-base&type=dev [npm-url]: https://www.npmjs.com/package/@opentelemetry/sdk-metrics-base -[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fmetrics.svg +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fsdk-metrics-base.svg diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/package.json b/experimental/packages/opentelemetry-sdk-metrics-base/package.json index 862e167d1d..0673fedef5 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/package.json +++ b/experimental/packages/opentelemetry-sdk-metrics-base/package.json @@ -46,7 +46,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@types/lodash.merge": "4.6.6", "@types/mocha": "8.2.3", "@types/node": "14.17.11", @@ -55,12 +55,12 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@opentelemetry/api-metrics": "0.26.0", diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/BatchObserver.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/BatchObserver.ts deleted file mode 100644 index 90c5384465..0000000000 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/BatchObserver.ts +++ /dev/null @@ -1,64 +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 api from '@opentelemetry/api-metrics'; -import { diag } from '@opentelemetry/api'; -import { BatchObserverResult } from './BatchObserverResult'; - -const NOOP_CALLBACK = () => {}; -const MAX_TIMEOUT_UPDATE_MS = 500; - -/** This is a SDK implementation of Batch Observer. */ -export class BatchObserver { - private _callback: (observerResult: api.BatchObserverResult) => void; - private _maxTimeoutUpdateMS: number; - - constructor( - options: api.BatchObserverOptions, - callback?: (observerResult: api.BatchObserverResult) => void - ) { - this._maxTimeoutUpdateMS = - options.maxTimeoutUpdateMS ?? MAX_TIMEOUT_UPDATE_MS; - this._callback = callback || NOOP_CALLBACK; - } - - collect(): Promise { - diag.debug('getMetricRecord - start'); - return new Promise(resolve => { - const observerResult = new BatchObserverResult(); - - // cancels after MAX_TIMEOUT_MS - no more waiting for results - const timer = setTimeout(() => { - observerResult.cancelled = true; - // remove callback to prevent user from updating the values later if - // for any reason the observerBatchResult will be referenced - observerResult.onObserveCalled(); - resolve(); - diag.debug('getMetricRecord - timeout'); - }, this._maxTimeoutUpdateMS); - - // sets callback for each "observe" method - observerResult.onObserveCalled(() => { - clearTimeout(timer); - resolve(); - diag.debug('getMetricRecord - end'); - }); - - // calls the BatchObserverResult callback - this._callback(observerResult); - }); - } -} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/BatchObserverResult.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/BatchObserverResult.ts deleted file mode 100644 index 4e2c0c8b28..0000000000 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/BatchObserverResult.ts +++ /dev/null @@ -1,60 +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 api from '@opentelemetry/api-metrics'; - -/** - * Implementation of api BatchObserverResult - */ -export class BatchObserverResult implements api.BatchObserverResult { - private _callback: (() => void) | undefined; - private _immediate: NodeJS.Immediate | undefined; - /** - * Cancels the further updates. - * This is used to prevent updating the value of result that took too - * long to update. For example to avoid update after timeout. - * See {@link BatchObserver.collect} - */ - cancelled = false; - - /** - * used to save a callback that will be called after the observations are - * updated - * @param [callback] - */ - onObserveCalled(callback?: () => void): void { - this._callback = callback; - } - - observe(labels: api.Labels, observations: api.Observation[]): void { - if (this.cancelled || !this._callback) { - return; - } - observations.forEach(observation => { - observation.observer.bind(labels).update(observation.value); - }); - if (!this._immediate) { - this._immediate = setImmediate(() => { - if (typeof this._callback === 'function') { - this._callback(); - // prevent user from updating the values later if for any reason - // the observerBatchResult will be referenced and then try to use - this._callback = undefined; - } - }); - } - } -} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/BoundInstrument.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/BoundInstrument.ts index 296bf72909..71d330626b 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/BoundInstrument.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/BoundInstrument.ts @@ -23,15 +23,15 @@ import { Aggregator } from './export/types'; * the TimeSeries. */ export class BaseBoundInstrument { - protected _labels: api.Labels; + protected _attributes: api.Attributes; constructor( - labels: api.Labels, + attributes: api.Attributes, private readonly _disabled: boolean, private readonly _valueType: api.ValueType, private readonly _aggregator: Aggregator ) { - this._labels = labels; + this._attributes = attributes; } update(value: number): void { @@ -39,7 +39,7 @@ export class BaseBoundInstrument { if (typeof value !== 'number') { diag.error( `Metric cannot accept a non-number value for ${Object.values( - this._labels + this._attributes )}.` ); return; @@ -48,7 +48,7 @@ export class BaseBoundInstrument { if (this._valueType === api.ValueType.INT && !Number.isInteger(value)) { diag.warn( `INT value type cannot accept a floating-point value for ${Object.values( - this._labels + this._attributes )}, ignoring the fractional digits.` ); value = Math.trunc(value); @@ -57,8 +57,8 @@ export class BaseBoundInstrument { this._aggregator.update(value); } - getLabels(): api.Labels { - return this._labels; + getAttributes(): api.Attributes { + return this._attributes; } getAggregator(): Aggregator { @@ -68,23 +68,23 @@ export class BaseBoundInstrument { /** * BoundCounter allows the SDK to observe/record a single metric event. The - * value of single instrument in the `Counter` associated with specified Labels. + * value of single instrument in the `Counter` associated with specified Attributes. */ export class BoundCounter extends BaseBoundInstrument - implements api.BoundCounter { + implements api.Counter { constructor( - labels: api.Labels, + attributes: api.Attributes, disabled: boolean, valueType: api.ValueType, aggregator: Aggregator ) { - super(labels, disabled, valueType, aggregator); + super(attributes, disabled, valueType, aggregator); } add(value: number): void { if (value < 0) { - diag.error(`Counter cannot descend for ${Object.values(this._labels)}`); + diag.error(`Counter cannot descend for ${Object.values(this._attributes)}`); return; } @@ -95,18 +95,18 @@ export class BoundCounter /** * BoundUpDownCounter allows the SDK to observe/record a single metric event. * The value of single instrument in the `UpDownCounter` associated with - * specified Labels. + * specified Attributes. */ export class BoundUpDownCounter extends BaseBoundInstrument - implements api.BoundCounter { + implements api.UpDownCounter { constructor( - labels: api.Labels, + attributes: api.Attributes, disabled: boolean, valueType: api.ValueType, aggregator: Aggregator ) { - super(labels, disabled, valueType, aggregator); + super(attributes, disabled, valueType, aggregator); } add(value: number): void { @@ -117,16 +117,16 @@ export class BoundUpDownCounter /** * BoundMeasure is an implementation of the {@link BoundMeasure} interface. */ -export class BoundValueRecorder +export class BoundHistogram extends BaseBoundInstrument - implements api.BoundValueRecorder { + implements api.Histogram { constructor( - labels: api.Labels, + attributes: api.Attributes, disabled: boolean, valueType: api.ValueType, aggregator: Aggregator ) { - super(labels, disabled, valueType, aggregator); + super(attributes, disabled, valueType, aggregator); } record(value: number): void { @@ -135,17 +135,15 @@ export class BoundValueRecorder } /** - * BoundObserver is an implementation of the {@link BoundObserver} interface. + * BoundObservable is an implementation of the {@link BoundObservable} interface. */ -export class BoundObserver - extends BaseBoundInstrument - implements api.BoundBaseObserver { +export class BoundObservable extends BaseBoundInstrument { constructor( - labels: api.Labels, + attributes: api.Attributes, disabled: boolean, valueType: api.ValueType, aggregator: Aggregator ) { - super(labels, disabled, valueType, aggregator); + super(attributes, disabled, valueType, aggregator); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/CounterMetric.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/CounterMetric.ts index 4f4fe3f04d..cda71ac921 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/CounterMetric.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/CounterMetric.ts @@ -33,9 +33,9 @@ export class CounterMetric extends Metric implements api.Counter { ) { super(name, options, MetricKind.COUNTER, resource, instrumentationLibrary); } - protected _makeInstrument(labels: api.Labels): BoundCounter { + protected _makeInstrument(attributes: api.Attributes): BoundCounter { return new BoundCounter( - labels, + attributes, this._disabled, this._valueType, this._processor.aggregatorFor(this._descriptor) @@ -45,10 +45,10 @@ export class CounterMetric extends Metric implements api.Counter { /** * Adds the given value to the current value. Values cannot be negative. * @param value the value to add. - * @param [labels = {}] key-values pairs that are associated with a specific metric + * @param [attributes = {}] key-values pairs that are associated with a specific metric * that you want to record. */ - add(value: number, labels: api.Labels = {}): void { - this.bind(labels).add(value); + add(value: number, attributes: api.Attributes = {}): void { + this.bind(attributes).add(value); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/ValueRecorderMetric.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/HistogramMetric.ts similarity index 73% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/ValueRecorderMetric.ts rename to experimental/packages/opentelemetry-sdk-metrics-base/src/HistogramMetric.ts index 28e9d7e1b2..07c969b51d 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/ValueRecorderMetric.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/HistogramMetric.ts @@ -17,15 +17,15 @@ import * as api from '@opentelemetry/api-metrics'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { BoundValueRecorder } from './BoundInstrument'; +import { BoundHistogram } from './BoundInstrument'; import { Processor } from './export/Processor'; import { MetricKind } from './export/types'; import { Metric } from './Metric'; -/** This is a SDK implementation of Value Recorder Metric. */ -export class ValueRecorderMetric - extends Metric - implements api.ValueRecorder { +/** This is a SDK implementation of Histogram Metric. */ +export class HistogramMetric + extends Metric + implements api.Histogram { constructor( name: string, options: api.MetricOptions, @@ -36,22 +36,22 @@ export class ValueRecorderMetric super( name, options, - MetricKind.VALUE_RECORDER, + MetricKind.HISTOGRAM, resource, instrumentationLibrary ); } - protected _makeInstrument(labels: api.Labels): BoundValueRecorder { - return new BoundValueRecorder( - labels, + protected _makeInstrument(attributes: api.Attributes): BoundHistogram { + return new BoundHistogram( + attributes, this._disabled, this._valueType, this._processor.aggregatorFor(this._descriptor) ); } - record(value: number, labels: api.Labels = {}): void { - this.bind(labels).record(value); + record(value: number, attributes: api.Attributes = {}): void { + this.bind(attributes).record(value); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts index 9a77e865bb..d4f3692451 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts @@ -18,19 +18,18 @@ import { diag } from '@opentelemetry/api'; import * as api from '@opentelemetry/api-metrics'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { BatchObserver } from './BatchObserver'; import { BaseBoundInstrument } from './BoundInstrument'; import { CounterMetric } from './CounterMetric'; import { PushController } from './export/Controller'; import { NoopExporter } from './export/NoopExporter'; import { Processor, UngroupedProcessor } from './export/Processor'; import { Metric } from './Metric'; -import { SumObserverMetric } from './SumObserverMetric'; +import { ObservableCounterMetric } from './ObservableCounterMetric'; import { DEFAULT_CONFIG, DEFAULT_METRIC_OPTIONS, MeterConfig } from './types'; import { UpDownCounterMetric } from './UpDownCounterMetric'; -import { UpDownSumObserverMetric } from './UpDownSumObserverMetric'; -import { ValueObserverMetric } from './ValueObserverMetric'; -import { ValueRecorderMetric } from './ValueRecorderMetric'; +import { ObservableUpDownCounterMetric } from './ObservableUpDownCounterMetric'; +import { ObservableGaugeMetric } from './ObservableGaugeMetric'; +import { HistogramMetric } from './HistogramMetric'; // eslint-disable-next-line @typescript-eslint/no-var-requires const merge = require('lodash.merge'); // @TODO - replace once the core is released @@ -40,7 +39,6 @@ const merge = require('lodash.merge'); * Meter is an implementation of the {@link Meter} interface. */ export class Meter implements api.Meter { - private readonly _batchObservers: BatchObserver[] = []; private readonly _metrics = new Map>(); private readonly _processor: Processor; private readonly _resource: Resource; @@ -68,34 +66,34 @@ export class Meter implements api.Meter { } /** - * Creates and returns a new {@link ValueRecorder}. + * Creates and returns a new {@link Histogram}. * @param name the name of the metric. * @param [options] the metric options. */ - createValueRecorder( + createHistogram( name: string, options?: api.MetricOptions - ): api.ValueRecorder { + ): api.Histogram { if (!this._isValidName(name)) { diag.warn( `Invalid metric name ${name}. Defaulting to noop metric implementation.` ); - return api.NOOP_VALUE_RECORDER_METRIC; + return api.NOOP_HISTOGRAM_METRIC; } const opt: api.MetricOptions = { ...DEFAULT_METRIC_OPTIONS, ...options, }; - const valueRecorder = new ValueRecorderMetric( + const histogram = new HistogramMetric( name, opt, this._processor, this._resource, this._instrumentationLibrary ); - this._registerMetric(name, valueRecorder); - return valueRecorder; + this._registerMetric(name, histogram); + return histogram; } /** @@ -163,27 +161,27 @@ export class Meter implements api.Meter { } /** - * Creates a new `ValueObserver` metric. + * Creates a new `ObservableGauge` metric. * @param name the name of the metric. * @param [options] the metric options. - * @param [callback] the value observer callback + * @param [callback] the observable gauge callback */ - createValueObserver( + createObservableGauge( name: string, options: api.MetricOptions = {}, - callback?: (observerResult: api.ObserverResult) => unknown - ): api.ValueObserver { + callback?: (observableResult: api.ObservableResult) => unknown + ): api.ObservableGauge { if (!this._isValidName(name)) { diag.warn( `Invalid metric name ${name}. Defaulting to noop metric implementation.` ); - return api.NOOP_VALUE_OBSERVER_METRIC; + return api.NOOP_OBSERVABLE_GAUGE_METRIC; } const opt: api.MetricOptions = { ...DEFAULT_METRIC_OPTIONS, ...options, }; - const valueObserver = new ValueObserverMetric( + const observableGauge = new ObservableGaugeMetric( name, opt, this._processor, @@ -191,26 +189,26 @@ export class Meter implements api.Meter { this._instrumentationLibrary, callback ); - this._registerMetric(name, valueObserver); - return valueObserver; + this._registerMetric(name, observableGauge); + return observableGauge; } - createSumObserver( + createObservableCounter( name: string, options: api.MetricOptions = {}, - callback?: (observerResult: api.ObserverResult) => unknown - ): api.SumObserver { + callback?: (observableResult: api.ObservableResult) => unknown + ): api.ObservableCounter { if (!this._isValidName(name)) { diag.warn( `Invalid metric name ${name}. Defaulting to noop metric implementation.` ); - return api.NOOP_SUM_OBSERVER_METRIC; + return api.NOOP_OBSERVABLE_COUNTER_METRIC; } const opt: api.MetricOptions = { ...DEFAULT_METRIC_OPTIONS, ...options, }; - const sumObserver = new SumObserverMetric( + const observableCounter = new ObservableCounterMetric( name, opt, this._processor, @@ -218,32 +216,32 @@ export class Meter implements api.Meter { this._instrumentationLibrary, callback ); - this._registerMetric(name, sumObserver); - return sumObserver; + this._registerMetric(name, observableCounter); + return observableCounter; } /** - * Creates a new `UpDownSumObserver` metric. + * Creates a new `ObservableUpDownCounter` metric. * @param name the name of the metric. * @param [options] the metric options. - * @param [callback] the value observer callback + * @param [callback] the observable gauge callback */ - createUpDownSumObserver( + createObservableUpDownCounter( name: string, options: api.MetricOptions = {}, - callback?: (observerResult: api.ObserverResult) => unknown - ): api.UpDownSumObserver { + callback?: (observableResult: api.ObservableResult) => unknown + ): api.ObservableUpDownCounter { if (!this._isValidName(name)) { diag.warn( `Invalid metric name ${name}. Defaulting to noop metric implementation.` ); - return api.NOOP_UP_DOWN_SUM_OBSERVER_METRIC; + return api.NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC; } const opt: api.MetricOptions = { ...DEFAULT_METRIC_OPTIONS, ...options, }; - const upDownSumObserver = new UpDownSumObserverMetric( + const observableUpDownCounter = new ObservableUpDownCounterMetric( name, opt, this._processor, @@ -251,25 +249,8 @@ export class Meter implements api.Meter { this._instrumentationLibrary, callback ); - this._registerMetric(name, upDownSumObserver); - return upDownSumObserver; - } - - /** - * Creates a new batch observer. - * @param callback the batch observer callback - * @param [options] the batch options. - */ - createBatchObserver( - callback: (observerResult: api.BatchObserverResult) => void, - options: api.BatchObserverOptions = {} - ): BatchObserver { - const opt: api.BatchObserverOptions = { - ...options, - }; - const batchObserver = new BatchObserver(opt, callback); - this._batchObservers.push(batchObserver); - return batchObserver; + this._registerMetric(name, observableUpDownCounter); + return observableUpDownCounter; } /** @@ -280,12 +261,6 @@ export class Meter implements api.Meter { * meter instance. */ async collect(): Promise { - // call batch observers first - const observations = this._batchObservers.map(observer => { - return observer.collect(); - }); - await Promise.all(observations); - // after this all remaining metrics can be run const metricsRecords = Array.from(this._metrics.values()).map(metric => { return metric.getMetricRecord(); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts index c7edefd0d7..392b1699f3 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts @@ -48,12 +48,17 @@ export class MeterProvider implements api.MeterProvider { * * @returns Meter A Meter with the given name and version */ - getMeter(name: string, version?: string, config?: MeterConfig): Meter { - const key = `${name}@${version || ''}`; + getMeter(name: string, version?: string, options?: api.MeterOptions): Meter { + const key = `${name}@${version ?? ''}:${options?.schemaUrl ?? ''}`; if (!this._meters.has(key)) { this._meters.set( key, - new Meter({ name, version }, config || this._config) + new Meter({ + name, + version, + // @ts-expect-error ts(2345) TODO: upgrade @opentelemetry/core InstrumentationLibrary definition + schemaUrl: options?.schemaUrl + }, this._config) ); } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Metric.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/Metric.ts index fc3cc06664..dd7ad028fa 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/Metric.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/Metric.ts @@ -18,11 +18,10 @@ import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; import { BaseBoundInstrument } from './BoundInstrument'; import { MetricDescriptor, MetricKind, MetricRecord } from './export/types'; -import { hashLabels } from './Utils'; +import { hashAttributes } from './Utils'; /** This is a SDK implementation of {@link Metric} interface. */ -export abstract class Metric - implements api.UnboundMetric { +export abstract class Metric { protected readonly _disabled: boolean; protected readonly _valueType: api.ValueType; protected readonly _descriptor: MetricDescriptor; @@ -51,28 +50,28 @@ export abstract class Metric } /** - * Returns an Instrument associated with specified Labels. + * Returns an Instrument associated with specified Attributes. * It is recommended to keep a reference to the Instrument instead of always * calling this method for each operation. - * @param labels key-values pairs that are associated with a specific metric + * @param attributes key-values pairs that are associated with a specific metric * that you want to record. */ - bind(labels: api.Labels): T { - const hash = hashLabels(labels); + bind(attributes: api.Attributes): T { + const hash = hashAttributes(attributes); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (this._instruments.has(hash)) return this._instruments.get(hash)!; - const instrument = this._makeInstrument(labels); + const instrument = this._makeInstrument(attributes); this._instruments.set(hash, instrument); return instrument; } /** * Removes the Instrument from the metric, if it is present. - * @param labels key-values pairs that are associated with a specific metric. + * @param attributes key-values pairs that are associated with a specific metric. */ - unbind(labels: api.Labels): void { - this._instruments.delete(hashLabels(labels)); + unbind(attributes: api.Attributes): void { + this._instruments.delete(hashAttributes(attributes)); } /** @@ -98,7 +97,7 @@ export abstract class Metric resolve( Array.from(this._instruments.values()).map(instrument => ({ descriptor: this._descriptor, - labels: instrument.getLabels(), + attributes: instrument.getAttributes(), aggregator: instrument.getAggregator(), aggregationTemporality: this.getAggregationTemporality(), resource: this.resource, @@ -119,5 +118,5 @@ export abstract class Metric }; } - protected abstract _makeInstrument(labels: api.Labels): T; + protected abstract _makeInstrument(attributes: api.Attributes): T; } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/BaseObserverMetric.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableBaseMetric.ts similarity index 66% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/BaseObserverMetric.ts rename to experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableBaseMetric.ts index 6f48df49bf..a5c24c9c0b 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/BaseObserverMetric.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableBaseMetric.ts @@ -17,22 +17,22 @@ import * as api from '@opentelemetry/api-metrics'; import { Observation } from '@opentelemetry/api-metrics'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { BoundObserver } from './BoundInstrument'; +import { BoundObservable } from './BoundInstrument'; import { Processor } from './export/Processor'; import { MetricKind, MetricRecord } from './export/types'; import { Metric } from './Metric'; -import { ObserverResult } from './ObserverResult'; +import { ObservableResult } from './ObservableResult'; const NOOP_CALLBACK = () => {}; /** * This is a SDK implementation of Base Observer Metric. - * All observers should extend this class + * All observables should extend this class */ -export abstract class BaseObserverMetric - extends Metric - implements api.BaseObserver { - protected _callback: (observerResult: api.ObserverResult) => unknown; +export abstract class ObservableBaseMetric + extends Metric + implements api.ObservableBase { + protected _callback: (observableResult: api.ObservableResult) => unknown; constructor( name: string, @@ -41,15 +41,15 @@ export abstract class BaseObserverMetric resource: Resource, metricKind: MetricKind, instrumentationLibrary: InstrumentationLibrary, - callback?: (observerResult: api.ObserverResult) => unknown + callback?: (observableResult: api.ObservableResult) => unknown ) { super(name, options, metricKind, resource, instrumentationLibrary); this._callback = callback || NOOP_CALLBACK; } - protected _makeInstrument(labels: api.Labels): BoundObserver { - return new BoundObserver( - labels, + protected _makeInstrument(attributes: api.Attributes): BoundObservable { + return new BoundObservable( + attributes, this._disabled, this._valueType, this._processor.aggregatorFor(this._descriptor) @@ -57,17 +57,17 @@ export abstract class BaseObserverMetric } override async getMetricRecord(): Promise { - const observerResult = new ObserverResult(); - await this._callback(observerResult); + const observableResult = new ObservableResult(); + await this._callback(observableResult); - this._processResults(observerResult); + this._processResults(observableResult); return super.getMetricRecord(); } - protected _processResults(observerResult: ObserverResult): void { - observerResult.values.forEach((value, labels) => { - const instrument = this.bind(labels); + protected _processResults(observableResult: ObservableResult): void { + observableResult.values.forEach((value, attributes) => { + const instrument = this.bind(attributes); instrument.update(value); }); } @@ -75,7 +75,7 @@ export abstract class BaseObserverMetric observation(value: number): Observation { return { value, - observer: this as BaseObserverMetric, + observable: this as ObservableBaseMetric, }; } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/SumObserverMetric.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableCounterMetric.ts similarity index 70% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/SumObserverMetric.ts rename to experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableCounterMetric.ts index 8f58727ceb..e4b79b5878 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/SumObserverMetric.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableCounterMetric.ts @@ -17,38 +17,38 @@ import * as api from '@opentelemetry/api-metrics'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { BaseObserverMetric } from './BaseObserverMetric'; +import { ObservableBaseMetric } from './ObservableBaseMetric'; import { Processor } from './export/Processor'; import { LastValue, MetricKind } from './export/types'; -import { ObserverResult } from './ObserverResult'; +import { ObservableResult } from './ObservableResult'; -/** This is a SDK implementation of SumObserver Metric. */ -export class SumObserverMetric - extends BaseObserverMetric - implements api.SumObserver { +/** This is a SDK implementation of ObservableCounter Metric. */ +export class ObservableCounterMetric + extends ObservableBaseMetric + implements api.ObservableCounter { constructor( name: string, options: api.MetricOptions, processor: Processor, resource: Resource, instrumentationLibrary: InstrumentationLibrary, - callback?: (observerResult: api.ObserverResult) => unknown + callback?: (observableResult: api.ObservableResult) => unknown ) { super( name, options, processor, resource, - MetricKind.SUM_OBSERVER, + MetricKind.OBSERVABLE_COUNTER, instrumentationLibrary, callback ); } - protected override _processResults(observerResult: ObserverResult): void { - observerResult.values.forEach((value, labels) => { - const instrument = this.bind(labels); - // SumObserver is monotonic which means it should only accept values + protected override _processResults(observableResult: ObservableResult): void { + observableResult.values.forEach((value, attributes) => { + const instrument = this.bind(attributes); + // ObservableCounter is monotonic which means it should only accept values // greater or equal then previous value const previous = instrument.getAggregator().toPoint(); let previousValue = -Infinity; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/ValueObserverMetric.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableGaugeMetric.ts similarity index 78% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/ValueObserverMetric.ts rename to experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableGaugeMetric.ts index a7ac5c5ff5..2d59e78f95 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/ValueObserverMetric.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableGaugeMetric.ts @@ -16,28 +16,28 @@ import * as api from '@opentelemetry/api-metrics'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { BaseObserverMetric } from './BaseObserverMetric'; +import { ObservableBaseMetric } from './ObservableBaseMetric'; import { Processor } from './export/Processor'; import { MetricKind } from './export/types'; -/** This is a SDK implementation of Value Observer Metric. */ -export class ValueObserverMetric - extends BaseObserverMetric - implements api.ValueObserver { +/** This is a SDK implementation of ObservableGauge Metric. */ +export class ObservableGaugeMetric + extends ObservableBaseMetric + implements api.ObservableGauge { constructor( name: string, options: api.MetricOptions, processor: Processor, resource: Resource, instrumentationLibrary: InstrumentationLibrary, - callback?: (observerResult: api.ObserverResult) => unknown + callback?: (observableResult: api.ObservableResult) => unknown ) { super( name, options, processor, resource, - MetricKind.VALUE_OBSERVER, + MetricKind.OBSERVABLE_GAUGE, instrumentationLibrary, callback ); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/ObserverResult.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts similarity index 66% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/ObserverResult.ts rename to experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts index 60dcc04449..3ad7ee8a60 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/ObserverResult.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts @@ -15,17 +15,17 @@ */ import { - ObserverResult as TypeObserverResult, - Labels, + ObservableResult as TypeObservableResult, + Attributes, } from '@opentelemetry/api-metrics'; /** - * Implementation of {@link TypeObserverResult} + * Implementation of {@link TypeObservableResult} */ -export class ObserverResult implements TypeObserverResult { - values: Map = new Map(); +export class ObservableResult implements TypeObservableResult { + values: Map = new Map(); - observe(value: number, labels: Labels): void { - this.values.set(labels, value); + observe(value: number, attributes: Attributes): void { + this.values.set(attributes, value); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/UpDownSumObserverMetric.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableUpDownCounterMetric.ts similarity index 76% rename from experimental/packages/opentelemetry-sdk-metrics-base/src/UpDownSumObserverMetric.ts rename to experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableUpDownCounterMetric.ts index 31cec8af7a..d9a767044a 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/UpDownSumObserverMetric.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableUpDownCounterMetric.ts @@ -17,28 +17,28 @@ import * as api from '@opentelemetry/api-metrics'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { BaseObserverMetric } from './BaseObserverMetric'; +import { ObservableBaseMetric } from './ObservableBaseMetric'; import { Processor } from './export/Processor'; import { MetricKind } from './export/types'; -/** This is a SDK implementation of UpDownSumObserver Metric. */ -export class UpDownSumObserverMetric - extends BaseObserverMetric - implements api.UpDownSumObserver { +/** This is a SDK implementation of ObservableUpDownCounter Metric. */ +export class ObservableUpDownCounterMetric + extends ObservableBaseMetric + implements api.ObservableUpDownCounter { constructor( name: string, options: api.MetricOptions, processor: Processor, resource: Resource, instrumentationLibrary: InstrumentationLibrary, - callback?: (observerResult: api.ObserverResult) => unknown + callback?: (observableResult: api.ObservableResult) => unknown ) { super( name, options, processor, resource, - MetricKind.UP_DOWN_SUM_OBSERVER, + MetricKind.OBSERVABLE_UP_DOWN_COUNTER, instrumentationLibrary, callback ); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/UpDownCounterMetric.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/UpDownCounterMetric.ts index 491a4647dc..6706ee01f7 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/UpDownCounterMetric.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/UpDownCounterMetric.ts @@ -41,9 +41,9 @@ export class UpDownCounterMetric instrumentationLibrary ); } - protected _makeInstrument(labels: api.Labels): BoundUpDownCounter { + protected _makeInstrument(attributes: api.Attributes): BoundUpDownCounter { return new BoundUpDownCounter( - labels, + attributes, this._disabled, this._valueType, this._processor.aggregatorFor(this._descriptor) @@ -53,10 +53,10 @@ export class UpDownCounterMetric /** * Adds the given value to the current value. Values cannot be negative. * @param value the value to add. - * @param [labels = {}] key-values pairs that are associated with a specific + * @param [attributes = {}] key-values pairs that are associated with a specific * metric that you want to record. */ - add(value: number, labels: api.Labels = {}): void { - this.bind(labels).add(value); + add(value: number, attributes: api.Attributes = {}): void { + this.bind(attributes).add(value); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Utils.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/Utils.ts index 6b0fa1503d..8de8687fe6 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/Utils.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/Utils.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Labels } from '@opentelemetry/api-metrics'; +import { Attributes } from '@opentelemetry/api-metrics'; /** * Type guard to remove nulls from arrays @@ -26,11 +26,11 @@ export function notNull(value: T | null): value is T { } /** - * Converting the unordered labels into unique identifier string. - * @param labels user provided unordered Labels. + * Converting the unordered attributes into unique identifier string. + * @param attributes user provided unordered Attributes. */ -export function hashLabels(labels: Labels): string { - let keys = Object.keys(labels); +export function hashAttributes(attributes: Attributes): string { + let keys = Object.keys(attributes); if (keys.length === 0) return ''; keys = keys.sort(); @@ -38,6 +38,6 @@ export function hashLabels(labels: Labels): string { if (result.length > 2) { result += ','; } - return (result += key + ':' + labels[key]); + return (result += key + ':' + attributes[key]); }, '|#'); } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/ConsoleMetricExporter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/ConsoleMetricExporter.ts index acade23dc7..ccdcc8400d 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/ConsoleMetricExporter.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/ConsoleMetricExporter.ts @@ -30,7 +30,7 @@ export class ConsoleMetricExporter implements MetricExporter { ): void { for (const metric of metrics) { console.log(metric.descriptor); - console.log(metric.labels); + console.log(metric.attributes); const point = metric.aggregator.toPoint(); if (typeof point.value === 'number') { console.log('value: ' + point.value); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/Processor.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/Processor.ts index 03d2cbcf52..519ffe99d4 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/Processor.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/Processor.ts @@ -44,7 +44,7 @@ export abstract class Processor { } /** - * Processor which retains all dimensions/labels. It accepts all records and + * Processor which retains all dimensions/attributes. It accepts all records and * passes them for exporting. */ export class UngroupedProcessor extends Processor { @@ -54,12 +54,12 @@ export class UngroupedProcessor extends Processor { case MetricKind.UP_DOWN_COUNTER: return new aggregators.SumAggregator(); - case MetricKind.SUM_OBSERVER: - case MetricKind.UP_DOWN_SUM_OBSERVER: - case MetricKind.VALUE_OBSERVER: + case MetricKind.OBSERVABLE_COUNTER: + case MetricKind.OBSERVABLE_UP_DOWN_COUNTER: + case MetricKind.OBSERVABLE_GAUGE: return new aggregators.LastValueAggregator(); - case MetricKind.VALUE_RECORDER: + case MetricKind.HISTOGRAM: return new aggregators.HistogramAggregator( metricDescriptor.boundaries || [Infinity] ); @@ -70,9 +70,9 @@ export class UngroupedProcessor extends Processor { } process(record: MetricRecord): void { - const labels = Object.keys(record.labels) - .map(k => `${k}=${record.labels[k]}`) + const attributes = Object.keys(record.attributes) + .map(k => `${k}=${record.attributes[k]}`) .join(','); - this._batchMap.set(record.descriptor.name + labels, record); + this._batchMap.set(record.descriptor.name + attributes, record); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/types.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/types.ts index 889e96598d..0f64af0901 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/types.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/types.ts @@ -16,7 +16,7 @@ import { HrTime } from '@opentelemetry/api'; import { - Labels, + Attributes, AggregationTemporality, ValueType, } from '@opentelemetry/api-metrics'; @@ -27,11 +27,10 @@ import { Resource } from '@opentelemetry/resources'; export enum MetricKind { COUNTER, UP_DOWN_COUNTER, - VALUE_RECORDER, - SUM_OBSERVER, - UP_DOWN_SUM_OBSERVER, - VALUE_OBSERVER, - BATCH_OBSERVER, + HISTOGRAM, + OBSERVABLE_COUNTER, + OBSERVABLE_UP_DOWN_COUNTER, + OBSERVABLE_GAUGE, } export const MetricKindValues = Object.values(MetricKind); @@ -78,7 +77,7 @@ export type PointValueType = Sum | LastValue | Histogram; export interface MetricRecord { readonly descriptor: MetricDescriptor; - readonly labels: Labels; + readonly attributes: Attributes; readonly aggregator: Aggregator; readonly aggregationTemporality: AggregationTemporality; readonly resource: Resource; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/index.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/index.ts index afcdeea5b1..a3d74d5352 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/index.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/index.ts @@ -16,11 +16,11 @@ export * from './BoundInstrument'; export * from './CounterMetric'; -export * from './ValueRecorderMetric'; +export * from './HistogramMetric'; export * from './Meter'; export * from './MeterProvider'; export * from './Metric'; -export * from './ValueObserverMetric'; +export * from './ObservableGaugeMetric'; export * from './export/aggregators'; export * from './export/ConsoleMetricExporter'; export * from './export/Processor'; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/types.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/types.ts index a9385a3268..338d5805ae 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/types.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/types.ts @@ -20,7 +20,7 @@ import { Processor } from './export/Processor'; import { MetricExporter } from './export/types'; /** MeterConfig provides an interface for configuring a Meter. */ -export interface MeterConfig { +export interface MeterConfig extends api.MeterOptions { /** Metric exporter. */ exporter?: MetricExporter; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/Meter.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/Meter.test.ts index 0fcc05ede3..7d227177dc 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/Meter.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/Meter.test.ts @@ -21,7 +21,6 @@ import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; import * as sinon from 'sinon'; import { - Aggregator, CounterMetric, Histogram, LastValue, @@ -29,21 +28,17 @@ import { Meter, MeterProvider, Metric, - MetricDescriptor, MetricKind, MetricRecord, Sum, UpDownCounterMetric, - ValueObserverMetric, - ValueRecorderMetric, + ObservableGaugeMetric, + HistogramMetric, } from '../src'; -import { BatchObserver } from '../src/BatchObserver'; -import { BatchObserverResult } from '../src/BatchObserverResult'; import { SumAggregator } from '../src/export/aggregators'; -import { Processor } from '../src/export/Processor'; -import { SumObserverMetric } from '../src/SumObserverMetric'; -import { UpDownSumObserverMetric } from '../src/UpDownSumObserverMetric'; -import { hashLabels } from '../src/Utils'; +import { ObservableCounterMetric } from '../src/ObservableCounterMetric'; +import { ObservableUpDownCounterMetric } from '../src/ObservableUpDownCounterMetric'; +import { hashAttributes } from '../src/Utils'; const nonNumberValues = [ // type undefined @@ -76,7 +71,7 @@ describe('Meter', () => { let meter: Meter; const keya = 'keya'; const keyb = 'keyb'; - const labels: api.Labels = { [keyb]: 'value2', [keya]: 'value1' }; + const attributes: api.Attributes = { [keyb]: 'value2', [keya]: 'value1' }; beforeEach(() => { meter = new MeterProvider().getMeter('test-meter'); @@ -105,7 +100,7 @@ describe('Meter', () => { it('should be able to call add() directly on counter', async () => { const counter = meter.createCounter('name') as CounterMetric; - counter.add(10, labels); + counter.add(10, attributes); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); @@ -115,7 +110,7 @@ describe('Meter', () => { hrTimeToNanoseconds(lastTimestamp) > hrTimeToNanoseconds(performanceTimeOrigin) ); - counter.add(10, labels); + counter.add(10, attributes); assert.strictEqual(record1.aggregator.toPoint().value, 20); assert.ok( @@ -124,7 +119,7 @@ describe('Meter', () => { ); }); - it('should be able to call add with no labels', async () => { + it('should be able to call add with no attributes', async () => { const counter = meter.createCounter('name', { description: 'desc', unit: '1', @@ -161,7 +156,7 @@ describe('Meter', () => { describe('.bind()', () => { it('should create a counter instrument', async () => { const counter = meter.createCounter('name') as CounterMetric; - const boundCounter = counter.bind(labels); + const boundCounter = counter.bind(attributes); boundCounter.add(10); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); @@ -173,15 +168,15 @@ describe('Meter', () => { it('should return the aggregator', () => { const counter = meter.createCounter('name') as CounterMetric; - const boundCounter = counter.bind(labels); + const boundCounter = counter.bind(attributes); boundCounter.add(20); assert.ok(boundCounter.getAggregator() instanceof SumAggregator); - assert.strictEqual(boundCounter.getLabels(), labels); + assert.strictEqual(boundCounter.getAttributes(), attributes); }); it('should add positive values only', async () => { const counter = meter.createCounter('name') as CounterMetric; - const boundCounter = counter.bind(labels); + const boundCounter = counter.bind(attributes); boundCounter.add(10); assert.strictEqual(meter.getProcessor().checkPointSet().length, 0); await meter.collect(); @@ -196,18 +191,18 @@ describe('Meter', () => { const counter = meter.createCounter('name', { disabled: true, }) as CounterMetric; - const boundCounter = counter.bind(labels); + const boundCounter = counter.bind(attributes); boundCounter.add(10); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); assert.strictEqual(record1.aggregator.toPoint().value, 0); }); - it('should return same instrument on same label values', async () => { + it('should return same instrument on same attribute values', async () => { const counter = meter.createCounter('name') as CounterMetric; - const boundCounter = counter.bind(labels); + const boundCounter = counter.bind(attributes); boundCounter.add(10); - const boundCounter1 = counter.bind(labels); + const boundCounter1 = counter.bind(attributes); boundCounter1.add(10); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); @@ -220,23 +215,23 @@ describe('Meter', () => { describe('.unbind()', () => { it('should remove a counter instrument', () => { const counter = meter.createCounter('name') as CounterMetric; - const boundCounter = counter.bind(labels); + const boundCounter = counter.bind(attributes); assert.strictEqual(counter['_instruments'].size, 1); - counter.unbind(labels); + counter.unbind(attributes); assert.strictEqual(counter['_instruments'].size, 0); - const boundCounter1 = counter.bind(labels); + const boundCounter1 = counter.bind(attributes); assert.strictEqual(counter['_instruments'].size, 1); assert.notStrictEqual(boundCounter, boundCounter1); }); it('should not fail when removing non existing instrument', () => { - const counter = meter.createCounter('name'); + const counter = meter.createCounter('name') as CounterMetric; counter.unbind({}); }); it('should clear all instruments', () => { const counter = meter.createCounter('name') as CounterMetric; - counter.bind(labels); + counter.bind(attributes); assert.strictEqual(counter['_instruments'].size, 1); counter.clear(); assert.strictEqual(counter['_instruments'].size, 0); @@ -246,13 +241,13 @@ describe('Meter', () => { describe('.registerMetric()', () => { it('skip already registered Metric', async () => { const counter1 = meter.createCounter('name1') as CounterMetric; - counter1.bind(labels).add(10); + counter1.bind(attributes).add(10); // should skip below metric const counter2 = meter.createCounter('name1', { valueType: api.ValueType.INT, }) as CounterMetric; - counter2.bind(labels).add(500); + counter2.bind(attributes).add(500); await meter.collect(); const record = meter.getProcessor().checkPointSet(); @@ -324,7 +319,7 @@ describe('Meter', () => { it('should be able to call add() directly on UpDownCounter', async () => { const upDownCounter = meter.createUpDownCounter('name'); - upDownCounter.add(10, labels); + upDownCounter.add(10, attributes); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); @@ -334,7 +329,7 @@ describe('Meter', () => { hrTimeToNanoseconds(lastTimestamp) > hrTimeToNanoseconds(performanceTimeOrigin) ); - upDownCounter.add(10, labels); + upDownCounter.add(10, attributes); assert.strictEqual(record1.aggregator.toPoint().value, 20); assert.ok( @@ -343,7 +338,7 @@ describe('Meter', () => { ); }); - it('should be able to call add with no labels', async () => { + it('should be able to call add with no attributes', async () => { const upDownCounter = meter.createUpDownCounter('name', { description: 'desc', unit: '1', @@ -369,8 +364,8 @@ describe('Meter', () => { describe('.bind()', () => { it('should create a UpDownCounter instrument', async () => { - const upDownCounter = meter.createUpDownCounter('name'); - const boundCounter = upDownCounter.bind(labels); + const upDownCounter = meter.createUpDownCounter('name') as UpDownCounterMetric; + const boundCounter = upDownCounter.bind(attributes); boundCounter.add(10); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); @@ -384,28 +379,28 @@ describe('Meter', () => { const upDownCounter = meter.createUpDownCounter( 'name' ) as UpDownCounterMetric; - const boundCounter = upDownCounter.bind(labels); + const boundCounter = upDownCounter.bind(attributes); boundCounter.add(20); assert.ok(boundCounter.getAggregator() instanceof SumAggregator); - assert.strictEqual(boundCounter.getLabels(), labels); + assert.strictEqual(boundCounter.getAttributes(), attributes); }); it('should not add the instrument data when disabled', async () => { const upDownCounter = meter.createUpDownCounter('name', { disabled: true, - }); - const boundCounter = upDownCounter.bind(labels); + }) as UpDownCounterMetric; + const boundCounter = upDownCounter.bind(attributes); boundCounter.add(10); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); assert.strictEqual(record1.aggregator.toPoint().value, 0); }); - it('should return same instrument on same label values', async () => { - const upDownCounter = meter.createUpDownCounter('name'); - const boundCounter = upDownCounter.bind(labels); + it('should return same instrument on same attribute values', async () => { + const upDownCounter = meter.createUpDownCounter('name') as UpDownCounterMetric; + const boundCounter = upDownCounter.bind(attributes); boundCounter.add(10); - const boundCounter1 = upDownCounter.bind(labels); + const boundCounter1 = upDownCounter.bind(attributes); boundCounter1.add(10); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); @@ -417,8 +412,8 @@ describe('Meter', () => { it('should truncate non-integer values for INT valueType', async () => { const upDownCounter = meter.createUpDownCounter('name', { valueType: api.ValueType.INT, - }); - const boundCounter = upDownCounter.bind(labels); + }) as UpDownCounterMetric; + const boundCounter = upDownCounter.bind(attributes); [-1.1, 2.2].forEach(val => { boundCounter.add(val); @@ -431,8 +426,8 @@ describe('Meter', () => { it('should ignore non-number values for INT valueType', async () => { const upDownCounter = meter.createUpDownCounter('name', { valueType: api.ValueType.DOUBLE, - }); - const boundCounter = upDownCounter.bind(labels); + }) as UpDownCounterMetric; + const boundCounter = upDownCounter.bind(attributes); await Promise.all( nonNumberValues.map(async val => { @@ -449,8 +444,8 @@ describe('Meter', () => { it('should ignore non-number values for DOUBLE valueType', async () => { const upDownCounter = meter.createUpDownCounter('name', { valueType: api.ValueType.DOUBLE, - }); - const boundCounter = upDownCounter.bind(labels); + }) as UpDownCounterMetric; + const boundCounter = upDownCounter.bind(attributes); await Promise.all( nonNumberValues.map(async val => { @@ -470,17 +465,17 @@ describe('Meter', () => { const upDownCounter = meter.createUpDownCounter( 'name' ) as UpDownCounterMetric; - const boundCounter = upDownCounter.bind(labels); + const boundCounter = upDownCounter.bind(attributes); assert.strictEqual(upDownCounter['_instruments'].size, 1); - upDownCounter.unbind(labels); + upDownCounter.unbind(attributes); assert.strictEqual(upDownCounter['_instruments'].size, 0); - const boundCounter1 = upDownCounter.bind(labels); + const boundCounter1 = upDownCounter.bind(attributes); assert.strictEqual(upDownCounter['_instruments'].size, 1); assert.notStrictEqual(boundCounter, boundCounter1); }); it('should not fail when removing non existing instrument', () => { - const upDownCounter = meter.createUpDownCounter('name'); + const upDownCounter = meter.createUpDownCounter('name') as UpDownCounterMetric; upDownCounter.unbind({}); }); @@ -488,7 +483,7 @@ describe('Meter', () => { const upDownCounter = meter.createUpDownCounter( 'name' ) as CounterMetric; - upDownCounter.bind(labels); + upDownCounter.bind(attributes); assert.strictEqual(upDownCounter['_instruments'].size, 1); upDownCounter.clear(); assert.strictEqual(upDownCounter['_instruments'].size, 0); @@ -498,13 +493,13 @@ describe('Meter', () => { describe('.registerMetric()', () => { it('skip already registered Metric', async () => { const counter1 = meter.createCounter('name1') as CounterMetric; - counter1.bind(labels).add(10); + counter1.bind(attributes).add(10); // should skip below metric const counter2 = meter.createCounter('name1', { valueType: api.ValueType.INT, }) as CounterMetric; - counter2.bind(labels).add(500); + counter2.bind(attributes).add(500); await meter.collect(); const record = meter.getProcessor().checkPointSet(); @@ -550,33 +545,33 @@ describe('Meter', () => { }); }); - describe('#ValueRecorder', () => { - it('should create a valueRecorder', () => { - const valueRecorder = meter.createValueRecorder('name'); - assert.ok(valueRecorder instanceof Metric); + describe('#Histogram', () => { + it('should create a histogram', () => { + const histogram = meter.createHistogram('name'); + assert.ok(histogram instanceof Metric); }); - it('should create a valueRecorder with options', () => { - const valueRecorder = meter.createValueRecorder('name', { + it('should create a histogram with options', () => { + const histogram = meter.createHistogram('name', { description: 'desc', unit: '1', disabled: false, }); - assert.ok(valueRecorder instanceof Metric); + assert.ok(histogram instanceof Metric); }); - it('should set histogram boundaries for value recorder', async () => { - const valueRecorder = meter.createValueRecorder('name', { + it('should set histogram boundaries for histogram', async () => { + const histogram = meter.createHistogram('name', { description: 'desc', unit: '1', disabled: false, boundaries: [10, 20, 30, 100], - }) as ValueRecorderMetric; + }) as HistogramMetric; - valueRecorder.record(10); - valueRecorder.record(30); - valueRecorder.record(50); - valueRecorder.record(200); + histogram.record(10); + histogram.record(30); + histogram.record(50); + histogram.record(200); await meter.collect(); const [record] = meter.getProcessor().checkPointSet(); @@ -589,30 +584,30 @@ describe('Meter', () => { sum: 290, }); - assert.ok(valueRecorder instanceof Metric); + assert.ok(histogram instanceof Metric); }); it('should pipe through resource', async () => { - const valueRecorder = meter.createValueRecorder( + const histogram = meter.createHistogram( 'name' - ) as ValueRecorderMetric; - assert.ok(valueRecorder.resource instanceof Resource); + ) as HistogramMetric; + assert.ok(histogram.resource instanceof Resource); - valueRecorder.record(1, { foo: 'bar' }); + histogram.record(1, { foo: 'bar' }); - const [record] = await valueRecorder.getMetricRecord(); + const [record] = await histogram.getMetricRecord(); assert.ok(record.resource instanceof Resource); }); it('should pipe through instrumentation library', async () => { - const valueRecorder = meter.createValueRecorder( + const histogram = meter.createHistogram( 'name' - ) as ValueRecorderMetric; - assert.ok(valueRecorder.instrumentationLibrary); + ) as HistogramMetric; + assert.ok(histogram.instrumentationLibrary); - valueRecorder.record(1, { foo: 'bar' }); + histogram.record(1, { foo: 'bar' }); - const [record] = await valueRecorder.getMetricRecord(); + const [record] = await histogram.getMetricRecord(); const { name, version } = record.instrumentationLibrary; assert.strictEqual(name, 'test-meter'); assert.strictEqual(version, undefined); @@ -620,42 +615,42 @@ describe('Meter', () => { describe('names', () => { it('should return no op metric if name is an empty string', () => { - const valueRecorder = meter.createValueRecorder(''); - assert.ok(valueRecorder instanceof api.NoopMetric); + const histogram = meter.createHistogram(''); + assert.ok(histogram instanceof api.NoopMetric); }); it('should return no op metric if name does not start with a letter', () => { - const valueRecorder1 = meter.createValueRecorder('1name'); - const valueRecorder_ = meter.createValueRecorder('_name'); - assert.ok(valueRecorder1 instanceof api.NoopMetric); - assert.ok(valueRecorder_ instanceof api.NoopMetric); + const histogram1 = meter.createHistogram('1name'); + const histogram_ = meter.createHistogram('_name'); + assert.ok(histogram1 instanceof api.NoopMetric); + assert.ok(histogram_ instanceof api.NoopMetric); }); it('should return no op metric if name is an empty string contain only letters, numbers, ".", "_", and "-"', () => { - const valueRecorder = meter.createValueRecorder( + const histogram = meter.createHistogram( 'name with invalid characters^&*(' ); - assert.ok(valueRecorder instanceof api.NoopMetric); + assert.ok(histogram instanceof api.NoopMetric); }); }); describe('.bind()', () => { const performanceTimeOrigin = hrTime(); - it('should create a valueRecorder instrument', () => { - const valueRecorder = meter.createValueRecorder( + it('should create a histogram instrument', () => { + const histogram = meter.createHistogram( 'name' - ) as ValueRecorderMetric; - const boundValueRecorder = valueRecorder.bind(labels); - assert.doesNotThrow(() => boundValueRecorder.record(10)); + ) as HistogramMetric; + const boundHistogram = histogram.bind(attributes); + assert.doesNotThrow(() => boundHistogram.record(10)); }); it('should not set the instrument data when disabled', async () => { - const valueRecorder = meter.createValueRecorder('name', { + const histogram = meter.createHistogram('name', { disabled: true, - }) as ValueRecorderMetric; - const boundValueRecorder = valueRecorder.bind(labels); - boundValueRecorder.record(10); + }) as HistogramMetric; + const boundHistogram = histogram.bind(attributes); + boundHistogram.record(10); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); @@ -673,10 +668,10 @@ describe('Meter', () => { }); it('should accept negative (and positive) values', async () => { - const valueRecorder = meter.createValueRecorder('name'); - const boundValueRecorder = valueRecorder.bind(labels); - boundValueRecorder.record(-10); - boundValueRecorder.record(50); + const histogram = meter.createHistogram('name') as HistogramMetric; + const boundHistogram = histogram.bind(attributes); + boundHistogram.record(-10); + boundHistogram.record(50); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); @@ -697,14 +692,14 @@ describe('Meter', () => { ); }); - it('should return same instrument on same label values', async () => { - const valueRecorder = meter.createValueRecorder( + it('should return same instrument on same attribute values', async () => { + const histogram = meter.createHistogram( 'name' - ) as ValueRecorderMetric; - const boundValueRecorder1 = valueRecorder.bind(labels); - boundValueRecorder1.record(10); - const boundValueRecorder2 = valueRecorder.bind(labels); - boundValueRecorder2.record(100); + ) as HistogramMetric; + const boundHistogram1 = histogram.bind(attributes); + boundHistogram1.record(10); + const boundHistogram2 = histogram.bind(attributes); + boundHistogram2.record(100); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); assert.deepStrictEqual( @@ -718,19 +713,19 @@ describe('Meter', () => { sum: 110, } ); - assert.strictEqual(boundValueRecorder1, boundValueRecorder2); + assert.strictEqual(boundHistogram1, boundHistogram2); }); it('should ignore non-number values', async () => { - const valueRecorder = meter.createValueRecorder( + const histogram = meter.createHistogram( 'name' - ) as ValueRecorderMetric; - const boundValueRecorder = valueRecorder.bind(labels); + ) as HistogramMetric; + const boundHistogram = histogram.bind(attributes); await Promise.all( nonNumberValues.map(async val => { // @ts-expect-error verify non number types - boundValueRecorder.record(val); + boundHistogram.record(val); await meter.collect(); const [record1] = meter.getProcessor().checkPointSet(); assert.deepStrictEqual( @@ -750,47 +745,47 @@ describe('Meter', () => { }); describe('.unbind()', () => { - it('should remove the valueRecorder instrument', () => { - const valueRecorder = meter.createValueRecorder( + it('should remove the histogram instrument', () => { + const histogram = meter.createHistogram( 'name' - ) as ValueRecorderMetric; - const boundValueRecorder = valueRecorder.bind(labels); - assert.strictEqual(valueRecorder['_instruments'].size, 1); - valueRecorder.unbind(labels); - assert.strictEqual(valueRecorder['_instruments'].size, 0); - const boundValueRecorder2 = valueRecorder.bind(labels); - assert.strictEqual(valueRecorder['_instruments'].size, 1); - assert.notStrictEqual(boundValueRecorder, boundValueRecorder2); + ) as HistogramMetric; + const boundHistogram = histogram.bind(attributes); + assert.strictEqual(histogram['_instruments'].size, 1); + histogram.unbind(attributes); + assert.strictEqual(histogram['_instruments'].size, 0); + const boundHistogram2 = histogram.bind(attributes); + assert.strictEqual(histogram['_instruments'].size, 1); + assert.notStrictEqual(boundHistogram, boundHistogram2); }); it('should not fail when removing non existing instrument', () => { - const valueRecorder = meter.createValueRecorder('name'); - valueRecorder.unbind({}); + const histogram = meter.createHistogram('name') as HistogramMetric; + histogram.unbind({}); }); it('should clear all instruments', () => { - const valueRecorder = meter.createValueRecorder( + const histogram = meter.createHistogram( 'name' - ) as ValueRecorderMetric; - valueRecorder.bind(labels); - assert.strictEqual(valueRecorder['_instruments'].size, 1); - valueRecorder.clear(); - assert.strictEqual(valueRecorder['_instruments'].size, 0); + ) as HistogramMetric; + histogram.bind(attributes); + assert.strictEqual(histogram['_instruments'].size, 1); + histogram.clear(); + assert.strictEqual(histogram['_instruments'].size, 0); }); }); }); - describe('#SumObserverMetric', () => { - it('should create an Sum observer', () => { - const sumObserver = meter.createSumObserver('name') as SumObserverMetric; - assert.ok(sumObserver instanceof Metric); + describe('#ObservableCounterMetric', () => { + it('should create an ObservableCounter', () => { + const observableCounter = meter.createObservableCounter('name') as ObservableCounterMetric; + assert.ok(observableCounter instanceof Metric); }); - it('should return noop observer when name is invalid', () => { + it('should return noop observable counter when name is invalid', () => { // Need to stub/spy on the underlying logger as the "diag" instance is global const spy = sinon.stub(diag, 'warn'); - const sumObserver = meter.createSumObserver('na me'); - assert.ok(sumObserver === api.NOOP_SUM_OBSERVER_METRIC); + const observableCounter = meter.createObservableCounter('na me'); + assert.ok(observableCounter === api.NOOP_OBSERVABLE_COUNTER_METRIC); const args = spy.args[0]; assert.ok( args[0], @@ -798,13 +793,13 @@ describe('Meter', () => { ); }); - it('should create observer with options', () => { - const sumObserver = meter.createSumObserver('name', { + it('should create observable counter with options', () => { + const observableCounter = meter.createObservableCounter('name', { description: 'desc', unit: '1', disabled: false, - }) as SumObserverMetric; - assert.ok(sumObserver instanceof Metric); + }) as ObservableCounterMetric; + assert.ok(observableCounter instanceof Metric); }); it('should set callback and observe value ', async () => { @@ -818,54 +813,54 @@ describe('Meter', () => { return -1; } - const sumObserver = meter.createSumObserver( + const observableCounter = meter.createObservableCounter( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { + (observableResult: api.ObservableResult) => { // simulate async return new Promise(resolve => { setTimeout(() => { - observerResult.observe(getValue(), { pid: '123', core: '1' }); + observableResult.observe(getValue(), { pid: '123', core: '1' }); resolve(); }, 1); }); } - ) as SumObserverMetric; + ) as ObservableCounterMetric; - let metricRecords = await sumObserver.getMetricRecord(); + let metricRecords = await observableCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); let point = metricRecords[0].aggregator.toPoint(); assert.strictEqual(point.value, -1); assert.strictEqual( - hashLabels(metricRecords[0].labels), + hashAttributes(metricRecords[0].attributes), '|#core:1,pid:123' ); - metricRecords = await sumObserver.getMetricRecord(); + metricRecords = await observableCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); point = metricRecords[0].aggregator.toPoint(); assert.strictEqual(point.value, 3); - metricRecords = await sumObserver.getMetricRecord(); + metricRecords = await observableCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); point = metricRecords[0].aggregator.toPoint(); assert.strictEqual(point.value, 3); }); it('should set callback and observe value when callback returns nothing', async () => { - const sumObserver = meter.createSumObserver( + const observableCounter = meter.createObservableCounter( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { - observerResult.observe(1, { pid: '123', core: '1' }); + (observableResult: api.ObservableResult) => { + observableResult.observe(1, { pid: '123', core: '1' }); } - ) as SumObserverMetric; + ) as ObservableCounterMetric; - const metricRecords = await sumObserver.getMetricRecord(); + const metricRecords = await observableCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); }); @@ -873,34 +868,34 @@ describe('Meter', () => { 'should set callback and observe value when callback returns anything' + ' but Promise', async () => { - const sumObserver = meter.createSumObserver( + const observableCounter = meter.createObservableCounter( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { - observerResult.observe(1, { pid: '123', core: '1' }); + (observableResult: api.ObservableResult) => { + observableResult.observe(1, { pid: '123', core: '1' }); return '1'; } - ) as SumObserverMetric; + ) as ObservableCounterMetric; - const metricRecords = await sumObserver.getMetricRecord(); + const metricRecords = await observableCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); } ); it('should reject getMetricRecord when callback throws an error', async () => { - const sumObserver = meter.createSumObserver( + const observableCounter = meter.createObservableCounter( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { - observerResult.observe(1, { pid: '123', core: '1' }); + (observableResult: api.ObservableResult) => { + observableResult.observe(1, { pid: '123', core: '1' }); throw new Error('Boom'); } - ) as SumObserverMetric; - await sumObserver + ) as ObservableCounterMetric; + await observableCounter .getMetricRecord() .then() .catch(e => { @@ -909,30 +904,30 @@ describe('Meter', () => { }); it('should pipe through resource', async () => { - const sumObserver = meter.createSumObserver('name', {}, result => { + const observableCounter = meter.createObservableCounter('name', {}, result => { result.observe(42, { foo: 'bar' }); return Promise.resolve(); - }) as SumObserverMetric; - assert.ok(sumObserver.resource instanceof Resource); + }) as ObservableCounterMetric; + assert.ok(observableCounter.resource instanceof Resource); - const [record] = await sumObserver.getMetricRecord(); + const [record] = await observableCounter.getMetricRecord(); assert.ok(record.resource instanceof Resource); }); }); - describe('#ValueObserver', () => { - it('should create a value observer', () => { - const valueObserver = meter.createValueObserver( + describe('#ObservableGauge', () => { + it('should create an observable gauge', () => { + const observableGauge = meter.createObservableGauge( 'name' - ) as ValueObserverMetric; - assert.ok(valueObserver instanceof Metric); + ) as ObservableGaugeMetric; + assert.ok(observableGauge instanceof Metric); }); - it('should return noop observer when name is invalid', () => { + it('should return noop observable gauge when name is invalid', () => { // Need to stub/spy on the underlying logger as the "diag" instance is global const spy = sinon.stub(diag, 'warn'); - const valueObserver = meter.createValueObserver('na me'); - assert.ok(valueObserver === api.NOOP_VALUE_OBSERVER_METRIC); + const observableGauge = meter.createObservableGauge('na me'); + assert.ok(observableGauge === api.NOOP_OBSERVABLE_GAUGE_METRIC); const args = spy.args[0]; assert.ok( args[0], @@ -940,50 +935,50 @@ describe('Meter', () => { ); }); - it('should create observer with options', () => { - const valueObserver = meter.createValueObserver('name', { + it('should create observable gauge with options', () => { + const observableGauge = meter.createObservableGauge('name', { description: 'desc', unit: '1', disabled: false, - }) as ValueObserverMetric; - assert.ok(valueObserver instanceof Metric); + }) as ObservableGaugeMetric; + assert.ok(observableGauge instanceof Metric); }); it('should set callback and observe value ', async () => { - const valueObserver = meter.createValueObserver( + const observableGauge = meter.createObservableGauge( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { + (observableResult: api.ObservableResult) => { // simulate async return new Promise(resolve => { setTimeout(() => { - observerResult.observe(getCpuUsage(), { pid: '123', core: '1' }); - observerResult.observe(getCpuUsage(), { pid: '123', core: '2' }); - observerResult.observe(getCpuUsage(), { pid: '123', core: '3' }); - observerResult.observe(getCpuUsage(), { pid: '123', core: '4' }); + observableResult.observe(getCpuUsage(), { pid: '123', core: '1' }); + observableResult.observe(getCpuUsage(), { pid: '123', core: '2' }); + observableResult.observe(getCpuUsage(), { pid: '123', core: '3' }); + observableResult.observe(getCpuUsage(), { pid: '123', core: '4' }); resolve(); }, 1); }); } - ) as ValueObserverMetric; + ) as ObservableGaugeMetric; function getCpuUsage() { return Math.random(); } - const metricRecords: MetricRecord[] = await valueObserver.getMetricRecord(); + const metricRecords: MetricRecord[] = await observableGauge.getMetricRecord(); assert.strictEqual(metricRecords.length, 4); const metric1 = metricRecords[0]; const metric2 = metricRecords[1]; const metric3 = metricRecords[2]; const metric4 = metricRecords[3]; - assert.strictEqual(hashLabels(metric1.labels), '|#core:1,pid:123'); - assert.strictEqual(hashLabels(metric2.labels), '|#core:2,pid:123'); - assert.strictEqual(hashLabels(metric3.labels), '|#core:3,pid:123'); - assert.strictEqual(hashLabels(metric4.labels), '|#core:4,pid:123'); + assert.strictEqual(hashAttributes(metric1.attributes), '|#core:1,pid:123'); + assert.strictEqual(hashAttributes(metric2.attributes), '|#core:2,pid:123'); + assert.strictEqual(hashAttributes(metric3.attributes), '|#core:3,pid:123'); + assert.strictEqual(hashAttributes(metric4.attributes), '|#core:4,pid:123'); ensureMetric(metric1); ensureMetric(metric2); @@ -992,29 +987,29 @@ describe('Meter', () => { }); it('should pipe through resource', async () => { - const valueObserver = meter.createValueObserver('name', {}, result => { + const observableGauge = meter.createObservableGauge('name', {}, result => { result.observe(42, { foo: 'bar' }); - }) as ValueObserverMetric; - assert.ok(valueObserver.resource instanceof Resource); + }) as ObservableGaugeMetric; + assert.ok(observableGauge.resource instanceof Resource); - const [record] = await valueObserver.getMetricRecord(); + const [record] = await observableGauge.getMetricRecord(); assert.ok(record.resource instanceof Resource); }); }); - describe('#UpDownSumObserverMetric', () => { - it('should create an UpDownSum observer', () => { - const upDownSumObserver = meter.createUpDownSumObserver( + describe('#ObservableUpDownCounterMetric', () => { + it('should create an ObservableUpDownCounter', () => { + const observableUpDownCounter = meter.createObservableUpDownCounter( 'name' - ) as UpDownSumObserverMetric; - assert.ok(upDownSumObserver instanceof Metric); + ) as ObservableUpDownCounterMetric; + assert.ok(observableUpDownCounter instanceof Metric); }); - it('should return noop observer when name is invalid', () => { + it('should return noop observable up down counter when name is invalid', () => { // Need to stub/spy on the underlying logger as the "diag" instance is global const spy = sinon.stub(diag, 'warn'); - const upDownSumObserver = meter.createUpDownSumObserver('na me'); - assert.ok(upDownSumObserver === api.NOOP_UP_DOWN_SUM_OBSERVER_METRIC); + const observableUpDownCounter = meter.createObservableUpDownCounter('na me'); + assert.ok(observableUpDownCounter === api.NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC); const args = spy.args[0]; assert.ok( args[0], @@ -1022,13 +1017,13 @@ describe('Meter', () => { ); }); - it('should create observer with options', () => { - const upDownSumObserver = meter.createUpDownSumObserver('name', { + it('should create observable up down counter with options', () => { + const observableUpDownCounter = meter.createObservableUpDownCounter('name', { description: 'desc', unit: '1', disabled: false, - }) as UpDownSumObserverMetric; - assert.ok(upDownSumObserver instanceof Metric); + }) as ObservableUpDownCounterMetric; + assert.ok(observableUpDownCounter instanceof Metric); }); it('should set callback and observe value ', async () => { @@ -1042,54 +1037,54 @@ describe('Meter', () => { return 3; } - const upDownSumObserver = meter.createUpDownSumObserver( + const observableUpDownCounter = meter.createObservableUpDownCounter( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { + (observableResult: api.ObservableResult) => { // simulate async return new Promise(resolve => { setTimeout(() => { - observerResult.observe(getValue(), { pid: '123', core: '1' }); + observableResult.observe(getValue(), { pid: '123', core: '1' }); resolve(); }, 1); }); } - ) as UpDownSumObserverMetric; + ) as ObservableUpDownCounterMetric; - let metricRecords = await upDownSumObserver.getMetricRecord(); + let metricRecords = await observableUpDownCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); let point = metricRecords[0].aggregator.toPoint(); assert.strictEqual(point.value, 3); assert.strictEqual( - hashLabels(metricRecords[0].labels), + hashAttributes(metricRecords[0].attributes), '|#core:1,pid:123' ); - metricRecords = await upDownSumObserver.getMetricRecord(); + metricRecords = await observableUpDownCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); point = metricRecords[0].aggregator.toPoint(); assert.strictEqual(point.value, 2); - metricRecords = await upDownSumObserver.getMetricRecord(); + metricRecords = await observableUpDownCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); point = metricRecords[0].aggregator.toPoint(); assert.strictEqual(point.value, 3); }); it('should set callback and observe value when callback returns nothing', async () => { - const upDownSumObserver = meter.createUpDownSumObserver( + const observableUpDownCounter = meter.createObservableUpDownCounter( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { - observerResult.observe(1, { pid: '123', core: '1' }); + (observableResult: api.ObservableResult) => { + observableResult.observe(1, { pid: '123', core: '1' }); } - ) as UpDownSumObserverMetric; + ) as ObservableUpDownCounterMetric; - const metricRecords = await upDownSumObserver.getMetricRecord(); + const metricRecords = await observableUpDownCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); }); @@ -1097,34 +1092,34 @@ describe('Meter', () => { 'should set callback and observe value when callback returns anything' + ' but Promise', async () => { - const upDownSumObserver = meter.createUpDownSumObserver( + const observableUpDownCounter = meter.createObservableUpDownCounter( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { - observerResult.observe(1, { pid: '123', core: '1' }); + (observableResult: api.ObservableResult) => { + observableResult.observe(1, { pid: '123', core: '1' }); return '1'; } - ) as UpDownSumObserverMetric; + ) as ObservableUpDownCounterMetric; - const metricRecords = await upDownSumObserver.getMetricRecord(); + const metricRecords = await observableUpDownCounter.getMetricRecord(); assert.strictEqual(metricRecords.length, 1); } ); it('should reject getMetricRecord when callback throws an error', async () => { - const upDownSumObserver = meter.createUpDownSumObserver( + const observableUpDownCounter = meter.createObservableUpDownCounter( 'name', { description: 'desc', }, - (observerResult: api.ObserverResult) => { - observerResult.observe(1, { pid: '123', core: '1' }); + (observableResult: api.ObservableResult) => { + observableResult.observe(1, { pid: '123', core: '1' }); throw new Error('Boom'); } - ) as UpDownSumObserverMetric; - await upDownSumObserver + ) as ObservableUpDownCounterMetric; + await observableUpDownCounter .getMetricRecord() .then() .catch(e => { @@ -1133,193 +1128,29 @@ describe('Meter', () => { }); it('should pipe through resource', async () => { - const upDownSumObserver = meter.createUpDownSumObserver( + const observableUpDownCounter = meter.createObservableUpDownCounter( 'name', {}, result => { result.observe(42, { foo: 'bar' }); return Promise.resolve(); } - ) as UpDownSumObserverMetric; - assert.ok(upDownSumObserver.resource instanceof Resource); + ) as ObservableUpDownCounterMetric; + assert.ok(observableUpDownCounter.resource instanceof Resource); - const [record] = await upDownSumObserver.getMetricRecord(); + const [record] = await observableUpDownCounter.getMetricRecord(); assert.ok(record.resource instanceof Resource); }); }); - describe('#batchObserver', () => { - it('should create a batch observer', () => { - const observer = meter.createBatchObserver(() => {}); - assert.ok(observer instanceof BatchObserver); - }); - - it('should create batch observer with options', () => { - const observer = meter.createBatchObserver(() => {}, { - maxTimeoutUpdateMS: 100, - }); - assert.ok(observer instanceof BatchObserver); - }); - - it('should use callback to observe values ', async () => { - const tempMetric = meter.createValueObserver('cpu_temp_per_app', { - description: 'desc', - }) as ValueObserverMetric; - - const cpuUsageMetric = meter.createValueObserver('cpu_usage_per_app', { - description: 'desc', - }) as ValueObserverMetric; - - meter.createBatchObserver(observerBatchResult => { - interface StatItem { - usage: number; - temp: number; - } - - interface Stat { - name: string; - core1: StatItem; - core2: StatItem; - } - - function someAsyncMetrics() { - return new Promise(resolve => { - const stats: Stat[] = [ - { - name: 'app1', - core1: { usage: 2.1, temp: 67 }, - core2: { usage: 3.1, temp: 69 }, - }, - { - name: 'app2', - core1: { usage: 1.2, temp: 67 }, - core2: { usage: 4.5, temp: 69 }, - }, - ]; - resolve(stats); - }); - } - - Promise.all([ - someAsyncMetrics(), - // simulate waiting - new Promise((resolve, reject) => { - setTimeout(resolve, 1); - }), - ]).then((stats: unknown[]) => { - const apps = (stats[0] as unknown) as Stat[]; - apps.forEach(app => { - observerBatchResult.observe({ app: app.name, core: '1' }, [ - tempMetric.observation(app.core1.temp), - cpuUsageMetric.observation(app.core1.usage), - ]); - observerBatchResult.observe({ app: app.name, core: '2' }, [ - tempMetric.observation(app.core2.temp), - cpuUsageMetric.observation(app.core2.usage), - ]); - }); - }); - }); - - await meter.collect(); - const records = meter.getProcessor().checkPointSet(); - assert.strictEqual(records.length, 8); - - const metric1 = records[0]; - const metric2 = records[1]; - const metric3 = records[2]; - const metric4 = records[3]; - assert.strictEqual(hashLabels(metric1.labels), '|#app:app1,core:1'); - assert.strictEqual(hashLabels(metric2.labels), '|#app:app1,core:2'); - assert.strictEqual(hashLabels(metric3.labels), '|#app:app2,core:1'); - assert.strictEqual(hashLabels(metric4.labels), '|#app:app2,core:2'); - - ensureMetric(metric1, 'cpu_temp_per_app', 67); - ensureMetric(metric2, 'cpu_temp_per_app', 69); - ensureMetric(metric3, 'cpu_temp_per_app', 67); - ensureMetric(metric4, 'cpu_temp_per_app', 69); - - const metric5 = records[4]; - const metric6 = records[5]; - const metric7 = records[6]; - const metric8 = records[7]; - assert.strictEqual(hashLabels(metric5.labels), '|#app:app1,core:1'); - assert.strictEqual(hashLabels(metric6.labels), '|#app:app1,core:2'); - assert.strictEqual(hashLabels(metric7.labels), '|#app:app2,core:1'); - assert.strictEqual(hashLabels(metric8.labels), '|#app:app2,core:2'); - - ensureMetric(metric5, 'cpu_usage_per_app', 2.1); - ensureMetric(metric6, 'cpu_usage_per_app', 3.1); - ensureMetric(metric7, 'cpu_usage_per_app', 1.2); - ensureMetric(metric8, 'cpu_usage_per_app', 4.5); - }); - - it('should not observe values when timeout', done => { - const cpuUsageMetric = meter.createValueObserver('cpu_usage_per_app', { - description: 'desc', - }) as ValueObserverMetric; - - meter.createBatchObserver( - observerBatchResult => { - Promise.all([ - // simulate waiting 11ms - new Promise((resolve, reject) => { - setTimeout(resolve, 11); - }), - ]).then(async () => { - // try to hack to be able to update - (observerBatchResult as BatchObserverResult).cancelled = false; - observerBatchResult.observe({ foo: 'bar' }, [ - cpuUsageMetric.observation(123), - ]); - - // simulate some waiting - await setTimeout(() => {}, 5); - - const cpuUsageMetricRecords: MetricRecord[] = await cpuUsageMetric.getMetricRecord(); - const value = cpuUsageMetric - .bind({ foo: 'bar' }) - .getAggregator() - .toPoint().value; - - assert.deepStrictEqual(value, 0); - assert.strictEqual(cpuUsageMetricRecords.length, 0); - done(); - }); - }, - { - maxTimeoutUpdateMS: 10, // timeout after 10ms - } - ); - - meter.collect(); - }); - - it('should pipe through instrumentation library', async () => { - const observer = meter.createValueObserver( - 'name', - {}, - (observerResult: api.ObserverResult) => { - observerResult.observe(42, { foo: 'bar' }); - } - ) as ValueObserverMetric; - assert.ok(observer.instrumentationLibrary); - - const [record] = await observer.getMetricRecord(); - const { name, version } = record.instrumentationLibrary; - assert.strictEqual(name, 'test-meter'); - assert.strictEqual(version, undefined); - }); - }); - describe('#getMetrics', () => { it('should create a DOUBLE counter', async () => { const key = 'key'; const counter = meter.createCounter('counter', { description: 'test', - }); - const labels = { [key]: 'counter-value' }; - const boundCounter = counter.bind(labels); + }) as CounterMetric; + const attributes = { [key]: 'counter-value' }; + const boundCounter = counter.bind(attributes); boundCounter.add(10.45); await meter.collect(); @@ -1333,7 +1164,7 @@ describe('Meter', () => { unit: '1', valueType: api.ValueType.DOUBLE, }); - assert.strictEqual(record[0].labels, labels); + assert.strictEqual(record[0].attributes, attributes); const value = record[0].aggregator.toPoint().value as Sum; assert.strictEqual(value, 10.45); }); @@ -1343,9 +1174,9 @@ describe('Meter', () => { const counter = meter.createCounter('counter', { description: 'test', valueType: api.ValueType.INT, - }); - const labels = { [key]: 'counter-value' }; - const boundCounter = counter.bind(labels); + }) as CounterMetric; + const attributes = { [key]: 'counter-value' }; + const boundCounter = counter.bind(attributes); boundCounter.add(10.45); await meter.collect(); @@ -1359,33 +1190,13 @@ describe('Meter', () => { unit: '1', valueType: api.ValueType.INT, }); - assert.strictEqual(record[0].labels, labels); + assert.strictEqual(record[0].attributes, attributes); const value = record[0].aggregator.toPoint().value as Sum; assert.strictEqual(value, 10); }); }); - - it('should allow custom processor', () => { - const customMeter = new MeterProvider().getMeter('custom-processor', '*', { - processor: new CustomProcessor(), - }); - assert.throws(() => { - const valueRecorder = customMeter.createValueRecorder('myValueRecorder'); - valueRecorder.bind({}).record(1); - }, /aggregatorFor method not implemented/); - }); }); -class CustomProcessor extends Processor { - process(record: MetricRecord): void { - throw new Error('process method not implemented.'); - } - - aggregatorFor(metricKind: MetricDescriptor): Aggregator { - throw new Error('aggregatorFor method not implemented.'); - } -} - function ensureMetric(metric: MetricRecord, name?: string, value?: LastValue) { assert.ok(metric.aggregator instanceof LastValueAggregator); const lastValue = metric.aggregator.toPoint().value; @@ -1396,6 +1207,6 @@ function ensureMetric(metric: MetricRecord, name?: string, value?: LastValue) { assert.strictEqual(descriptor.name, name || 'name'); assert.strictEqual(descriptor.description, 'desc'); assert.strictEqual(descriptor.unit, '1'); - assert.strictEqual(descriptor.metricKind, MetricKind.VALUE_OBSERVER); + assert.strictEqual(descriptor.metricKind, MetricKind.OBSERVABLE_GAUGE); assert.strictEqual(descriptor.valueType, api.ValueType.DOUBLE); } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts index b7bb7bd42f..36e68e1271 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts @@ -16,7 +16,15 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { MeterProvider, Meter, CounterMetric } from '../src'; +import { + MeterProvider, + Meter, + CounterMetric, + MetricRecord, + MetricDescriptor, + Aggregator, + Processor, +} from '../src'; describe('MeterProvider', () => { afterEach(() => { @@ -74,6 +82,27 @@ describe('MeterProvider', () => { const meter4 = provider.getMeter('meter3', 'ver2'); assert.notEqual(meter3, meter4); }); + + it('should allow custom processor', () => { + class CustomProcessor extends Processor { + process(record: MetricRecord): void { + throw new Error('process method not implemented.'); + } + + aggregatorFor(metricKind: MetricDescriptor): Aggregator { + throw new Error('aggregatorFor method not implemented.'); + } + } + + const meter = new MeterProvider({ + processor: new CustomProcessor(), + }).getMeter('custom-processor', '*'); + + assert.throws(() => { + const histogram = meter.createHistogram('myHistogram'); + histogram.record(1); + }, /aggregatorFor method not implemented/); + }); }); describe('shutdown()', () => { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/Processor.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/Processor.test.ts index cd2ac2c4df..72af5f7bb6 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/Processor.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/Processor.test.ts @@ -16,19 +16,18 @@ import * as api from '@opentelemetry/api-metrics'; import * as assert from 'assert'; -import { Meter, MeterProvider } from '../src'; +import { CounterMetric, Meter, MeterProvider } from '../src'; describe('Processor', () => { describe('Ungrouped', () => { let meter: Meter; - let fooCounter: api.BoundCounter; - let barCounter: api.BoundCounter; - let counter: api.Counter; + let fooCounter: api.Counter; + let barCounter: api.Counter; beforeEach(() => { meter = new MeterProvider({ interval: 10000, }).getMeter('test-meter'); - counter = meter.createCounter('ungrouped-processor-test'); + const counter = meter.createCounter('ungrouped-processor-test') as CounterMetric; fooCounter = counter.bind({ key: 'foo' }); barCounter = counter.bind({ key: 'bar' }); }); @@ -41,7 +40,7 @@ describe('Processor', () => { const checkPointSet = meter.getProcessor().checkPointSet(); assert.strictEqual(checkPointSet.length, 2); for (const record of checkPointSet) { - switch (record.labels.key) { + switch (record.attributes.key) { case 'foo': assert.strictEqual(record.aggregator.toPoint().value, 1); break; @@ -49,7 +48,7 @@ describe('Processor', () => { assert.strictEqual(record.aggregator.toPoint().value, 3); break; default: - throw new Error('Unknown labelset'); + throw new Error('Unknown attributeset'); } } }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/ConsoleMetricExporter.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/ConsoleMetricExporter.test.ts index 0cd111cc5c..10168b0174 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/ConsoleMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/ConsoleMetricExporter.test.ts @@ -16,7 +16,7 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { ConsoleMetricExporter, MeterProvider, MetricKind } from '../../src'; +import { ConsoleMetricExporter, CounterMetric, MeterProvider, MetricKind } from '../../src'; import { ValueType } from '@opentelemetry/api-metrics'; /* eslint-disable no-console */ @@ -43,17 +43,17 @@ describe('ConsoleMetricExporter', () => { ); const counter = meter.createCounter('counter', { description: 'a test description', - }); + }) as CounterMetric; const boundCounter = counter.bind({ - key1: 'labelValue1', - key2: 'labelValue2', + key1: 'attributeValue1', + key2: 'attributeValue2', }); boundCounter.add(10); await meter.collect(); consoleExporter.export(meter.getProcessor().checkPointSet(), () => {}); assert.strictEqual(spyConsole.args.length, 3); - const [descriptor, labels, value] = spyConsole.args; + const [descriptor, attributes, value] = spyConsole.args; assert.deepStrictEqual(descriptor, [ { description: 'a test description', @@ -63,10 +63,10 @@ describe('ConsoleMetricExporter', () => { valueType: ValueType.DOUBLE, }, ]); - assert.deepStrictEqual(labels, [ + assert.deepStrictEqual(attributes, [ { - key1: 'labelValue1', - key2: 'labelValue2', + key1: 'attributeValue1', + key2: 'attributeValue2', }, ]); assert.deepStrictEqual(value[0], 'value: 10'); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/Controller.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/Controller.test.ts index ec7c872648..c753db6a48 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/Controller.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/Controller.test.ts @@ -16,7 +16,7 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { MeterProvider, MetricExporter, MetricRecord } from '../../src'; +import { CounterMetric, MeterProvider, MetricExporter, MetricRecord } from '../../src'; import { ExportResult, ExportResultCode, @@ -50,10 +50,10 @@ describe('Controller', () => { error: expectedError, }), }).getMeter('test-console-metric-exporter'); - const counter = meter + const counter = (meter .createCounter('counter', { description: 'a test description', - }) + }) as CounterMetric) .bind({}); counter.add(10); diff --git a/experimental/packages/opentelemetry-sdk-node/package.json b/experimental/packages/opentelemetry-sdk-node/package.json index dddf6d0845..5a6965a3cb 100644 --- a/experimental/packages/opentelemetry-sdk-node/package.json +++ b/experimental/packages/opentelemetry-sdk-node/package.json @@ -42,21 +42,21 @@ "access": "public" }, "dependencies": { - "@opentelemetry/api-metrics": "0.26.0", - "@opentelemetry/core": "1.0.0", - "@opentelemetry/instrumentation": "0.26.0", - "@opentelemetry/resource-detector-aws": "0.24.0", - "@opentelemetry/resource-detector-gcp": "0.24.0", - "@opentelemetry/resources": "1.0.0", - "@opentelemetry/sdk-metrics-base": "0.26.0", - "@opentelemetry/sdk-trace-base": "1.0.0", - "@opentelemetry/sdk-trace-node": "1.0.0" + "@opentelemetry/api-metrics": "~0.26.0", + "@opentelemetry/core": "~1.0.0", + "@opentelemetry/instrumentation": "~0.26.0", + "@opentelemetry/resource-detector-aws": "~1.0.0", + "@opentelemetry/resource-detector-gcp": "~0.26.0", + "@opentelemetry/resources": "~1.0.0", + "@opentelemetry/sdk-metrics-base": "~0.26.0", + "@opentelemetry/sdk-trace-base": "~1.0.0", + "@opentelemetry/sdk-trace-node": "~1.0.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@opentelemetry/context-async-hooks": "1.0.0", "@types/mocha": "8.2.3", "@types/node": "14.17.11", @@ -69,7 +69,7 @@ "nock": "12.0.3", "nyc": "15.1.0", "semver": "7.3.5", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5" diff --git a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts index 5b593cba4c..7bfc913ce1 100644 --- a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts +++ b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts @@ -131,7 +131,7 @@ describe('Node SDK', () => { assert.ok(metrics.getMeterProvider() instanceof NoopMeterProvider); assert.ok( - context['_getContextManager']() instanceof DefaultContextManager + context['_getContextManager']().constructor.name === DefaultContextManager.name ); assert.ok( propagation['_getGlobalPropagator']() instanceof CompositePropagator @@ -154,7 +154,7 @@ describe('Node SDK', () => { assert.ok(metrics.getMeterProvider() instanceof NoopMeterProvider); assert.ok( - context['_getContextManager']() instanceof DefaultContextManager + context['_getContextManager']().constructor.name === DefaultContextManager.name ); assert.ok( propagation['_getGlobalPropagator']() instanceof CompositePropagator diff --git a/experimental/tsconfig.esm.json b/experimental/tsconfig.esm.json index a233a3b76d..d2bedd4f38 100644 --- a/experimental/tsconfig.esm.json +++ b/experimental/tsconfig.esm.json @@ -6,13 +6,13 @@ "path": "packages/opentelemetry-api-metrics/tsconfig.esm.json" }, { - "path": "packages/opentelemetry-exporter-otlp-grpc" + "path": "packages/opentelemetry-exporter-trace-otlp-grpc" }, { - "path": "packages/opentelemetry-exporter-otlp-http/tsconfig.esm.json" + "path": "packages/opentelemetry-exporter-trace-otlp-http/tsconfig.esm.json" }, { - "path": "packages/opentelemetry-exporter-otlp-proto" + "path": "packages/opentelemetry-exporter-trace-otlp-proto" }, { "path": "packages/opentelemetry-exporter-prometheus" diff --git a/experimental/tsconfig.json b/experimental/tsconfig.json index 3ae14512e2..5a53c080f2 100644 --- a/experimental/tsconfig.json +++ b/experimental/tsconfig.json @@ -6,13 +6,13 @@ "path": "packages/opentelemetry-api-metrics" }, { - "path": "packages/opentelemetry-exporter-otlp-grpc" + "path": "packages/opentelemetry-exporter-trace-otlp-grpc" }, { - "path": "packages/opentelemetry-exporter-otlp-http" + "path": "packages/opentelemetry-exporter-trace-otlp-http" }, { - "path": "packages/opentelemetry-exporter-otlp-proto" + "path": "packages/opentelemetry-exporter-trace-otlp-proto" }, { "path": "packages/opentelemetry-exporter-prometheus" @@ -32,6 +32,15 @@ { "path": "packages/opentelemetry-instrumentation" }, + { + "path": "packages/opentelemetry-exporter-metrics-otlp-http" + }, + { + "path": "packages/opentelemetry-exporter-metrics-otlp-grpc" + }, + { + "path": "packages/opentelemetry-exporter-metrics-otlp-proto" + }, { "path": "packages/opentelemetry-sdk-metrics-base" }, diff --git a/getting-started/.eslintrc.js b/getting-started/.eslintrc.js deleted file mode 100644 index 8580fbfb04..0000000000 --- a/getting-started/.eslintrc.js +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-disable global-require */ -/* eslint-disable strict */ - -module.exports = { - ...require('../examples/.eslintrc.json'), -}; diff --git a/getting-started/README.md b/getting-started/README.md deleted file mode 100644 index 132bd340ae..0000000000 --- a/getting-started/README.md +++ /dev/null @@ -1,398 +0,0 @@ -# Getting started with OpenTelemetry JS - -This guide walks you through the setup and configuration process for a tracing backend (in this case [Zipkin](https://zipkin.io), but [Jaeger](https://www.jaegertracing.io) is simple to use as well), a metrics backend like [Prometheus](https://prometheus.io), and auto-instrumentation of NodeJS. [You can find the guide for TypeScript here](ts-example/README.md#getting-started-with-opentelemetry-js-typescript). - -- [Getting started with OpenTelemetry JS](#getting-started-with-opentelemetry-js) - - [Trace your application with OpenTelemetry](#trace-your-application-with-opentelemetry) - - [Set up a tracing backend](#set-up-a-tracing-backend) - - [Trace your NodeJS application](#trace-your-nodejs-application) - - [Install the required OpenTelemetry libraries](#install-the-required-opentelemetry-libraries) - - [Initialize a global tracer](#initialize-a-global-tracer) - - [Initialize and register a trace exporter](#initialize-and-register-a-trace-exporter) - - [Collect metrics using OpenTelemetry](#collect-metrics-using-opentelemetry) - - [Set up a metrics backend](#set-up-a-metrics-backend) - - [Monitor your NodeJS application](#monitor-your-nodejs-application) - - [Install the required OpenTelemetry metrics libraries](#install-the-required-opentelemetry-metrics-libraries) - - [Initialize a meter and collect metrics](#initialize-a-meter-and-collect-metrics) - - [Initialize and register a metrics exporter](#initialize-and-register-a-metrics-exporter) - -## Trace your application with OpenTelemetry - -([link to TypeScript version](ts-example/README.md#trace-your-application-with-opentelemetry)) - -This guide assumes you're using Zipkin as your tracing backend, but modifying it for Jaeger should be straightforward. - -You can find an example application to use with this guide in the [example directory](example). See what it looks like with tracing enabled in the [traced-example directory](traced-example). - -### Set up a tracing backend - -([link to TypeScript version](ts-example/README.md#set-up-a-tracing-backend)) - -The first thing you need before you can start collecting traces is a tracing backend like Zipkin that you can export traces to. If you already have a supported tracing backend (Zipkin or Jaeger), you can skip this step. If not, you need to run one. - -To set up Zipkin as quickly as possible, run the latest [Docker Zipkin](https://github.com/openzipkin/docker-zipkin) container, exposing port `9411`. If you can’t run Docker containers, you need to download and run Zipkin by following the Zipkin [quickstart guide](https://zipkin.io/pages/quickstart.html). - -```sh -docker run --rm -d -p 9411:9411 --name zipkin openzipkin/zipkin -``` - -Browse to to make sure you can see the Zipkin UI. - -

      - -### Trace your NodeJS application - -([link to TypeScript version](ts-example/README.md#trace-your-nodejs-application)) - -This guide uses the example application provided in the [example directory](example), but the steps to instrument your own application should be broadly the same. Here's an overview of what you'll be doing: - -1. Install the required OpenTelemetry libraries -2. Initialize a global tracer -3. Initialize and register a trace exporter - -#### Install the required OpenTelemetry libraries - -([link to TypeScript version](ts-example/README.md#install-the-required-opentelemetry-libraries)) - -To create traces on NodeJS, you need `@opentelemetry/sdk-trace-node`, `@opentelemetry/core`, and any instrumentation required by your application such as gRPC or HTTP. If you're using the example application, you need to install `@opentelemetry/instrumentation-http` and `@opentelemetry/instrumentation-express`. - -```sh -$ npm install \ - @opentelemetry/api \ - @opentelemetry/sdk-trace-node \ - @opentelemetry/instrumentation-http \ - @opentelemetry/instrumentation-express \ - @opentelemetry/instrumentation-grpc -``` - -#### Initialize a global tracer - -([link to TypeScript version](ts-example/README.md#initialize-a-global-tracer)) - -All tracing initialization should happen before your application code runs. The easiest way to do this is to initialize tracing in a separate file that is required using the `node` `-r` option before your application code runs. - -Create a file named `tracing.js` and add the following code: - -```javascript -'use strict'; - -const { diag, DiagConsoleLogger, DiagLogLevel } = require("@opentelemetry/api"); -const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node"); -const { registerInstrumentations } = require("@opentelemetry/instrumentation"); -const { HttpInstrumentation } = require("@opentelemetry/instrumentation-http"); -const { GrpcInstrumentation } = require("@opentelemetry/instrumentation-grpc"); - -const provider = new NodeTracerProvider(); - -diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ALL); - -provider.register(); - -registerInstrumentations({ - instrumentations: [ - new HttpInstrumentation(), - new GrpcInstrumentation(), - ], -}); - -``` - -Now, if you run your application with `node -r ./tracing.js app.js`, your application will create and propagate traces over HTTP. If an already instrumented service that supports [Trace Context](https://www.w3.org/TR/trace-context/) headers calls your application using HTTP, and you call another application using HTTP, the Trace Context headers will be correctly propagated. - -However, if you want to see a completed trace, you need to register an exporter to send traces to a tracing backend. - -#### Initialize and register a trace exporter - -([link to TypeScript version](ts-example/README.md#initialize-and-register-a-trace-exporter)) - -This guide uses the Zipkin tracing backend. However, if you're using another backend like [Jaeger](https://www.jaegertracing.io), make your change there. - -To export traces, you need a few more dependencies. Install them with the following command: - -```sh -$ npm install \ - @opentelemetry/sdk-trace-base \ - @opentelemetry/exporter-zipkin - -$ # for jaeger you would run this command: -$ # npm install @opentelemetry/exporter-jaeger -``` - -After you install these dependencies, initialize and register them. Modify `tracing.js` so it matches the following code snippet. Optionally replace the service name `"getting-started"` with your own service name: - -```javascript -'use strict'; - -const { diag, DiagConsoleLogger, DiagLogLevel } = require("@opentelemetry/api"); -const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node"); -const { Resource } = require('@opentelemetry/resources'); -const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions'); -const { SimpleSpanProcessor } = require("@opentelemetry/sdk-trace-base"); -const { ZipkinExporter } = require("@opentelemetry/exporter-zipkin"); -const { registerInstrumentations } = require("@opentelemetry/instrumentation"); -const { HttpInstrumentation } = require("@opentelemetry/instrumentation-http"); -const { GrpcInstrumentation } = require("@opentelemetry/instrumentation-grpc"); - -const provider = new NodeTracerProvider({ - resource: new Resource({ - [SemanticResourceAttributes.SERVICE_NAME]: "getting-started", - }) -}); - -diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ALL); - -provider.addSpanProcessor( - new SimpleSpanProcessor( - new ZipkinExporter({ - // If you are running your tracing backend on another host, - // you can point to it using the `url` parameter of the - // exporter config. - }) - ) -); - -provider.register(); - -registerInstrumentations({ - instrumentations: [ - new HttpInstrumentation(), - new GrpcInstrumentation(), - ], -}); - -console.log("tracing initialized"); -``` - -Now if you run your application with the `tracing.js` file loaded, and you send requests to your application over HTTP (in the sample application just browse to ), you'll see traces exported to your tracing backend that look like this: - -```sh -node -r ./tracing.js app.js -``` - -

      - -**Note:** Some spans appear to be duplicated, but they're not. This is because the sample application is both the client and the server for these requests. You see one span which is the client-side request timing, and one span which is the server side request timing. Anywhere they don’t overlap is network time. - -## Collect metrics using OpenTelemetry - -([link to TypeScript version](ts-example/README.md#collect-metrics-using-opentelemetry)) - -This guide assumes you're using Prometheus as your metrics backend. It's currently the only metrics backend supported by OpenTelemetry JS. - -**Note**: This section is a work in progress. - -### Set up a metrics backend - -([link to TypeScript version](ts-example/README.md#set-up-a-metrics-backend)) - -Now that you have end-to-end traces, you can collect and export some basic metrics. - -Currently, the only supported metrics backend is [Prometheus](https://prometheus.io). Go to the [Prometheus download page](https://prometheus.io/download/) and download the latest release of Prometheus for your operating system. - -Open a command line and `cd` into the directory where you downloaded the Prometheus tarball. Untar it into the newly created directory. - -```sh -$ cd Downloads - -$ # Replace the file name below with your downloaded tarball -$ tar xvfz prometheus-2.20.1.darwin-amd64.tar - -$ # Replace the dir below with your created directory -$ cd prometheus-2.20.1.darwin-amd64 - -$ ls -LICENSE console_libraries data prometheus.yml tsdb -NOTICE consoles prometheus promtool -``` - -The created directory should have a file named `prometheus.yml`. This is the file used to configure Prometheus. For now, just make sure Prometheus starts by running the `./prometheus` binary in the folder and browse to . - -```sh -$ ./prometheus -# some output elided for brevity -msg="Starting Prometheus" version="(version=2.14.0, branch=HEAD, revision=edeb7a44cbf745f1d8be4ea6f215e79e651bfe19)" -# some output elided for brevity -level=info ts=2019-11-21T20:39:40.262Z caller=web.go:496 component=web msg="Start listening for connections" address=0.0.0.0:9090 -# some output elided for brevity -level=info ts=2019-11-21T20:39:40.383Z caller=main.go:626 msg="Server is ready to receive web requests." -``` - -

      - -Once you confirm that Prometheus starts, replace the contents of `prometheus.yml` with the following: - -```yaml -# my global config -global: - scrape_interval: 15s # Set the scrape interval to every 15 seconds. - -scrape_configs: - - job_name: 'opentelemetry' - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - static_configs: - - targets: ['localhost:9464'] -``` - -### Monitor your NodeJS application - -([link to TypeScript version](ts-example/README.md#monitor-your-nodejs-application)) - -You can find an example application to use with this guide in the [example directory](example). See what it looks like with metric monitoring enabled in the [monitored-example directory](monitored-example). - -Here's an overview of what you'll be doing: - -1. Install the required OpenTelemetry metrics libraries -2. Initialize a meter and collect metrics -3. Initialize and register a metrics exporter - -#### Install the required OpenTelemetry metrics libraries - -([link to TypeScript version](ts-example/README.md#install-the-required-opentelemetry-sdk-metrics-base-libraries)) - -To create metrics on NodeJS, you need `@opentelemetry/sdk-metrics-base`. - -```sh -$ npm install \ - @opentelemetry/sdk-metrics-base -``` - -#### Initialize a meter and collect metrics - -([link to TypeScript version](ts-example/README.md#initialize-a-meter-and-collect-metrics)) - -You need a `Meter` to create and monitor metrics. A `Meter` in OpenTelemetry is the mechanism used to create and manage metrics, labels, and metric exporters. - -Create a file named `monitoring.js` and add the following code: - -```javascript -'use strict'; - -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); - -const meter = new MeterProvider().getMeter('your-meter-name'); -``` - -Now you can require this file from your application code and use the `Meter` to create and manage metrics. The simplest of these metrics is a counter. Create and export from your `monitoring.js` file a middleware function that express can use to count all requests by route. Modify the `monitoring.js` file so it looks like this: - -```javascript -'use strict'; - -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); - -const meter = new MeterProvider().getMeter('your-meter-name'); - -const requestCount = meter.createCounter("requests", { - description: "Count all incoming requests" -}); - -const boundInstruments = new Map(); - -module.exports.countAllRequests = () => { - return (req, res, next) => { - if (!boundInstruments.has(req.path)) { - const labels = { route: req.path }; - const boundCounter = requestCount.bind(labels); - boundInstruments.set(req.path, boundCounter); - } - - boundInstruments.get(req.path).add(1); - next(); - }; -}; -``` - -Now import and use this middleware in your application code: - -```javascript -const { countAllRequests } = require("./monitoring"); -const app = express(); -app.use(countAllRequests()); -``` - -Now when you make requests to your service, your meter will count all requests. - -**Note**: Creating a new `labelSet` and `binding` on every request is not ideal because creating the `labelSet` can often be an expensive operation. Therefore, the instruments are created and stored in a `Map` according to the route key. - -#### Initialize and register a metrics exporter - -([link to TypeScript version](ts-example/README.md#initialize-and-register-a-metrics-exporter)) - -Counting metrics is only useful if you can export them somewhere where you can see them. For this, w'ere going to use Prometheus. Creating and registering a metrics exporter is much like the tracing exporter above. First you need to install the Prometheus exporter by running the following command: - -```sh -npm install @opentelemetry/exporter-prometheus -``` - -Next, modify your `monitoring.js` file to look like this: - -```javascript -"use strict"; - -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); -const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); - -const prometheusPort = PrometheusExporter.DEFAULT_OPTIONS.port -const prometheusEndpoint = PrometheusExporter.DEFAULT_OPTIONS.endpoint - -const exporter = new PrometheusExporter( - { - startServer: true, - }, - () => { - console.log( - `prometheus scrape endpoint: http://localhost:${prometheusPort}${prometheusEndpoint}`, - ); - }, -); - -const meter = new MeterProvider({ - exporter, - interval: 1000, -}).getMeter('your-meter-name'); - -const requestCount = meter.createCounter("requests", { - description: "Count all incoming requests" -}); - -const boundInstruments = new Map(); - -module.exports.countAllRequests = () => { - return (req, res, next) => { - if (!boundInstruments.has(req.path)) { - const labels = { route: req.path }; - const boundCounter = requestCount.bind(labels); - boundInstruments.set(req.path, boundCounter); - } - - boundInstruments.get(req.path).add(1); - next(); - }; -}; -``` - -Ensure Prometheus is running by running the `prometheus` binary from earlier and start your application. - -```sh -$ npm start - -> @opentelemetry/getting-started@1.0.0 start /App/opentelemetry-js/getting-started/monitored-example -> node app.js - -prometheus scrape endpoint: http://localhost:9464/metrics -Listening for requests on http://localhost:8080 -``` - -Now each time you browse to you should see "Hello from the backend" in your browser and your metrics in Prometheus should update. You can verify the current metrics by browsing to , which should look like this: - -```sh -# HELP requests Count all incoming requests -# TYPE requests counter -requests{route="/"} 1 -requests{route="/middle-tier"} 2 -requests{route="/backend"} 4 -``` - -You should also be able to see gathered metrics in your Prometheus web UI. - -

      diff --git a/getting-started/example/app.js b/getting-started/example/app.js deleted file mode 100644 index 287ab78cb3..0000000000 --- a/getting-started/example/app.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -const PORT = process.env.PORT || '8080'; - -const express = require('express'); -const axios = require('axios'); - -const app = express(); - -app.get('/', (req, res) => { - axios - .get(`http://localhost:${PORT}/middle-tier`) - .then(() => axios.get(`http://localhost:${PORT}/middle-tier`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/middle-tier', (req, res) => { - axios - .get(`http://localhost:${PORT}/backend`) - .then(() => axios.get(`http://localhost:${PORT}/backend`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/backend', (req, res) => { - res.send('Hello from the backend'); -}); - -app.listen(parseInt(PORT, 10), () => { - console.log(`Listening for requests on http://localhost:${PORT}`); -}); diff --git a/getting-started/example/package.json b/getting-started/example/package.json deleted file mode 100644 index 4c4e289434..0000000000 --- a/getting-started/example/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "@opentelemetry/getting-started-example", - "version": "0.25.0", - "description": "This repository provides everything required to follow the OpenTelemetry Getting Started Guide", - "main": "app.js", - "scripts": { - "start": "node app.js" - }, - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "dependencies": { - "axios": "^0.21.0", - "express": "^4.17.1" - } -} diff --git a/getting-started/images/prometheus-graph.png b/getting-started/images/prometheus-graph.png deleted file mode 100644 index c4e174ffd3..0000000000 Binary files a/getting-started/images/prometheus-graph.png and /dev/null differ diff --git a/getting-started/images/prometheus.png b/getting-started/images/prometheus.png deleted file mode 100644 index ef94a1faf0..0000000000 Binary files a/getting-started/images/prometheus.png and /dev/null differ diff --git a/getting-started/images/zipkin-trace.png b/getting-started/images/zipkin-trace.png deleted file mode 100644 index c00c86865d..0000000000 Binary files a/getting-started/images/zipkin-trace.png and /dev/null differ diff --git a/getting-started/images/zipkin.png b/getting-started/images/zipkin.png deleted file mode 100644 index 77e23745b4..0000000000 Binary files a/getting-started/images/zipkin.png and /dev/null differ diff --git a/getting-started/monitored-example/app.js b/getting-started/monitored-example/app.js deleted file mode 100644 index af61cef67e..0000000000 --- a/getting-started/monitored-example/app.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -const PORT = process.env.PORT || '8080'; - -const express = require('express'); -const axios = require('axios'); - -const { countAllRequests } = require('./monitoring'); - -const app = express(); -app.use(countAllRequests()); - -app.get('/', (req, res) => { - axios - .get(`http://localhost:${PORT}/middle-tier`) - .then(() => axios.get(`http://localhost:${PORT}/middle-tier`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/middle-tier', (req, res) => { - axios - .get(`http://localhost:${PORT}/backend`) - .then(() => axios.get(`http://localhost:${PORT}/backend`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/backend', (req, res) => { - res.send('Hello from the backend'); -}); - -app.listen(parseInt(PORT, 10), () => { - console.log(`Listening for requests on http://localhost:${PORT}`); -}); diff --git a/getting-started/monitored-example/monitoring.js b/getting-started/monitored-example/monitoring.js deleted file mode 100644 index ca20e8d2fd..0000000000 --- a/getting-started/monitored-example/monitoring.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -const { MeterProvider } = require('@opentelemetry/sdk-metrics-base'); -const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); - -const prometheusPort = PrometheusExporter.DEFAULT_OPTIONS.port; -const prometheusEndpoint = PrometheusExporter.DEFAULT_OPTIONS.endpoint; - -const exporter = new PrometheusExporter( - { - startServer: true, - }, - () => { - console.log( - `prometheus scrape endpoint: http://localhost:${prometheusPort}${prometheusEndpoint}`, - ); - }, -); - -const meter = new MeterProvider({ - exporter, - interval: 1000, -}).getMeter('your-meter-name'); - -const requestCount = meter.createCounter('requests', { - description: 'Count all incoming requests', -}); - -const boundInstruments = new Map(); - -module.exports.countAllRequests = () => (req, res, next) => { - if (!boundInstruments.has(req.path)) { - const labels = { route: req.path }; - const boundCounter = requestCount.bind(labels); - boundInstruments.set(req.path, boundCounter); - } - - boundInstruments.get(req.path).add(1); - next(); -}; diff --git a/getting-started/monitored-example/package.json b/getting-started/monitored-example/package.json deleted file mode 100644 index a8b6c3a66c..0000000000 --- a/getting-started/monitored-example/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@opentelemetry/getting-started-monitored-example", - "version": "0.25.0", - "description": "This repository provides everything required to follow the OpenTelemetry Getting Started Guide", - "main": "app.js", - "scripts": { - "start": "node app.js" - }, - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/exporter-prometheus": "0.25.0", - "@opentelemetry/sdk-metrics-base": "0.25.0", - "axios": "^0.21.0", - "express": "^4.17.1" - } -} diff --git a/getting-started/traced-example/app.js b/getting-started/traced-example/app.js deleted file mode 100644 index 287ab78cb3..0000000000 --- a/getting-started/traced-example/app.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -const PORT = process.env.PORT || '8080'; - -const express = require('express'); -const axios = require('axios'); - -const app = express(); - -app.get('/', (req, res) => { - axios - .get(`http://localhost:${PORT}/middle-tier`) - .then(() => axios.get(`http://localhost:${PORT}/middle-tier`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/middle-tier', (req, res) => { - axios - .get(`http://localhost:${PORT}/backend`) - .then(() => axios.get(`http://localhost:${PORT}/backend`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/backend', (req, res) => { - res.send('Hello from the backend'); -}); - -app.listen(parseInt(PORT, 10), () => { - console.log(`Listening for requests on http://localhost:${PORT}`); -}); diff --git a/getting-started/traced-example/package.json b/getting-started/traced-example/package.json deleted file mode 100644 index 8268cd9ddc..0000000000 --- a/getting-started/traced-example/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@opentelemetry/getting-started-traced-example", - "version": "0.25.0", - "description": "This repository provides everything required to follow the OpenTelemetry Getting Started Guide", - "main": "app.js", - "scripts": { - "start": "node -r ./tracing.js app.js" - }, - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.0.0", - "@opentelemetry/exporter-zipkin": "1.0.0", - "@opentelemetry/instrumentation-express": "^0.24.0", - "@opentelemetry/instrumentation-http": "0.25.0", - "@opentelemetry/instrumentation": "0.25.0", - "@opentelemetry/sdk-trace-node": "1.0.0", - "@opentelemetry/sdk-trace-base": "1.0.0", - "axios": "^0.21.0", - "express": "^4.17.1" - } -} diff --git a/getting-started/traced-example/tracing.js b/getting-started/traced-example/tracing.js deleted file mode 100644 index ae6b88b015..0000000000 --- a/getting-started/traced-example/tracing.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node'); -const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base'); -const { Resource } = require('@opentelemetry/resources'); -const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions'); -const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin'); -const { registerInstrumentations } = require('@opentelemetry/instrumentation'); -const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express'); -const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http'); - -const provider = new NodeTracerProvider({ - resource: new Resource({ - [SemanticResourceAttributes.SERVICE_NAME]: 'getting-started', - }), -}); - -provider.addSpanProcessor( - new SimpleSpanProcessor( - new ZipkinExporter({ - // If you are running your tracing backend on another host, - // you can point to it using the `url` parameter of the - // exporter config. - }), - ), -); - -provider.register(); - -// load old default plugins -registerInstrumentations({ - instrumentations: [ - new ExpressInstrumentation(), - new HttpInstrumentation(), - ], -}); - -console.log('tracing initialized'); diff --git a/getting-started/ts-example/.eslintrc b/getting-started/ts-example/.eslintrc deleted file mode 100644 index 6564779085..0000000000 --- a/getting-started/ts-example/.eslintrc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "plugins": ["@typescript-eslint", "node"], - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - "parser": "@typescript-eslint/parser", - "rules": { - "@typescript-eslint/no-var-requires": 0, - "import/prefer-default-export": "off", - "import/extensions": [ - "error", - "ignorePackages", - { - "": "never" - } - ] - } -} diff --git a/getting-started/ts-example/README.md b/getting-started/ts-example/README.md deleted file mode 100644 index a1ccd6a1cb..0000000000 --- a/getting-started/ts-example/README.md +++ /dev/null @@ -1,389 +0,0 @@ -# Getting Started with OpenTelemetry JS (TypeScript) - -This TypeScript guide will walk you through the setup and configuration process for a tracing backend (in this case [Zipkin](https://zipkin.io), but [Jaeger](https://www.jaegertracing.io) would be simple to use as well), a metrics backend like [Prometheus](https://prometheus.io), and auto-instrumentation of NodeJS. [You can find the guide for JavaScript here](../README.md#getting-started-with-opentelemetry-js). - -- [Getting Started with OpenTelemetry JS (TypeScript)](#getting-started-with-opentelemetry-js-typescript) - - [Tracing Your Application with OpenTelemetry](#tracing-your-application-with-opentelemetry) - - [Setting up a Tracing Backend](#setting-up-a-tracing-backend) - - [Trace Your NodeJS Application](#trace-your-nodejs-application) - - [Install the required OpenTelemetry libraries](#install-the-required-opentelemetry-libraries) - - [Initialize a global tracer](#initialize-a-global-tracer) - - [Initialize and Register a Trace Exporter](#initialize-and-register-a-trace-exporter) - - [Collect Metrics Using OpenTelemetry](#collect-metrics-using-opentelemetry) - - [Set up a Metrics Backend](#set-up-a-metrics-backend) - - [Monitor Your NodeJS Application](#monitor-your-nodejs-application) - - [Install the required OpenTelemetry metrics libraries](#install-the-required-opentelemetry-sdk-metrics-base-libraries) - - [Initialize a meter and collect metrics](#initialize-a-meter-and-collect-metrics) - - [Initialize and register a metrics exporter](#initialize-and-register-a-metrics-exporter) - -## Tracing Your Application with OpenTelemetry - -([link to JavaScript version](../README.md#tracing-your-application-with-opentelemetry)) - -This guide assumes you are going to be using Zipkin as your tracing backend, but modifying it for Jaeger should be straightforward. - -An example application which can be used with this guide can be found in the [example directory](example). You can see what it looks like with tracing enabled in the [traced-example directory](traced-example). - -### Setting up a Tracing Backend - -([link to JavaScript version](../README.md#setting-up-a-tracing-backend)) - -The first thing we will need before we can start collecting traces is a tracing backend like Zipkin that we can export traces to. If you already have a supported tracing backend (Zipkin or Jaeger), you can skip this step. If not, you will need to run one. - -In order to set up Zipkin as quickly as possible, run the latest [Docker Zipkin](https://github.com/openzipkin/docker-zipkin) container, exposing port `9411`. If you can’t run Docker containers, you will need to download and run Zipkin by following the Zipkin [quickstart guide](https://zipkin.io/pages/quickstart.html). - -```sh -docker run --rm -d -p 9411:9411 --name zipkin openzipkin/zipkin -``` - -Browse to to ensure that you can see the Zipkin UI. - -

      - -### Trace Your NodeJS Application - -([link to JavaScript version](../README.md#trace-your-nodejs-application)) - -This guide uses the example application provided in the [example directory](example) but the steps to instrument your own application should be broadly the same. Here is an overview of what we will be doing. - -1. Install the required OpenTelemetry libraries -2. Initialize a global tracer -3. Initialize and register a trace exporter - -#### Install the required OpenTelemetry libraries - -([link to JavaScript version](../README.md#install-the-required-opentelemetry-libraries)) - -To create traces on NodeJS, you will need `@opentelemetry/sdk-trace-node`, `@opentelemetry/api`, and any plugins required by your application such as gRPC, or HTTP. If you are using the example application, you will need to install `@opentelemetry/instrumentation-http` and `@opentelemetry/instrumentation-express`. - -```sh -$ npm install \ - @opentelemetry/api \ - @opentelemetry/sdk-trace-node \ - @opentelemetry/instrumentation \ - @opentelemetry/instrumentation-http \ - @opentelemetry/instrumentation-express \ - @@opentelemetry/resources \ - @opentelemetry/semantic-conventions -``` - -#### Initialize a global tracer - -([link to JavaScript version](../README.md#initialize-a-global-tracer)) - -All tracing initialization should happen before your application’s code runs. The easiest way to do this is to initialize tracing in a separate file that is required using node’s `-r` option before application code runs. - -Create a file named `tracing.ts` and add the following code: - -```typescript -import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api'; -import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; -import { registerInstrumentations } from '@opentelemetry/instrumentation'; -import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; -import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; - - -const provider: NodeTracerProvider = new NodeTracerProvider(); - -diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ALL); - -provider.register(); - -registerInstrumentations({ - instrumentations: [ - new ExpressInstrumentation(), - new HttpInstrumentation(), - ], -}); - -``` - -If you run your application now with `ts-node -r ./tracing.ts app.ts`, your application will create and propagate traces over HTTP. If an already instrumented service that supports [Trace Context](https://www.w3.org/TR/trace-context/) headers calls your application using HTTP, and you call another application using HTTP, the Trace Context headers will be correctly propagated. - -If you wish to see a completed trace, however, there is one more step. You must register an exporter to send traces to a tracing backend. - -#### Initialize and Register a Trace Exporter - -([link to JavaScript version](../README.md#initialize-and-register-a-trace-exporter)) - -This guide uses the Zipkin tracing backend, but if you are using another backend like [Jaeger](https://www.jaegertracing.io), this is where you would make your change. - -To export traces, we will need a few more dependencies. Install them with the following command: - -```sh -$ npm install \ - @opentelemetry/sdk-trace-base \ - @opentelemetry/exporter-zipkin - -$ # for jaeger you would run this command: -$ # npm install @opentelemetry/exporter-jaeger -``` - -After these dependencies are installed, we will need to initialize and register them. Modify `tracing.ts` so that it matches the following code snippet, replacing the service name `"getting-started"` with your own service name if you wish. - -```typescript -import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api'; -import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; -import { registerInstrumentations } from '@opentelemetry/instrumentation'; -import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; -import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; -import { Resource } from '@opentelemetry/resources' -import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' -import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; -import { ZipkinExporter } from '@opentelemetry/exporter-zipkin'; -// For Jaeger, use the following line instead: -// import { JaegerExporter } from '@opentelemetry/exporter-jaeger'; - -const provider: NodeTracerProvider = new NodeTracerProvider({ - resource: new Resource({ - [SemanticResourceAttributes.SERVICE_NAME]: 'getting-started', - }), -}); - -diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ALL); - -provider.addSpanProcessor( - new SimpleSpanProcessor( - new ZipkinExporter({ - // For Jaeger, use the following line instead: - // new JaegerExporter({ - // If you are running your tracing backend on another host, - // you can point to it using the `url` parameter of the - // exporter config. - }), - ), -); -provider.register(); - -registerInstrumentations({ - instrumentations: [ - new ExpressInstrumentation(), - new HttpInstrumentation(), - ], -}); - -console.log('tracing initialized'); -``` - -Now if you run your application with the `tracing.ts` file loaded, and you send requests to your application over HTTP (in the sample application just browse to you will see traces exported to your tracing backend that look like this: - -```sh -ts-node -r ./tracing.ts app.ts -``` - -

      - -**Note:** Some spans appear to be duplicated, but they are not. This is because the sample application is both the client and the server for these requests. You see one span that is the client side request timing, and one span that is the server side request timing. Anywhere they don’t overlap is network time. - -## Collect Metrics Using OpenTelemetry - -([link to JavaScript version](../README.md#collect-metrics-using-opentelemetry)) - -This guide assumes you are going to be using Prometheus as your metrics backend. It is currently the only metrics backend supported by OpenTelemetry JS. - -**Note**: This section is a work in progress - -### Set up a Metrics Backend - -([link to JavaScript version](../README.md#set-up-a-metrics-backend)) - -Now that we have end-to-end traces, we will collect and export some basic metrics. - -Currently, the only supported metrics backend is [Prometheus](https://prometheus.io). Head to the [Prometheus download page](https://prometheus.io/download/) and download the latest release of Prometheus for your operating system. - -Open a command line and `cd` into the directory where you downloaded the Prometheus tarball. Untar it and change into the newly created directory. - -```sh -$ cd Downloads - -$ # Replace the file name below with your downloaded tarball -$ tar xvfz prometheus-2.20.1.darwin-amd64.tar - -$ # Replace the dir below with your created directory -$ cd prometheus-2.20.1.darwin-amd64 - -$ ls -LICENSE console_libraries data prometheus.yml tsdb -NOTICE consoles prometheus promtool -``` - -The created directory should have a file named `prometheus.yml`. This is the file used to configure Prometheus. For now, just make sure Prometheus starts by running the `./prometheus` binary in the folder and browse to . - -```sh -$ ./prometheus -# some output elided for brevity -msg="Starting Prometheus" version="(version=2.14.0, branch=HEAD, revision=edeb7a44cbf745f1d8be4ea6f215e79e651bfe19)" -# some output elided for brevity -level=info ts=2019-11-21T20:39:40.262Z caller=web.go:496 component=web msg="Start listening for connections" address=0.0.0.0:9090 -# some output elided for brevity -level=info ts=2019-11-21T20:39:40.383Z caller=main.go:626 msg="Server is ready to receive web requests." -``` - -

      - -Once we know prometheus starts, replace the contents of `prometheus.yml` with the following: - -```yaml -# my global config -global: - scrape_interval: 15s # Set the scrape interval to every 15 seconds. - -scrape_configs: - - job_name: 'opentelemetry' - # metrics_path defaults to '/metrics' - # scheme defaults to 'http'. - static_configs: - - targets: ['localhost:9464'] -``` - -### Monitor Your NodeJS Application - -([link to JavaScript version](../README.md#monitor-your-nodejs-application)) - -An example application which can be used with this guide can be found at in the [example directory](example). You can see what it looks like with metric monitoring enabled in the [monitored-example directory](monitored-example). - -1. Install the required OpenTelemetry metrics libraries -2. Initialize a meter and collect metrics -3. Initialize and register a metrics exporter - -#### Install the required OpenTelemetry metrics libraries - -([link to JavaScript version](../README.md#install-the-required-opentelemetry-sdk-metrics-base-libraries)) - -To create metrics on NodeJS, you will need `@opentelemetry/sdk-metrics-base`. - -```sh -npm install @opentelemetry/sdk-metrics-base -``` - -#### Initialize a meter and collect metrics - -([link to JavaScript version](../README.md#initialize-a-meter-and-collect-metrics)) - -In order to create and monitor metrics, we will need a `Meter`. In OpenTelemetry, a `Meter` is the mechanism used to create and manage metrics, labels, and metric exporters. - -Create a file named `monitoring.ts` and add the following code: - -```typescript -import { MeterProvider } from '@opentelemetry/sdk-metrics-base'; - -const meter = new MeterProvider().getMeter('your-meter-name'); -``` - -Now, you can require this file from your application code and use the `Meter` to create and manage metrics. The simplest of these metrics is a counter. Let's create and export from our `monitoring.ts` file a middleware function that express can use to count all requests by route. Modify the `monitoring.ts` file so that it looks like this: - -```typescript -import { MeterProvider } from '@opentelemetry/sdk-metrics-base'; -import { Request, Response, NextFunction } from 'express'; - -const meter = new MeterProvider().getMeter('your-meter-name'); - -const requestCount = meter.createCounter('requests', { - description: 'Count all incoming requests', -}); - -const handles = new Map(); - -export const countAllRequests = () => { - return (req: Request, _res: Response, next: NextFunction) => { - if (!handles.has(req.path)) { - const labels = { route: req.path }; - const handle = requestCount.bind(labels); - handles.set(req.path, handle); - } - - handles.get(req.path).add(1); - next(); - }; -}; -``` - -Now let's import and use this middleware in our application code: - -```typescript -import { countAllRequests } from './monitoring'; -const app = express(); -app.use(countAllRequests()); -``` - -Now, when we make requests to our service our meter will count all requests. - -**Note**: Creating a new `labelSet` and `handle` on every request is not ideal as creating the `labelSet` can often be an expensive operation. This is why handles are created and stored in a `Map` according to the route key. - -#### Initialize and register a metrics exporter - -([link to JavaScript version](../README.md#initialize-and-register-a-metrics-exporter)) - -Counting metrics is only useful if we can export them somewhere that we can see them. For this, we're going to use prometheus. Creating and registering a metrics exporter is much like the tracing exporter above. First we will need to install the prometheus exporter. - -```sh -npm install @opentelemetry/exporter-prometheus -``` - -Next, modify your `monitoring.ts` file to look like this: - -```typescript -import { Request, Response, NextFunction } from 'express'; -import { MeterProvider } from '@opentelemetry/sdk-metrics-base'; -import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'; - -const prometheusPort = PrometheusExporter.DEFAULT_OPTIONS.port; -const prometheusEndpoint = PrometheusExporter.DEFAULT_OPTIONS.endpoint; - -const exporter = new PrometheusExporter( - { - startServer: true, - }, - () => { - console.log( - `prometheus scrape endpoint: http://localhost:${prometheusPort}${prometheusEndpoint}`, - ); - }, -); - -const meter = new MeterProvider({ - exporter, - interval: 1000, -}).getMeter('your-meter-name'); - -const requestCount = meter.createCounter('requests', { - description: 'Count all incoming requests', -}); - -const handles = new Map(); - -export const countAllRequests = () => { - return (req: Request, _res: Response, next: NextFunction) => { - if (!handles.has(req.path)) { - const labels = { route: req.path }; - const handle = requestCount.bind(labels); - handles.set(req.path, handle); - } - - handles.get(req.path).add(1); - next(); - }; -}; -``` - -Ensure prometheus is running by running the `prometheus` binary from earlier and start your application. - -```sh -$ ts-node app.ts -prometheus scrape endpoint: http://localhost:9464/metrics -Listening for requests on http://localhost:8080 -``` - -Now, each time you browse to you should see "Hello from the backend" in your browser and your metrics in prometheus should update. You can verify the current metrics by browsing to , which should look like this: - -```sh -# HELP requests Count all incoming requests -# TYPE requests counter -requests{route="/"} 1 -requests{route="/middle-tier"} 2 -requests{route="/backend"} 4 -``` - -You should also be able to see gathered metrics in your prometheus web UI. - -

      diff --git a/getting-started/ts-example/example/app.ts b/getting-started/ts-example/example/app.ts deleted file mode 100644 index a252668ebe..0000000000 --- a/getting-started/ts-example/example/app.ts +++ /dev/null @@ -1,40 +0,0 @@ -import * as express from 'express'; -import axios from 'axios'; - -const PORT: string = process.env.PORT || '8080'; - -const app = express(); - -app.get('/', (req, res) => { - axios - .get(`http://localhost:${PORT}/middle-tier`) - .then(() => axios.get(`http://localhost:${PORT}/middle-tier`)) - .then((response) => { - res.send(response.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/middle-tier', (req, res) => { - axios - .get(`http://localhost:${PORT}/backend`) - .then(() => axios.get(`http://localhost:${PORT}/backend`)) - .then((response) => { - res.send(response.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/backend', (req, res) => { - res.send('Hello from the backend'); -}); - -app.listen(parseInt(PORT, 10), () => { - console.log(`Listening for requests on http://localhost:${PORT}`); -}); diff --git a/getting-started/ts-example/example/package.json b/getting-started/ts-example/example/package.json deleted file mode 100644 index 08ab0b4634..0000000000 --- a/getting-started/ts-example/example/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@opentelemetry/getting-started-ts-example", - "version": "0.25.0", - "description": "This repository provides everything required to follow the OpenTelemetry Getting Started Guide", - "main": "app.ts", - "scripts": { - "start": "ts-node app.ts" - }, - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "devDependencies": { - "@types/express": "4.17.13", - "@types/node": "14.17.11", - "ts-node": "10.2.1" - }, - "dependencies": { - "axios": "^0.21.0", - "express": "^4.17.1" - } -} diff --git a/getting-started/ts-example/monitored-example/app.ts b/getting-started/ts-example/monitored-example/app.ts deleted file mode 100644 index 9307eba1ac..0000000000 --- a/getting-started/ts-example/monitored-example/app.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as express from 'express'; -import axios from 'axios'; - -import { countAllRequests } from './monitoring'; - -const PORT: string = process.env.PORT || '8080'; -const app = express(); -app.use(countAllRequests()); - -app.get('/', (req, res) => { - axios - .get(`http://localhost:${PORT}/middle-tier`) - .then(() => axios.get(`http://localhost:${PORT}/middle-tier`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/middle-tier', (req, res) => { - axios - .get(`http://localhost:${PORT}/backend`) - .then(() => axios.get(`http://localhost:${PORT}/backend`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/backend', (req, res) => { - res.send('Hello from the backend'); -}); - -app.listen(parseInt(PORT, 10), () => { - console.log(`Listening for requests on http://localhost:${PORT}`); -}); diff --git a/getting-started/ts-example/monitored-example/monitoring.ts b/getting-started/ts-example/monitored-example/monitoring.ts deleted file mode 100644 index 5e933e4a93..0000000000 --- a/getting-started/ts-example/monitored-example/monitoring.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Request, Response, NextFunction } from 'express'; -import { MeterProvider } from '@opentelemetry/sdk-metrics-base'; -import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'; - -const prometheusPort = PrometheusExporter.DEFAULT_OPTIONS.port; -const prometheusEndpoint = PrometheusExporter.DEFAULT_OPTIONS.endpoint; - -const exporter = new PrometheusExporter( - { - startServer: true, - }, - () => { - console.log( - `prometheus scrape endpoint: http://localhost:${prometheusPort}${prometheusEndpoint}`, - ); - }, -); - -const meter = new MeterProvider({ - exporter, - interval: 1000, -}).getMeter('your-meter-name'); - -const requestCount = meter.createCounter('requests', { - description: 'Count all incoming requests', -}); - -const handles = new Map(); - -export const countAllRequests = () => (req: Request, _res: Response, next: NextFunction): void => { - if (!handles.has(req.path)) { - const labels = { route: req.path }; - const handle = requestCount.bind(labels); - handles.set(req.path, handle); - } - - handles.get(req.path).add(1); - next(); -}; diff --git a/getting-started/ts-example/monitored-example/package.json b/getting-started/ts-example/monitored-example/package.json deleted file mode 100644 index 3e4138059e..0000000000 --- a/getting-started/ts-example/monitored-example/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@opentelemetry/getting-started-monitored-ts-example", - "version": "0.25.0", - "description": "This repository provides everything required to follow the OpenTelemetry Getting Started Guide", - "main": "app.ts", - "scripts": { - "start": "ts-node app.ts" - }, - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "devDependencies": { - "@types/express": "4.17.13", - "@types/node": "14.17.11", - "ts-node": "10.2.1" - }, - "dependencies": { - "@opentelemetry/exporter-prometheus": "0.25.0", - "@opentelemetry/sdk-metrics-base": "0.25.0", - "axios": "^0.21.0", - "express": "^4.17.1" - } -} diff --git a/getting-started/ts-example/traced-example/app.ts b/getting-started/ts-example/traced-example/app.ts deleted file mode 100644 index 58fb8ab589..0000000000 --- a/getting-started/ts-example/traced-example/app.ts +++ /dev/null @@ -1,40 +0,0 @@ -import * as express from 'express'; -import axios from 'axios'; - -const PORT: string = process.env.PORT || '8080'; - -const app = express(); - -app.get('/', (req, res) => { - axios - .get(`http://localhost:${PORT}/middle-tier`) - .then(() => axios.get(`http://localhost:${PORT}/middle-tier`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/middle-tier', (req, res) => { - axios - .get(`http://localhost:${PORT}/backend`) - .then(() => axios.get(`http://localhost:${PORT}/backend`)) - .then((result) => { - res.send(result.data); - }) - .catch((err) => { - console.error(err); - res.status(500).send(); - }); -}); - -app.get('/backend', (req, res) => { - res.send('Hello from the backend'); -}); - -app.listen(parseInt(PORT, 10), () => { - console.log(`Listening for requests on http://localhost:${PORT}`); -}); diff --git a/getting-started/ts-example/traced-example/package.json b/getting-started/ts-example/traced-example/package.json deleted file mode 100644 index f157176404..0000000000 --- a/getting-started/ts-example/traced-example/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "@opentelemetry/getting-started-traced-ts-example", - "version": "0.25.0", - "description": "This repository provides everything required to follow the OpenTelemetry Getting Started Guide", - "main": "app.ts", - "scripts": { - "start": "ts-node app.ts" - }, - "author": "OpenTelemetry Authors", - "license": "Apache-2.0", - "devDependencies": { - "@types/express": "4.17.13", - "@types/node": "14.17.11", - "ts-node": "10.2.1" - }, - "dependencies": { - "@opentelemetry/core": "1.0.0", - "@opentelemetry/exporter-zipkin": "1.0.0", - "@opentelemetry/instrumentation": "0.25.0", - "@opentelemetry/instrumentation-express": "^0.24.0", - "@opentelemetry/sdk-trace-node": "1.0.0", - "@opentelemetry/instrumentation-http": "0.25.0", - "@opentelemetry/sdk-trace-base": "1.0.0", - "axios": "^0.21.0", - "express": "^4.17.1" - } -} diff --git a/getting-started/ts-example/traced-example/tracing.ts b/getting-started/ts-example/traced-example/tracing.ts deleted file mode 100644 index 8d4628a06e..0000000000 --- a/getting-started/ts-example/traced-example/tracing.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api'; -import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; -import { registerInstrumentations } from '@opentelemetry/instrumentation'; -import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; -import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; -import { Resource } from '@opentelemetry/resources' -import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' -import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; -import { ZipkinExporter } from '@opentelemetry/exporter-zipkin'; -// For Jaeger, use the following line instead: -// import { JaegerExporter } from '@opentelemetry/exporter-jaeger'; - -const provider: NodeTracerProvider = new NodeTracerProvider({ - resource: new Resource({ - [SemanticResourceAttributes.SERVICE_NAME]: 'getting-started', - }), -}); - -diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ALL); - -provider.addSpanProcessor( - new SimpleSpanProcessor( - new ZipkinExporter({ - // For Jaeger, use the following line instead: - // new JaegerExporter({ - // If you are running your tracing backend on another host, - // you can point to it using the `url` parameter of the - // exporter config. - }), - ), -); -provider.register(); - -registerInstrumentations({ - instrumentations: [ - new ExpressInstrumentation(), - new HttpInstrumentation(), - ], -}); - -console.log('tracing initialized'); \ No newline at end of file diff --git a/integration-tests/propagation-validation-server/package.json b/integration-tests/propagation-validation-server/package.json index 7c11eb10b1..d36492b47f 100644 --- a/integration-tests/propagation-validation-server/package.json +++ b/integration-tests/propagation-validation-server/package.json @@ -11,7 +11,7 @@ "compile": "tsc --build" }, "dependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@opentelemetry/context-async-hooks": "1.0.0", "@opentelemetry/core": "1.0.0", "@opentelemetry/sdk-trace-base": "1.0.0", diff --git a/lerna.json b/lerna.json index b530144ffc..2c0b8bd664 100644 --- a/lerna.json +++ b/lerna.json @@ -5,6 +5,7 @@ "packages": [ "benchmark/*", "packages/*", - "integration-tests/*" + "integration-tests/*", + "selenium-tests" ] } diff --git a/package.json b/package.json index 56a145db98..0e476e5ca6 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,6 @@ "lint:fix:changed": "lerna run --concurrency 1 --stream lint:fix --since HEAD --exclude-dependents", "lint:examples": "eslint --no-error-on-unmatched-pattern ./examples/**/*.js", "lint:examples:fix": "eslint --no-error-on-unmatched-pattern ./examples/**/*.js --fix", - "lint:getting-started": "eslint --no-error-on-unmatched-pattern ./getting-started/**/*.{js,ts}", - "lint:getting-started:fix": "eslint --no-error-on-unmatched-pattern ./getting-started/**/*.{js,ts} --fix", "lint:markdown": "./node_modules/.bin/markdownlint $(git ls-files '*.md') -i ./CHANGELOG.md", "lint:markdown:fix": "./node_modules/.bin/markdownlint $(git ls-files '*.md') -i ./CHANGELOG.md --fix", "reset": "lerna clean -y && rm -rf node_modules && npm i && npm run compile && npm run lint:fix", @@ -50,10 +48,10 @@ "author": "OpenTelemetry Authors", "license": "Apache-2.0", "devDependencies": { - "@commitlint/cli": "13.1.0", - "@commitlint/config-conventional": "13.1.0", - "@typescript-eslint/eslint-plugin": "4.29.3", - "@typescript-eslint/parser": "4.29.3", + "@commitlint/cli": "14.1.0", + "@commitlint/config-conventional": "14.1.0", + "@typescript-eslint/eslint-plugin": "5.0.0", + "@typescript-eslint/parser": "5.0.0", "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", "eslint": "7.32.0", @@ -66,6 +64,7 @@ "lerna": "3.22.1", "lerna-changelog": "1.0.1", "markdownlint-cli": "0.28.1", + "semver": "7.3.5", "typedoc": "0.21.6", "typescript": "4.3.5", "update-ts-references": "2.4.0" diff --git a/packages/opentelemetry-context-async-hooks/package.json b/packages/opentelemetry-context-async-hooks/package.json index 67b4751d95..470e1d209c 100644 --- a/packages/opentelemetry-context-async-hooks/package.json +++ b/packages/opentelemetry-context-async-hooks/package.json @@ -42,7 +42,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "codecov": "3.8.3", @@ -53,6 +53,6 @@ "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" } } diff --git a/packages/opentelemetry-context-zone-peer-dep/package.json b/packages/opentelemetry-context-zone-peer-dep/package.json index 94c21e2a08..df2a0f8cd0 100644 --- a/packages/opentelemetry-context-zone-peer-dep/package.json +++ b/packages/opentelemetry-context-zone-peer-dep/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", @@ -57,7 +57,7 @@ "babel-loader": "8.2.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -66,7 +66,7 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", @@ -75,7 +75,7 @@ "zone.js": "0.11.4" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": ">=1.0.0 <1.1.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 f844a972d5..06e85ed972 100644 --- a/packages/opentelemetry-context-zone/package.json +++ b/packages/opentelemetry-context-zone/package.json @@ -51,7 +51,7 @@ "@types/webpack-env": "1.16.2", "babel-loader": "8.2.2", "codecov": "3.8.3", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-mocha": "2.0.1", "karma-spec-reporter": "0.0.32", @@ -59,7 +59,7 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", diff --git a/packages/opentelemetry-core/package.json b/packages/opentelemetry-core/package.json index 573ea927be..098eeee1a8 100644 --- a/packages/opentelemetry-core/package.json +++ b/packages/opentelemetry-core/package.json @@ -57,14 +57,14 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", "@types/webpack-env": "1.16.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -74,14 +74,14 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", "webpack": "4.46.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "dependencies": { "@opentelemetry/semantic-conventions": "1.0.0" diff --git a/packages/opentelemetry-core/src/common/time.ts b/packages/opentelemetry-core/src/common/time.ts index bb7b2bd3d7..52a3fc0fd1 100644 --- a/packages/opentelemetry-core/src/common/time.ts +++ b/packages/opentelemetry-core/src/common/time.ts @@ -22,7 +22,15 @@ const NANOSECOND_DIGITS = 9; const SECOND_TO_NANOSECONDS = Math.pow(10, NANOSECOND_DIGITS); /** - * Converts a number to HrTime + * Converts a number to HrTime, HrTime = [number, number]. + * The first number is UNIX Epoch time in seconds since 00:00:00 UTC on 1 January 1970. + * The second number represents the partial second elapsed since Unix Epoch time represented by first number in nanoseconds. + * For example, 2021-01-01T12:30:10.150Z in UNIX Epoch time in milliseconds is represented as 1609504210150. + * numberToHrtime calculates the first number by converting and truncating the Epoch time in milliseconds to seconds: + * HrTime[0] = Math.trunc(1609504210150 / 1000) = 1609504210. + * numberToHrtime calculates the second number by converting the digits after the decimal point of the subtraction, (1609504210150 / 1000) - HrTime[0], to nanoseconds: + * HrTime[1] = Number((1609504210.150 - HrTime[0]).toFixed(9)) * SECOND_TO_NANOSECONDS = 150000000. + * This is represented in HrTime format as [1609504210, 150000000]. * @param epochMillis */ function numberToHrtime(epochMillis: number): api.HrTime { diff --git a/packages/opentelemetry-core/src/common/types.ts b/packages/opentelemetry-core/src/common/types.ts index 99ab0d08fd..6aabc592ee 100644 --- a/packages/opentelemetry-core/src/common/types.ts +++ b/packages/opentelemetry-core/src/common/types.ts @@ -47,6 +47,7 @@ export interface ShimWrapped extends Function { export interface InstrumentationLibrary { readonly name: string; readonly version?: string; + readonly schemaUrl?: string; } /** Defines an error handler function */ diff --git a/packages/opentelemetry-core/src/platform/browser/environment.ts b/packages/opentelemetry-core/src/platform/browser/environment.ts index ea9514e4ac..c752ae8a30 100644 --- a/packages/opentelemetry-core/src/platform/browser/environment.ts +++ b/packages/opentelemetry-core/src/platform/browser/environment.ts @@ -20,12 +20,12 @@ import { RAW_ENVIRONMENT, parseEnvironment, } from '../../utils/environment'; +import { _globalThis } from './globalThis'; /** * Gets the environment variables */ export function getEnv(): Required { - const _window = window as typeof window & RAW_ENVIRONMENT; - const globalEnv = parseEnvironment(_window); + const globalEnv = parseEnvironment(_globalThis as typeof globalThis & RAW_ENVIRONMENT); return Object.assign({}, DEFAULT_ENVIRONMENT, globalEnv); } diff --git a/packages/opentelemetry-core/src/platform/browser/globalThis.ts b/packages/opentelemetry-core/src/platform/browser/globalThis.ts new file mode 100644 index 0000000000..53dd1c3d02 --- /dev/null +++ b/packages/opentelemetry-core/src/platform/browser/globalThis.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// Updates to this file should also be replicated to @opentelemetry/api and +// @opentelemetry/api-metrics too. + +/** + * - globalThis (New standard) + * - self (Will return the current window instance for supported browsers) + * - window (fallback for older browser implementations) + * - global (NodeJS implementation) + * - (When all else fails) + */ + +/** only globals that common to node and browsers are allowed */ +// eslint-disable-next-line node/no-unsupported-features/es-builtins, no-undef +export const _globalThis: typeof globalThis = + typeof globalThis === 'object' ? globalThis : + typeof self === 'object' ? self : + typeof window === 'object' ? window : + typeof global === 'object' ? global : + {} as typeof globalThis; diff --git a/packages/opentelemetry-core/src/platform/browser/index.ts b/packages/opentelemetry-core/src/platform/browser/index.ts index c18c66118d..e2860192ef 100644 --- a/packages/opentelemetry-core/src/platform/browser/index.ts +++ b/packages/opentelemetry-core/src/platform/browser/index.ts @@ -15,6 +15,7 @@ */ export * from './environment'; +export * from './globalThis'; export * from './hex-to-base64'; export * from './RandomIdGenerator'; export * from './performance'; diff --git a/packages/opentelemetry-core/src/platform/node/globalThis.ts b/packages/opentelemetry-core/src/platform/node/globalThis.ts new file mode 100644 index 0000000000..36e97e2732 --- /dev/null +++ b/packages/opentelemetry-core/src/platform/node/globalThis.ts @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** only globals that common to node and browsers are allowed */ +// eslint-disable-next-line node/no-unsupported-features/es-builtins +export const _globalThis = typeof globalThis === 'object' ? globalThis : global; diff --git a/packages/opentelemetry-core/src/platform/node/index.ts b/packages/opentelemetry-core/src/platform/node/index.ts index c18c66118d..e2860192ef 100644 --- a/packages/opentelemetry-core/src/platform/node/index.ts +++ b/packages/opentelemetry-core/src/platform/node/index.ts @@ -15,6 +15,7 @@ */ export * from './environment'; +export * from './globalThis'; export * from './hex-to-base64'; export * from './RandomIdGenerator'; export * from './performance'; diff --git a/packages/opentelemetry-core/src/utils/url.ts b/packages/opentelemetry-core/src/utils/url.ts index 9db9725b82..a6122ae784 100644 --- a/packages/opentelemetry-core/src/utils/url.ts +++ b/packages/opentelemetry-core/src/utils/url.ts @@ -17,7 +17,7 @@ export function urlMatches(url: string, urlToMatch: string | RegExp): boolean { if (typeof urlToMatch === 'string') { return url === urlToMatch; } else { - return urlToMatch.test(url); + return !!url.match(urlToMatch); } } /** diff --git a/packages/opentelemetry-core/test/platform/browser/environment.test.ts b/packages/opentelemetry-core/test/platform/browser/environment.test.ts new file mode 100644 index 0000000000..0117be82b0 --- /dev/null +++ b/packages/opentelemetry-core/test/platform/browser/environment.test.ts @@ -0,0 +1,25 @@ +/* + * 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 { getEnv } from '../../../src/platform/browser/environment'; + +describe('getEnv', () => { + it('get environments variables in a browser', () => { + const env = getEnv(); + assert.strictEqual(typeof env, 'object'); + }); +}); diff --git a/packages/opentelemetry-core/test/utils/url.test.ts b/packages/opentelemetry-core/test/utils/url.test.ts index 91ae9b75c5..8855cff23c 100644 --- a/packages/opentelemetry-core/test/utils/url.test.ts +++ b/packages/opentelemetry-core/test/utils/url.test.ts @@ -71,5 +71,18 @@ describe('Core - Utils - url', () => { ); }); }); + describe('when regex has global flag', () => { + it('should return true', () => { + const ignoredUrls = [/myaddr/g]; + // Run test multiple times to ensure same result (git.io/JimS1) + for (let i = 0; i < 3; i++) { + assert.strictEqual( + isUrlIgnored(urlToTest, ignoredUrls), + true, + urlIgnored + ); + } + }); + }); }); }); diff --git a/packages/opentelemetry-exporter-jaeger/package.json b/packages/opentelemetry-exporter-jaeger/package.json index e2988c1869..23a3859aff 100644 --- a/packages/opentelemetry-exporter-jaeger/package.json +++ b/packages/opentelemetry-exporter-jaeger/package.json @@ -42,7 +42,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@opentelemetry/resources": "1.0.0", "@types/mocha": "8.2.3", "@types/node": "14.17.11", @@ -52,12 +52,12 @@ "nock": "12.0.3", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/packages/opentelemetry-exporter-zipkin/package.json b/packages/opentelemetry-exporter-zipkin/package.json index 653dc8a321..73dc9126d1 100644 --- a/packages/opentelemetry-exporter-zipkin/package.json +++ b/packages/opentelemetry-exporter-zipkin/package.json @@ -54,7 +54,7 @@ }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "^1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", @@ -62,7 +62,7 @@ "babel-loader": "8.2.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -72,7 +72,7 @@ "nock": "12.0.3", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", @@ -81,7 +81,7 @@ "webpack-merge": "5.8.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": "^1.0.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/packages/opentelemetry-propagator-b3/package.json b/packages/opentelemetry-propagator-b3/package.json index 5015c0a74b..c7e1e42fe9 100644 --- a/packages/opentelemetry-propagator-b3/package.json +++ b/packages/opentelemetry-propagator-b3/package.json @@ -48,10 +48,10 @@ "@opentelemetry/core": "1.0.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "codecov": "3.8.3", diff --git a/packages/opentelemetry-propagator-jaeger/package.json b/packages/opentelemetry-propagator-jaeger/package.json index 16fe043690..47eff749cc 100644 --- a/packages/opentelemetry-propagator-jaeger/package.json +++ b/packages/opentelemetry-propagator-jaeger/package.json @@ -49,14 +49,14 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", "@types/webpack-env": "1.16.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -65,14 +65,14 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", "webpack": "4.46.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "dependencies": { "@opentelemetry/core": "1.0.0" diff --git a/packages/opentelemetry-resources/package.json b/packages/opentelemetry-resources/package.json index 2eb290aa59..ed85855f3d 100644 --- a/packages/opentelemetry-resources/package.json +++ b/packages/opentelemetry-resources/package.json @@ -50,7 +50,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", @@ -59,12 +59,12 @@ "nock": "12.0.3", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/packages/opentelemetry-sdk-trace-base/README.md b/packages/opentelemetry-sdk-trace-base/README.md index 8e744ed13e..d1a988f6d4 100644 --- a/packages/opentelemetry-sdk-trace-base/README.md +++ b/packages/opentelemetry-sdk-trace-base/README.md @@ -70,4 +70,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-sdk-trace-base&type=dev [devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-sdk-trace-base&type=dev [npm-url]: https://www.npmjs.com/package/@opentelemetry/sdk-trace-base -[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Ftracing.svg +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fsdk-trace-base.svg diff --git a/packages/opentelemetry-sdk-trace-base/package.json b/packages/opentelemetry-sdk-trace-base/package.json index 9f52b0efa0..e1b483c381 100644 --- a/packages/opentelemetry-sdk-trace-base/package.json +++ b/packages/opentelemetry-sdk-trace-base/package.json @@ -55,14 +55,14 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@types/mocha": "8.2.3", "@types/node": "14.17.11", "@types/sinon": "10.0.2", "@types/webpack-env": "1.16.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-mocha": "2.0.1", @@ -71,14 +71,14 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", "webpack": "4.46.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/packages/opentelemetry-sdk-trace-node/README.md b/packages/opentelemetry-sdk-trace-node/README.md index e882cb48d4..68bafc52fb 100644 --- a/packages/opentelemetry-sdk-trace-node/README.md +++ b/packages/opentelemetry-sdk-trace-node/README.md @@ -124,4 +124,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-sdk-trace-node&type=dev [devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-sdk-trace-node&type=dev [npm-url]: https://www.npmjs.com/package/@opentelemetry/sdk-trace-node -[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fnode.svg +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fsdk-trace-node.svg diff --git a/packages/opentelemetry-sdk-trace-node/package.json b/packages/opentelemetry-sdk-trace-node/package.json index 69d5195d6d..029b2bf63e 100644 --- a/packages/opentelemetry-sdk-trace-node/package.json +++ b/packages/opentelemetry-sdk-trace-node/package.json @@ -43,7 +43,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@opentelemetry/resources": "1.0.0", "@opentelemetry/semantic-conventions": "1.0.0", "@types/mocha": "8.2.3", @@ -54,12 +54,12 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-mocha": "8.0.0", "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "dependencies": { "@opentelemetry/context-async-hooks": "1.0.0", diff --git a/packages/opentelemetry-sdk-trace-web/README.md b/packages/opentelemetry-sdk-trace-web/README.md index cdced55ab3..aeccc6ff88 100644 --- a/packages/opentelemetry-sdk-trace-web/README.md +++ b/packages/opentelemetry-sdk-trace-web/README.md @@ -74,4 +74,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [devDependencies-image]: https://status.david-dm.org/gh/open-telemetry/opentelemetry-js.svg?path=packages%2Fopentelemetry-sdk-trace-web&type=dev [devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-sdk-trace-web&type=dev [npm-url]: https://www.npmjs.com/package/@opentelemetry/sdk-trace-web -[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fweb.svg +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fsdk-trace-web.svg diff --git a/packages/opentelemetry-sdk-trace-web/package.json b/packages/opentelemetry-sdk-trace-web/package.json index ca9cb92643..d05298d136 100644 --- a/packages/opentelemetry-sdk-trace-web/package.json +++ b/packages/opentelemetry-sdk-trace-web/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@babel/core": "7.15.0", - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@opentelemetry/context-zone": "1.0.0", "@opentelemetry/propagator-b3": "1.0.0", "@opentelemetry/resources": "1.0.0", @@ -60,7 +60,7 @@ "babel-loader": "8.2.2", "codecov": "3.8.3", "istanbul-instrumenter-loader": "3.0.1", - "karma": "5.2.3", + "karma": "6.3.7", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "3.0.3", "karma-jquery": "0.2.4", @@ -70,7 +70,7 @@ "mocha": "7.2.0", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-loader": "8.3.0", "ts-mocha": "8.0.0", "typescript": "4.3.5", @@ -79,7 +79,7 @@ "webpack-merge": "5.8.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/packages/opentelemetry-semantic-conventions/package.json b/packages/opentelemetry-semantic-conventions/package.json index 54114b923c..9e38eec3ff 100644 --- a/packages/opentelemetry-semantic-conventions/package.json +++ b/packages/opentelemetry-semantic-conventions/package.json @@ -53,7 +53,7 @@ "nock": "12.0.3", "nyc": "15.1.0", "rimraf": "3.0.2", - "sinon": "11.1.2", + "sinon": "12.0.1", "ts-mocha": "8.0.0", "typescript": "4.3.5" } diff --git a/packages/opentelemetry-semantic-conventions/src/resource/SemanticResourceAttributes.ts b/packages/opentelemetry-semantic-conventions/src/resource/SemanticResourceAttributes.ts index 382e315a24..9e3a9d02ae 100644 --- a/packages/opentelemetry-semantic-conventions/src/resource/SemanticResourceAttributes.ts +++ b/packages/opentelemetry-semantic-conventions/src/resource/SemanticResourceAttributes.ts @@ -476,141 +476,145 @@ As an alternative, consider setting `faas.id` as a span attribute instead. WEBENGINE_DESCRIPTION: 'webengine.description', } -// Enum definitions - -export enum CloudProviderValues { +export const CloudProviderValues = { /** Alibaba Cloud. */ - ALIBABA_CLOUD = 'alibaba_cloud', + ALIBABA_CLOUD: 'alibaba_cloud', /** Amazon Web Services. */ - AWS = 'aws', + AWS: 'aws', /** Microsoft Azure. */ - AZURE = 'azure', + AZURE: 'azure', /** Google Cloud Platform. */ - GCP = 'gcp', -} + GCP: 'gcp', +} as const +export type CloudProviderValues = typeof CloudProviderValues[keyof typeof CloudProviderValues] -export enum CloudPlatformValues { +export const CloudPlatformValues = { /** Alibaba Cloud Elastic Compute Service. */ - ALIBABA_CLOUD_ECS = 'alibaba_cloud_ecs', + ALIBABA_CLOUD_ECS: 'alibaba_cloud_ecs', /** Alibaba Cloud Function Compute. */ - ALIBABA_CLOUD_FC = 'alibaba_cloud_fc', + ALIBABA_CLOUD_FC: 'alibaba_cloud_fc', /** AWS Elastic Compute Cloud. */ - AWS_EC2 = 'aws_ec2', + AWS_EC2: 'aws_ec2', /** AWS Elastic Container Service. */ - AWS_ECS = 'aws_ecs', + AWS_ECS: 'aws_ecs', /** AWS Elastic Kubernetes Service. */ - AWS_EKS = 'aws_eks', + AWS_EKS: 'aws_eks', /** AWS Lambda. */ - AWS_LAMBDA = 'aws_lambda', + AWS_LAMBDA: 'aws_lambda', /** AWS Elastic Beanstalk. */ - AWS_ELASTIC_BEANSTALK = 'aws_elastic_beanstalk', + AWS_ELASTIC_BEANSTALK: 'aws_elastic_beanstalk', /** Azure Virtual Machines. */ - AZURE_VM = 'azure_vm', + AZURE_VM: 'azure_vm', /** Azure Container Instances. */ - AZURE_CONTAINER_INSTANCES = 'azure_container_instances', + AZURE_CONTAINER_INSTANCES: 'azure_container_instances', /** Azure Kubernetes Service. */ - AZURE_AKS = 'azure_aks', + AZURE_AKS: 'azure_aks', /** Azure Functions. */ - AZURE_FUNCTIONS = 'azure_functions', + AZURE_FUNCTIONS: 'azure_functions', /** Azure App Service. */ - AZURE_APP_SERVICE = 'azure_app_service', + AZURE_APP_SERVICE: 'azure_app_service', /** Google Cloud Compute Engine (GCE). */ - GCP_COMPUTE_ENGINE = 'gcp_compute_engine', + GCP_COMPUTE_ENGINE: 'gcp_compute_engine', /** Google Cloud Run. */ - GCP_CLOUD_RUN = 'gcp_cloud_run', + GCP_CLOUD_RUN: 'gcp_cloud_run', /** Google Cloud Kubernetes Engine (GKE). */ - GCP_KUBERNETES_ENGINE = 'gcp_kubernetes_engine', + GCP_KUBERNETES_ENGINE: 'gcp_kubernetes_engine', /** Google Cloud Functions (GCF). */ - GCP_CLOUD_FUNCTIONS = 'gcp_cloud_functions', + GCP_CLOUD_FUNCTIONS: 'gcp_cloud_functions', /** Google Cloud App Engine (GAE). */ - GCP_APP_ENGINE = 'gcp_app_engine', -} + GCP_APP_ENGINE: 'gcp_app_engine', +} as const +export type CloudPlatformValues = typeof CloudPlatformValues[keyof typeof CloudPlatformValues] -export enum AwsEcsLaunchtypeValues { +export const AwsEcsLaunchtypeValues = { /** ec2. */ - EC2 = 'ec2', + EC2: 'ec2', /** fargate. */ - FARGATE = 'fargate', -} + FARGATE: 'fargate', +} as const +export type AwsEcsLaunchtypeValues = typeof AwsEcsLaunchtypeValues[keyof typeof AwsEcsLaunchtypeValues] -export enum HostArchValues { +export const HostArchValues = { /** AMD64. */ - AMD64 = 'amd64', + AMD64: 'amd64', /** ARM32. */ - ARM32 = 'arm32', + ARM32: 'arm32', /** ARM64. */ - ARM64 = 'arm64', + ARM64: 'arm64', /** Itanium. */ - IA64 = 'ia64', + IA64: 'ia64', /** 32-bit PowerPC. */ - PPC32 = 'ppc32', + PPC32: 'ppc32', /** 64-bit PowerPC. */ - PPC64 = 'ppc64', + PPC64: 'ppc64', /** 32-bit x86. */ - X86 = 'x86', -} + X86: 'x86', +} as const +export type HostArchValues = typeof HostArchValues[keyof typeof HostArchValues] -export enum OsTypeValues { +export const OsTypeValues = { /** Microsoft Windows. */ - WINDOWS = 'windows', + WINDOWS: 'windows', /** Linux. */ - LINUX = 'linux', + LINUX: 'linux', /** Apple Darwin. */ - DARWIN = 'darwin', + DARWIN: 'darwin', /** FreeBSD. */ - FREEBSD = 'freebsd', + FREEBSD: 'freebsd', /** NetBSD. */ - NETBSD = 'netbsd', + NETBSD: 'netbsd', /** OpenBSD. */ - OPENBSD = 'openbsd', + OPENBSD: 'openbsd', /** DragonFly BSD. */ - DRAGONFLYBSD = 'dragonflybsd', + DRAGONFLYBSD: 'dragonflybsd', /** HP-UX (Hewlett Packard Unix). */ - HPUX = 'hpux', + HPUX: 'hpux', /** AIX (Advanced Interactive eXecutive). */ - AIX = 'aix', + AIX: 'aix', /** Oracle Solaris. */ - SOLARIS = 'solaris', + SOLARIS: 'solaris', /** IBM z/OS. */ - Z_OS = 'z_os', -} + Z_OS: 'z_os', +} as const +export type OsTypeValues = typeof OsTypeValues[keyof typeof OsTypeValues] -export enum TelemetrySdkLanguageValues { +export const TelemetrySdkLanguageValues = { /** cpp. */ - CPP = 'cpp', + CPP: 'cpp', /** dotnet. */ - DOTNET = 'dotnet', + DOTNET: 'dotnet', /** erlang. */ - ERLANG = 'erlang', + ERLANG: 'erlang', /** go. */ - GO = 'go', + GO: 'go', /** java. */ - JAVA = 'java', + JAVA: 'java', /** nodejs. */ - NODEJS = 'nodejs', + NODEJS: 'nodejs', /** php. */ - PHP = 'php', + PHP: 'php', /** python. */ - PYTHON = 'python', + PYTHON: 'python', /** ruby. */ - RUBY = 'ruby', + RUBY: 'ruby', /** webjs. */ - WEBJS = 'webjs', -} + WEBJS: 'webjs', +} as const +export type TelemetrySdkLanguageValues = typeof TelemetrySdkLanguageValues[keyof typeof TelemetrySdkLanguageValues] diff --git a/packages/opentelemetry-semantic-conventions/src/trace/SemanticAttributes.ts b/packages/opentelemetry-semantic-conventions/src/trace/SemanticAttributes.ts index 48fecf29be..052d36e4c0 100644 --- a/packages/opentelemetry-semantic-conventions/src/trace/SemanticAttributes.ts +++ b/packages/opentelemetry-semantic-conventions/src/trace/SemanticAttributes.ts @@ -723,343 +723,354 @@ the closest proxy. MESSAGE_UNCOMPRESSED_SIZE: 'message.uncompressed_size', } -// Enum definitions - -export enum DbSystemValues { +export const DbSystemValues = { /** Some other SQL database. Fallback only. See notes. */ - OTHER_SQL = 'other_sql', + OTHER_SQL: 'other_sql', /** Microsoft SQL Server. */ - MSSQL = 'mssql', + MSSQL: 'mssql', /** MySQL. */ - MYSQL = 'mysql', + MYSQL: 'mysql', /** Oracle Database. */ - ORACLE = 'oracle', + ORACLE: 'oracle', /** IBM Db2. */ - DB2 = 'db2', + DB2: 'db2', /** PostgreSQL. */ - POSTGRESQL = 'postgresql', + POSTGRESQL: 'postgresql', /** Amazon Redshift. */ - REDSHIFT = 'redshift', + REDSHIFT: 'redshift', /** Apache Hive. */ - HIVE = 'hive', + HIVE: 'hive', /** Cloudscape. */ - CLOUDSCAPE = 'cloudscape', + CLOUDSCAPE: 'cloudscape', /** HyperSQL DataBase. */ - HSQLDB = 'hsqldb', + HSQLDB: 'hsqldb', /** Progress Database. */ - PROGRESS = 'progress', + PROGRESS: 'progress', /** SAP MaxDB. */ - MAXDB = 'maxdb', + MAXDB: 'maxdb', /** SAP HANA. */ - HANADB = 'hanadb', + HANADB: 'hanadb', /** Ingres. */ - INGRES = 'ingres', + INGRES: 'ingres', /** FirstSQL. */ - FIRSTSQL = 'firstsql', + FIRSTSQL: 'firstsql', /** EnterpriseDB. */ - EDB = 'edb', + EDB: 'edb', /** InterSystems Caché. */ - CACHE = 'cache', + CACHE: 'cache', /** Adabas (Adaptable Database System). */ - ADABAS = 'adabas', + ADABAS: 'adabas', /** Firebird. */ - FIREBIRD = 'firebird', + FIREBIRD: 'firebird', /** Apache Derby. */ - DERBY = 'derby', + DERBY: 'derby', /** FileMaker. */ - FILEMAKER = 'filemaker', + FILEMAKER: 'filemaker', /** Informix. */ - INFORMIX = 'informix', + INFORMIX: 'informix', /** InstantDB. */ - INSTANTDB = 'instantdb', + INSTANTDB: 'instantdb', /** InterBase. */ - INTERBASE = 'interbase', + INTERBASE: 'interbase', /** MariaDB. */ - MARIADB = 'mariadb', + MARIADB: 'mariadb', /** Netezza. */ - NETEZZA = 'netezza', + NETEZZA: 'netezza', /** Pervasive PSQL. */ - PERVASIVE = 'pervasive', + PERVASIVE: 'pervasive', /** PointBase. */ - POINTBASE = 'pointbase', + POINTBASE: 'pointbase', /** SQLite. */ - SQLITE = 'sqlite', + SQLITE: 'sqlite', /** Sybase. */ - SYBASE = 'sybase', + SYBASE: 'sybase', /** Teradata. */ - TERADATA = 'teradata', + TERADATA: 'teradata', /** Vertica. */ - VERTICA = 'vertica', + VERTICA: 'vertica', /** H2. */ - H2 = 'h2', + H2: 'h2', /** ColdFusion IMQ. */ - COLDFUSION = 'coldfusion', + COLDFUSION: 'coldfusion', /** Apache Cassandra. */ - CASSANDRA = 'cassandra', + CASSANDRA: 'cassandra', /** Apache HBase. */ - HBASE = 'hbase', + HBASE: 'hbase', /** MongoDB. */ - MONGODB = 'mongodb', + MONGODB: 'mongodb', /** Redis. */ - REDIS = 'redis', + REDIS: 'redis', /** Couchbase. */ - COUCHBASE = 'couchbase', + COUCHBASE: 'couchbase', /** CouchDB. */ - COUCHDB = 'couchdb', + COUCHDB: 'couchdb', /** Microsoft Azure Cosmos DB. */ - COSMOSDB = 'cosmosdb', + COSMOSDB: 'cosmosdb', /** Amazon DynamoDB. */ - DYNAMODB = 'dynamodb', + DYNAMODB: 'dynamodb', /** Neo4j. */ - NEO4J = 'neo4j', + NEO4J: 'neo4j', /** Apache Geode. */ - GEODE = 'geode', + GEODE: 'geode', /** Elasticsearch. */ - ELASTICSEARCH = 'elasticsearch', + ELASTICSEARCH: 'elasticsearch', /** Memcached. */ - MEMCACHED = 'memcached', + MEMCACHED: 'memcached', /** CockroachDB. */ - COCKROACHDB = 'cockroachdb', -} + COCKROACHDB: 'cockroachdb', +} as const +export type DbSystemValues = typeof DbSystemValues[keyof typeof DbSystemValues] -export enum DbCassandraConsistencyLevelValues { +export const DbCassandraConsistencyLevelValues = { /** all. */ - ALL = 'all', + ALL: 'all', /** each_quorum. */ - EACH_QUORUM = 'each_quorum', + EACH_QUORUM: 'each_quorum', /** quorum. */ - QUORUM = 'quorum', + QUORUM: 'quorum', /** local_quorum. */ - LOCAL_QUORUM = 'local_quorum', + LOCAL_QUORUM: 'local_quorum', /** one. */ - ONE = 'one', + ONE: 'one', /** two. */ - TWO = 'two', + TWO: 'two', /** three. */ - THREE = 'three', + THREE: 'three', /** local_one. */ - LOCAL_ONE = 'local_one', + LOCAL_ONE: 'local_one', /** any. */ - ANY = 'any', + ANY: 'any', /** serial. */ - SERIAL = 'serial', + SERIAL: 'serial', /** local_serial. */ - LOCAL_SERIAL = 'local_serial', -} + LOCAL_SERIAL: 'local_serial', +} as const +export type DbCassandraConsistencyLevelValues = typeof DbCassandraConsistencyLevelValues[keyof typeof DbCassandraConsistencyLevelValues] -export enum FaasTriggerValues { +export const FaasTriggerValues = { /** A response to some data source operation such as a database or filesystem read/write. */ - DATASOURCE = 'datasource', + DATASOURCE: 'datasource', /** To provide an answer to an inbound HTTP request. */ - HTTP = 'http', + HTTP: 'http', /** A function is set to be executed when messages are sent to a messaging system. */ - PUBSUB = 'pubsub', + PUBSUB: 'pubsub', /** A function is scheduled to be executed regularly. */ - TIMER = 'timer', + TIMER: 'timer', /** If none of the others apply. */ - OTHER = 'other', -} + OTHER: 'other', +} as const +export type FaasTriggerValues = typeof FaasTriggerValues[keyof typeof FaasTriggerValues] -export enum FaasDocumentOperationValues { +export const FaasDocumentOperationValues = { /** When a new object is created. */ - INSERT = 'insert', + INSERT: 'insert', /** When an object is modified. */ - EDIT = 'edit', + EDIT: 'edit', /** When an object is deleted. */ - DELETE = 'delete', -} + DELETE: 'delete', +} as const +export type FaasDocumentOperationValues = typeof FaasDocumentOperationValues[keyof typeof FaasDocumentOperationValues] -export enum FaasInvokedProviderValues { +export const FaasInvokedProviderValues = { /** Alibaba Cloud. */ - ALIBABA_CLOUD = 'alibaba_cloud', + ALIBABA_CLOUD: 'alibaba_cloud', /** Amazon Web Services. */ - AWS = 'aws', + AWS: 'aws', /** Microsoft Azure. */ - AZURE = 'azure', + AZURE: 'azure', /** Google Cloud Platform. */ - GCP = 'gcp', -} + GCP: 'gcp', +} as const +export type FaasInvokedProviderValues = typeof FaasInvokedProviderValues[keyof typeof FaasInvokedProviderValues] -export enum NetTransportValues { +export const NetTransportValues = { /** ip_tcp. */ - IP_TCP = 'ip_tcp', + IP_TCP: 'ip_tcp', /** ip_udp. */ - IP_UDP = 'ip_udp', + IP_UDP: 'ip_udp', /** Another IP-based protocol. */ - IP = 'ip', + IP: 'ip', /** Unix Domain socket. See below. */ - UNIX = 'unix', + UNIX: 'unix', /** Named or anonymous pipe. See note below. */ - PIPE = 'pipe', + PIPE: 'pipe', /** In-process communication. */ - INPROC = 'inproc', + INPROC: 'inproc', /** Something else (non IP-based). */ - OTHER = 'other', -} + OTHER: 'other', +} as const +export type NetTransportValues = typeof NetTransportValues[keyof typeof NetTransportValues] -export enum NetHostConnectionTypeValues { +export const NetHostConnectionTypeValues = { /** wifi. */ - WIFI = 'wifi', + WIFI: 'wifi', /** wired. */ - WIRED = 'wired', + WIRED: 'wired', /** cell. */ - CELL = 'cell', + CELL: 'cell', /** unavailable. */ - UNAVAILABLE = 'unavailable', + UNAVAILABLE: 'unavailable', /** unknown. */ - UNKNOWN = 'unknown', -} + UNKNOWN: 'unknown', +} as const +export type NetHostConnectionTypeValues = typeof NetHostConnectionTypeValues[keyof typeof NetHostConnectionTypeValues] -export enum NetHostConnectionSubtypeValues { +export const NetHostConnectionSubtypeValues = { /** GPRS. */ - GPRS = 'gprs', + GPRS: 'gprs', /** EDGE. */ - EDGE = 'edge', + EDGE: 'edge', /** UMTS. */ - UMTS = 'umts', + UMTS: 'umts', /** CDMA. */ - CDMA = 'cdma', + CDMA: 'cdma', /** EVDO Rel. 0. */ - EVDO_0 = 'evdo_0', + EVDO_0: 'evdo_0', /** EVDO Rev. A. */ - EVDO_A = 'evdo_a', + EVDO_A: 'evdo_a', /** CDMA2000 1XRTT. */ - CDMA2000_1XRTT = 'cdma2000_1xrtt', + CDMA2000_1XRTT: 'cdma2000_1xrtt', /** HSDPA. */ - HSDPA = 'hsdpa', + HSDPA: 'hsdpa', /** HSUPA. */ - HSUPA = 'hsupa', + HSUPA: 'hsupa', /** HSPA. */ - HSPA = 'hspa', + HSPA: 'hspa', /** IDEN. */ - IDEN = 'iden', + IDEN: 'iden', /** EVDO Rev. B. */ - EVDO_B = 'evdo_b', + EVDO_B: 'evdo_b', /** LTE. */ - LTE = 'lte', + LTE: 'lte', /** EHRPD. */ - EHRPD = 'ehrpd', + EHRPD: 'ehrpd', /** HSPAP. */ - HSPAP = 'hspap', + HSPAP: 'hspap', /** GSM. */ - GSM = 'gsm', + GSM: 'gsm', /** TD-SCDMA. */ - TD_SCDMA = 'td_scdma', + TD_SCDMA: 'td_scdma', /** IWLAN. */ - IWLAN = 'iwlan', + IWLAN: 'iwlan', /** 5G NR (New Radio). */ - NR = 'nr', + NR: 'nr', /** 5G NRNSA (New Radio Non-Standalone). */ - NRNSA = 'nrnsa', + NRNSA: 'nrnsa', /** LTE CA. */ - LTE_CA = 'lte_ca', -} + LTE_CA: 'lte_ca', +} as const +export type NetHostConnectionSubtypeValues = typeof NetHostConnectionSubtypeValues[keyof typeof NetHostConnectionSubtypeValues] -export enum HttpFlavorValues { +export const HttpFlavorValues = { /** HTTP 1.0. */ - HTTP_1_0 = '1.0', + HTTP_1_0: '1.0', /** HTTP 1.1. */ - HTTP_1_1 = '1.1', + HTTP_1_1: '1.1', /** HTTP 2. */ - HTTP_2_0 = '2.0', + HTTP_2_0: '2.0', /** SPDY protocol. */ - SPDY = 'SPDY', + SPDY: 'SPDY', /** QUIC protocol. */ - QUIC = 'QUIC', -} + QUIC: 'QUIC', +} as const +export type HttpFlavorValues = typeof HttpFlavorValues[keyof typeof HttpFlavorValues] -export enum MessagingDestinationKindValues { +export const MessagingDestinationKindValues = { /** A message sent to a queue. */ - QUEUE = 'queue', + QUEUE: 'queue', /** A message sent to a topic. */ - TOPIC = 'topic', -} + TOPIC: 'topic', +} as const +export type MessagingDestinationKindValues = typeof MessagingDestinationKindValues[keyof typeof MessagingDestinationKindValues] -export enum MessagingOperationValues { +export const MessagingOperationValues = { /** receive. */ - RECEIVE = 'receive', + RECEIVE: 'receive', /** process. */ - PROCESS = 'process', -} + PROCESS: 'process', +} as const +export type MessagingOperationValues = typeof MessagingOperationValues[keyof typeof MessagingOperationValues] -export enum RpcGrpcStatusCodeValues { +export const RpcGrpcStatusCodeValues = { /** OK. */ - OK = 0, + OK: 0, /** CANCELLED. */ - CANCELLED = 1, + CANCELLED: 1, /** UNKNOWN. */ - UNKNOWN = 2, + UNKNOWN: 2, /** INVALID_ARGUMENT. */ - INVALID_ARGUMENT = 3, + INVALID_ARGUMENT: 3, /** DEADLINE_EXCEEDED. */ - DEADLINE_EXCEEDED = 4, + DEADLINE_EXCEEDED: 4, /** NOT_FOUND. */ - NOT_FOUND = 5, + NOT_FOUND: 5, /** ALREADY_EXISTS. */ - ALREADY_EXISTS = 6, + ALREADY_EXISTS: 6, /** PERMISSION_DENIED. */ - PERMISSION_DENIED = 7, + PERMISSION_DENIED: 7, /** RESOURCE_EXHAUSTED. */ - RESOURCE_EXHAUSTED = 8, + RESOURCE_EXHAUSTED: 8, /** FAILED_PRECONDITION. */ - FAILED_PRECONDITION = 9, + FAILED_PRECONDITION: 9, /** ABORTED. */ - ABORTED = 10, + ABORTED: 10, /** OUT_OF_RANGE. */ - OUT_OF_RANGE = 11, + OUT_OF_RANGE: 11, /** UNIMPLEMENTED. */ - UNIMPLEMENTED = 12, + UNIMPLEMENTED: 12, /** INTERNAL. */ - INTERNAL = 13, + INTERNAL: 13, /** UNAVAILABLE. */ - UNAVAILABLE = 14, + UNAVAILABLE: 14, /** DATA_LOSS. */ - DATA_LOSS = 15, + DATA_LOSS: 15, /** UNAUTHENTICATED. */ - UNAUTHENTICATED = 16, -} + UNAUTHENTICATED: 16, +} as const +export type RpcGrpcStatusCodeValues = typeof RpcGrpcStatusCodeValues[keyof typeof RpcGrpcStatusCodeValues] -export enum MessageTypeValues { +export const MessageTypeValues = { /** sent. */ - SENT = 'SENT', + SENT: 'SENT', /** received. */ - RECEIVED = 'RECEIVED', -} + RECEIVED: 'RECEIVED', +} as const +export type MessageTypeValues = typeof MessageTypeValues[keyof typeof MessageTypeValues] diff --git a/packages/opentelemetry-shim-opentracing/package.json b/packages/opentelemetry-shim-opentracing/package.json index 496657c20a..b84d7dce3d 100644 --- a/packages/opentelemetry-shim-opentracing/package.json +++ b/packages/opentelemetry-shim-opentracing/package.json @@ -40,7 +40,7 @@ "access": "public" }, "devDependencies": { - "@opentelemetry/api": "^1.0.2", + "@opentelemetry/api": "~1.0.3", "@opentelemetry/propagator-b3": "1.0.0", "@opentelemetry/propagator-jaeger": "1.0.0", "@opentelemetry/sdk-trace-base": "1.0.0", @@ -54,7 +54,7 @@ "typescript": "4.3.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.2" + "@opentelemetry/api": ">=1.0.0 <1.1.0" }, "dependencies": { "@opentelemetry/core": "1.0.0", diff --git a/scripts/peer-api-check.js b/scripts/peer-api-check.js index 6e359e0473..3d79e60f44 100644 --- a/scripts/peer-api-check.js +++ b/scripts/peer-api-check.js @@ -17,6 +17,7 @@ const fs = require('fs'); const os = require('os'); const path = require('path'); +const semver = require('semver'); const appRoot = process.cwd(); @@ -29,7 +30,7 @@ if (pjson.dependencies && pjson.dependencies["@opentelemetry/api"]) const peerVersion = pjson.peerDependencies && pjson.peerDependencies["@opentelemetry/api"] const devVersion = pjson.devDependencies && pjson.devDependencies["@opentelemetry/api"] if (peerVersion) { - if (peerVersion !== devVersion) { + if (!semver.subset(devVersion, peerVersion)) { throw new Error(`Package ${pjson.name} depends on peer API version ${peerVersion} but version ${devVersion} in development`); } console.log(`${pjson.name} OK`); diff --git a/scripts/semconv/templates/SemanticAttributes.ts.j2 b/scripts/semconv/templates/SemanticAttributes.ts.j2 index 18004561d9..eb144b93b2 100644 --- a/scripts/semconv/templates/SemanticAttributes.ts.j2 +++ b/scripts/semconv/templates/SemanticAttributes.ts.j2 @@ -44,19 +44,19 @@ export const {{class}} = { {%- endfor %} } -// Enum definitions {%- for attribute in attributes if attribute.is_local and not attribute.ref %} {%- if attribute.is_enum %} {%- set class_name = attribute.fqn | to_camelcase(True) ~ "Values" %} {%- set type = attribute.attr_type.enum_type %} {% if attribute.attr_type.members is defined and attribute.attr_type.members|length > 0 %} -export enum {{class_name}} { +export const {{class_name}} = { {%- for member in attribute.attr_type.members if attribute.is_local and not attribute.ref %} /** {% filter escape %}{{member.brief | to_doc_brief}}.{% endfilter %} */ - {{ member.member_id | to_const_name }} = {{ print_value(type, member.value) }}, + {{ member.member_id | to_const_name }}: {{ print_value(type, member.value) }}, {%- endfor %} -} +} as const +export type {{class_name}} = typeof {{class_name}}[keyof typeof {{class_name}}] {% endif %} {% endif %} diff --git a/selenium-tests/.gitignore b/selenium-tests/.gitignore new file mode 100644 index 0000000000..53b77116ea --- /dev/null +++ b/selenium-tests/.gitignore @@ -0,0 +1,2 @@ +tests_output +tmp diff --git a/selenium-tests/README.md b/selenium-tests/README.md new file mode 100644 index 0000000000..eda21150fc --- /dev/null +++ b/selenium-tests/README.md @@ -0,0 +1,54 @@ +## Selenium Tests + +Selenium tests are to help verify the working of opentelemetry in different browsers. For that the nightwatch is used. +This can be run either locally or in github actions with usage of browserstack. +Browser stack also gives possibility of running tests in browserstack on different browsers using our local environment. +This helps to test and debug things locally using any browser we want. + +## Running tests locally using local browser - this is also useful when adding new test + +1. run server + +```shell +npm run server +``` + +1. run local test for example for xhr + +```shell +npm run local:xhr +``` + +Please wait a bit it should run selenium tests using our local version of chrome + +## Running tests locally using browser stack account - for that you need to have a browser stack account + +If you have it please create a file ".env" based on "example.env" + +1. run server + +```shell +npm run server +``` + +1. Run local test for example for xhr + +```shell +npm run local:bs:xhr +``` + +## Architecture + +1. Folder pages contains all the pages that can be entered after running `npn run server` at . +These are fully functioning pages and can be run without running tests. + +2. To be able to test it automatically instead of manually we have to create a test. Tests are kept in folder "tests". +For each page there is a corresponding folder with exactly the same name. There are additional 2 files + +- helper.js - this file keeps some helpers functions that are included in page automatically and they are available in tests only in section "execute". +This is because this section is being sent to the browser and executed automatically. This is the only way of "sending" and "reading" data back to test +When data is being sent between browser and selenium it needs to be stringified that's why we have one more helper for that called "JSONSafeStringify" +The last helper is the one that helps to verify test has finished successfully "OTELSeleniumDone". + +- tracing.js - this file contains the skeleton for tracing and export function "loadOtel" this is a helper function that accepts instrumentations as param. +This way it is easy to add different tests that has different lists of instrumentations. diff --git a/selenium-tests/babel.config.js b/selenium-tests/babel.config.js new file mode 100644 index 0000000000..26b15edca0 --- /dev/null +++ b/selenium-tests/babel.config.js @@ -0,0 +1,33 @@ +module.exports = function (api) { + api.cache(true); + const presets = [ + [ + '@babel/preset-env', + { + corejs: { + version: '3', + proposals: true, + }, + useBuiltIns: 'entry', + targets: { + // 'edge': 16, + // 'safari': 9, + // 'firefox': 57, + 'ie': 11, + // 'ios': 9, + // 'chrome': 49, + }, + }, + ], + ]; + const plugins = [ + ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }], + ['@babel/plugin-proposal-class-properties', { 'loose': true }], + ["@babel/plugin-proposal-private-methods", { "loose": true }], + ["@babel/plugin-proposal-private-property-in-object", { "loose": true }], + ]; + return { + presets, + plugins, + }; +}; \ No newline at end of file diff --git a/selenium-tests/example.env b/selenium-tests/example.env new file mode 100644 index 0000000000..28fc9739b0 --- /dev/null +++ b/selenium-tests/example.env @@ -0,0 +1,2 @@ +BROWSERSTACK_USER="YOUR USER" +BROWSERSTACK_KEY="YOUR BROWSER STACK KEY" \ No newline at end of file diff --git a/selenium-tests/nightwatch.conf.js b/selenium-tests/nightwatch.conf.js new file mode 100644 index 0000000000..8547bc2422 --- /dev/null +++ b/selenium-tests/nightwatch.conf.js @@ -0,0 +1,287 @@ +// Autogenerated by Nightwatch +// Refer to the online docs for more details: https://nightwatchjs.org/gettingstarted/configuration/ +const Services = {}; loadServices(); + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/working-with-page-objects/ + page_objects_path: '', + + // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands + custom_commands_path: '', + + // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-assertions + custom_assertions_path: '', + + // See https://nightwatchjs.org/guide/#external-globals + globals_path : '', + + webdriver: {}, + + test_settings: { + default: { + disable_error_log: false, + launch_url: 'https://nightwatchjs.org', + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName : 'firefox' + }, + + webdriver: { + start_process: true, + server_path: (Services.geckodriver ? Services.geckodriver.path : '') + } + }, + + safari: { + desiredCapabilities : { + browserName : 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + port: 4445, + start_process: true, + server_path: '/usr/bin/safaridriver' + } + }, + + firefox: { + desiredCapabilities : { + browserName : 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + + }, + webdriver: { + start_process: true, + port: 4444, + server_path: (Services.geckodriver ? Services.geckodriver.path : ''), + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities : { + browserName : 'chrome', + 'goog:chromeOptions' : { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // This tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: false, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + port: 9515, + server_path: (Services.chromedriver ? Services.chromedriver.path : ''), + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities : { + browserName : 'MicrosoftEdge', + 'ms:edgeOptions' : { + w3c: false, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + ////////////////////////////////////////////////////////////////////////////////// + // Configuration for when using the browserstack.com cloud service | + // | + // Please set the username and access key by setting the environment variables: | + // - BROWSERSTACK_USER | + // - BROWSERSTACK_KEY | + // .env files are supported | + ////////////////////////////////////////////////////////////////////////////////// + browserstack: { + selenium: { + host: 'hub-cloud.browserstack.com', + port: 443 + }, + // More info on configuring capabilities can be found on: + // https://www.browserstack.com/automate/capabilities?tag=selenium-4 + desiredCapabilities: { + 'bstack:options' : { + userName: '${BROWSERSTACK_USER}', + accessKey: '${BROWSERSTACK_KEY}', + } + }, + + disable_error_log: true, + webdriver: { + timeout_options: { + timeout: 15000, + retry_attempts: 3 + }, + keep_alive: true, + start_process: false + } + }, + + 'browserstack.local': { + extends: 'browserstack', + desiredCapabilities: { + 'browserstack.local': true, + 'browserstack.console': 'errors' + } + }, + + 'browserstack.chrome': { + extends: 'browserstack', + desiredCapabilities: { + browserName: 'chrome', + chromeOptions : { + w3c: false + } + } + }, + + 'browserstack.firefox': { + extends: 'browserstack', + desiredCapabilities: { + browserName: 'firefox' + } + }, + + 'browserstack.ie': { + extends: 'browserstack', + desiredCapabilities: { + browserName: 'internet explorer', + browserVersion: '11.0' + } + }, + + 'browserstack.safari': { + extends: 'browserstack', + desiredCapabilities: { + browserName: 'safari' + } + }, + + 'browserstack.local_chrome': { + extends: 'browserstack.local', + desiredCapabilities: { + browserName: 'chrome' + } + }, + + 'browserstack.local_firefox': { + extends: 'browserstack.local', + desiredCapabilities: { + browserName: 'firefox' + } + }, + 'browserstack.local_ie': { + extends: 'browserstack.local', + desiredCapabilities: { + browserName: 'internet explorer', + browserVersion: '11.0' + } + }, + 'browserstack.local_safari': { + extends: 'browserstack.local', + desiredCapabilities: { + browserName: 'safari', + } + }, + ////////////////////////////////////////////////////////////////////////////////// + // Configuration for when using the Selenium service, either locally or remote, | + // like Selenium Grid | + ////////////////////////////////////////////////////////////////////////////////// + selenium_server: { + // Selenium Server is running locally and is managed by Nightwatch + selenium: { + start_process: true, + port: 4444, + server_path: (Services.seleniumServer ? Services.seleniumServer.path : ''), + cli_args: { + 'webdriver.gecko.driver': (Services.geckodriver ? Services.geckodriver.path : ''), + 'webdriver.chrome.driver': (Services.chromedriver ? Services.chromedriver.path : '') + } + } + }, + + 'selenium.chrome': { + extends: 'selenium_server', + desiredCapabilities: { + browserName: 'chrome', + chromeOptions : { + w3c: false, + } + } + }, + + 'selenium.firefox': { + extends: 'selenium_server', + desiredCapabilities: { + browserName: 'firefox', + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + } + } +}; + +function loadServices() { + try { + Services.seleniumServer = require('selenium-server'); + } catch (err) {} + + try { + Services.chromedriver = require('chromedriver'); + } catch (err) {} + + try { + Services.geckodriver = require('geckodriver'); + } catch (err) {} +} diff --git a/selenium-tests/package.json b/selenium-tests/package.json new file mode 100644 index 0000000000..fd78e47105 --- /dev/null +++ b/selenium-tests/package.json @@ -0,0 +1,70 @@ +{ + "name": "@opentelemetry/selenium-tests", + "version": "0.0.1", + "description": "OpenTelemetry Selenium Tests", + "main": "index.js", + "repository": "open-telemetry/opentelemetry-js", + "scripts": { + "all:bs": "nightwatch ./tests --parallel --env browserstack.chrome,browserstack.safari,browserstack.firefox", + "all:local": "nightwatch ./tests --parallel --env selenium.chrome", + "local:bs:fetch": "node scripts/local.runner.js --test ./tests/fetch/fetch.js --parallel --env browserstack.local_chrome,browserstack.local_firefox,browserstack.local_safari", + "local:bs:xhr": "node scripts/local.runner.js --test ./tests/xhr/xhr.js --parallel --env browserstack.local_chrome,browserstack.local_firefox,browserstack.local_ie,browserstack.local_safari", + "local:fetch": "nightwatch ./tests/fetch/fetch.js --env selenium.chrome", + "local:xhr": "nightwatch ./tests/xhr/xhr.js --env selenium.chrome", + "server": "webpack serve --progress --port 8090 --config webpack.dev.js --hot --host 0.0.0.0" + }, + "keywords": [ + "opentelemetry", + "web", + "tracing", + "profiling", + "metrics", + "stats" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=10.0.0" + }, + "publishConfig": { + "access": "private" + }, + "devDependencies": { + "@babel/core": "^7.15.8", + "@babel/plugin-proposal-class-properties": "^7.14.5", + "@babel/plugin-proposal-decorators": "^7.15.8", + "@babel/plugin-transform-runtime": "^7.15.8", + "@babel/preset-env": "^7.15.0", + "@opentelemetry/api": "^1.0.3", + "babel-loader": "^8.2.3", + "babel-polyfill": "^6.26.0", + "browserstack-local": "^1.4.8", + "chromedriver": "^95.0.0", + "dotenv": "^10.0.0", + "fast-safe-stringify": "^2.1.1", + "geckodriver": "^2.0.4", + "nightwatch": "^1.7.11", + "selenium-server": "^3.141.59", + "terser-webpack-plugin": "^5.2.4", + "webpack": "^5.60.0", + "webpack-cli": "^4.9.1", + "webpack-dev-server": "^4.3.1", + "webpack-merge": "^5.8.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.3" + }, + "dependencies": { + "@opentelemetry/context-zone-peer-dep": "^1.0.0", + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/exporter-otlp-http": "^0.26.0", + "@opentelemetry/exporter-zipkin": "^1.0.0", + "@opentelemetry/instrumentation": "^0.26.0", + "@opentelemetry/instrumentation-fetch": "^0.26.0", + "@opentelemetry/instrumentation-xml-http-request": "^0.26.0", + "@opentelemetry/sdk-metrics-base": "^0.26.0", + "@opentelemetry/sdk-trace-base": "^1.0.0", + "@opentelemetry/sdk-trace-web": "^1.0.0", + "zone.js": "^0.10.3" + } +} diff --git a/selenium-tests/pages/fetch/index.html b/selenium-tests/pages/fetch/index.html new file mode 100644 index 0000000000..a43e52d2ef --- /dev/null +++ b/selenium-tests/pages/fetch/index.html @@ -0,0 +1,20 @@ + + + + + + Fetch Plugin + + + + + + + Example of using Web Tracer with Fetch plugin and console exporter + +
      + + + + + diff --git a/selenium-tests/pages/fetch/index.js b/selenium-tests/pages/fetch/index.js new file mode 100644 index 0000000000..dbd2fe1166 --- /dev/null +++ b/selenium-tests/pages/fetch/index.js @@ -0,0 +1,51 @@ +'use strict'; +import '../helper'; + +import { context, trace } from '@opentelemetry/api'; + +import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch'; +import { loadOtel } from '../tracing'; + +const provider = loadOtel([ + new FetchInstrumentation({ + ignoreUrls: [/localhost:8090\/sockjs-node/], + propagateTraceHeaderCorsUrls: [ + 'https://cors-test.appspot.com/test', + 'https://httpbin.org/get', + ], + clearTimingResources: true, + }), +]); + +const webTracerWithZone = provider.getTracer('example-tracer-web'); + +const getData = (url) => fetch(url, { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, +}); + +// example of keeping track of context between async operations +const prepareClickEvent = () => { + const url = 'https://httpbin.org/get'; + + const element = document.getElementById('button1'); + + const onClick = () => { + const singleSpan = webTracerWithZone.startSpan(`files-series-info`); + context.with(trace.setSpan(context.active(), singleSpan), () => { + getData(url).then((_data) => { + trace.getSpan(context.active()).addEvent('fetching-single-span-completed'); + singleSpan.end(); + }).finally(()=> { + otel.OTELSeleniumDone(); + console.log(otel.memoryExporter.getFinishedSpans()); + }); + }); + }; + element.addEventListener('click', onClick); +}; + +window.addEventListener('load', prepareClickEvent); diff --git a/selenium-tests/pages/helper.js b/selenium-tests/pages/helper.js new file mode 100644 index 0000000000..8f7c23bfd8 --- /dev/null +++ b/selenium-tests/pages/helper.js @@ -0,0 +1,46 @@ +/** + * These are all needed to make otel to work correctly for IE + */ +window.__Zone_enable_cross_context_check = true; +import 'babel-polyfill'; +import 'zone.js'; + +const safeStringify = require('fast-safe-stringify'); + +/** + * Function to stringify data between browser and selenium + * It works fine for circular dependency + * @param obj + * @return {*|string} + * @constructor + */ +function JSONSafeStringify(obj) { + return safeStringify( + obj, + function replacer(key, value) { + // Remove the circular structure + if (value === '[Circular]') { + return; + } + return value; + }, + 2, + ); +} + +/** + * Function helper to mark action on page as finished. This way selenium understands that test is finished + */ +function OTELSeleniumDone() { + const element = document.createElement('div'); + element.setAttribute('id', 'otelSeleniumDone'); + element.innerHTML = 'OTELSeleniumDone'; + window.setTimeout(() => { + document.body.appendChild(element); + }, 1000); +} + +window.otel = Object.assign({}, window.otel, { + JSONSafeStringify: JSONSafeStringify, + OTELSeleniumDone: OTELSeleniumDone, +}); diff --git a/selenium-tests/pages/tracing.js b/selenium-tests/pages/tracing.js new file mode 100644 index 0000000000..6dd6e5f26f --- /dev/null +++ b/selenium-tests/pages/tracing.js @@ -0,0 +1,32 @@ +'use strict'; + +import { ConsoleSpanExporter, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'; +import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; +import { ZoneContextManager } from '@opentelemetry/context-zone-peer-dep'; +import { registerInstrumentations } from '@opentelemetry/instrumentation'; + +/** + * Function helper to load the tracing with predefined instrumentations + * @param instrumentations + * @return {WebTracerProvider} + */ +export function loadOtel(instrumentations) { + const provider = new WebTracerProvider(); + const memoryExporter = new InMemorySpanExporter(); + provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); + provider.register({ + contextManager: new ZoneContextManager(), + }); + + registerInstrumentations({ + instrumentations: [ + instrumentations, + ], + }); + window.otel = Object.assign({}, window.otel, { + provider, + memoryExporter, + }); + return provider; +} \ No newline at end of file diff --git a/selenium-tests/pages/xhr/index.html b/selenium-tests/pages/xhr/index.html new file mode 100644 index 0000000000..0914215d3c --- /dev/null +++ b/selenium-tests/pages/xhr/index.html @@ -0,0 +1,20 @@ + + + + + + XHR Plugin + + + + + + + Example of using Web Tracer with XHR plugin and console exporter + +
      + + + + + diff --git a/selenium-tests/pages/xhr/index.js b/selenium-tests/pages/xhr/index.js new file mode 100644 index 0000000000..e998c58962 --- /dev/null +++ b/selenium-tests/pages/xhr/index.js @@ -0,0 +1,56 @@ +'use strict'; +import '../helper'; + +import { context, trace } from '@opentelemetry/api'; + +import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request'; +import { loadOtel } from '../tracing'; + +const provider = loadOtel([ + new XMLHttpRequestInstrumentation({ + ignoreUrls: [/localhost:8090\/sockjs-node/], + propagateTraceHeaderCorsUrls: [ + 'https://httpbin.org/get', + ], + clearTimingResources: true, + }), +]); + +const webTracerWithZone = provider.getTracer('example-tracer-web'); + +const getData = (url) => new Promise((resolve, reject) => { + // eslint-disable-next-line no-undef + const req = new XMLHttpRequest(); + req.open('GET', url, true); + req.setRequestHeader('Content-Type', 'application/json'); + req.setRequestHeader('Accept', 'application/json'); + req.onload = () => { + resolve(); + }; + req.onerror = () => { + reject(); + }; + req.send(); +}); + +// example of keeping track of context between async operations +const prepareClickEvent = () => { + const url = 'https://httpbin.org/get'; + + const element = document.getElementById('button1'); + + const onClick = () => { + const singleSpan = webTracerWithZone.startSpan(`files-series-info`); + context.with(trace.setSpan(context.active(), singleSpan), () => { + getData(url).then((_data) => { + trace.getSpan(context.active()).addEvent('fetching-single-span-completed'); + singleSpan.end(); + }).finally(() => { + otel.OTELSeleniumDone(); + }); + }); + }; + element.addEventListener('click', onClick); +}; + +window.addEventListener('load', prepareClickEvent); diff --git a/selenium-tests/scripts/local.runner.js b/selenium-tests/scripts/local.runner.js new file mode 100755 index 0000000000..295b4b2c61 --- /dev/null +++ b/selenium-tests/scripts/local.runner.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node + +const Nightwatch = require('nightwatch'); +const browserstack = require('browserstack-local'); +require('dotenv').config(); + +let bs_local; + +try { + require.main.filename = './node_modules/.bin/nightwatch'; + // Code to start browserstack local before start of test + console.log('Connecting local'); + Nightwatch.bs_local = bs_local = new browserstack.Local(); + bs_local.start({ key: process.env.BROWSERSTACK_KEY }, function (error) { + if (error) { + bs_local.stop(function () {}); + throw error; + } + + console.log('Connected. Now testing...'); + Nightwatch.cli(function (argv) { + Nightwatch.CliRunner(argv) + .setup() + .runTests() + .catch((err) => { + throw err; + }) + .finally(() => { + // Code to stop browserstack local after end of single test + bs_local.stop(function () {}); + }); + }); + }); +} catch (ex) { + console.log('There was an error while starting the test runner:\n\n'); + process.stderr.write(ex.stack + '\n'); + process.exit(2); +} diff --git a/selenium-tests/tests-helpers/constants.js b/selenium-tests/tests-helpers/constants.js new file mode 100644 index 0000000000..3362a3585c --- /dev/null +++ b/selenium-tests/tests-helpers/constants.js @@ -0,0 +1,5 @@ +const TIMEOUT_ELEMENT_MS = 5000; + +module.exports = { + TIMEOUT_ELEMENT_MS, +}; \ No newline at end of file diff --git a/selenium-tests/tests/fetch/fetch.js b/selenium-tests/tests/fetch/fetch.js new file mode 100644 index 0000000000..c60a5e1b87 --- /dev/null +++ b/selenium-tests/tests/fetch/fetch.js @@ -0,0 +1,27 @@ +const { TIMEOUT_ELEMENT_MS } = require('../../tests-helpers/constants'); + +module.exports = { + 'Fetch instrumentation': function (browser) { + browser + .url('http://localhost:8090/fetch') + .waitForElementVisible('body', TIMEOUT_ELEMENT_MS) + .waitForElementVisible('#button1', TIMEOUT_ELEMENT_MS) + .click('#button1') + .waitForElementVisible('#otelSeleniumDone', TIMEOUT_ELEMENT_MS) + .execute( + () => { + const spans = otel.memoryExporter.getFinishedSpans(); + return otel.JSONSafeStringify(spans); + }, + [], + (result) => { + const spans = JSON.parse(result.value); + browser.assert.equal(spans.length, 2, 'Should export 2 spans'); + }, + ) + + browser.end(() => { + console.log('end'); + }); + }, +}; diff --git a/selenium-tests/tests/xhr/xhr.js b/selenium-tests/tests/xhr/xhr.js new file mode 100644 index 0000000000..5204f527ff --- /dev/null +++ b/selenium-tests/tests/xhr/xhr.js @@ -0,0 +1,26 @@ +const { TIMEOUT_ELEMENT_MS } = require('../../tests-helpers/constants'); +module.exports = { + 'XHR instrumentation': function (browser) { + browser + .url('http://localhost:8090/xhr') + .waitForElementVisible('body', TIMEOUT_ELEMENT_MS) + .waitForElementVisible('#button1', TIMEOUT_ELEMENT_MS) + .click('#button1') + .waitForElementVisible('#otelSeleniumDone', TIMEOUT_ELEMENT_MS) + .execute( + function() { + const spans = otel.memoryExporter.getFinishedSpans(); + return otel.JSONSafeStringify(spans); + }, + [], + function(result) { + const spans = JSON.parse(result.value); + browser.assert.equal(spans.length, 2, 'Should export 2 spans'); + }, + ) + + browser.end(() => { + console.log('end'); + }); + }, +}; diff --git a/selenium-tests/webpack.common.js b/selenium-tests/webpack.common.js new file mode 100644 index 0000000000..0d00b07c60 --- /dev/null +++ b/selenium-tests/webpack.common.js @@ -0,0 +1,38 @@ +const path = require('path'); +const directory = path.resolve(__dirname); + +module.exports = { + entry: { + fetch: 'pages/fetch/index.js', + xhr: 'pages/xhr/index.js', + }, + output: { + path: path.resolve(__dirname, 'dist'), + filename: '[name].js', + sourceMapFilename: '[file].map', + }, + target: ['web', 'es5'], + module: { + rules: [ + { + test: /\.js[x]?$/, + exclude: /(node_modules)/, + use: { + loader: 'babel-loader', + options: { + babelrc: false, + configFile: path.resolve(__dirname, 'babel.config.js'), + presets: ['@babel/preset-env'], + }, + }, + }, + ], + }, + resolve: { + modules: [ + path.resolve(directory), + 'node_modules', + ], + extensions: ['.ts', '.js', '.jsx', '.json'], + }, +}; \ No newline at end of file diff --git a/selenium-tests/webpack.config.js b/selenium-tests/webpack.config.js new file mode 100644 index 0000000000..061ab2a770 --- /dev/null +++ b/selenium-tests/webpack.config.js @@ -0,0 +1,57 @@ +const webpack = require('webpack'); +const webpackMerge = require('webpack-merge'); +const path = require('path'); + +const directory = path.resolve(__dirname); + +const common = { + mode: 'development', + entry: { + fetch: 'pages/fetch/index.js', + // xhr: 'pages/xhr/index.js', + }, + output: { + path: path.resolve(__dirname, 'dist'), + filename: '[name].js', + sourceMapFilename: '[file].map', + }, + target: 'web', + module: { + rules: [ + { + test: /\.js[x]?$/, + exclude: /(node_modules)/, + use: { + loader: 'babel-loader', + options: { + babelrc: false, + configFile: path.resolve(__dirname, 'babel.config.js'), + presets: ['@babel/preset-env'], + }, + }, + include: [ + path.resolve(__dirname, 'pages/helper.js'), + ], + }, + ], + }, + resolve: { + modules: [ + path.resolve(directory), + 'node_modules', + ], + extensions: ['.js', '.jsx', '.json'], + }, +}; + +module.exports = webpackMerge(common, { + devtool: 'eval-source-map', + devServer: { + static: path.resolve(__dirname), + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify('development'), + }), + ], +}); diff --git a/selenium-tests/webpack.dev.js b/selenium-tests/webpack.dev.js new file mode 100644 index 0000000000..abdc9f3d2b --- /dev/null +++ b/selenium-tests/webpack.dev.js @@ -0,0 +1,11 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common.js'); +const path = require('path'); + +module.exports = merge(common, { + mode: 'development', + // devtool: 'inline-source-map', + devServer: { + static: path.resolve(__dirname, 'pages'), + }, +}); \ No newline at end of file diff --git a/selenium-tests/webpack.production.js b/selenium-tests/webpack.production.js new file mode 100644 index 0000000000..d5fd171c2d --- /dev/null +++ b/selenium-tests/webpack.production.js @@ -0,0 +1,17 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common.js'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = merge(common, { + mode: 'production', + optimization: { + minimize: true, + minimizer: [new TerserPlugin({ + extractComments: false, + terserOptions: { + ie8: true, + safari10: true, + }, + })], + }, +}); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 17cfa10261..44577914a9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,9 +4,9 @@ "typedocOptions": { "packages": [ "experimental/packages/opentelemetry-api-metrics", - "experimental/packages/opentelemetry-exporter-otlp-grpc", - "experimental/packages/opentelemetry-exporter-otlp-http", - "experimental/packages/opentelemetry-exporter-otlp-proto", + "experimental/packages/opentelemetry-exporter-trace-otlp-grpc", + "experimental/packages/opentelemetry-exporter-trace-otlp-http", + "experimental/packages/opentelemetry-exporter-trace-otlp-proto", "experimental/packages/opentelemetry-exporter-prometheus", "experimental/packages/opentelemetry-instrumentation-fetch", "experimental/packages/opentelemetry-instrumentation-grpc", @@ -14,6 +14,9 @@ "experimental/packages/opentelemetry-instrumentation-xml-http-request", "experimental/packages/opentelemetry-instrumentation", "experimental/packages/opentelemetry-sdk-node", + "experimental/packages/opentelemetry-exporter-metrics-otlp-http", + "experimental/packages/opentelemetry-exporter-metrics-otlp-grpc", + "experimental/packages/opentelemetry-exporter-metrics-otlp-proto", "packages/opentelemetry-context-async-hooks", "packages/opentelemetry-context-zone-peer-dep", "packages/opentelemetry-context-zone",