From 3d5447defa9faf279a89cb486ddd5842d7704318 Mon Sep 17 00:00:00 2001 From: Rauno Viskus Date: Tue, 4 Jan 2022 21:54:48 +0200 Subject: [PATCH 01/16] chore: rename `--include-filtered-dependencies` (#2699) --- experimental/lerna.json | 1 - experimental/packages/opentelemetry-api-metrics/package.json | 2 +- .../opentelemetry-exporter-metrics-otlp-grpc/package.json | 2 +- .../opentelemetry-exporter-metrics-otlp-http/package.json | 2 +- .../opentelemetry-exporter-metrics-otlp-proto/package.json | 2 +- .../packages/opentelemetry-exporter-prometheus/package.json | 2 +- .../packages/opentelemetry-instrumentation-fetch/package.json | 2 +- .../packages/opentelemetry-instrumentation-grpc/package.json | 2 +- .../packages/opentelemetry-instrumentation-http/package.json | 2 +- .../opentelemetry-instrumentation-xml-http-request/package.json | 2 +- .../packages/opentelemetry-instrumentation/package.json | 2 +- .../packages/opentelemetry-sdk-metrics-base/package.json | 2 +- experimental/packages/opentelemetry-sdk-node/package.json | 2 +- lerna.json | 1 - packages/exporter-trace-otlp-grpc/package.json | 2 +- packages/exporter-trace-otlp-http/package.json | 2 +- packages/exporter-trace-otlp-proto/package.json | 2 +- packages/opentelemetry-context-async-hooks/package.json | 2 +- packages/opentelemetry-context-zone-peer-dep/package.json | 2 +- packages/opentelemetry-context-zone/package.json | 2 +- packages/opentelemetry-core/package.json | 2 +- packages/opentelemetry-exporter-jaeger/package.json | 2 +- packages/opentelemetry-exporter-zipkin/package.json | 2 +- packages/opentelemetry-propagator-b3/package.json | 2 +- packages/opentelemetry-propagator-jaeger/package.json | 2 +- packages/opentelemetry-resources/package.json | 2 +- packages/opentelemetry-sdk-trace-base/package.json | 2 +- packages/opentelemetry-sdk-trace-node/package.json | 2 +- packages/opentelemetry-sdk-trace-web/package.json | 2 +- packages/opentelemetry-semantic-conventions/package.json | 2 +- packages/opentelemetry-shim-opentracing/package.json | 2 +- packages/template/package.json | 2 +- 32 files changed, 30 insertions(+), 32 deletions(-) diff --git a/experimental/lerna.json b/experimental/lerna.json index 02f1f102c7..1b4e1af995 100644 --- a/experimental/lerna.json +++ b/experimental/lerna.json @@ -1,5 +1,4 @@ { - "lerna": "3.13.4", "version": "0.27.0", "npmClient": "npm", "packages": [ diff --git a/experimental/packages/opentelemetry-api-metrics/package.json b/experimental/packages/opentelemetry-api-metrics/package.json index e4a17b9943..9b56c5a985 100644 --- a/experimental/packages/opentelemetry-api-metrics/package.json +++ b/experimental/packages/opentelemetry-api-metrics/package.json @@ -26,7 +26,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "node ../../../scripts/version-update.js" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json index 715b7748f3..b630a9575c 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json @@ -17,7 +17,7 @@ "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", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json index 26eaafa001..2479082cb4 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json @@ -25,7 +25,7 @@ "test:browser": "nyc karma start --single-run", "version": "node ../../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json index 05f99fac9b..bb4fb0539b 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json @@ -17,7 +17,7 @@ "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", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-exporter-prometheus/package.json b/experimental/packages/opentelemetry-exporter-prometheus/package.json index eeaf834ea7..536f61e136 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/package.json +++ b/experimental/packages/opentelemetry-exporter-prometheus/package.json @@ -15,7 +15,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../../scripts/version-update.js", "watch": "tsc --build --watch", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/package.json b/experimental/packages/opentelemetry-instrumentation-fetch/package.json index 342002661e..f76f5d3e70 100644 --- a/experimental/packages/opentelemetry-instrumentation-fetch/package.json +++ b/experimental/packages/opentelemetry-instrumentation-fetch/package.json @@ -17,7 +17,7 @@ "tdd": "karma start", "test:browser": "nyc karma start --single-run", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "node ../../../scripts/version-update.js" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/package.json b/experimental/packages/opentelemetry-instrumentation-grpc/package.json index 7b1fc0de22..126e8e53f8 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/package.json +++ b/experimental/packages/opentelemetry-instrumentation-grpc/package.json @@ -15,7 +15,7 @@ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", "version": "node ../../../scripts/version-update.js", "watch": "tsc --build --watch", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "node ../../../scripts/version-update.js" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-instrumentation-http/package.json b/experimental/packages/opentelemetry-instrumentation-http/package.json index 5ab6eac35b..e287d9429a 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/package.json +++ b/experimental/packages/opentelemetry-instrumentation-http/package.json @@ -15,7 +15,7 @@ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", "version": "node ../../../scripts/version-update.js", "watch": "tsc --build --watch", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "node ../../../scripts/version-update.js" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json index 897517fe8c..ab67c95e65 100644 --- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json +++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json @@ -17,7 +17,7 @@ "tdd": "karma start", "test:browser": "nyc karma start --single-run", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "node ../../../scripts/version-update.js" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-instrumentation/package.json b/experimental/packages/opentelemetry-instrumentation/package.json index a96b3ff1c6..c3dbab04e6 100644 --- a/experimental/packages/opentelemetry-instrumentation/package.json +++ b/experimental/packages/opentelemetry-instrumentation/package.json @@ -47,7 +47,7 @@ "test:browser": "nyc karma start --single-run", "version": "node ../../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "node ../../../scripts/version-update.js" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/package.json b/experimental/packages/opentelemetry-sdk-metrics-base/package.json index 2f37a9d304..ce653a0f4c 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/package.json +++ b/experimental/packages/opentelemetry-sdk-metrics-base/package.json @@ -18,7 +18,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "node ../../../scripts/version-update.js" }, "keywords": [ diff --git a/experimental/packages/opentelemetry-sdk-node/package.json b/experimental/packages/opentelemetry-sdk-node/package.json index 1f9de6fb71..88c35e48dc 100644 --- a/experimental/packages/opentelemetry-sdk-node/package.json +++ b/experimental/packages/opentelemetry-sdk-node/package.json @@ -14,7 +14,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../../scripts/version-update.js", "watch": "tsc --build --watch", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/lerna.json b/lerna.json index 8629bd0fa8..fa3749c7d4 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,4 @@ { - "lerna": "3.13.4", "version": "1.0.1", "npmClient": "npm", "packages": [ diff --git a/packages/exporter-trace-otlp-grpc/package.json b/packages/exporter-trace-otlp-grpc/package.json index 9f410d18f2..1d136a0368 100644 --- a/packages/exporter-trace-otlp-grpc/package.json +++ b/packages/exporter-trace-otlp-grpc/package.json @@ -17,7 +17,7 @@ "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", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/exporter-trace-otlp-http/package.json b/packages/exporter-trace-otlp-http/package.json index e3eb9afe55..69d8e5a329 100644 --- a/packages/exporter-trace-otlp-http/package.json +++ b/packages/exporter-trace-otlp-http/package.json @@ -25,7 +25,7 @@ "test:browser": "nyc karma start --single-run", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/exporter-trace-otlp-proto/package.json b/packages/exporter-trace-otlp-proto/package.json index 71e22f062f..5fa58b260c 100644 --- a/packages/exporter-trace-otlp-proto/package.json +++ b/packages/exporter-trace-otlp-proto/package.json @@ -17,7 +17,7 @@ "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", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-context-async-hooks/package.json b/packages/opentelemetry-context-async-hooks/package.json index e53221926a..05c5730772 100644 --- a/packages/opentelemetry-context-async-hooks/package.json +++ b/packages/opentelemetry-context-async-hooks/package.json @@ -14,7 +14,7 @@ "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../scripts/version-update.js", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-context-zone-peer-dep/package.json b/packages/opentelemetry-context-zone-peer-dep/package.json index e4741ec251..71029e1b78 100644 --- a/packages/opentelemetry-context-zone-peer-dep/package.json +++ b/packages/opentelemetry-context-zone-peer-dep/package.json @@ -17,7 +17,7 @@ "tdd": "karma start", "test:browser": "nyc karma start --single-run", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-context-zone/package.json b/packages/opentelemetry-context-zone/package.json index caace574ae..0733ef75ba 100644 --- a/packages/opentelemetry-context-zone/package.json +++ b/packages/opentelemetry-context-zone/package.json @@ -14,7 +14,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-core/package.json b/packages/opentelemetry-core/package.json index bedf0f7d83..fcaac4c362 100644 --- a/packages/opentelemetry-core/package.json +++ b/packages/opentelemetry-core/package.json @@ -27,7 +27,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-exporter-jaeger/package.json b/packages/opentelemetry-exporter-jaeger/package.json index 1ce8fb80fb..d40f4d9c90 100644 --- a/packages/opentelemetry-exporter-jaeger/package.json +++ b/packages/opentelemetry-exporter-jaeger/package.json @@ -15,7 +15,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-exporter-zipkin/package.json b/packages/opentelemetry-exporter-zipkin/package.json index 063555c51c..8f450ed956 100644 --- a/packages/opentelemetry-exporter-zipkin/package.json +++ b/packages/opentelemetry-exporter-zipkin/package.json @@ -25,7 +25,7 @@ "test:browser": "nyc karma start --single-run", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-propagator-b3/package.json b/packages/opentelemetry-propagator-b3/package.json index ba03744813..830a0002f9 100644 --- a/packages/opentelemetry-propagator-b3/package.json +++ b/packages/opentelemetry-propagator-b3/package.json @@ -16,7 +16,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-propagator-jaeger/package.json b/packages/opentelemetry-propagator-jaeger/package.json index 6b92f785e0..aca7f476e7 100644 --- a/packages/opentelemetry-propagator-jaeger/package.json +++ b/packages/opentelemetry-propagator-jaeger/package.json @@ -19,7 +19,7 @@ "lint:fix": "eslint . --ext .ts --fix", "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", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-resources/package.json b/packages/opentelemetry-resources/package.json index 655f318550..6c650ef9ae 100644 --- a/packages/opentelemetry-resources/package.json +++ b/packages/opentelemetry-resources/package.json @@ -22,7 +22,7 @@ "tdd": "npm run test -- --watch-extensions ts --watch", "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", "version": "node ../../scripts/version-update.js", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-sdk-trace-base/package.json b/packages/opentelemetry-sdk-trace-base/package.json index 21885ee250..a2f38bb6ad 100644 --- a/packages/opentelemetry-sdk-trace-base/package.json +++ b/packages/opentelemetry-sdk-trace-base/package.json @@ -26,7 +26,7 @@ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-sdk-trace-node/package.json b/packages/opentelemetry-sdk-trace-node/package.json index a926914406..b3c8c9431e 100644 --- a/packages/opentelemetry-sdk-trace-node/package.json +++ b/packages/opentelemetry-sdk-trace-node/package.json @@ -15,7 +15,7 @@ "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-sdk-trace-web/package.json b/packages/opentelemetry-sdk-trace-web/package.json index 21d2f7fbd9..2e88f6520e 100644 --- a/packages/opentelemetry-sdk-trace-web/package.json +++ b/packages/opentelemetry-sdk-trace-web/package.json @@ -17,7 +17,7 @@ "tdd": "karma start", "test:browser": "nyc karma start --single-run", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-semantic-conventions/package.json b/packages/opentelemetry-semantic-conventions/package.json index 30b1fd9cea..116e34923b 100644 --- a/packages/opentelemetry-semantic-conventions/package.json +++ b/packages/opentelemetry-semantic-conventions/package.json @@ -16,7 +16,7 @@ "tdd": "npm run test -- --watch-extensions ts --watch", "version": "node ../../scripts/version-update.js", "watch": "tsc --build --watch tsconfig.all.json", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/opentelemetry-shim-opentracing/package.json b/packages/opentelemetry-shim-opentracing/package.json index ab86bd7f03..4fd7c83dc1 100644 --- a/packages/opentelemetry-shim-opentracing/package.json +++ b/packages/opentelemetry-shim-opentracing/package.json @@ -14,7 +14,7 @@ "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "version": "node ../../scripts/version-update.js", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "keywords": [ diff --git a/packages/template/package.json b/packages/template/package.json index 518029fa49..956ba645f3 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -25,7 +25,7 @@ "compile": "tsc --build", "version": "node ../../scripts/version-update.js", "clean": "tsc --build --clean", - "precompile": "lerna run version --scope $(npm pkg get name) --include-filtered-dependencies", + "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, "Add these to scripts": { From 9a727f8b21b12f2ad1f79c90c8851a56bb078a01 Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Wed, 5 Jan 2022 04:05:26 -0500 Subject: [PATCH 02/16] chore: add Rauno Viskus as maintainer (#2701) --- README.md | 1 + renovate.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 33eeeff0b2..e6c68a574e 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,7 @@ Approvers ([@open-telemetry/js-approvers](https://github.com/orgs/open-telemetry Maintainers ([@open-telemetry/js-maintainers](https://github.com/orgs/open-telemetry/teams/javascript-maintainers)): - [Daniel Dyla](https://github.com/dyladan), Dynatrace +- [Rauno Viskus](https://github.com/Rauno56), Splunk - [Valentin Marchaud](https://github.com/vmarchaud), Open Source Contributor *Find more about the maintainer role in [community repository](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer).* diff --git a/renovate.json b/renovate.json index b3b968bd10..56807558a4 100644 --- a/renovate.json +++ b/renovate.json @@ -17,7 +17,7 @@ } ], "ignoreDeps": ["gcp-metadata", "got", "mocha", "husky", "karma-webpack"], - "assignees": ["@dyladan", "@vmarchaud"], + "assignees": ["@dyladan", "@Rauno56", "@vmarchaud"], "schedule": ["before 3am on Friday"], "labels": ["dependencies"] } From dce6eb7abc32bf39a051ee25e2cebfc921d9572f Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Wed, 5 Jan 2022 08:27:06 -0500 Subject: [PATCH 03/16] chore: add Amir Blum as maintainer (#2703) Co-authored-by: Valentin Marchaud --- README.md | 1 + renovate.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e6c68a574e..d1b0ddba7f 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,7 @@ Approvers ([@open-telemetry/js-approvers](https://github.com/orgs/open-telemetry Maintainers ([@open-telemetry/js-maintainers](https://github.com/orgs/open-telemetry/teams/javascript-maintainers)): +- [Amir Blum](https://github.com/blumamir), Aspecto - [Daniel Dyla](https://github.com/dyladan), Dynatrace - [Rauno Viskus](https://github.com/Rauno56), Splunk - [Valentin Marchaud](https://github.com/vmarchaud), Open Source Contributor diff --git a/renovate.json b/renovate.json index 56807558a4..a41608a9c2 100644 --- a/renovate.json +++ b/renovate.json @@ -17,7 +17,7 @@ } ], "ignoreDeps": ["gcp-metadata", "got", "mocha", "husky", "karma-webpack"], - "assignees": ["@dyladan", "@Rauno56", "@vmarchaud"], + "assignees": ["@blumamir", "@dyladan", "@Rauno56", "@vmarchaud"], "schedule": ["before 3am on Friday"], "labels": ["dependencies"] } From fb2031be6b7d2464ccd72163baa9cf52362d56e7 Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Wed, 5 Jan 2022 08:43:01 -0500 Subject: [PATCH 04/16] chore: add Chengzhong Wu as maintainer (#2702) --- README.md | 2 +- renovate.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d1b0ddba7f..18d6cbf629 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,6 @@ We have a weekly SIG meeting! See the [community page](https://github.com/open-t Approvers ([@open-telemetry/js-approvers](https://github.com/orgs/open-telemetry/teams/javascript-approvers)): -- [Chengzhong Wu](https://github.com/legendecas), Alibaba - [Gerhard Stöbich](https://github.com/Flarna), Dynatrace - [John Bley](https://github.com/johnbley), Splunk - [Mark Wolff](https://github.com/markwolff), Microsoft @@ -193,6 +192,7 @@ Approvers ([@open-telemetry/js-approvers](https://github.com/orgs/open-telemetry Maintainers ([@open-telemetry/js-maintainers](https://github.com/orgs/open-telemetry/teams/javascript-maintainers)): - [Amir Blum](https://github.com/blumamir), Aspecto +- [Chengzhong Wu](https://github.com/legendecas), Alibaba - [Daniel Dyla](https://github.com/dyladan), Dynatrace - [Rauno Viskus](https://github.com/Rauno56), Splunk - [Valentin Marchaud](https://github.com/vmarchaud), Open Source Contributor diff --git a/renovate.json b/renovate.json index a41608a9c2..f284cae23d 100644 --- a/renovate.json +++ b/renovate.json @@ -17,7 +17,7 @@ } ], "ignoreDeps": ["gcp-metadata", "got", "mocha", "husky", "karma-webpack"], - "assignees": ["@blumamir", "@dyladan", "@Rauno56", "@vmarchaud"], + "assignees": ["@blumamir", "@dyladan", "@legendecas", "@Rauno56", "@vmarchaud"], "schedule": ["before 3am on Friday"], "labels": ["dependencies"] } From 5f3cbc2c2dee6482d396c627a45c951664be3e36 Mon Sep 17 00:00:00 2001 From: Nikolay Lagutko Date: Wed, 5 Jan 2022 22:21:08 +0300 Subject: [PATCH 05/16] fix(propagator-jaeger): 0-pad span-id to match 16-symbol validation (#2694) Co-authored-by: Daniel Dyla --- .../src/JaegerPropagator.ts | 3 ++- .../test/JaegerPropagator.test.ts | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts b/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts index 18cf2cee59..f41f6adf13 100644 --- a/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts +++ b/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts @@ -141,9 +141,10 @@ function deserializeSpanContext(serializedString: string): SpanContext | null { return null; } - const [_traceId, spanId, , flags] = headers; + const [_traceId, _spanId, , flags] = headers; const traceId = _traceId.padStart(32, '0'); + const spanId = _spanId.padStart(16, '0'); const traceFlags = flags.match(/^[0-9a-f]{2}$/i) ? parseInt(flags) & 1 : 1; return { traceId, spanId, isRemote: true, traceFlags }; diff --git a/packages/opentelemetry-propagator-jaeger/test/JaegerPropagator.test.ts b/packages/opentelemetry-propagator-jaeger/test/JaegerPropagator.test.ts index be93f05194..f0683898bf 100644 --- a/packages/opentelemetry-propagator-jaeger/test/JaegerPropagator.test.ts +++ b/packages/opentelemetry-propagator-jaeger/test/JaegerPropagator.test.ts @@ -299,6 +299,21 @@ describe('JaegerPropagator', () => { assert(typeof firstEntry !== 'undefined'); assert(firstEntry.value === 'one'); }); + + it('should 0-pad span and trace id from header', () => { + carrier[UBER_TRACE_ID_HEADER] = '4cda95b652f4a1592b449d5929fda1b:e0c63257de34c92:0:01'; + const extractedSpanContext = trace.getSpanContext( + jaegerPropagator.extract( + ROOT_CONTEXT, + carrier, + defaultTextMapGetter + ) + ); + + assert.ok(extractedSpanContext); + assert.equal(extractedSpanContext.spanId, '0e0c63257de34c92'); + assert.equal(extractedSpanContext.traceId, '04cda95b652f4a1592b449d5929fda1b'); + }); }); describe('.fields()', () => { From d61f7bee0f7f60fed794d956e122decd0ce6748f Mon Sep 17 00:00:00 2001 From: legendecas Date: Fri, 7 Jan 2022 01:20:45 +0800 Subject: [PATCH 06/16] refactor: unifying shutdown once with BindOnceFuture (#2695) Co-authored-by: Valentin Marchaud --- .../exporter-trace-otlp-grpc/tsconfig.json | 9 +++ .../src/OTLPExporterBase.ts | 38 ++++------- .../browser/OTLPExporterBrowserBase.ts | 2 +- .../src/platform/node/OTLPExporterNodeBase.ts | 6 +- .../exporter-trace-otlp-http/tsconfig.json | 11 ++++ .../exporter-trace-otlp-proto/tsconfig.json | 9 +++ packages/opentelemetry-core/src/index.ts | 1 + .../opentelemetry-core/src/utils/callback.ts | 54 ++++++++++++++++ .../opentelemetry-core/src/utils/promise.ts | 39 ++++++++++++ .../opentelemetry-core/test/test-utils.ts | 30 +++++++++ .../test/utils/callback.test.ts | 63 +++++++++++++++++++ .../test/utils/promise.test.ts | 41 ++++++++++++ .../src/jaeger.ts | 54 ++++++---------- .../src/export/BatchSpanProcessorBase.ts | 47 +++++++------- .../src/export/SimpleSpanProcessor.ts | 30 ++++----- 15 files changed, 323 insertions(+), 111 deletions(-) create mode 100644 packages/opentelemetry-core/src/utils/callback.ts create mode 100644 packages/opentelemetry-core/src/utils/promise.ts create mode 100644 packages/opentelemetry-core/test/test-utils.ts create mode 100644 packages/opentelemetry-core/test/utils/callback.test.ts create mode 100644 packages/opentelemetry-core/test/utils/promise.test.ts diff --git a/packages/exporter-trace-otlp-grpc/tsconfig.json b/packages/exporter-trace-otlp-grpc/tsconfig.json index e95e7e3c76..573e18d61f 100644 --- a/packages/exporter-trace-otlp-grpc/tsconfig.json +++ b/packages/exporter-trace-otlp-grpc/tsconfig.json @@ -11,6 +11,15 @@ "references": [ { "path": "../exporter-trace-otlp-http" + }, + { + "path": "../opentelemetry-core" + }, + { + "path": "../opentelemetry-resources" + }, + { + "path": "../opentelemetry-sdk-trace-base" } ] } diff --git a/packages/exporter-trace-otlp-http/src/OTLPExporterBase.ts b/packages/exporter-trace-otlp-http/src/OTLPExporterBase.ts index 1cbf94f633..2dc095bcc5 100644 --- a/packages/exporter-trace-otlp-http/src/OTLPExporterBase.ts +++ b/packages/exporter-trace-otlp-http/src/OTLPExporterBase.ts @@ -15,7 +15,7 @@ */ import { SpanAttributes, diag } from '@opentelemetry/api'; -import { ExportResult, ExportResultCode } from '@opentelemetry/core'; +import { ExportResult, ExportResultCode, BindOnceFuture } from '@opentelemetry/core'; import { OTLPExporterError, OTLPExporterConfigBase, @@ -34,9 +34,8 @@ export abstract class OTLPExporterBase< public readonly hostname: string | undefined; public readonly attributes?: SpanAttributes; protected _concurrencyLimit: number; - protected _isShutdown: boolean = false; - private _shuttingDownPromise: Promise = Promise.resolve(); protected _sendingPromises: Promise[] = []; + protected _shutdownOnce: BindOnceFuture; /** * @param config @@ -50,6 +49,7 @@ export abstract class OTLPExporterBase< this.attributes = config.attributes; this.shutdown = this.shutdown.bind(this); + this._shutdownOnce = new BindOnceFuture(this._shutdown, this); this._concurrencyLimit = typeof config.concurrencyLimit === 'number' @@ -66,7 +66,7 @@ export abstract class OTLPExporterBase< * @param resultCallback */ export(items: ExportItem[], resultCallback: (result: ExportResult) => void): void { - if (this._isShutdown) { + if (this._shutdownOnce.isCalled) { resultCallback({ code: ExportResultCode.FAILED, error: new Error('Exporter has been shutdown'), @@ -106,28 +106,16 @@ export abstract class OTLPExporterBase< * Shutdown the exporter. */ shutdown(): Promise { - if (this._isShutdown) { - diag.debug('shutdown already started'); - return this._shuttingDownPromise; - } - this._isShutdown = true; + return this._shutdownOnce.call(); + } + + private _shutdown(): Promise { diag.debug('shutdown started'); - this._shuttingDownPromise = new Promise((resolve, reject) => { - Promise.resolve() - .then(() => { - return this.onShutdown(); - }) - .then(() => { - return Promise.all(this._sendingPromises); - }) - .then(() => { - resolve(); - }) - .catch(e => { - reject(e); - }); - }); - return this._shuttingDownPromise; + this.onShutdown(); + return Promise.all(this._sendingPromises) + .then(() => { + /** ignore resolved values */ + }); } abstract onShutdown(): void; diff --git a/packages/exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts b/packages/exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts index 421772fcc2..9e6ff10144 100644 --- a/packages/exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts +++ b/packages/exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts @@ -69,7 +69,7 @@ export abstract class OTLPExporterBrowserBase< onSuccess: () => void, onError: (error: otlpTypes.OTLPExporterError) => void ): void { - if (this._isShutdown) { + if (this._shutdownOnce.isCalled) { diag.debug('Shutdown already started. Cannot send objects'); return; } diff --git a/packages/exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts b/packages/exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts index 920f0ac043..c48d49fc42 100644 --- a/packages/exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts +++ b/packages/exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts @@ -56,16 +56,14 @@ export abstract class OTLPExporterNodeBase< this.compression = config.compression || CompressionAlgorithm.NONE; } - onInit(_config: OTLPExporterNodeConfigBase): void { - this._isShutdown = false; - } + onInit(_config: OTLPExporterNodeConfigBase): void {} send( objects: ExportItem[], onSuccess: () => void, onError: (error: otlpTypes.OTLPExporterError) => void ): void { - if (this._isShutdown) { + if (this._shutdownOnce.isCalled) { diag.debug('Shutdown already started. Cannot send objects'); return; } diff --git a/packages/exporter-trace-otlp-http/tsconfig.json b/packages/exporter-trace-otlp-http/tsconfig.json index bdc94d2213..1d7ba827ac 100644 --- a/packages/exporter-trace-otlp-http/tsconfig.json +++ b/packages/exporter-trace-otlp-http/tsconfig.json @@ -7,5 +7,16 @@ "include": [ "src/**/*.ts", "test/**/*.ts" + ], + "references": [ + { + "path": "../opentelemetry-core" + }, + { + "path": "../opentelemetry-resources" + }, + { + "path": "../opentelemetry-sdk-trace-base" + } ] } diff --git a/packages/exporter-trace-otlp-proto/tsconfig.json b/packages/exporter-trace-otlp-proto/tsconfig.json index e95e7e3c76..573e18d61f 100644 --- a/packages/exporter-trace-otlp-proto/tsconfig.json +++ b/packages/exporter-trace-otlp-proto/tsconfig.json @@ -11,6 +11,15 @@ "references": [ { "path": "../exporter-trace-otlp-http" + }, + { + "path": "../opentelemetry-core" + }, + { + "path": "../opentelemetry-resources" + }, + { + "path": "../opentelemetry-sdk-trace-base" } ] } diff --git a/packages/opentelemetry-core/src/index.ts b/packages/opentelemetry-core/src/index.ts index ea9e2d2a37..9316774752 100644 --- a/packages/opentelemetry-core/src/index.ts +++ b/packages/opentelemetry-core/src/index.ts @@ -39,4 +39,5 @@ export * from './utils/merge'; export * from './utils/sampling'; export * from './utils/url'; export * from './utils/wrap'; +export * from './utils/callback'; export * from './version'; diff --git a/packages/opentelemetry-core/src/utils/callback.ts b/packages/opentelemetry-core/src/utils/callback.ts new file mode 100644 index 0000000000..1757fcfc1d --- /dev/null +++ b/packages/opentelemetry-core/src/utils/callback.ts @@ -0,0 +1,54 @@ +/* + * 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 { Deferred } from './promise'; + +/** + * Bind the callback and only invoke the callback once regardless how many times `BindOnceFuture.call` is invoked. + */ +export class BindOnceFuture< + R, + This = unknown, + T extends (this: This, ...args: unknown[]) => R = () => R +> { + private _isCalled = false; + private _deferred = new Deferred(); + constructor(private _callback: T, private _that: This) {} + + get isCalled() { + return this._isCalled; + } + + get promise() { + return this._deferred.promise; + } + + call(...args: Parameters): Promise { + if (!this._isCalled) { + this._isCalled = true; + try { + Promise.resolve(this._callback.call(this._that, ...args)) + .then( + val => this._deferred.resolve(val), + err => this._deferred.reject(err) + ); + } catch (err) { + this._deferred.reject(err); + } + } + return this._deferred.promise; + } +} diff --git a/packages/opentelemetry-core/src/utils/promise.ts b/packages/opentelemetry-core/src/utils/promise.ts new file mode 100644 index 0000000000..ff0c8e90de --- /dev/null +++ b/packages/opentelemetry-core/src/utils/promise.ts @@ -0,0 +1,39 @@ +/* + * 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 class Deferred { + private _promise: Promise; + private _resolve!: (val: T) => void; + private _reject!: (error: unknown) => void; + constructor() { + this._promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + }); + } + + get promise() { + return this._promise; + } + + resolve(val: T) { + this._resolve(val); + } + + reject(err: unknown) { + this._reject(err); + } +} diff --git a/packages/opentelemetry-core/test/test-utils.ts b/packages/opentelemetry-core/test/test-utils.ts new file mode 100644 index 0000000000..72ec427730 --- /dev/null +++ b/packages/opentelemetry-core/test/test-utils.ts @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as assert from 'assert'; + +/** + * Node.js v8.x and browser compatible `assert.rejects`. + */ +export async function assertRejects(promise: any, expect: any) { + try { + await promise; + } catch (err) { + assert.throws(() => { + throw err; + }, expect); + } +} diff --git a/packages/opentelemetry-core/test/utils/callback.test.ts b/packages/opentelemetry-core/test/utils/callback.test.ts new file mode 100644 index 0000000000..72805d0f5e --- /dev/null +++ b/packages/opentelemetry-core/test/utils/callback.test.ts @@ -0,0 +1,63 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as assert from 'assert'; +import * as sinon from 'sinon'; +import { BindOnceFuture } from '../../src'; +import { assertRejects } from '../test-utils'; + +describe('callback', () => { + describe('BindOnceFuture', () => { + it('should call once', async () => { + const stub = sinon.stub(); + const that = {}; + const future = new BindOnceFuture(stub, that); + + await Promise.all([ + future.call(1), + future.call(2), + ]); + await future.call(3); + await future.promise; + + assert.strictEqual(stub.callCount, 1); + assert.deepStrictEqual(stub.firstCall.args, [1]); + assert.deepStrictEqual(stub.firstCall.thisValue, that); + + assert(future.isCalled); + }); + + it('should handle thrown errors', async () => { + const stub = sinon.stub(); + stub.throws(new Error('foo')); + const future = new BindOnceFuture(stub, undefined); + + await assertRejects(future.call(), /foo/); + await assertRejects(future.call(), /foo/); + await assertRejects(future.promise, /foo/); + }); + + it('should handle rejections', async () => { + const stub = sinon.stub(); + stub.rejects(new Error('foo')); + const future = new BindOnceFuture(stub, undefined); + + await assertRejects(future.call(), /foo/); + await assertRejects(future.call(), /foo/); + await assertRejects(future.promise, /foo/); + }); + }); +}); diff --git a/packages/opentelemetry-core/test/utils/promise.test.ts b/packages/opentelemetry-core/test/utils/promise.test.ts new file mode 100644 index 0000000000..cf97fdf3b1 --- /dev/null +++ b/packages/opentelemetry-core/test/utils/promise.test.ts @@ -0,0 +1,41 @@ +/* + * 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 { Deferred } from '../../src/utils/promise'; +import { assertRejects } from '../test-utils'; + +describe('promise', () => { + describe('Deferred', () => { + it('should resolve', async () => { + const deferred = new Deferred(); + deferred.resolve(1); + deferred.resolve(2); + deferred.reject(new Error('foo')); + + const ret = await deferred.promise; + assert.strictEqual(ret, 1); + }); + + it('should reject', async () => { + const deferred = new Deferred(); + deferred.reject(new Error('foo')); + deferred.reject(new Error('bar')); + + await assertRejects(deferred.promise, /foo/); + }); + }); +}); diff --git a/packages/opentelemetry-exporter-jaeger/src/jaeger.ts b/packages/opentelemetry-exporter-jaeger/src/jaeger.ts index 319d99ce37..3ae5880710 100644 --- a/packages/opentelemetry-exporter-jaeger/src/jaeger.ts +++ b/packages/opentelemetry-exporter-jaeger/src/jaeger.ts @@ -15,7 +15,7 @@ */ import { diag } from '@opentelemetry/api'; -import { ExportResult, ExportResultCode, getEnv } from '@opentelemetry/core'; +import { BindOnceFuture, ExportResult, ExportResultCode, getEnv } from '@opentelemetry/core'; import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'; import { Socket } from 'dgram'; import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; @@ -28,9 +28,7 @@ import * as jaegerTypes from './types'; export class JaegerExporter implements SpanExporter { private readonly _onShutdownFlushTimeout: number; private readonly _localConfig: jaegerTypes.ExporterConfig; - private _isShutdown = false; - private _shutdownFlushTimeout: NodeJS.Timeout | undefined; - private _shuttingDownPromise: Promise = Promise.resolve(); + private _shutdownOnce: BindOnceFuture; private _sender?: typeof jaegerTypes.UDPSender; @@ -57,6 +55,8 @@ export class JaegerExporter implements SpanExporter { localConfig.host = localConfig.host || env.OTEL_EXPORTER_JAEGER_AGENT_HOST; this._localConfig = localConfig; + + this._shutdownOnce = new BindOnceFuture(this._shutdown, this); } /** Exports a list of spans to Jaeger. */ @@ -64,6 +64,9 @@ export class JaegerExporter implements SpanExporter { spans: ReadableSpan[], resultCallback: (result: ExportResult) => void ): void { + if (this._shutdownOnce.isCalled) { + return; + } if (spans.length === 0) { return resultCallback({ code: ExportResultCode.SUCCESS }); } @@ -75,39 +78,18 @@ export class JaegerExporter implements SpanExporter { /** Shutdown exporter. */ shutdown(): Promise { - if (this._isShutdown) { - return this._shuttingDownPromise; - } - this._isShutdown = true; - - this._shuttingDownPromise = new Promise((resolve, reject) => { - let rejected = false; - this._shutdownFlushTimeout = setTimeout(() => { - rejected = true; - reject('timeout'); - this._sender.close(); - }, this._onShutdownFlushTimeout); - - Promise.resolve() - .then(() => { - // Make an optimistic flush. - return this._flush(); - }) - .then(() => { - if (rejected) { - return; - } else { - this._shutdownFlushTimeout && - clearTimeout(this._shutdownFlushTimeout); - resolve(); - this._sender.close(); - } - }) - .catch(e => { - reject(e); - }); + return this._shutdownOnce.call(); + } + + private _shutdown(): Promise { + return Promise.race([ + new Promise((_resolve, reject) => { + setTimeout(() => reject(new Error('Flush timeout')), this._onShutdownFlushTimeout); + }), + this._flush(), + ]).finally(() => { + this._sender?.close(); }); - return this._shuttingDownPromise; } /** Transform spans and sends to Jaeger service. */ diff --git a/packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts b/packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts index 3785a6ea28..1c32c83d89 100644 --- a/packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts +++ b/packages/opentelemetry-sdk-trace-base/src/export/BatchSpanProcessorBase.ts @@ -16,6 +16,7 @@ import { context, TraceFlags } from '@opentelemetry/api'; import { + BindOnceFuture, ExportResultCode, getEnv, globalErrorHandler, @@ -40,8 +41,7 @@ export abstract class BatchSpanProcessorBase implements private _finishedSpans: ReadableSpan[] = []; private _timer: NodeJS.Timeout | undefined; - private _isShutdown = false; - private _shuttingDownPromise: Promise = Promise.resolve(); + private _shutdownOnce: BindOnceFuture; constructor(private readonly _exporter: SpanExporter, config?: T) { const env = getEnv(); @@ -61,11 +61,13 @@ export abstract class BatchSpanProcessorBase implements typeof config?.exportTimeoutMillis === 'number' ? config.exportTimeoutMillis : env.OTEL_BSP_EXPORT_TIMEOUT; + + this._shutdownOnce = new BindOnceFuture(this._shutdown, this); } forceFlush(): Promise { - if (this._isShutdown) { - return this._shuttingDownPromise; + if (this._shutdownOnce.isCalled) { + return this._shutdownOnce.promise; } return this._flushAll(); } @@ -74,7 +76,7 @@ export abstract class BatchSpanProcessorBase implements onStart(_span: Span): void {} onEnd(span: ReadableSpan): void { - if (this._isShutdown) { + if (this._shutdownOnce.isCalled) { return; } @@ -86,27 +88,20 @@ export abstract class BatchSpanProcessorBase implements } shutdown(): Promise { - if (this._isShutdown) { - return this._shuttingDownPromise; - } - this._isShutdown = true; - this._shuttingDownPromise = new Promise((resolve, reject) => { - Promise.resolve() - .then(() => { - return this.onShutdown(); - }) - .then(() => { - return this._flushAll(); - }) - .then(() => { - return this._exporter.shutdown(); - }) - .then(resolve) - .catch(e => { - reject(e); - }); - }); - return this._shuttingDownPromise; + return this._shutdownOnce.call(); + } + + private _shutdown() { + return Promise.resolve() + .then(() => { + return this.onShutdown(); + }) + .then(() => { + return this._flushAll(); + }) + .then(() => { + return this._exporter.shutdown(); + }); } /** Add a span in the buffer. */ diff --git a/packages/opentelemetry-sdk-trace-base/src/export/SimpleSpanProcessor.ts b/packages/opentelemetry-sdk-trace-base/src/export/SimpleSpanProcessor.ts index 20c096dbbe..c87b864825 100644 --- a/packages/opentelemetry-sdk-trace-base/src/export/SimpleSpanProcessor.ts +++ b/packages/opentelemetry-sdk-trace-base/src/export/SimpleSpanProcessor.ts @@ -19,6 +19,7 @@ import { ExportResultCode, globalErrorHandler, suppressTracing, + BindOnceFuture, } from '@opentelemetry/core'; import { Span } from '../Span'; import { SpanProcessor } from '../SpanProcessor'; @@ -32,10 +33,11 @@ import { SpanExporter } from './SpanExporter'; * Only spans that are sampled are converted. */ export class SimpleSpanProcessor implements SpanProcessor { - constructor(private readonly _exporter: SpanExporter) {} + private _shutdownOnce: BindOnceFuture; - private _isShutdown = false; - private _shuttingDownPromise: Promise = Promise.resolve(); + constructor(private readonly _exporter: SpanExporter) { + this._shutdownOnce = new BindOnceFuture(this._shutdown, this); + } forceFlush(): Promise { // do nothing as all spans are being exported without waiting @@ -46,7 +48,7 @@ export class SimpleSpanProcessor implements SpanProcessor { onStart(_span: Span): void {} onEnd(span: ReadableSpan): void { - if (this._isShutdown) { + if (this._shutdownOnce.isCalled) { return; } @@ -70,20 +72,10 @@ export class SimpleSpanProcessor implements SpanProcessor { } shutdown(): Promise { - if (this._isShutdown) { - return this._shuttingDownPromise; - } - this._isShutdown = true; - this._shuttingDownPromise = new Promise((resolve, reject) => { - Promise.resolve() - .then(() => { - return this._exporter.shutdown(); - }) - .then(resolve) - .catch(e => { - reject(e); - }); - }); - return this._shuttingDownPromise; + return this._shutdownOnce.call(); + } + + private _shutdown(): Promise { + return this._exporter.shutdown(); } } From 354c002283466436397e5640d591171f7fd78135 Mon Sep 17 00:00:00 2001 From: Marc Pichler Date: Fri, 7 Jan 2022 19:48:39 +0100 Subject: [PATCH 07/16] feat(metric-reader): add metric-reader (#2681) --- .../src/export/MetricReader.ts | 119 +++++- .../export/PeriodicExportingMetricReader.ts | 95 +++++ .../src/state/MetricCollector.ts | 4 +- .../src/utils.ts | 44 ++ .../PeriodicExportingMetricReader.test.ts | 379 ++++++++++++++++++ .../test/export/TestMetricReader.ts | 30 ++ .../test/state/MetricCollector.test.ts | 12 +- 7 files changed, 658 insertions(+), 25 deletions(-) create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts index 2d4cd5c0a7..b67876c9b1 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts @@ -14,52 +14,143 @@ * limitations under the License. */ +import * as api from '@opentelemetry/api'; import { AggregationTemporality } from './AggregationTemporality'; -import { MetricExporter } from './MetricExporter'; import { MetricProducer } from './MetricProducer'; +import { MetricData } from './MetricData'; +import { callWithTimeout } from '../utils'; + +export type ReaderOptions = { + timeoutMillis?: number +} + +export type ReaderCollectionOptions = ReaderOptions; + +export type ReaderShutdownOptions = ReaderOptions; + +export type ReaderForceFlushOptions = ReaderOptions; // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#metricreader +/** + * A registered reader of metrics that, when linked to a {@link MetricProducer}, offers global + * control over metrics. + */ export abstract class MetricReader { + // Tracks the shutdown state. + // TODO: use BindOncePromise here once a new version of @opentelemetry/core is available. private _shutdown = false; + // MetricProducer used by this instance. private _metricProducer?: MetricProducer; - constructor(private _exporter: MetricExporter) {} + constructor(private readonly _preferredAggregationTemporality = AggregationTemporality.CUMULATIVE) { + } + /** + * Set the {@link MetricProducer} used by this instance. + * + * @param metricProducer + */ setMetricProducer(metricProducer: MetricProducer) { this._metricProducer = metricProducer; + this.onInitialized(); } + /** + * Get the {@link AggregationTemporality} preferred by this {@link MetricReader} + */ getPreferredAggregationTemporality(): AggregationTemporality { - return this._exporter.getPreferredAggregationTemporality(); + return this._preferredAggregationTemporality; + } + + /** + * Handle once the SDK has initialized this {@link MetricReader} + * Overriding this method is optional. + */ + protected onInitialized(): void { + // Default implementation is empty. } - async collect(): Promise { + /** + * Handle a shutdown signal by the SDK. + * + *

For push exporters, this should shut down any intervals and close any open connections. + * @protected + */ + protected abstract onShutdown(): Promise; + + /** + * Handle a force flush signal by the SDK. + * + *

In all scenarios metrics should be collected via {@link collect()}. + *

For push exporters, this should collect and report metrics. + * @protected + */ + protected abstract onForceFlush(): Promise; + + /** + * Collect all metrics from the associated {@link MetricProducer} + */ + async collect(options?: ReaderCollectionOptions): Promise { if (this._metricProducer === undefined) { - throw new Error('MetricReader is not bound to a MeterProvider'); + throw new Error('MetricReader is not bound to a MetricProducer'); } - const metrics = await this._metricProducer.collect(); - // errors thrown to caller - await this._exporter.export(metrics); + // Subsequent invocations to collect are not allowed. SDKs SHOULD return some failure for these calls. + if (this._shutdown) { + api.diag.warn('Collection is not allowed after shutdown'); + return []; + } + + // No timeout if timeoutMillis is undefined or null. + if (options?.timeoutMillis == null) { + return await this._metricProducer.collect(); + } + + return await callWithTimeout(this._metricProducer.collect(), options.timeoutMillis); } - async shutdown(): Promise { + /** + * Shuts down the metric reader, the promise will reject after the optional timeout or resolve after completion. + * + *

NOTE: this operation will continue even after the promise rejects due to a timeout. + * @param options options with timeout. + */ + async shutdown(options?: ReaderShutdownOptions): Promise { + // Do not call shutdown again if it has already been called. if (this._shutdown) { + api.diag.error('Cannot call shutdown twice.'); return; } + // No timeout if timeoutMillis is undefined or null. + if (options?.timeoutMillis == null) { + await this.onShutdown(); + } else { + await callWithTimeout(this.onShutdown(), options.timeoutMillis); + } + this._shutdown = true; - // errors thrown to caller - await this._exporter.shutdown(); } - async forceFlush(): Promise { + /** + * Flushes metrics read by this reader, the promise will reject after the optional timeout or resolve after completion. + * + *

NOTE: this operation will continue even after the promise rejects due to a timeout. + * @param options options with timeout. + */ + async forceFlush(options?: ReaderForceFlushOptions): Promise { if (this._shutdown) { + api.diag.warn('Cannot forceFlush on already shutdown MetricReader.'); + return; + } + + // No timeout if timeoutMillis is undefined or null. + if (options?.timeoutMillis == null) { + await this.onForceFlush(); return; } - // errors thrown to caller - await this._exporter.forceFlush(); + await callWithTimeout(this.onForceFlush(), options.timeoutMillis); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts new file mode 100644 index 0000000000..f7e5453076 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts @@ -0,0 +1,95 @@ +/* + * 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'; +import { MetricReader } from './MetricReader'; +import { MetricExporter } from './MetricExporter'; +import { callWithTimeout, TimeoutError } from '../utils'; + +export type PeriodicExportingMetricReaderOptions = { + exporter: MetricExporter + exportIntervalMillis?: number, + exportTimeoutMillis?: number +} + +/** + * {@link MetricReader} which collects metrics based on a user-configurable time interval, and passes the metrics to + * the configured {@link MetricExporter} + */ +export class PeriodicExportingMetricReader extends MetricReader { + private _interval?: ReturnType; + + private _exporter: MetricExporter; + + private readonly _exportInterval: number; + + private readonly _exportTimeout: number; + + constructor(options: PeriodicExportingMetricReaderOptions) { + super(options.exporter.getPreferredAggregationTemporality()); + + if (options.exportIntervalMillis !== undefined && options.exportIntervalMillis <= 0) { + throw Error('exportIntervalMillis must be greater than 0'); + } + + if (options.exportTimeoutMillis !== undefined && options.exportTimeoutMillis <= 0) { + throw Error('exportTimeoutMillis must be greater than 0'); + } + + if (options.exportTimeoutMillis !== undefined && + options.exportIntervalMillis !== undefined && + options.exportIntervalMillis < options.exportTimeoutMillis) { + throw Error('exportIntervalMillis must be greater than or equal to exportTimeoutMillis'); + } + + this._exportInterval = options.exportIntervalMillis ?? 60000; + this._exportTimeout = options.exportTimeoutMillis ?? 30000; + this._exporter = options.exporter; + } + + private async _runOnce(): Promise { + const metrics = await this.collect({}); + await this._exporter.export(metrics); + } + + protected override onInitialized(): void { + // start running the interval as soon as this reader is initialized and keep handle for shutdown. + this._interval = setInterval(async () => { + try { + await callWithTimeout(this._runOnce(), this._exportTimeout); + } catch (err) { + if (err instanceof TimeoutError) { + api.diag.error('Export took longer than %s milliseconds and timed out.', this._exportTimeout); + return; + } + + api.diag.error('Unexpected error during export: %s', err); + } + }, this._exportInterval); + } + + protected async onForceFlush(): Promise { + await this._exporter.forceFlush(); + } + + protected async onShutdown(): Promise { + if (this._interval) { + clearInterval(this._interval); + } + + await this._exporter.shutdown(); + } +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts index c1bea5e369..3841354e4b 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts @@ -44,14 +44,14 @@ export class MetricCollector implements MetricProducer { * Delegates for MetricReader.forceFlush. */ async forceFlush(): Promise { - return this._metricReader.forceFlush(); + await this._metricReader.forceFlush(); } /** * Delegates for MetricReader.shutdown. */ async shutdown(): Promise { - return this._metricReader.shutdown(); + await this._metricReader.shutdown(); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/utils.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/utils.ts index 7f269755f2..5ae4e0ee10 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/utils.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/utils.ts @@ -38,3 +38,47 @@ export function hashAttributes(attributes: Attributes): string { return (result += key + ':' + attributes[key]); }, '|#'); } + +/** + * Error that is thrown on timeouts. + */ +export class TimeoutError extends Error { + constructor(message?: string) { + super(message); + + // manually adjust prototype to retain `instanceof` functionality when targeting ES5, see: + // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work + Object.setPrototypeOf(this, TimeoutError.prototype); + } +} + +/** + * Adds a timeout to a promise and rejects if the specified timeout has elapsed. Also rejects if the specified promise + * rejects, and resolves if the specified promise resolves. + * + *

NOTE: this operation will continue even after it throws a {@link TimeoutError}. + * + * @param promise promise to use with timeout. + * @param timeout the timeout in milliseconds until the returned promise is rejected. + */ +export function callWithTimeout(promise: Promise, timeout: number): Promise { + let timeoutHandle: ReturnType; + + const timeoutPromise = new Promise(function timeoutFunction(_resolve, reject) { + timeoutHandle = setTimeout( + function timeoutHandler() { + reject(new TimeoutError('Operation timed out.')); + }, + timeout + ); + }); + + return Promise.race([promise, timeoutPromise]).then(result => { + clearTimeout(timeoutHandle); + return result; + }, + reason => { + clearTimeout(timeoutHandle); + throw reason; + }); +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts new file mode 100644 index 0000000000..ca426e2908 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts @@ -0,0 +1,379 @@ +/* + * 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 { PeriodicExportingMetricReader } from '../../src/export/PeriodicExportingMetricReader'; +import { AggregationTemporality } from '../../src/export/AggregationTemporality'; +import { MetricExporter } from '../../src'; +import { MetricData } from '../../src/export/MetricData'; +import * as assert from 'assert'; +import * as sinon from 'sinon'; +import { MetricProducer } from '../../src/export/MetricProducer'; +import { TimeoutError } from '../../src/utils'; + +const MAX_32_BIT_INT = 2 ** 31 - 1 + +class TestMetricExporter extends MetricExporter { + public exportTime = 0; + public forceFlushTime = 0; + public throwException = false; + private _batches: MetricData[][] = []; + + async export(batch: MetricData[]): Promise { + this._batches.push(batch); + + if (this.throwException) { + throw new Error('Error during export'); + } + await new Promise(resolve => setTimeout(resolve, this.exportTime)); + } + + async forceFlush(): Promise { + if (this.throwException) { + throw new Error('Error during forceFlush'); + } + + await new Promise(resolve => setTimeout(resolve, this.forceFlushTime)); + } + + async waitForNumberOfExports(numberOfExports: number): Promise { + if (numberOfExports <= 0) { + throw new Error('numberOfExports must be greater than or equal to 0'); + } + + while (this._batches.length < numberOfExports) { + await new Promise(resolve => setTimeout(resolve, 20)); + } + return this._batches.slice(0, numberOfExports); + } + + getPreferredAggregationTemporality(): AggregationTemporality { + return AggregationTemporality.CUMULATIVE; + } +} + +class TestDeltaMetricExporter extends TestMetricExporter { + override getPreferredAggregationTemporality(): AggregationTemporality { + return AggregationTemporality.DELTA; + } +} + +class TestMetricProducer implements MetricProducer { + public collectionTime = 0; + + async collect(): Promise { + await new Promise(resolve => setTimeout(resolve, this.collectionTime)); + return []; + } +} + +describe('PeriodicExportingMetricReader', () => { + afterEach(() => { + sinon.restore(); + }); + + describe('constructor', () => { + it('should construct PeriodicExportingMetricReader without exceptions', () => { + const exporter = new TestDeltaMetricExporter(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: 4000, + exportTimeoutMillis: 3000 + } + ); + assert.strictEqual(reader.getPreferredAggregationTemporality(), exporter.getPreferredAggregationTemporality()); + }) + + it('should throw when interval less or equal to 0', () => { + const exporter = new TestDeltaMetricExporter(); + assert.throws(() => new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: 0, + exportTimeoutMillis: 0 + }), new Error('exportIntervalMillis must be greater than 0')); + }) + + it('should throw when timeout less or equal to 0', () => { + const exporter = new TestDeltaMetricExporter(); + assert.throws(() => new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: 1, + exportTimeoutMillis: 0 + }), new Error('exportTimeoutMillis must be greater than 0')); + }) + + it('should throw when timeout less or equal to interval', () => { + const exporter = new TestDeltaMetricExporter(); + assert.throws(() => new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: 100, + exportTimeoutMillis: 200 + }), new Error('exportIntervalMillis must be greater than or equal to exportTimeoutMillis')); + }) + + it('should not start exporting', async () => { + const exporter = new TestDeltaMetricExporter(); + const exporterMock = sinon.mock(exporter); + exporterMock.expects('export').never(); + + new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: 1, + exportTimeoutMillis: 1 + }); + await new Promise(resolve => setTimeout(resolve, 50)); + + exporterMock.verify(); + }) + }); + + describe('setMetricProducer', () => { + it('should start exporting periodically', async () => { + const exporter = new TestMetricExporter(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: 30, + exportTimeoutMillis: 20 + }); + + reader.setMetricProducer(new TestMetricProducer()); + const result = await exporter.waitForNumberOfExports(2); + + assert.deepEqual(result, [[], []]); + await reader.shutdown(); + }); + }); + + describe('periodic export', () => { + it('should keep running on export errors', async () => { + const exporter = new TestMetricExporter(); + exporter.throwException = true; + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: 30, + exportTimeoutMillis: 20 + }); + + reader.setMetricProducer(new TestMetricProducer()); + + const result = await exporter.waitForNumberOfExports(2); + assert.deepEqual(result, [[], []]); + + exporter.throwException = false; + await reader.shutdown(); + }); + + it('should keep exporting on export timeouts', async () => { + const exporter = new TestMetricExporter(); + // set time longer than timeout. + exporter.exportTime = 40; + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: 30, + exportTimeoutMillis: 20 + }); + + reader.setMetricProducer(new TestMetricProducer()); + + const result = await exporter.waitForNumberOfExports(2); + assert.deepEqual(result, [[], []]); + + exporter.throwException = false; + await reader.shutdown(); + }); + }); + + describe('forceFlush', () => { + afterEach(() => { + sinon.restore(); + }); + + it('should forceFlush exporter', async () => { + const exporter = new TestMetricExporter(); + const exporterMock = sinon.mock(exporter); + exporterMock.expects('forceFlush').calledOnceWithExactly(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80 + }); + + reader.setMetricProducer(new TestMetricProducer()); + await reader.forceFlush(); + exporterMock.verify(); + await reader.shutdown(); + }); + + it('should throw TimeoutError when forceFlush takes too long', async () => { + const exporter = new TestMetricExporter(); + exporter.forceFlushTime = 60; + + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80, + }); + + reader.setMetricProducer(new TestMetricProducer()); + await assert.rejects(() => reader.forceFlush({ timeoutMillis: 20 }), + TimeoutError); + await reader.shutdown(); + }); + + it('should throw when exporter throws', async () => { + const exporter = new TestMetricExporter(); + exporter.throwException = true; + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80, + }); + + await assert.rejects(() => reader.forceFlush()); + }); + + it('should not forceFlush exporter after shutdown', async () => { + const exporter = new TestMetricExporter(); + const exporterMock = sinon.mock(exporter); + // expect once on shutdown. + exporterMock.expects('forceFlush').once(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80, + }); + + reader.setMetricProducer(new TestMetricProducer()); + await reader.shutdown(); + await reader.forceFlush(); + + exporterMock.verify(); + }); + }); + + describe('shutdown', () => { + afterEach(() => { + sinon.restore(); + }); + + it('should forceFlush', async () => { + const exporter = new TestMetricExporter(); + const exporterMock = sinon.mock(exporter); + exporterMock.expects('forceFlush').calledOnceWithExactly(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80 + }); + + reader.setMetricProducer(new TestMetricProducer()); + await reader.shutdown(); + exporterMock.verify(); + }); + + it('should throw TimeoutError when forceFlush takes too long', async () => { + const exporter = new TestMetricExporter(); + exporter.forceFlushTime = 1000; + + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80, + }); + + reader.setMetricProducer(new TestMetricProducer()); + await assert.rejects(() => reader.shutdown({ timeoutMillis: 20 }), + TimeoutError); + }); + + it('called twice should call export shutdown only once', async () => { + const exporter = new TestMetricExporter(); + const exporterMock = sinon.mock(exporter); + exporterMock.expects('shutdown').calledOnceWithExactly(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80 + }); + + reader.setMetricProducer(new TestMetricProducer()); + + // call twice, the exporter's shutdown must only be called once. + await reader.shutdown(); + await reader.shutdown(); + + exporterMock.verify(); + }); + + it('should throw on non-initialized instance.', async () => { + const exporter = new TestMetricExporter(); + exporter.throwException = true; + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80, + }); + + await assert.rejects(() => reader.shutdown()); + }); + }) + ; + + describe('collect', () => { + it('should throw on non-initialized instance', async () => { + const exporter = new TestMetricExporter(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80, + }); + + await assert.rejects(() => reader.collect()); + }); + + it('should return empty on shut-down instance', async () => { + const exporter = new TestMetricExporter(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80, + }); + + reader.setMetricProducer(new TestMetricProducer()); + + await reader.shutdown(); + assert.deepEqual([], await reader.collect()); + }); + + it('should time out when timeoutMillis is set', async () => { + const exporter = new TestMetricExporter(); + const reader = new PeriodicExportingMetricReader({ + exporter: exporter, + exportIntervalMillis: MAX_32_BIT_INT, + exportTimeoutMillis: 80, + }); + const producer = new TestMetricProducer(); + producer.collectionTime = 40; + reader.setMetricProducer(producer); + + await assert.rejects( + () => reader.collect({ timeoutMillis: 20 }), + TimeoutError + ); + + await reader.shutdown(); + }); + }); +}); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts new file mode 100644 index 0000000000..02c076e675 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { MetricReader } from '../../src'; + +/** + * A test metric reader that implements no-op onForceFlush() and onShutdown() handlers. + */ +export class TestMetricReader extends MetricReader { + protected onForceFlush(): Promise { + return Promise.resolve(undefined); + } + + protected onShutdown(): Promise { + return Promise.resolve(undefined); + } +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts index 900225cdf3..ce94c080cb 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts @@ -19,11 +19,11 @@ import * as sinon from 'sinon'; import { AggregationTemporality } from '../../src/export/AggregationTemporality'; import { MetricData, PointDataType } from '../../src/export/MetricData'; import { MetricExporter } from '../../src/export/MetricExporter'; -import { MetricReader } from '../../src/export/MetricReader'; import { Meter } from '../../src/Meter'; import { MeterProviderSharedState } from '../../src/state/MeterProviderSharedState'; import { MetricCollector } from '../../src/state/MetricCollector'; import { defaultInstrumentationLibrary, defaultResource, assertMetricData, assertPointData } from '../util'; +import { TestMetricReader } from '../export/TestMetricReader'; class TestMetricExporter extends MetricExporter { metricDataList: MetricData[] = [] @@ -44,12 +44,6 @@ class TestDeltaMetricExporter extends TestMetricExporter { } } -class TestMetricReader extends MetricReader { - getMetricCollector(): MetricCollector { - return this['_metricProducer'] as MetricCollector; - } -} - describe('MetricCollector', () => { afterEach(() => { sinon.restore(); @@ -60,7 +54,7 @@ describe('MetricCollector', () => { const meterProviderSharedState = new MeterProviderSharedState(defaultResource); const exporters = [ new TestMetricExporter(), new TestDeltaMetricExporter() ]; for (const exporter of exporters) { - const reader = new TestMetricReader(exporter); + const reader = new TestMetricReader(exporter.getPreferredAggregationTemporality()); const metricCollector = new MetricCollector(meterProviderSharedState, reader); assert.strictEqual(metricCollector.aggregatorTemporality, exporter.getPreferredAggregationTemporality()); @@ -73,7 +67,7 @@ describe('MetricCollector', () => { // TODO(legendecas): setup with MeterProvider when meter identity was settled. const meterProviderSharedState = new MeterProviderSharedState(defaultResource); - const reader = new TestMetricReader(exporter); + const reader = new TestMetricReader(exporter.getPreferredAggregationTemporality()); const metricCollector = new MetricCollector(meterProviderSharedState, reader); meterProviderSharedState.metricCollectors.push(metricCollector); From 6b94e260225ea8f45d0e8bd19bd6b61e2b8607a8 Mon Sep 17 00:00:00 2001 From: legendecas Date: Sun, 9 Jan 2022 05:36:52 +0800 Subject: [PATCH 08/16] feat(sdk-metrics-base): meter registration (#2666) --- .../src/Meter.ts | 4 +- .../src/MeterProvider.ts | 8 +-- .../src/state/MeterProviderSharedState.ts | 2 +- .../src/state/MetricCollector.ts | 2 +- .../test/MeterProvider.test.ts | 50 +++++++++++++++++++ .../test/export/TestMetricReader.ts | 5 ++ .../test/state/MetricCollector.test.ts | 14 +++--- 7 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts index b47da6e835..a9a3beb556 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts @@ -34,7 +34,9 @@ export class Meter implements metrics.Meter { // instrumentation library required by spec to be on meter // spec requires provider config changes to apply to previously created meters, achieved by holding a reference to the provider - constructor(private _meterProviderSharedState: MeterProviderSharedState, private _instrumentationLibrary: InstrumentationLibrary) { } + constructor(private _meterProviderSharedState: MeterProviderSharedState, private _instrumentationLibrary: InstrumentationLibrary) { + this._meterProviderSharedState.meters.push(this); + } /** this exists just to prevent ts errors from unused variables and may be removed */ getInstrumentationLibrary(): InstrumentationLibrary { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts index 62c8892cbe..5a53453303 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts @@ -35,8 +35,8 @@ export class MeterProvider { private _sharedState: MeterProviderSharedState; private _shutdown = false; - constructor(options: MeterProviderOptions) { - this._sharedState = new MeterProviderSharedState(options.resource ?? Resource.empty()); + constructor(options?: MeterProviderOptions) { + this._sharedState = new MeterProviderSharedState(options?.resource ?? Resource.empty()); } getMeter(name: string, version = '', options: metrics.MeterOptions = {}): metrics.Meter { @@ -46,10 +46,6 @@ export class MeterProvider { return metrics.NOOP_METER; } - // Spec leaves it unspecified if creating a meter with duplicate - // name/version returns the same meter. We create a new one here - // for simplicity. This may change in the future. - // TODO: consider returning the same meter if the same name/version is used return new Meter(this._sharedState, { name, version, schemaUrl: options.schemaUrl }); } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts index 2f59eade1f..f6d81a82f9 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MeterProviderSharedState.ts @@ -30,7 +30,7 @@ export class MeterProviderSharedState { metricCollectors: MetricCollector[] = []; - meters: Map = new Map(); + meters: Meter[] = []; constructor(public resource: Resource) {} } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts index 3841354e4b..46fc576f50 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/MetricCollector.ts @@ -34,7 +34,7 @@ export class MetricCollector implements MetricProducer { async collect(): Promise { const collectionTime = hrTime(); - const results = await Promise.all(Array.from(this._sharedState.meters.values()) + const results = await Promise.all(this._sharedState.meters .map(meter => meter.collect(this, collectionTime))); return results.reduce((cumulation, current) => cumulation.concat(current), []); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts new file mode 100644 index 0000000000..a2c7802b87 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/MeterProvider.test.ts @@ -0,0 +1,50 @@ +/* + * 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 { NOOP_METER } from '@opentelemetry/api-metrics-wip'; +import { Meter } from '../src/Meter'; +import { MeterProvider } from '../src/MeterProvider'; +import { defaultResource } from './util'; + +describe('MeterProvider', () => { + describe('constructor', () => { + it('should construct without exceptions', () => { + const meterProvider = new MeterProvider(); + assert(meterProvider instanceof MeterProvider); + }); + + it('construct with resource', () => { + const meterProvider = new MeterProvider({ resource: defaultResource }); + assert(meterProvider instanceof MeterProvider); + }); + }); + + describe('getMeter', () => { + it('should get a meter', () => { + const meterProvider = new MeterProvider(); + const meter = meterProvider.getMeter('meter1', '1.0.0'); + assert(meter instanceof Meter); + }); + + it('get a noop meter on shutdown', () => { + const meterProvider = new MeterProvider(); + meterProvider.shutdown(); + const meter = meterProvider.getMeter('meter1', '1.0.0'); + assert.strictEqual(meter, NOOP_METER); + }); + }); +}); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts index 02c076e675..172301d958 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/TestMetricReader.ts @@ -15,6 +15,7 @@ */ import { MetricReader } from '../../src'; +import { MetricCollector } from '../../src/state/MetricCollector'; /** * A test metric reader that implements no-op onForceFlush() and onShutdown() handlers. @@ -27,4 +28,8 @@ export class TestMetricReader extends MetricReader { protected onShutdown(): Promise { return Promise.resolve(undefined); } + + getMetricCollector(): MetricCollector { + return this['_metricProducer'] as MetricCollector; + } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts index ce94c080cb..4aba1f7146 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts @@ -16,10 +16,10 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; +import { MeterProvider } from '../../src'; import { AggregationTemporality } from '../../src/export/AggregationTemporality'; import { MetricData, PointDataType } from '../../src/export/MetricData'; import { MetricExporter } from '../../src/export/MetricExporter'; -import { Meter } from '../../src/Meter'; import { MeterProviderSharedState } from '../../src/state/MeterProviderSharedState'; import { MetricCollector } from '../../src/state/MetricCollector'; import { defaultInstrumentationLibrary, defaultResource, assertMetricData, assertPointData } from '../util'; @@ -64,15 +64,15 @@ describe('MetricCollector', () => { describe('collect', () => { function setupInstruments(exporter: MetricExporter) { - // TODO(legendecas): setup with MeterProvider when meter identity was settled. - const meterProviderSharedState = new MeterProviderSharedState(defaultResource); + const meterProvider = new MeterProvider({ resource: defaultResource }); const reader = new TestMetricReader(exporter.getPreferredAggregationTemporality()); - const metricCollector = new MetricCollector(meterProviderSharedState, reader); - meterProviderSharedState.metricCollectors.push(metricCollector); + meterProvider.addMetricReader(reader); + const metricCollector = reader.getMetricCollector(); - const meter = new Meter(meterProviderSharedState, defaultInstrumentationLibrary); - meterProviderSharedState.meters.set('test-meter', meter); + const meter = meterProvider.getMeter(defaultInstrumentationLibrary.name, defaultInstrumentationLibrary.version, { + schemaUrl: defaultInstrumentationLibrary.schemaUrl, + }); return { metricCollector, meter }; } From 4909cf122abacfe1f2aa428ed8134fe5eabeb76b Mon Sep 17 00:00:00 2001 From: legendecas Date: Tue, 11 Jan 2022 00:50:08 +0800 Subject: [PATCH 09/16] fix(sdk-metrics-base): remove aggregator.toMetricData dependency on AggregationTemporality (#2676) Co-authored-by: Valentin Marchaud --- .../src/aggregator/Drop.ts | 7 +-- .../src/aggregator/Histogram.ts | 11 ++-- .../src/aggregator/LastValue.ts | 11 ++-- .../src/aggregator/Sum.ts | 11 ++-- .../src/aggregator/types.ts | 13 ++-- .../src/state/TemporalMetricProcessor.ts | 8 +-- .../test/aggregator/Drop.test.ts | 12 ++-- .../test/aggregator/Histogram.test.ts | 62 +++---------------- .../test/aggregator/LastValue.test.ts | 56 +++-------------- .../test/aggregator/Sum.test.ts | 54 +++------------- 10 files changed, 46 insertions(+), 199 deletions(-) diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Drop.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Drop.ts index 2ff35d8b86..54ad0ce7ed 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Drop.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Drop.ts @@ -17,7 +17,6 @@ import { HrTime } from '@opentelemetry/api'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { AggregationTemporality } from '../export/AggregationTemporality'; import { MetricData } from '../export/MetricData'; import { InstrumentDescriptor } from '../InstrumentDescriptor'; import { Maybe } from '../utils'; @@ -48,10 +47,8 @@ export class DropAggregator implements Aggregator { _instrumentationLibrary: InstrumentationLibrary, _instrumentDescriptor: InstrumentDescriptor, _accumulationByAttributes: AccumulationRecord[], - _temporality: AggregationTemporality, - _sdkStartTime: HrTime, - _lastCollectionTime: HrTime, - _collectionTime: HrTime): Maybe { + _startTime: HrTime, + _endTime: HrTime): Maybe { return undefined; } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts index 820f0c4898..fadfc1f303 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts @@ -25,7 +25,6 @@ import { HistogramMetricData, PointDataType } from '../export/MetricData'; import { Resource } from '@opentelemetry/resources'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { HrTime } from '@opentelemetry/api'; -import { AggregationTemporality } from '../export/AggregationTemporality'; import { InstrumentDescriptor } from '../InstrumentDescriptor'; import { Maybe } from '../utils'; @@ -143,10 +142,8 @@ export class HistogramAggregator implements Aggregator { instrumentationLibrary: InstrumentationLibrary, metricDescriptor: InstrumentDescriptor, accumulationByAttributes: AccumulationRecord[], - temporality: AggregationTemporality, - sdkStartTime: HrTime, - lastCollectionTime: HrTime, - collectionTime: HrTime): Maybe { + startTime: HrTime, + endTime: HrTime): Maybe { return { resource, instrumentationLibrary, @@ -155,8 +152,8 @@ export class HistogramAggregator implements Aggregator { pointData: accumulationByAttributes.map(([attributes, accumulation]) => { return { attributes, - startTime: temporality === AggregationTemporality.CUMULATIVE ? sdkStartTime : lastCollectionTime, - endTime: collectionTime, + startTime, + endTime, point: accumulation.toPoint(), } }) diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts index fb86c26d0b..2ed5b93817 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts @@ -18,7 +18,6 @@ import { LastValue, AggregatorKind, Aggregator, Accumulation, AccumulationRecord import { HrTime } from '@opentelemetry/api'; import { hrTime, hrTimeToMicroseconds, InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { AggregationTemporality } from '../export/AggregationTemporality'; import { PointDataType, SingularMetricData } from '../export/MetricData'; import { InstrumentDescriptor } from '../InstrumentDescriptor'; import { Maybe } from '../utils'; @@ -72,10 +71,8 @@ export class LastValueAggregator implements Aggregator { instrumentationLibrary: InstrumentationLibrary, instrumentDescriptor: InstrumentDescriptor, accumulationByAttributes: AccumulationRecord[], - temporality: AggregationTemporality, - sdkStartTime: HrTime, - lastCollectionTime: HrTime, - collectionTime: HrTime): Maybe { + startTime: HrTime, + endTime: HrTime): Maybe { return { resource, instrumentationLibrary, @@ -84,8 +81,8 @@ export class LastValueAggregator implements Aggregator { pointData: accumulationByAttributes.map(([attributes, accumulation]) => { return { attributes, - startTime: temporality === AggregationTemporality.CUMULATIVE ? sdkStartTime : lastCollectionTime, - endTime: collectionTime, + startTime, + endTime, point: accumulation.toPoint(), } }) diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts index 081ccf802e..28cb68f77c 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts @@ -19,7 +19,6 @@ import { HrTime } from '@opentelemetry/api'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; import { PointDataType, SingularMetricData } from '../export/MetricData'; -import { AggregationTemporality } from '../export/AggregationTemporality'; import { InstrumentDescriptor } from '../InstrumentDescriptor'; import { Maybe } from '../utils'; @@ -62,10 +61,8 @@ export class SumAggregator implements Aggregator { instrumentationLibrary: InstrumentationLibrary, instrumentDescriptor: InstrumentDescriptor, accumulationByAttributes: AccumulationRecord[], - temporality: AggregationTemporality, - sdkStartTime: HrTime, - lastCollectionTime: HrTime, - collectionTime: HrTime): Maybe { + startTime: HrTime, + endTime: HrTime): Maybe { return { resource, instrumentationLibrary, @@ -74,8 +71,8 @@ export class SumAggregator implements Aggregator { pointData: accumulationByAttributes.map(([attributes, accumulation]) => { return { attributes, - startTime: temporality === AggregationTemporality.CUMULATIVE ? sdkStartTime : lastCollectionTime, - endTime: collectionTime, + startTime, + endTime, point: accumulation.toPoint(), } }) diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/types.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/types.ts index 8a8e689792..28d20a634e 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/types.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/types.ts @@ -18,7 +18,6 @@ import { HrTime } from '@opentelemetry/api'; import { Attributes } from '@opentelemetry/api-metrics'; import { InstrumentationLibrary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; -import { AggregationTemporality } from '../export/AggregationTemporality'; import { MetricData } from '../export/MetricData'; import { InstrumentDescriptor } from '../InstrumentDescriptor'; import { Maybe } from '../utils'; @@ -113,18 +112,14 @@ export interface Aggregator { * @param instrumentationLibrary the library that instrumented the metric * @param instrumentDescriptor the metric instrument descriptor. * @param accumulationByAttributes the array of attributes and accumulation pairs. - * @param temporality the temporality of the accumulation. - * @param sdkStartTime the start time of the sdk. - * @param lastCollectionTime the last collection time of the instrument. - * @param collectionTime the active collection time of the instrument. + * @param startTime the start time of the metric data. + * @param endTime the end time of the metric data. * @return the {@link MetricData} that this {@link Aggregator} will produce. */ toMetricData(resource: Resource, instrumentationLibrary: InstrumentationLibrary, instrumentDescriptor: InstrumentDescriptor, accumulationByAttributes: AccumulationRecord[], - temporality: AggregationTemporality, - sdkStartTime: HrTime, - lastCollectionTime: HrTime, - collectionTime: HrTime): Maybe; + startTime: HrTime, + endTime: HrTime): Maybe; } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts index f7154469dd..1853adc8e5 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts @@ -107,7 +107,7 @@ export class TemporalMetricProcessor { collectionTime, }); - // Metric data time span is determined in Aggregator.toMetricData with aggregation temporality: + // Metric data time span is determined as: // 1. Cumulative Aggregation time span: (sdkStartTime, collectionTime] // 2. Delta Aggregation time span: (lastCollectionTime, collectionTime] return this._aggregator.toMetricData( @@ -115,10 +115,8 @@ export class TemporalMetricProcessor { instrumentationLibrary, instrumentDescriptor, AttributesMapToAccumulationRecords(result), - aggregationTemporality, - sdkStartTime, - lastCollectionTime, - collectionTime); + /* startTime */ aggregationTemporality === AggregationTemporality.CUMULATIVE ? sdkStartTime : lastCollectionTime, + /* endTime */ collectionTime); } private _stashAccumulations(collectors: MetricCollectorHandle[], currentAccumulation: AttributeHashMap) { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Drop.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Drop.test.ts index bc264cc8f8..4d12e38511 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Drop.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Drop.test.ts @@ -17,7 +17,6 @@ import { HrTime } from '@opentelemetry/api'; import * as assert from 'assert'; import { DropAggregator } from '../../src/aggregator'; -import { AggregationTemporality } from '../../src/export/AggregationTemporality'; import { defaultInstrumentationLibrary, defaultInstrumentDescriptor, defaultResource } from '../util'; describe('DropAggregator', () => { @@ -51,19 +50,16 @@ describe('DropAggregator', () => { it('no exceptions', () => { const aggregator = new DropAggregator(); - const sdkStartTime: HrTime = [0, 0]; - const lastCollectionTime: HrTime = [1, 1]; - const collectionTime: HrTime = [2, 2]; + const startTime: HrTime = [0, 0]; + const endTime: HrTime = [1, 1]; assert.strictEqual(aggregator.toMetricData( defaultResource, defaultInstrumentationLibrary, defaultInstrumentDescriptor, [[{}, undefined]], - AggregationTemporality.DELTA, - sdkStartTime, - lastCollectionTime, - collectionTime, + startTime, + endTime, ), undefined); }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Histogram.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Histogram.test.ts index 21ba31b848..2af44dc804 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Histogram.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Histogram.test.ts @@ -17,7 +17,6 @@ import { HrTime } from '@opentelemetry/api'; import * as assert from 'assert'; import { HistogramAccumulation, HistogramAggregator } from '../../src/aggregator'; -import { AggregationTemporality } from '../../src/export/AggregationTemporality'; import { MetricData, PointDataType } from '../../src/export/MetricData'; import { commonValues, defaultInstrumentationLibrary, defaultInstrumentDescriptor, defaultResource } from '../util'; @@ -82,16 +81,15 @@ describe('HistogramAggregator', () => { }); describe('toMetricData', () => { - it('transform with AggregationTemporality.DELTA', () => { + it('transform without exception', () => { const aggregator = new HistogramAggregator([1, 10, 100]); const accumulation = aggregator.createAccumulation(); accumulation.record(0); accumulation.record(1); - const sdkStartTime: HrTime = [0, 0]; - const lastCollectionTime: HrTime = [1, 1]; - const collectionTime: HrTime = [2, 2]; + const startTime: HrTime = [0, 0]; + const endTime: HrTime = [1, 1]; const expected: MetricData = { resource: defaultResource, @@ -101,8 +99,8 @@ describe('HistogramAggregator', () => { pointData: [ { attributes: {}, - startTime: lastCollectionTime, - endTime: collectionTime, + startTime, + endTime, point: { buckets: { boundaries: [1, 10, 100], @@ -119,54 +117,8 @@ describe('HistogramAggregator', () => { defaultInstrumentationLibrary, defaultInstrumentDescriptor, [[{}, accumulation]], - AggregationTemporality.DELTA, - sdkStartTime, - lastCollectionTime, - collectionTime, - ), expected); - }); - - it('transform with AggregationTemporality.CUMULATIVE', () => { - const aggregator = new HistogramAggregator([1, 10, 100]); - - const accumulation = aggregator.createAccumulation(); - accumulation.record(0); - accumulation.record(1); - - const sdkStartTime: HrTime = [0, 0]; - const lastCollectionTime: HrTime = [1, 1]; - const collectionTime: HrTime = [2, 2]; - - const expected: MetricData = { - resource: defaultResource, - instrumentationLibrary: defaultInstrumentationLibrary, - instrumentDescriptor: defaultInstrumentDescriptor, - pointDataType: PointDataType.HISTOGRAM, - pointData: [ - { - attributes: {}, - startTime: sdkStartTime, - endTime: collectionTime, - point: { - buckets: { - boundaries: [1, 10, 100], - counts: [1, 1, 0, 0], - }, - count: 2, - sum: 1, - }, - }, - ], - }; - assert.deepStrictEqual(aggregator.toMetricData( - defaultResource, - defaultInstrumentationLibrary, - defaultInstrumentDescriptor, - [[{}, accumulation]], - AggregationTemporality.CUMULATIVE, - sdkStartTime, - lastCollectionTime, - collectionTime, + startTime, + endTime, ), expected); }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/LastValue.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/LastValue.test.ts index 1f6017f3af..5b7ec19e91 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/LastValue.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/LastValue.test.ts @@ -17,7 +17,6 @@ import { HrTime } from '@opentelemetry/api'; import * as assert from 'assert'; import { LastValueAccumulation, LastValueAggregator } from '../../src/aggregator'; -import { AggregationTemporality } from '../../src/export/AggregationTemporality'; import { MetricData, PointDataType } from '../../src/export/MetricData'; import { commonValues, defaultInstrumentationLibrary, defaultInstrumentDescriptor, defaultResource, sleep } from '../util'; @@ -88,7 +87,7 @@ describe('LastValueAggregator', () => { }); describe('toMetricData', () => { - it('transform with AggregationTemporality.DELTA', () => { + it('transform without exception', () => { const aggregator = new LastValueAggregator(); const accumulation = aggregator.createAccumulation(); @@ -97,9 +96,8 @@ describe('LastValueAggregator', () => { accumulation.record(1); accumulation.record(4); - const sdkStartTime: HrTime = [0, 0]; - const lastCollectionTime: HrTime = [1, 1]; - const collectionTime: HrTime = [2, 2]; + const startTime: HrTime = [0, 0]; + const endTime: HrTime = [1, 1]; const expected: MetricData = { resource: defaultResource, @@ -109,8 +107,8 @@ describe('LastValueAggregator', () => { pointData: [ { attributes: {}, - startTime: lastCollectionTime, - endTime: collectionTime, + startTime, + endTime, point: 4, }, ], @@ -120,48 +118,8 @@ describe('LastValueAggregator', () => { defaultInstrumentationLibrary, defaultInstrumentDescriptor, [[{}, accumulation]], - AggregationTemporality.DELTA, - sdkStartTime, - lastCollectionTime, - collectionTime, - ), expected); - }); - - it('transform with AggregationTemporality.CUMULATIVE', () => { - const aggregator = new LastValueAggregator(); - - const accumulation = aggregator.createAccumulation(); - accumulation.record(1); - accumulation.record(2); - accumulation.record(1); - - const sdkStartTime: HrTime = [0, 0]; - const lastCollectionTime: HrTime = [1, 1]; - const collectionTime: HrTime = [2, 2]; - - const expected: MetricData = { - resource: defaultResource, - instrumentationLibrary: defaultInstrumentationLibrary, - instrumentDescriptor: defaultInstrumentDescriptor, - pointDataType: PointDataType.SINGULAR, - pointData: [ - { - attributes: {}, - startTime: sdkStartTime, - endTime: collectionTime, - point: 1, - }, - ], - }; - assert.deepStrictEqual(aggregator.toMetricData( - defaultResource, - defaultInstrumentationLibrary, - defaultInstrumentDescriptor, - [[{}, accumulation]], - AggregationTemporality.CUMULATIVE, - sdkStartTime, - lastCollectionTime, - collectionTime, + startTime, + endTime, ), expected); }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Sum.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Sum.test.ts index 99db9b2712..26c322ebdc 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Sum.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/aggregator/Sum.test.ts @@ -17,7 +17,6 @@ import { HrTime } from '@opentelemetry/api'; import * as assert from 'assert'; import { SumAccumulation, SumAggregator } from '../../src/aggregator'; -import { AggregationTemporality } from '../../src/export/AggregationTemporality'; import { MetricData, PointDataType } from '../../src/export/MetricData'; import { commonValues, defaultInstrumentationLibrary, defaultInstrumentDescriptor, defaultResource } from '../util'; @@ -69,15 +68,14 @@ describe('SumAggregator', () => { }); describe('toMetricData', () => { - it('transform with AggregationTemporality.DELTA', () => { + it('transform without exception', () => { const aggregator = new SumAggregator(); const accumulation = aggregator.createAccumulation(); accumulation.record(1); accumulation.record(2); - const sdkStartTime: HrTime = [0, 0]; - const lastCollectionTime: HrTime = [1, 1]; - const collectionTime: HrTime = [2, 2]; + const startTime: HrTime = [0, 0]; + const endTime: HrTime = [1, 1]; const expected: MetricData = { resource: defaultResource, @@ -87,8 +85,8 @@ describe('SumAggregator', () => { pointData: [ { attributes: {}, - startTime: lastCollectionTime, - endTime: collectionTime, + startTime, + endTime, point: 3, }, ], @@ -98,46 +96,8 @@ describe('SumAggregator', () => { defaultInstrumentationLibrary, defaultInstrumentDescriptor, [[{}, accumulation]], - AggregationTemporality.DELTA, - sdkStartTime, - lastCollectionTime, - collectionTime, - ), expected); - }); - - it('transform with AggregationTemporality.CUMULATIVE', () => { - const aggregator = new SumAggregator(); - const accumulation = aggregator.createAccumulation(); - accumulation.record(1); - accumulation.record(2); - - const sdkStartTime: HrTime = [0, 0]; - const lastCollectionTime: HrTime = [1, 1]; - const collectionTime: HrTime = [2, 2]; - - const expected: MetricData = { - resource: defaultResource, - instrumentationLibrary: defaultInstrumentationLibrary, - instrumentDescriptor: defaultInstrumentDescriptor, - pointDataType: PointDataType.SINGULAR, - pointData: [ - { - attributes: {}, - startTime: sdkStartTime, - endTime: collectionTime, - point: 3, - }, - ], - }; - assert.deepStrictEqual(aggregator.toMetricData( - defaultResource, - defaultInstrumentationLibrary, - defaultInstrumentDescriptor, - [[{}, accumulation]], - AggregationTemporality.CUMULATIVE, - sdkStartTime, - lastCollectionTime, - collectionTime, + startTime, + endTime, ), expected); }); }); From 82e39c470a8f2767e095624497ed351745ad919e Mon Sep 17 00:00:00 2001 From: legendecas Date: Wed, 12 Jan 2022 00:07:40 +0800 Subject: [PATCH 10/16] chore: apply eslint rule semi (#2710) --- eslint.config.js | 3 ++ .../src/OTLPMetricExporter.ts | 4 +- .../src/platform/node/OTLPMetricExporter.ts | 2 +- .../src/http.ts | 2 +- .../src/types.ts | 2 +- .../src/utils.ts | 2 +- .../test/functionals/http-disable.test.ts | 2 +- .../test/functionals/http-enable.test.ts | 10 ++-- .../test/functionals/https-disable.test.ts | 2 +- .../test/functionals/utils.test.ts | 10 ++-- .../test/utils/assertSpan.ts | 2 +- .../src/platform/node/instrumentation.ts | 2 +- .../test/node/InstrumentationBase.test.ts | 24 ++++----- .../src/Measurement.ts | 6 +-- .../src/MeterProvider.ts | 10 ++-- .../src/aggregator/Histogram.ts | 4 +- .../src/aggregator/LastValue.ts | 4 +- .../src/aggregator/Sum.ts | 4 +- .../exemplar/AlwaysSampleExemplarFilter.ts | 4 +- .../src/exemplar/Exemplar.ts | 2 +- .../src/exemplar/ExemplarFilter.ts | 6 +-- .../src/exemplar/ExemplarReservoir.ts | 12 ++--- .../src/exemplar/NeverSampleExemplarFilter.ts | 4 +- .../SimpleFixedSizeExemplarReservoir.ts | 6 +-- .../src/exemplar/WithTraceExemplarFilter.ts | 4 +- .../src/export/MetricReader.ts | 2 +- .../export/PeriodicExportingMetricReader.ts | 2 +- .../src/view/InstrumentSelector.ts | 2 +- .../test/ExemplarFilter.test.ts | 6 +-- .../test/ExemplarReservoir.test.ts | 6 +-- .../PeriodicExportingMetricReader.test.ts | 12 ++--- .../test/state/MetricCollector.test.ts | 4 +- .../state/MultiWritableMetricStorage.test.ts | 4 +- .../test/util.ts | 2 +- .../test/view/ViewRegistry.test.ts | 6 +-- .../src/OTLPExporterNodeBase.ts | 4 +- .../src/OTLPTraceExporter.ts | 2 +- .../browser/OTLPExporterBrowserBase.ts | 2 +- .../src/platform/node/OTLPExporterNodeBase.ts | 2 +- .../test/browser/util.test.ts | 2 +- .../test/traceHelper.ts | 2 +- .../src/OTLPExporterNodeBase.ts | 4 +- .../exporter-trace-otlp-proto/src/util.ts | 2 +- .../src/jaeger.ts | 2 +- .../test/jaeger.test.ts | 2 +- .../src/zipkin.ts | 2 +- .../test/node/zipkin.test.ts | 6 +-- .../test/B3Propagator.test.ts | 2 +- .../opentelemetry-resources/src/Resource.ts | 2 +- .../browser/export/BatchSpanProcessor.ts | 14 ++--- .../browser/export/BatchSpanProcessor.test.ts | 34 ++++++------ .../test/common/Tracer.test.ts | 22 ++++---- .../test/registration.test.ts | 2 +- .../resource/SemanticResourceAttributes.ts | 26 ++++----- .../src/trace/SemanticAttributes.ts | 54 +++++++++---------- 55 files changed, 185 insertions(+), 182 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index c78e7b660d..61d75e5009 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -10,6 +10,8 @@ module.exports = { "project": "./tsconfig.json" }, rules: { + "no-trailing-spaces": "error", + "eol-last": "error", "quotes": [2, "single", { "avoidEscape": true }], "@typescript-eslint/no-floating-promises": 2, "@typescript-eslint/no-this-alias": "off", @@ -40,6 +42,7 @@ module.exports = { } }], "@typescript-eslint/no-shadow": ["warn"], + "@typescript-eslint/semi": "error", "arrow-parens": ["error", "as-needed"], "node/no-deprecated-api": ["warn"], "header/header": [2, "block", [{ diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts index 1816992850..3311eef290 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts @@ -15,7 +15,7 @@ */ import { otlpTypes } from '@opentelemetry/exporter-trace-otlp-http'; -import { toOTLPExportMetricServiceRequest } from '@opentelemetry/exporter-metrics-otlp-http' +import { toOTLPExportMetricServiceRequest } from '@opentelemetry/exporter-metrics-otlp-http'; import { MetricRecord, MetricExporter } from '@opentelemetry/sdk-metrics-base'; import { OTLPExporterConfigNode, @@ -45,7 +45,7 @@ export class OTLPMetricExporter const headers = baggageUtils.parseKeyPairsIntoRecord(getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS); this.metadata ||= new Metadata(); for (const [k, v] of Object.entries(headers)) { - this.metadata.set(k, v) + this.metadata.set(k, v); } } diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts index 05bf6af767..2e83ee6be6 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts @@ -15,7 +15,7 @@ */ import { MetricRecord, MetricExporter } from '@opentelemetry/sdk-metrics-base'; -import { +import { OTLPExporterNodeBase, OTLPExporterNodeConfigBase, otlpTypes, diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts index e183d5e5e6..ecfd1c4f85 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts @@ -685,6 +685,6 @@ export class HttpInstrumentation extends InstrumentationBase { captureRequestHeaders: utils.headerCapture('request', config.headersToSpanAttributes?.server?.requestHeaders ?? []), captureResponseHeaders: utils.headerCapture('response', config.headersToSpanAttributes?.server?.responseHeaders ?? []), } - } + }; } } diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/types.ts b/experimental/packages/opentelemetry-instrumentation-http/src/types.ts index 79f4e844cd..ed57c139f5 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/types.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/types.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { +import { Span, SpanAttributes, } from '@opentelemetry/api'; diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts b/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts index 4f8a03c7af..308cb7a439 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts @@ -501,7 +501,7 @@ export function headerCapture(type: 'request' | 'response', headers: string[]) { return (span: Span, getHeader: (key: string) => undefined | string | string[] | number) => { for (const [capturedHeader, normalizedHeader] of normalizedHeaders) { const value = getHeader(capturedHeader); - + if (value === undefined) { continue; } diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-disable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-disable.test.ts index b52b045109..77b7e03b97 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-disable.test.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-disable.test.ts @@ -36,7 +36,7 @@ describe('HttpInstrumentation', () => { describe('disable()', () => { let provider: TracerProvider; let startSpanStub: sinon.SinonStub; - + before(() => { provider = { getTracer: () => { diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts index 72c1ca5a1f..e72387088f 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts @@ -18,7 +18,7 @@ import { context, propagation, Span as ISpan, - SpanKind, + SpanKind, trace, SpanAttributes, } from '@opentelemetry/api'; @@ -100,13 +100,13 @@ export const responseHookFunction = ( export const startIncomingSpanHookFunction = ( request: IncomingMessage ): SpanAttributes => { - return {guid: request.headers?.guid} + return {guid: request.headers?.guid}; }; export const startOutgoingSpanHookFunction = ( request: RequestOptions ): SpanAttributes => { - return {guid: request.headers?.guid} + return {guid: request.headers?.guid}; }; describe('HttpInstrumentation', () => { @@ -507,12 +507,12 @@ describe('HttpInstrumentation', () => { hostname: 'localhost', pathname: '/', forceStatus: { - code: SpanStatusCode.ERROR, + code: SpanStatusCode.ERROR, message: err.message, }, component: 'http', noNetPeer: true, - } + }; assertSpan(spans[0], SpanKind.CLIENT, validations); return true; }); diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-disable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-disable.test.ts index c09b1742d2..f87fa54dd0 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-disable.test.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-disable.test.ts @@ -37,7 +37,7 @@ describe('HttpsInstrumentation', () => { describe('disable()', () => { let provider: TracerProvider; let startSpanStub: sinon.SinonStub; - + before(() => { provider = { getTracer: () => { diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts index 7b8a2e8d1e..e4837ab082 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts @@ -475,12 +475,12 @@ describe('Utility', () => { request.headers = { 'user-agent': 'chrome', 'x-forwarded-for': ', , ' - } - const attributes = utils.getIncomingRequestAttributes(request, { component: 'http'}) - assert.strictEqual(attributes[SemanticAttributes.HTTP_ROUTE], undefined) + }; + const attributes = utils.getIncomingRequestAttributes(request, { component: 'http'}); + assert.strictEqual(attributes[SemanticAttributes.HTTP_ROUTE], undefined); }); }); - + describe('headers to span attributes capture', () => { let span: Span; @@ -539,6 +539,6 @@ describe('Utility', () => { assert.deepStrictEqual(span.attributes['http.request.header.origin'], ['localhost']); assert.deepStrictEqual(span.attributes['http.request.header.accept'], undefined); - }) + }); }); }); diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts b/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts index a2d67fd7c6..b887a46649 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/utils/assertSpan.ts @@ -119,7 +119,7 @@ export const assertSpan = ( assert.ok( span.attributes[SemanticAttributes.NET_PEER_PORT], 'must have PEER_PORT' - ); + ); } assert.ok( (span.attributes[SemanticAttributes.HTTP_URL] as string).indexOf( diff --git a/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts index 92dab57c0a..f67476930d 100644 --- a/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts +++ b/experimental/packages/opentelemetry-instrumentation/src/platform/node/instrumentation.ts @@ -67,7 +67,7 @@ export abstract class InstrumentationBase } catch (error) { diag.warn('Failed extracting version', baseDir); } - + return undefined; } diff --git a/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts b/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts index e1c42681d3..4a44e91f61 100644 --- a/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts +++ b/experimental/packages/opentelemetry-instrumentation/test/node/InstrumentationBase.test.ts @@ -39,14 +39,14 @@ describe('InstrumentationBase', () => { let instrumentation: TestInstrumentation; let modulePatchSpy: sinon.SinonSpy; - + beforeEach(() => { instrumentation = new TestInstrumentation(); // @ts-expect-error access internal property for testing instrumentation._enabled = true; modulePatchSpy = sinon.spy(); }); - + describe('when patching a module', () => { describe('AND there is no wildcard supported version', () => { it('should not patch module', () => { @@ -56,7 +56,7 @@ describe('InstrumentationBase', () => { name: MODULE_NAME, patch: modulePatchSpy as unknown, } as InstrumentationModuleDefinition; - + // @ts-expect-error access internal property for testing instrumentation._onRequire( instrumentationModule, @@ -64,7 +64,7 @@ describe('InstrumentationBase', () => { MODULE_NAME, MODULE_DIR ); - + assert.strictEqual(instrumentationModule.moduleVersion, undefined); assert.strictEqual(instrumentationModule.moduleExports, undefined); sinon.assert.notCalled(modulePatchSpy); @@ -79,7 +79,7 @@ describe('InstrumentationBase', () => { name: MODULE_NAME, patch: modulePatchSpy as unknown, } as InstrumentationModuleDefinition; - + // @ts-expect-error access internal property for testing instrumentation._onRequire( instrumentationModule, @@ -87,20 +87,20 @@ describe('InstrumentationBase', () => { MODULE_NAME, MODULE_DIR ); - + assert.strictEqual(instrumentationModule.moduleVersion, undefined); assert.strictEqual(instrumentationModule.moduleExports, moduleExports); sinon.assert.calledOnceWithExactly(modulePatchSpy, moduleExports, undefined); }); }); }); - + describe('when patching module files', () => { let filePatchSpy: sinon.SinonSpy; beforeEach(() => { filePatchSpy = sinon.spy(); - }) + }); describe('AND there is no wildcard supported version', () => { it('should not patch module file', () => { @@ -116,7 +116,7 @@ describe('InstrumentationBase', () => { patch: filePatchSpy as unknown }] } as InstrumentationModuleDefinition; - + // @ts-expect-error access internal property for testing instrumentation._onRequire( instrumentationModule, @@ -124,7 +124,7 @@ describe('InstrumentationBase', () => { MODULE_FILE_NAME, MODULE_DIR ); - + assert.strictEqual(instrumentationModule.moduleVersion, undefined); assert.strictEqual(instrumentationModule.moduleExports, undefined); sinon.assert.notCalled(modulePatchSpy); @@ -146,7 +146,7 @@ describe('InstrumentationBase', () => { patch: filePatchSpy as unknown }] } as InstrumentationModuleDefinition; - + // @ts-expect-error access internal property for testing instrumentation._onRequire( instrumentationModule, @@ -154,7 +154,7 @@ describe('InstrumentationBase', () => { MODULE_FILE_NAME, MODULE_DIR ); - + assert.strictEqual(instrumentationModule.moduleVersion, undefined); assert.strictEqual(instrumentationModule.files[0].moduleExports, moduleExports); sinon.assert.notCalled(modulePatchSpy); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Measurement.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/Measurement.ts index 4ea34a6b6b..a83b42843c 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/Measurement.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/Measurement.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import * as api from '@opentelemetry/api' -import { Attributes } from '@opentelemetry/api-metrics-wip' +import * as api from '@opentelemetry/api'; +import { Attributes } from '@opentelemetry/api-metrics-wip'; // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#measurement @@ -24,4 +24,4 @@ export type Measurement = { // TODO use common attributes attributes: Attributes context?: api.Context; -} +}; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts index 5a53453303..d7b30e3081 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/MeterProvider.ts @@ -29,7 +29,7 @@ import { MetricCollector } from './state/MetricCollector'; export type MeterProviderOptions = { resource?: Resource; -} +}; export class MeterProvider { private _sharedState: MeterProviderSharedState; @@ -42,7 +42,7 @@ export class MeterProvider { getMeter(name: string, version = '', options: metrics.MeterOptions = {}): metrics.Meter { // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#meter-creation if (this._shutdown) { - api.diag.warn('A shutdown MeterProvider cannot provide a Meter') + api.diag.warn('A shutdown MeterProvider cannot provide a Meter'); return metrics.NOOP_METER; } @@ -84,7 +84,7 @@ export class MeterProvider { } catch (e) { // Log all Errors. if (e instanceof Error) { - api.diag.error(`Error shutting down: ${e.message}`) + api.diag.error(`Error shutting down: ${e.message}`); } } } @@ -103,7 +103,7 @@ export class MeterProvider { // do not flush after shutdown if (this._shutdown) { - api.diag.warn('invalid attempt to force flush after shutdown') + api.diag.warn('invalid attempt to force flush after shutdown'); return; } @@ -113,7 +113,7 @@ export class MeterProvider { } catch (e) { // Log all Errors. if (e instanceof Error) { - api.diag.error(`Error flushing: ${e.message}`) + api.diag.error(`Error flushing: ${e.message}`); } } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts index fadfc1f303..4caa575c3c 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Histogram.ts @@ -155,8 +155,8 @@ export class HistogramAggregator implements Aggregator { startTime, endTime, point: accumulation.toPoint(), - } + }; }) - } + }; } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts index 2ed5b93817..ddfc5a024b 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/LastValue.ts @@ -84,8 +84,8 @@ export class LastValueAggregator implements Aggregator { startTime, endTime, point: accumulation.toPoint(), - } + }; }) - } + }; } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts index 28cb68f77c..5a9aaac8d1 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/aggregator/Sum.ts @@ -74,8 +74,8 @@ export class SumAggregator implements Aggregator { startTime, endTime, point: accumulation.toPoint(), - } + }; }) - } + }; } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/AlwaysSampleExemplarFilter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/AlwaysSampleExemplarFilter.ts index 335da937fb..349cf9fea7 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/AlwaysSampleExemplarFilter.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/AlwaysSampleExemplarFilter.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { Attributes } from '@opentelemetry/api-metrics-wip' -import { Context, HrTime } from '@opentelemetry/api' +import { Attributes } from '@opentelemetry/api-metrics-wip'; +import { Context, HrTime } from '@opentelemetry/api'; import { ExemplarFilter } from './ExemplarFilter'; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/Exemplar.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/Exemplar.ts index 8b874b7520..1b22c086e2 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/Exemplar.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/Exemplar.ts @@ -44,4 +44,4 @@ export type Exemplar = { // trace_id may be missing if the measurement is not recorded inside a trace // or if the trace is not sampled. traceId?: string; -} +}; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarFilter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarFilter.ts index 435e3b37f9..e3f89b4305 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarFilter.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarFilter.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { Attributes } from '@opentelemetry/api-metrics-wip' -import { Context, HrTime } from '@opentelemetry/api' +import { Attributes } from '@opentelemetry/api-metrics-wip'; +import { Context, HrTime } from '@opentelemetry/api'; /** * This interface represents a ExemplarFilter. Exemplar filters are @@ -25,7 +25,7 @@ import { Context, HrTime } from '@opentelemetry/api' export interface ExemplarFilter { /** * Returns whether or not a reservoir should attempt to filter a measurement. - * + * * @param value The value of the measurement * @param timestamp A timestamp that best represents when the measurement was taken * @param attributes The complete set of Attributes of the measurement diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarReservoir.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarReservoir.ts index 09da8d4603..a6eb587722 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarReservoir.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/ExemplarReservoir.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import { Attributes } from '@opentelemetry/api-metrics-wip' -import { Context, HrTime, isSpanContextValid, trace } from '@opentelemetry/api' -import { Exemplar } from './Exemplar' +import { Attributes } from '@opentelemetry/api-metrics-wip'; +import { Context, HrTime, isSpanContextValid, trace } from '@opentelemetry/api'; +import { Exemplar } from './Exemplar'; /** @@ -29,13 +29,13 @@ export interface ExemplarReservoir { value: number, timestamp: HrTime, attributes: Attributes, - ctx: Context + ctx: Context ): void; /** * Returns accumulated Exemplars and also resets the reservoir * for the next sampling period - * - * @param pointAttributes The attributes associated with metric point. + * + * @param pointAttributes The attributes associated with metric point. * * @returns a list of {@link Exemplar}s. Retuned exemplars contain the attributes that were filtered out by the * aggregator, but recorded alongside the original measurement. diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/NeverSampleExemplarFilter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/NeverSampleExemplarFilter.ts index b20ea116e9..a66a755fe2 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/NeverSampleExemplarFilter.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/NeverSampleExemplarFilter.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { Attributes } from '@opentelemetry/api-metrics-wip' -import { Context, HrTime } from '@opentelemetry/api' +import { Attributes } from '@opentelemetry/api-metrics-wip'; +import { Context, HrTime } from '@opentelemetry/api'; import { ExemplarFilter } from './ExemplarFilter'; export class NeverSampleExemplarFilter implements ExemplarFilter { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/SimpleFixedSizeExemplarReservoir.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/SimpleFixedSizeExemplarReservoir.ts index 4184e09f37..ddf7ef268d 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/SimpleFixedSizeExemplarReservoir.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/SimpleFixedSizeExemplarReservoir.ts @@ -21,7 +21,7 @@ import { FixedSizeExemplarReservoirBase } from './ExemplarReservoir'; /** * Fixed size reservoir that uses equivalent of naive reservoir sampling * algorithm to accept measurements. - * + * */ export class SimpleFixedSizeExemplarReservoir extends FixedSizeExemplarReservoirBase { private _numMeasurementsSeen: number; @@ -31,7 +31,7 @@ export class SimpleFixedSizeExemplarReservoir extends FixedSizeExemplarReservoir } private getRandomInt(min: number, max: number) { //[min, max) - return Math.floor(Math.random() * (max - min) + min); + return Math.floor(Math.random() * (max - min) + min); } private _findBucketIndex(_value: number, _timestamp: HrTime, _attributes: Attributes, _ctx: Context) { @@ -43,7 +43,7 @@ export class SimpleFixedSizeExemplarReservoir extends FixedSizeExemplarReservoir offer(value: number, timestamp: HrTime, attributes: Attributes, ctx: Context): void { const index = this._findBucketIndex(value, timestamp, attributes, ctx); if (index !== -1) { - this._reservoirStorage[index].offer(value, timestamp, attributes, ctx) + this._reservoirStorage[index].offer(value, timestamp, attributes, ctx); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/WithTraceExemplarFilter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/WithTraceExemplarFilter.ts index f9f75e4ddd..77f3fb02af 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/WithTraceExemplarFilter.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/exemplar/WithTraceExemplarFilter.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { Attributes } from '@opentelemetry/api-metrics-wip' -import { Context, HrTime, isSpanContextValid, trace, TraceFlags } from '@opentelemetry/api' +import { Attributes } from '@opentelemetry/api-metrics-wip'; +import { Context, HrTime, isSpanContextValid, trace, TraceFlags } from '@opentelemetry/api'; import { ExemplarFilter } from './ExemplarFilter'; export class WithTraceExemplarFilter implements ExemplarFilter { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts index b67876c9b1..db0bc301b7 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/MetricReader.ts @@ -22,7 +22,7 @@ import { callWithTimeout } from '../utils'; export type ReaderOptions = { timeoutMillis?: number -} +}; export type ReaderCollectionOptions = ReaderOptions; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts index f7e5453076..0e5861941a 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/export/PeriodicExportingMetricReader.ts @@ -23,7 +23,7 @@ export type PeriodicExportingMetricReaderOptions = { exporter: MetricExporter exportIntervalMillis?: number, exportTimeoutMillis?: number -} +}; /** * {@link MetricReader} which collects metrics based on a user-configurable time interval, and passes the metrics to diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/InstrumentSelector.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/view/InstrumentSelector.ts index 40aa4778a9..c7dc6fa28e 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/InstrumentSelector.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/view/InstrumentSelector.ts @@ -32,7 +32,7 @@ export class InstrumentSelector { } getType() { - return this._type + return this._type; } getNameFilter() { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarFilter.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarFilter.test.ts index 22b86639ec..7365bbbd60 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarFilter.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarFilter.test.ts @@ -37,7 +37,7 @@ describe('ExemplarFilter', () => { describe('NeverSampleExemplarFilter', () => { it('should return false always for shouldSample', () => { - const filter = new NeverSampleExemplarFilter() + const filter = new NeverSampleExemplarFilter(); assert.strictEqual(filter.shouldSample(1, [0, 0], {}, ROOT_CONTEXT), false); }); }); @@ -50,7 +50,7 @@ describe('ExemplarFilter', () => { spanId: SPAN_ID, traceFlags: TraceFlags.NONE, }; - const ctx = trace.setSpanContext(ROOT_CONTEXT, spanContext) + const ctx = trace.setSpanContext(ROOT_CONTEXT, spanContext); assert.strictEqual(filter.shouldSample(5.3, [0, 0,], {}, ctx), false); }); @@ -61,7 +61,7 @@ describe('ExemplarFilter', () => { spanId: SPAN_ID, traceFlags: TraceFlags.SAMPLED, }; - const ctx = trace.setSpanContext(ROOT_CONTEXT, spanContext) + const ctx = trace.setSpanContext(ROOT_CONTEXT, spanContext); assert.strictEqual(filter.shouldSample(5.3, [0, 0,], {}, ctx), true); }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarReservoir.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarReservoir.test.ts index bfd2e5f404..d6917c172f 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarReservoir.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/ExemplarReservoir.test.ts @@ -16,7 +16,7 @@ import { ROOT_CONTEXT, SpanContext, TraceFlags, trace } from '@opentelemetry/api'; import { hrTime } from '@opentelemetry/core'; -import * as assert from 'assert' +import * as assert from 'assert'; import { SimpleFixedSizeExemplarReservoir, @@ -41,8 +41,8 @@ describe('ExemplarReservoir', () => { spanId: SPAN_ID, traceFlags: TraceFlags.SAMPLED, }; - const ctx = trace.setSpanContext(ROOT_CONTEXT, spanContext) - + const ctx = trace.setSpanContext(ROOT_CONTEXT, spanContext); + reservoir.offer(1, hrTime(), {}, ctx); const exemplars = reservoir.collect({}); assert.strictEqual(exemplars.length, 1); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts index ca426e2908..90962c8ca2 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts @@ -23,7 +23,7 @@ import * as sinon from 'sinon'; import { MetricProducer } from '../../src/export/MetricProducer'; import { TimeoutError } from '../../src/utils'; -const MAX_32_BIT_INT = 2 ** 31 - 1 +const MAX_32_BIT_INT = 2 ** 31 - 1; class TestMetricExporter extends MetricExporter { public exportTime = 0; @@ -94,7 +94,7 @@ describe('PeriodicExportingMetricReader', () => { } ); assert.strictEqual(reader.getPreferredAggregationTemporality(), exporter.getPreferredAggregationTemporality()); - }) + }); it('should throw when interval less or equal to 0', () => { const exporter = new TestDeltaMetricExporter(); @@ -103,7 +103,7 @@ describe('PeriodicExportingMetricReader', () => { exportIntervalMillis: 0, exportTimeoutMillis: 0 }), new Error('exportIntervalMillis must be greater than 0')); - }) + }); it('should throw when timeout less or equal to 0', () => { const exporter = new TestDeltaMetricExporter(); @@ -112,7 +112,7 @@ describe('PeriodicExportingMetricReader', () => { exportIntervalMillis: 1, exportTimeoutMillis: 0 }), new Error('exportTimeoutMillis must be greater than 0')); - }) + }); it('should throw when timeout less or equal to interval', () => { const exporter = new TestDeltaMetricExporter(); @@ -121,7 +121,7 @@ describe('PeriodicExportingMetricReader', () => { exportIntervalMillis: 100, exportTimeoutMillis: 200 }), new Error('exportIntervalMillis must be greater than or equal to exportTimeoutMillis')); - }) + }); it('should not start exporting', async () => { const exporter = new TestDeltaMetricExporter(); @@ -136,7 +136,7 @@ describe('PeriodicExportingMetricReader', () => { await new Promise(resolve => setTimeout(resolve, 50)); exporterMock.verify(); - }) + }); }); describe('setMetricProducer', () => { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts index 4aba1f7146..ea263bdd25 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MetricCollector.test.ts @@ -26,7 +26,7 @@ import { defaultInstrumentationLibrary, defaultResource, assertMetricData, asser import { TestMetricReader } from '../export/TestMetricReader'; class TestMetricExporter extends MetricExporter { - metricDataList: MetricData[] = [] + metricDataList: MetricData[] = []; async export(batch: MetricData[]): Promise { this.metricDataList.push(...batch); } @@ -47,7 +47,7 @@ class TestDeltaMetricExporter extends TestMetricExporter { describe('MetricCollector', () => { afterEach(() => { sinon.restore(); - }) + }); describe('constructor', () => { it('should construct MetricCollector without exceptions', () => { diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MultiWritableMetricStorage.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MultiWritableMetricStorage.test.ts index 64c8daaa6f..174c12f727 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MultiWritableMetricStorage.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/MultiWritableMetricStorage.test.ts @@ -49,8 +49,8 @@ describe('MultiMetricStorage', () => { const expectedMeasurements: Measurement[] = []; for (const value of commonValues) { for (const attributes of commonAttributes) { - const context = api.context.active() - expectedMeasurements.push({ value, attributes, context }) + const context = api.context.active(); + expectedMeasurements.push({ value, attributes, context }); metricStorage.record(value, attributes, context); } } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts index 58e8bcbb6c..301a2a9e44 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/util.ts @@ -45,7 +45,7 @@ export const defaultInstrumentationLibrary: InstrumentationLibrary = { export const commonValues: number[] = [1, -1, 1.0, Infinity, -Infinity, NaN]; export const commonAttributes: Attributes[] = [{}, {1: '1'}, {a: '2'}, new (class Foo{ -a = '1' +a = '1'; })]; export const sleep = (time: number) => diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/view/ViewRegistry.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/view/ViewRegistry.test.ts index e7185a1888..dd1321a400 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/view/ViewRegistry.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/view/ViewRegistry.test.ts @@ -50,7 +50,7 @@ describe('ViewRegistry', () => { }, defaultInstrumentationLibrary); assert.strictEqual(views.length, 2); - assert.strictEqual(views[0].name, 'no-filter') + assert.strictEqual(views[0].name, 'no-filter'); assert.strictEqual(views[1].name, 'foo'); } @@ -83,7 +83,7 @@ describe('ViewRegistry', () => { }, defaultInstrumentationLibrary); assert.strictEqual(views.length, 2); - assert.strictEqual(views[0].name, 'no-filter') + assert.strictEqual(views[0].name, 'no-filter'); assert.strictEqual(views[1].name, 'counter'); } @@ -118,7 +118,7 @@ describe('ViewRegistry', () => { }); assert.strictEqual(views.length, 2); - assert.strictEqual(views[0].name, 'no-filter') + assert.strictEqual(views[0].name, 'no-filter'); assert.strictEqual(views[1].name, 'foo'); } diff --git a/packages/exporter-trace-otlp-grpc/src/OTLPExporterNodeBase.ts b/packages/exporter-trace-otlp-grpc/src/OTLPExporterNodeBase.ts index 0c516865bd..a992a4f259 100644 --- a/packages/exporter-trace-otlp-grpc/src/OTLPExporterNodeBase.ts +++ b/packages/exporter-trace-otlp-grpc/src/OTLPExporterNodeBase.ts @@ -52,7 +52,7 @@ export abstract class OTLPExporterNodeBase< const headers = baggageUtils.parseKeyPairsIntoRecord(getEnv().OTEL_EXPORTER_OTLP_HEADERS); this.metadata = config.metadata || new Metadata(); for (const [k, v] of Object.entries(headers)) { - this.metadata.set(k, v) + this.metadata.set(k, v); } } @@ -70,7 +70,7 @@ export abstract class OTLPExporterNodeBase< const popPromise = () => { const index = this._sendingPromises.indexOf(promise); this._sendingPromises.splice(index, 1); - } + }; promise.then(popPromise, popPromise); } diff --git a/packages/exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts b/packages/exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts index 252a752a6d..871d3f31db 100644 --- a/packages/exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts +++ b/packages/exporter-trace-otlp-grpc/src/OTLPTraceExporter.ts @@ -42,7 +42,7 @@ export class OTLPTraceExporter const headers = baggageUtils.parseKeyPairsIntoRecord(getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS); this.metadata ||= new Metadata(); for (const [k, v] of Object.entries(headers)) { - this.metadata.set(k, v) + this.metadata.set(k, v); } } diff --git a/packages/exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts b/packages/exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts index 9e6ff10144..708702300b 100644 --- a/packages/exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts +++ b/packages/exporter-trace-otlp-http/src/platform/browser/OTLPExporterBrowserBase.ts @@ -89,7 +89,7 @@ export abstract class OTLPExporterBrowserBase< const popPromise = () => { const index = this._sendingPromises.indexOf(promise); this._sendingPromises.splice(index, 1); - } + }; promise.then(popPromise, popPromise); } } diff --git a/packages/exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts b/packages/exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts index c48d49fc42..11f582a83c 100644 --- a/packages/exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts +++ b/packages/exporter-trace-otlp-http/src/platform/node/OTLPExporterNodeBase.ts @@ -84,7 +84,7 @@ export abstract class OTLPExporterNodeBase< const popPromise = () => { const index = this._sendingPromises.indexOf(promise); this._sendingPromises.splice(index, 1); - } + }; promise.then(popPromise, popPromise); } diff --git a/packages/exporter-trace-otlp-http/test/browser/util.test.ts b/packages/exporter-trace-otlp-http/test/browser/util.test.ts index c4cb185da1..3cb6aa4474 100644 --- a/packages/exporter-trace-otlp-http/test/browser/util.test.ts +++ b/packages/exporter-trace-otlp-http/test/browser/util.test.ts @@ -44,7 +44,7 @@ describe('util - browser', () => { // ;charset=utf-8 is applied by sinon.fakeServer 'Content-Type': 'application/json;charset=utf-8', 'Accept': 'application/json', - } + }; }); describe('and Content-Type header is set', () => { beforeEach(()=>{ diff --git a/packages/exporter-trace-otlp-http/test/traceHelper.ts b/packages/exporter-trace-otlp-http/test/traceHelper.ts index 9975f05f3c..1ad9e891a7 100644 --- a/packages/exporter-trace-otlp-http/test/traceHelper.ts +++ b/packages/exporter-trace-otlp-http/test/traceHelper.ts @@ -42,7 +42,7 @@ export const mockedReadableSpan: ReadableSpan = { traceId: '1f1008dc8e270e85c40a0d7c3939b278', spanId: '5e107261f64fa53e', traceFlags: TraceFlags.SAMPLED, - } + }; }, parentSpanId: '78a8915098864388', startTime: [1574120165, 429803070], diff --git a/packages/exporter-trace-otlp-proto/src/OTLPExporterNodeBase.ts b/packages/exporter-trace-otlp-proto/src/OTLPExporterNodeBase.ts index bebc831650..19ddc423bf 100644 --- a/packages/exporter-trace-otlp-proto/src/OTLPExporterNodeBase.ts +++ b/packages/exporter-trace-otlp-proto/src/OTLPExporterNodeBase.ts @@ -39,7 +39,7 @@ export abstract class OTLPExporterNodeBase< private _send!: SendFn; constructor(config: OTLPExporterNodeConfigBase = {}) { - super(config) + super(config); } private _sendPromise( @@ -56,7 +56,7 @@ export abstract class OTLPExporterNodeBase< const popPromise = () => { const index = this._sendingPromises.indexOf(promise); this._sendingPromises.splice(index, 1); - } + }; promise.then(popPromise, popPromise); } diff --git a/packages/exporter-trace-otlp-proto/src/util.ts b/packages/exporter-trace-otlp-proto/src/util.ts index 007b35b56e..ea38e815d6 100644 --- a/packages/exporter-trace-otlp-proto/src/util.ts +++ b/packages/exporter-trace-otlp-proto/src/util.ts @@ -85,4 +85,4 @@ export function send( } else { onError(new otlpTypes.OTLPExporterError('No proto')); } -} \ No newline at end of file +} diff --git a/packages/opentelemetry-exporter-jaeger/src/jaeger.ts b/packages/opentelemetry-exporter-jaeger/src/jaeger.ts index 3ae5880710..ec9634793e 100644 --- a/packages/opentelemetry-exporter-jaeger/src/jaeger.ts +++ b/packages/opentelemetry-exporter-jaeger/src/jaeger.ts @@ -137,7 +137,7 @@ export class JaegerExporter implements SpanExporter { sender._client.unref(); } - const serviceNameTag = span.tags.find(t => t.key === SemanticResourceAttributes.SERVICE_NAME) + const serviceNameTag = span.tags.find(t => t.key === SemanticResourceAttributes.SERVICE_NAME); const serviceName = serviceNameTag?.vStr || 'unknown_service'; sender.setProcess({ diff --git a/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts b/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts index c51dd2b022..6193796268 100644 --- a/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts +++ b/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts @@ -69,7 +69,7 @@ describe('JaegerExporter', () => { const mockedEndpoint = 'http://testendpoint'; const scope =nock(mockedEndpoint) .post('/') - .reply(202) + .reply(202); const exporter = new JaegerExporter({ endpoint: mockedEndpoint, diff --git a/packages/opentelemetry-exporter-zipkin/src/zipkin.ts b/packages/opentelemetry-exporter-zipkin/src/zipkin.ts index 614d728cb5..3b228b3007 100644 --- a/packages/opentelemetry-exporter-zipkin/src/zipkin.ts +++ b/packages/opentelemetry-exporter-zipkin/src/zipkin.ts @@ -92,7 +92,7 @@ export class ZipkinExporter implements SpanExporter { const popPromise = () => { const index = this._sendingPromises.indexOf(promise); this._sendingPromises.splice(index, 1); - } + }; promise.then(popPromise, popPromise); } diff --git a/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts b/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts index d78b46159c..1b6465a656 100644 --- a/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts +++ b/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts @@ -512,10 +512,10 @@ describe('Zipkin Exporter - node', () => { describe('when env.OTEL_EXPORTER_ZIPKIN_ENDPOINT is set', () => { before(() => { process.env.OTEL_EXPORTER_ZIPKIN_ENDPOINT = 'http://localhost:9412'; - }) + }); after(() => { - delete process.env.OTEL_EXPORTER_ZIPKIN_ENDPOINT - }) + delete process.env.OTEL_EXPORTER_ZIPKIN_ENDPOINT; + }); it('should use url from env', () => { const scope = nock('http://localhost:9412').post('/').reply(200); diff --git a/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts b/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts index 6e5a7b4a7c..62d4643f45 100644 --- a/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts +++ b/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts @@ -163,7 +163,7 @@ describe('B3Propagator', () => { } return [carrier[key]]; }, - + keys: defaultTextMapGetter.keys } ); diff --git a/packages/opentelemetry-resources/src/Resource.ts b/packages/opentelemetry-resources/src/Resource.ts index f048ea3580..ac368d812e 100644 --- a/packages/opentelemetry-resources/src/Resource.ts +++ b/packages/opentelemetry-resources/src/Resource.ts @@ -45,7 +45,7 @@ export class Resource { SDK_INFO[SemanticResourceAttributes.TELEMETRY_SDK_NAME], [SemanticResourceAttributes.TELEMETRY_SDK_VERSION]: SDK_INFO[SemanticResourceAttributes.TELEMETRY_SDK_VERSION], - }) + }); } constructor( diff --git a/packages/opentelemetry-sdk-trace-base/src/platform/browser/export/BatchSpanProcessor.ts b/packages/opentelemetry-sdk-trace-base/src/platform/browser/export/BatchSpanProcessor.ts index 07156e7b90..d5a87cc10d 100644 --- a/packages/opentelemetry-sdk-trace-base/src/platform/browser/export/BatchSpanProcessor.ts +++ b/packages/opentelemetry-sdk-trace-base/src/platform/browser/export/BatchSpanProcessor.ts @@ -19,12 +19,12 @@ import { SpanExporter } from '../../../export/SpanExporter'; import { BatchSpanProcessorBrowserConfig } from '../../../types'; export class BatchSpanProcessor extends BatchSpanProcessorBase { - private _visibilityChangeListener?: () => void - private _pageHideListener?: () => void + private _visibilityChangeListener?: () => void; + private _pageHideListener?: () => void; constructor(_exporter: SpanExporter, config?: BatchSpanProcessorBrowserConfig) { - super(_exporter, config) - this.onInit(config) + super(_exporter, config); + this.onInit(config); } private onInit(config?: BatchSpanProcessorBrowserConfig): void { @@ -33,10 +33,10 @@ export class BatchSpanProcessor extends BatchSpanProcessorBase { - void this.forceFlush() - } + void this.forceFlush(); + }; document.addEventListener('visibilitychange', this._visibilityChangeListener); // use 'pagehide' event as a fallback for Safari; see https://bugs.webkit.org/show_bug.cgi?id=116769 diff --git a/packages/opentelemetry-sdk-trace-base/test/browser/export/BatchSpanProcessor.test.ts b/packages/opentelemetry-sdk-trace-base/test/browser/export/BatchSpanProcessor.test.ts index 9c422f2245..210b59612c 100644 --- a/packages/opentelemetry-sdk-trace-base/test/browser/export/BatchSpanProcessor.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/browser/export/BatchSpanProcessor.test.ts @@ -22,11 +22,11 @@ import { TestTracingSpanExporter } from '../../common/export/TestTracingSpanExpo describe('BatchSpanProcessor - web', () => { let visibilityState: VisibilityState = 'visible'; - let exporter: SpanExporter + let exporter: SpanExporter; let processor: BatchSpanProcessor; let forceFlushSpy: sinon.SinonStub; let visibilityChangeEvent: Event; - let pageHideEvent: Event + let pageHideEvent: Event; beforeEach(() => { sinon.replaceGetter(document, 'visibilityState', () => visibilityState); @@ -46,7 +46,7 @@ describe('BatchSpanProcessor - web', () => { const testDocumentHide = (hideDocument: () => void) => { it('should force flush spans', () => { assert.strictEqual(forceFlushSpy.callCount, 0); - hideDocument() + hideDocument(); assert.strictEqual(forceFlushSpy.callCount, 1); }); @@ -54,43 +54,43 @@ describe('BatchSpanProcessor - web', () => { it('should NOT force flush spans', async () => { assert.strictEqual(forceFlushSpy.callCount, 0); await processor.shutdown(); - hideDocument() + hideDocument(); assert.strictEqual(forceFlushSpy.callCount, 0); }); - }) + }); describe('AND disableAutoFlushOnDocumentHide configuration option', () => { it('set to false should force flush spans', () => { processor = new BatchSpanProcessor(exporter, { disableAutoFlushOnDocumentHide: false }); forceFlushSpy = sinon.stub(processor, 'forceFlush'); assert.strictEqual(forceFlushSpy.callCount, 0); - hideDocument() + hideDocument(); assert.strictEqual(forceFlushSpy.callCount, 1); - }) + }); it('set to true should NOT force flush spans', () => { processor = new BatchSpanProcessor(exporter, { disableAutoFlushOnDocumentHide: true }); forceFlushSpy = sinon.stub(processor, 'forceFlush'); assert.strictEqual(forceFlushSpy.callCount, 0); - hideDocument() + hideDocument(); assert.strictEqual(forceFlushSpy.callCount, 0); - }) - }) - } + }); + }); + }; describe('by the visibilitychange event', () => { testDocumentHide(() => { visibilityState = 'hidden'; document.dispatchEvent(visibilityChangeEvent); - }) - }) + }); + }); describe('by the pagehide event', () => { testDocumentHide(() => { document.dispatchEvent(pageHideEvent); - }) - }) - }) + }); + }); + }); describe('when document becomes visible', () => { it('should NOT force flush spans', () => { @@ -98,5 +98,5 @@ describe('BatchSpanProcessor - web', () => { document.dispatchEvent(visibilityChangeEvent); assert.strictEqual(forceFlushSpy.callCount, 0); }); - }) + }); }); diff --git a/packages/opentelemetry-sdk-trace-base/test/common/Tracer.test.ts b/packages/opentelemetry-sdk-trace-base/test/common/Tracer.test.ts index b0e56c2161..893f5219c6 100644 --- a/packages/opentelemetry-sdk-trace-base/test/common/Tracer.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/common/Tracer.test.ts @@ -242,9 +242,9 @@ describe('Tracer', () => { assert.strictEqual(tracer.startActiveSpan('my-span', span => { try { - assert(spy.calledWith('my-span')) - assert.strictEqual(getSpan(context.active()), span) - return 1 + assert(spy.calledWith('my-span')); + assert.strictEqual(getSpan(context.active()), span); + return 1; } finally { span.end(); } @@ -263,9 +263,9 @@ describe('Tracer', () => { assert.strictEqual(tracer.startActiveSpan('my-span', {attributes: {foo: 'bar'}}, span => { try { - assert(spy.calledWith('my-span', {attributes: {foo: 'bar'}})) - assert.strictEqual(getSpan(context.active()), span) - return 1 + assert(spy.calledWith('my-span', {attributes: {foo: 'bar'}})); + assert.strictEqual(getSpan(context.active()), span); + return 1; } finally { span.end(); } @@ -281,16 +281,16 @@ describe('Tracer', () => { const ctxKey = createContextKey('foo'); - const ctx = context.active().setValue(ctxKey, 'bar') + const ctx = context.active().setValue(ctxKey, 'bar'); const spy = sinon.spy(tracer, 'startSpan'); assert.strictEqual(tracer.startActiveSpan('my-span', {attributes: {foo: 'bar'}}, ctx, span => { try { - assert(spy.calledWith('my-span', {attributes: {foo: 'bar'}}, ctx)) - assert.strictEqual(getSpan(context.active()), span) - assert.strictEqual(ctx.getValue(ctxKey), 'bar') - return 1 + assert(spy.calledWith('my-span', {attributes: {foo: 'bar'}}, ctx)); + assert.strictEqual(getSpan(context.active()), span); + assert.strictEqual(ctx.getValue(ctxKey), 'bar'); + return 1; } finally { span.end(); } diff --git a/packages/opentelemetry-sdk-trace-web/test/registration.test.ts b/packages/opentelemetry-sdk-trace-web/test/registration.test.ts index e2c497883c..e001b2b742 100644 --- a/packages/opentelemetry-sdk-trace-web/test/registration.test.ts +++ b/packages/opentelemetry-sdk-trace-web/test/registration.test.ts @@ -84,7 +84,7 @@ describe('API registration', () => { propagator: null, }); - assert.strictEqual(propagation['_getGlobalPropagator'](), propagator, 'propagator should not change') + assert.strictEqual(propagation['_getGlobalPropagator'](), propagator, 'propagator should not change'); assert.ok(context['_getContextManager']() instanceof StackContextManager); const apiTracerProvider = trace.getTracerProvider() as ProxyTracerProvider; diff --git a/packages/opentelemetry-semantic-conventions/src/resource/SemanticResourceAttributes.ts b/packages/opentelemetry-semantic-conventions/src/resource/SemanticResourceAttributes.ts index 9e3a9d02ae..561a20c46c 100644 --- a/packages/opentelemetry-semantic-conventions/src/resource/SemanticResourceAttributes.ts +++ b/packages/opentelemetry-semantic-conventions/src/resource/SemanticResourceAttributes.ts @@ -474,7 +474,7 @@ As an alternative, consider setting `faas.id` as a span attribute instead. * Additional description of the web engine (e.g. detailed version and edition information). */ WEBENGINE_DESCRIPTION: 'webengine.description', -} +}; export const CloudProviderValues = { @@ -486,8 +486,8 @@ export const CloudProviderValues = { AZURE: 'azure', /** Google Cloud Platform. */ GCP: 'gcp', -} as const -export type CloudProviderValues = typeof CloudProviderValues[keyof typeof CloudProviderValues] +} as const; +export type CloudProviderValues = typeof CloudProviderValues[keyof typeof CloudProviderValues]; @@ -527,8 +527,8 @@ export const CloudPlatformValues = { GCP_CLOUD_FUNCTIONS: 'gcp_cloud_functions', /** Google Cloud App Engine (GAE). */ GCP_APP_ENGINE: 'gcp_app_engine', -} as const -export type CloudPlatformValues = typeof CloudPlatformValues[keyof typeof CloudPlatformValues] +} as const; +export type CloudPlatformValues = typeof CloudPlatformValues[keyof typeof CloudPlatformValues]; @@ -538,8 +538,8 @@ export const AwsEcsLaunchtypeValues = { EC2: 'ec2', /** fargate. */ FARGATE: 'fargate', -} as const -export type AwsEcsLaunchtypeValues = typeof AwsEcsLaunchtypeValues[keyof typeof AwsEcsLaunchtypeValues] +} as const; +export type AwsEcsLaunchtypeValues = typeof AwsEcsLaunchtypeValues[keyof typeof AwsEcsLaunchtypeValues]; @@ -559,8 +559,8 @@ export const HostArchValues = { PPC64: 'ppc64', /** 32-bit x86. */ X86: 'x86', -} as const -export type HostArchValues = typeof HostArchValues[keyof typeof HostArchValues] +} as const; +export type HostArchValues = typeof HostArchValues[keyof typeof HostArchValues]; @@ -588,8 +588,8 @@ export const OsTypeValues = { SOLARIS: 'solaris', /** IBM z/OS. */ Z_OS: 'z_os', -} as const -export type OsTypeValues = typeof OsTypeValues[keyof typeof OsTypeValues] +} as const; +export type OsTypeValues = typeof OsTypeValues[keyof typeof OsTypeValues]; @@ -615,6 +615,6 @@ export const TelemetrySdkLanguageValues = { RUBY: 'ruby', /** webjs. */ WEBJS: 'webjs', -} as const -export type TelemetrySdkLanguageValues = typeof TelemetrySdkLanguageValues[keyof typeof TelemetrySdkLanguageValues] +} 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 052d36e4c0..4f653555ed 100644 --- a/packages/opentelemetry-semantic-conventions/src/trace/SemanticAttributes.ts +++ b/packages/opentelemetry-semantic-conventions/src/trace/SemanticAttributes.ts @@ -721,7 +721,7 @@ the closest proxy. * Uncompressed size of the message in bytes. */ MESSAGE_UNCOMPRESSED_SIZE: 'message.uncompressed_size', -} +}; export const DbSystemValues = { @@ -819,8 +819,8 @@ export const DbSystemValues = { MEMCACHED: 'memcached', /** CockroachDB. */ COCKROACHDB: 'cockroachdb', -} as const -export type DbSystemValues = typeof DbSystemValues[keyof typeof DbSystemValues] +} as const; +export type DbSystemValues = typeof DbSystemValues[keyof typeof DbSystemValues]; @@ -848,8 +848,8 @@ export const DbCassandraConsistencyLevelValues = { SERIAL: 'serial', /** local_serial. */ LOCAL_SERIAL: 'local_serial', -} as const -export type DbCassandraConsistencyLevelValues = typeof DbCassandraConsistencyLevelValues[keyof typeof DbCassandraConsistencyLevelValues] +} as const; +export type DbCassandraConsistencyLevelValues = typeof DbCassandraConsistencyLevelValues[keyof typeof DbCassandraConsistencyLevelValues]; @@ -865,8 +865,8 @@ export const FaasTriggerValues = { TIMER: 'timer', /** If none of the others apply. */ OTHER: 'other', -} as const -export type FaasTriggerValues = typeof FaasTriggerValues[keyof typeof FaasTriggerValues] +} as const; +export type FaasTriggerValues = typeof FaasTriggerValues[keyof typeof FaasTriggerValues]; @@ -878,8 +878,8 @@ export const FaasDocumentOperationValues = { EDIT: 'edit', /** When an object is deleted. */ DELETE: 'delete', -} as const -export type FaasDocumentOperationValues = typeof FaasDocumentOperationValues[keyof typeof FaasDocumentOperationValues] +} as const; +export type FaasDocumentOperationValues = typeof FaasDocumentOperationValues[keyof typeof FaasDocumentOperationValues]; @@ -893,8 +893,8 @@ export const FaasInvokedProviderValues = { AZURE: 'azure', /** Google Cloud Platform. */ GCP: 'gcp', -} as const -export type FaasInvokedProviderValues = typeof FaasInvokedProviderValues[keyof typeof FaasInvokedProviderValues] +} as const; +export type FaasInvokedProviderValues = typeof FaasInvokedProviderValues[keyof typeof FaasInvokedProviderValues]; @@ -914,8 +914,8 @@ export const NetTransportValues = { INPROC: 'inproc', /** Something else (non IP-based). */ OTHER: 'other', -} as const -export type NetTransportValues = typeof NetTransportValues[keyof typeof NetTransportValues] +} as const; +export type NetTransportValues = typeof NetTransportValues[keyof typeof NetTransportValues]; @@ -931,8 +931,8 @@ export const NetHostConnectionTypeValues = { UNAVAILABLE: 'unavailable', /** unknown. */ UNKNOWN: 'unknown', -} as const -export type NetHostConnectionTypeValues = typeof NetHostConnectionTypeValues[keyof typeof NetHostConnectionTypeValues] +} as const; +export type NetHostConnectionTypeValues = typeof NetHostConnectionTypeValues[keyof typeof NetHostConnectionTypeValues]; @@ -980,8 +980,8 @@ export const NetHostConnectionSubtypeValues = { NRNSA: 'nrnsa', /** LTE CA. */ LTE_CA: 'lte_ca', -} as const -export type NetHostConnectionSubtypeValues = typeof NetHostConnectionSubtypeValues[keyof typeof NetHostConnectionSubtypeValues] +} as const; +export type NetHostConnectionSubtypeValues = typeof NetHostConnectionSubtypeValues[keyof typeof NetHostConnectionSubtypeValues]; @@ -997,8 +997,8 @@ export const HttpFlavorValues = { SPDY: 'SPDY', /** QUIC protocol. */ QUIC: 'QUIC', -} as const -export type HttpFlavorValues = typeof HttpFlavorValues[keyof typeof HttpFlavorValues] +} as const; +export type HttpFlavorValues = typeof HttpFlavorValues[keyof typeof HttpFlavorValues]; @@ -1008,8 +1008,8 @@ export const MessagingDestinationKindValues = { QUEUE: 'queue', /** A message sent to a topic. */ TOPIC: 'topic', -} as const -export type MessagingDestinationKindValues = typeof MessagingDestinationKindValues[keyof typeof MessagingDestinationKindValues] +} as const; +export type MessagingDestinationKindValues = typeof MessagingDestinationKindValues[keyof typeof MessagingDestinationKindValues]; @@ -1019,8 +1019,8 @@ export const MessagingOperationValues = { RECEIVE: 'receive', /** process. */ PROCESS: 'process', -} as const -export type MessagingOperationValues = typeof MessagingOperationValues[keyof typeof MessagingOperationValues] +} as const; +export type MessagingOperationValues = typeof MessagingOperationValues[keyof typeof MessagingOperationValues]; @@ -1060,8 +1060,8 @@ export const RpcGrpcStatusCodeValues = { DATA_LOSS: 15, /** UNAUTHENTICATED. */ UNAUTHENTICATED: 16, -} as const -export type RpcGrpcStatusCodeValues = typeof RpcGrpcStatusCodeValues[keyof typeof RpcGrpcStatusCodeValues] +} as const; +export type RpcGrpcStatusCodeValues = typeof RpcGrpcStatusCodeValues[keyof typeof RpcGrpcStatusCodeValues]; @@ -1071,6 +1071,6 @@ export const MessageTypeValues = { SENT: 'SENT', /** received. */ RECEIVED: 'RECEIVED', -} as const -export type MessageTypeValues = typeof MessageTypeValues[keyof typeof MessageTypeValues] +} as const; +export type MessageTypeValues = typeof MessageTypeValues[keyof typeof MessageTypeValues]; From d315b0a75eb9517537b96a4ace083371cbdba552 Mon Sep 17 00:00:00 2001 From: Mitar Milanovic Date: Wed, 12 Jan 2022 16:41:17 +0100 Subject: [PATCH 11/16] fix: span attribute count and value limits (#2671) (#2678) Co-authored-by: Rauno Viskus Co-authored-by: Daniel Dyla Co-authored-by: Valentin Marchaud Co-authored-by: legendecas --- .../src/BasicTracerProvider.ts | 3 +- .../src/utility.ts | 23 ++++-- .../test/common/Span.test.ts | 72 +++++++++++++++++++ 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/packages/opentelemetry-sdk-trace-base/src/BasicTracerProvider.ts b/packages/opentelemetry-sdk-trace-base/src/BasicTracerProvider.ts index ac6b3445ee..b8bbbbec91 100644 --- a/packages/opentelemetry-sdk-trace-base/src/BasicTracerProvider.ts +++ b/packages/opentelemetry-sdk-trace-base/src/BasicTracerProvider.ts @@ -37,6 +37,7 @@ import { NoopSpanProcessor } from './export/NoopSpanProcessor'; import { SDKRegistrationConfig, TracerConfig } from './types'; import { SpanExporter } from './export/SpanExporter'; import { BatchSpanProcessor } from './platform'; +import { reconfigureLimits } from './utility'; export type PROPAGATOR_FACTORY = () => TextMapPropagator; export type EXPORTER_FACTORY = () => SpanExporter; @@ -73,7 +74,7 @@ export class BasicTracerProvider implements TracerProvider { readonly resource: Resource; constructor(config: TracerConfig = {}) { - const mergedConfig = merge({}, DEFAULT_CONFIG, config); + const mergedConfig = merge({}, DEFAULT_CONFIG, reconfigureLimits(config)); this.resource = mergedConfig.resource ?? Resource.empty(); this.resource = Resource.default().merge(this.resource); this._config = Object.assign({}, mergedConfig, { diff --git a/packages/opentelemetry-sdk-trace-base/src/utility.ts b/packages/opentelemetry-sdk-trace-base/src/utility.ts index 44654ae87d..3492f3b050 100644 --- a/packages/opentelemetry-sdk-trace-base/src/utility.ts +++ b/packages/opentelemetry-sdk-trace-base/src/utility.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT, DEFAULT_ATTRIBUTE_COUNT_LIMIT } from '@opentelemetry/core'; - import { Sampler } from '@opentelemetry/api'; import { buildSamplerFromEnv, DEFAULT_CONFIG } from './config'; import { SpanLimits, TracerConfig, GeneralLimits } from './types'; @@ -52,21 +50,32 @@ export function mergeConfig(userConfig: TracerConfig): TracerConfig & { userConfig.spanLimits || {} ); + return target; +} + +/** + * When general limits are provided and model specific limits are not, + * configures the model specific limits by using the values from the general ones. + * @param userConfig User provided tracer configuration + */ +export function reconfigureLimits(userConfig: TracerConfig): TracerConfig { + const spanLimits = Object.assign({}, userConfig.spanLimits); + /** * When span attribute count limit is not defined, but general attribute count limit is defined * Then, span attribute count limit will be same as general one */ - if (target.spanLimits.attributeCountLimit === DEFAULT_ATTRIBUTE_COUNT_LIMIT && target.generalLimits.attributeCountLimit !== DEFAULT_ATTRIBUTE_COUNT_LIMIT) { - target.spanLimits.attributeCountLimit = target.generalLimits.attributeCountLimit; + if (spanLimits.attributeCountLimit == null && userConfig.generalLimits?.attributeCountLimit != null) { + spanLimits.attributeCountLimit = userConfig.generalLimits.attributeCountLimit; } /** * When span attribute value length limit is not defined, but general attribute value length limit is defined * Then, span attribute value length limit will be same as general one */ - if (target.spanLimits.attributeValueLengthLimit === DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT && target.generalLimits.attributeValueLengthLimit !== DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT) { - target.spanLimits.attributeValueLengthLimit = target.generalLimits.attributeValueLengthLimit; + if (spanLimits.attributeValueLengthLimit == null && userConfig.generalLimits?.attributeValueLengthLimit != null) { + spanLimits.attributeValueLengthLimit = userConfig.generalLimits.attributeValueLengthLimit; } - return target; + return Object.assign({}, userConfig, { spanLimits }); } diff --git a/packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts b/packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts index e29276b630..9f6c8e416f 100644 --- a/packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts @@ -23,6 +23,8 @@ import { TraceFlags, } from '@opentelemetry/api'; import { + DEFAULT_ATTRIBUTE_COUNT_LIMIT, + DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT, hrTime, hrTimeDuration, hrTimeToMilliseconds, @@ -486,6 +488,38 @@ describe('Span', () => { }); }); + describe('when span "attributeCountLimit" set to the default value and general "attributeCountLimit" option defined', () => { + const tracer = new BasicTracerProvider({ + generalLimits: { + // Setting count limit + attributeCountLimit: 10, + }, + spanLimits: { + attributeCountLimit: DEFAULT_ATTRIBUTE_COUNT_LIMIT, + } + }).getTracer('default'); + + const span = new Span( + tracer, + ROOT_CONTEXT, + name, + spanContext, + SpanKind.CLIENT + ); + for (let i = 0; i < 150; i++) { + span.setAttribute('foo' + i, 'bar' + i); + } + span.end(); + + it('should remove / drop all remaining values after the number of values exceeds the span limit', () => { + assert.strictEqual(Object.keys(span.attributes).length, DEFAULT_ATTRIBUTE_COUNT_LIMIT); + assert.strictEqual(span.attributes['foo0'], 'bar0'); + assert.strictEqual(span.attributes['foo10'], 'bar10'); + assert.strictEqual(span.attributes['foo127'], 'bar127'); + assert.strictEqual(span.attributes['foo128'], undefined); + }); + }); + describe('when "attributeValueLengthLimit" option defined', () => { const tracer = new BasicTracerProvider({ generalLimits: { @@ -528,6 +562,44 @@ describe('Span', () => { assert.strictEqual(span.attributes['attr-non-string'], true); }); }); + + describe('when span "attributeValueLengthLimit" set to the default value and general "attributeValueLengthLimit" option defined', () => { + const tracer = new BasicTracerProvider({ + generalLimits: { + // Setting attribute value length limit + attributeValueLengthLimit: 10, + }, + spanLimits: { + // Setting attribute value length limit + attributeValueLengthLimit: DEFAULT_ATTRIBUTE_VALUE_LENGTH_LIMIT, + }, + }).getTracer('default'); + + const span = new Span( + tracer, + ROOT_CONTEXT, + name, + spanContext, + SpanKind.CLIENT + ); + + it('should not truncate value', () => { + span.setAttribute('attr-with-more-length', 'abcdefghijklmn'); + assert.strictEqual(span.attributes['attr-with-more-length'], 'abcdefghijklmn'); + }); + + it('should not truncate value of arrays', () => { + span.setAttribute('attr-array-of-strings', ['abcdefghijklmn', 'abc', 'abcde', '']); + span.setAttribute('attr-array-of-bool', [true, false]); + assert.deepStrictEqual(span.attributes['attr-array-of-strings'], ['abcdefghijklmn', 'abc', 'abcde', '']); + assert.deepStrictEqual(span.attributes['attr-array-of-bool'], [true, false]); + }); + + it('should return same value for non-string values', () => { + span.setAttribute('attr-non-string', true); + assert.strictEqual(span.attributes['attr-non-string'], true); + }); + }); }); }); From 21fc8b5280af360a517707ee013a1f37ba38bdc0 Mon Sep 17 00:00:00 2001 From: legendecas Date: Mon, 17 Jan 2022 17:35:42 +0800 Subject: [PATCH 12/16] feat(instrumentation-http): add options to ignore requests (#2704) Co-authored-by: Valentin Marchaud --- .../README.md | 11 +++- .../src/http.ts | 22 ++++++- .../src/types.ts | 22 ++++++- .../src/utils.ts | 27 +++----- .../test/functionals/http-enable.test.ts | 62 ++++++++++++++++++- .../test/functionals/https-enable.test.ts | 49 ++++++++++++++- .../test/functionals/utils.test.ts | 25 +------- 7 files changed, 164 insertions(+), 54 deletions(-) diff --git a/experimental/packages/opentelemetry-instrumentation-http/README.md b/experimental/packages/opentelemetry-instrumentation-http/README.md index 340d658b24..4684adaa4c 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/README.md +++ b/experimental/packages/opentelemetry-instrumentation-http/README.md @@ -50,13 +50,20 @@ Http instrumentation has few options available to choose from. You can set the f | [`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 | +| `ignoreIncomingRequestHook` | `IgnoreIncomingRequestFunction` | Http instrumentation will not trace all incoming requests that matched with custom function | +| `ignoreOutgoingRequestHook` | `IgnoreOutgoingRequestFunction` | Http instrumentation will not trace all outgoing requests that matched with custom function | | [`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` | +The following options are deprecated: + +| Options | Type | Description | +| ------- | ---- | ----------- | +| `ignoreIncomingPaths` | `IgnoreMatcher[]` | Http instrumentation will not trace all incoming requests that match paths | +| `ignoreOutgoingUrls` | `IgnoreMatcher[]` | Http instrumentation will not trace all outgoing requests that match urls | + ## Useful links - For more information on OpenTelemetry, visit: diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts index ecfd1c4f85..b031cb57fc 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts @@ -382,7 +382,16 @@ export class HttpInstrumentation extends InstrumentationBase { utils.isIgnored( pathname, instrumentation._getConfig().ignoreIncomingPaths, - (e: Error) => instrumentation._diag.error('caught ignoreIncomingPaths error: ', e) + (e: unknown) => instrumentation._diag.error('caught ignoreIncomingPaths error: ', e) + ) || + safeExecuteInTheMiddle( + () => instrumentation._getConfig().ignoreIncomingRequestHook?.(request), + (e: unknown) => { + if (e != null) { + instrumentation._diag.error('caught ignoreIncomingRequestHook error: ', e); + } + }, + true ) ) { return context.with(suppressTracing(context.active()), () => { @@ -534,7 +543,16 @@ export class HttpInstrumentation extends InstrumentationBase { utils.isIgnored( origin + pathname, instrumentation._getConfig().ignoreOutgoingUrls, - (e: Error) => instrumentation._diag.error('caught ignoreOutgoingUrls error: ', e) + (e: unknown) => instrumentation._diag.error('caught ignoreOutgoingUrls error: ', e) + ) || + safeExecuteInTheMiddle( + () => instrumentation._getConfig().ignoreOutgoingRequestHook?.(optionsParsed), + (e: unknown) => { + if (e != null) { + instrumentation._diag.error('caught ignoreOutgoingRequestHook error: ', e); + } + }, + true ) ) { return original.apply(this, [optionsParsed, ...args]); diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/types.ts b/experimental/packages/opentelemetry-instrumentation-http/src/types.ts index ed57c139f5..6741d0a042 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/types.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/types.ts @@ -63,6 +63,14 @@ export interface HttpCustomAttributeFunction { ): void; } +export interface IgnoreIncomingRequestFunction { + (request: IncomingMessage ): boolean; +} + +export interface IgnoreOutgoingRequestFunction { + (request: RequestOptions ): boolean; +} + export interface HttpRequestCustomAttributeFunction { (span: Span, request: ClientRequest | IncomingMessage): void; } @@ -83,10 +91,20 @@ export interface StartOutgoingSpanCustomAttributeFunction { * Options available for the HTTP instrumentation (see [documentation](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-instrumentation-http#http-instrumentation-options)) */ export interface HttpInstrumentationConfig extends InstrumentationConfig { - /** Not trace all incoming requests that match paths */ + /** + * Not trace all incoming requests that match paths + * @deprecated use `ignoreIncomingRequestHook` instead + */ ignoreIncomingPaths?: IgnoreMatcher[]; - /** Not trace all outgoing requests that match urls */ + /** Not trace all incoming requests that matched with custom function */ + ignoreIncomingRequestHook?: IgnoreIncomingRequestFunction; + /** + * Not trace all outgoing requests that match urls + * @deprecated use `ignoreOutgoingRequestHook` instead + */ ignoreOutgoingUrls?: IgnoreMatcher[]; + /** Not trace all outgoing requests that matched with custom function */ + ignoreOutgoingRequestHook?: IgnoreOutgoingRequestFunction; /** Function for adding custom attributes after response is handled */ applyCustomAttributesOnSpan?: HttpCustomAttributeFunction; /** Function for adding custom attributes before request is handled */ diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts b/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts index 308cb7a439..0a102ae688 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/utils.ts @@ -85,19 +85,6 @@ export const parseResponseStatus = ( return { code: SpanStatusCode.ERROR }; }; -/** - * Returns whether the Expect header is on the given options object. - * @param options Options for http.request. - */ -export const hasExpectHeader = (options: RequestOptions): boolean => { - if (!options.headers) { - return false; - } - - const keys = Object.keys(options.headers); - return !!keys.find(key => key.toLowerCase() === 'expect'); -}; - /** * Check whether the given obj match pattern * @param constant e.g URL of request @@ -129,7 +116,7 @@ export const satisfiesPattern = ( export const isIgnored = ( constant: string, list?: IgnoreMatcher[], - onException?: (error: Error) => void + onException?: (error: unknown) => void ): boolean => { if (!list) { // No ignored urls - trace everything @@ -304,18 +291,18 @@ export const getRequestInfo = ( }`; } - if (hasExpectHeader(optionsParsed)) { - optionsParsed.headers = Object.assign({}, optionsParsed.headers); - } else if (!optionsParsed.headers) { - optionsParsed.headers = {}; - } + const headers = optionsParsed.headers ?? {}; + optionsParsed.headers = Object.keys(headers).reduce((normalizedHeader, key) => { + normalizedHeader[key.toLowerCase()] = headers[key]; + return normalizedHeader; + }, {} as OutgoingHttpHeaders); // some packages return method in lowercase.. // ensure upperCase for consistency const method = optionsParsed.method ? optionsParsed.method.toUpperCase() : 'GET'; - return { origin, pathname, method, optionsParsed }; + return { origin, pathname, method, optionsParsed, }; }; /** diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts index e72387088f..1ca36d2247 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts @@ -142,11 +142,17 @@ describe('HttpInstrumentation', () => { throw new Error('bad ignoreIncomingPaths function'); }, ], + ignoreIncomingRequestHook: _request => { + throw new Error('bad ignoreIncomingRequestHook function'); + }, ignoreOutgoingUrls: [ (url: string) => { throw new Error('bad ignoreOutgoingUrls function'); }, ], + ignoreOutgoingRequestHook: _request => { + throw new Error('bad ignoreOutgoingRequestHook function'); + }, applyCustomAttributesOnSpan: () => { throw new Error(applyCustomAttributesOnSpanErrorMessage); }, @@ -167,7 +173,12 @@ describe('HttpInstrumentation', () => { it('should generate valid spans (client side and server side)', async () => { const result = await httpRequest.get( - `${protocol}://${hostname}:${serverPort}${pathname}` + `${protocol}://${hostname}:${serverPort}${pathname}`, + { + headers: { + 'user-agent': 'tester' + } + } ); const spans = memoryExporter.getFinishedSpans(); const [incomingSpan, outgoingSpan] = spans; @@ -207,11 +218,20 @@ describe('HttpInstrumentation', () => { /\/ignored\/regexp$/i, (url: string) => url.endsWith('/ignored/function'), ], + ignoreIncomingRequestHook: request => { + return request.headers['user-agent']?.match('ignored-string') != null; + }, ignoreOutgoingUrls: [ `${protocol}://${hostname}:${serverPort}/ignored/string`, /\/ignored\/regexp$/i, (url: string) => url.endsWith('/ignored/function'), ], + ignoreOutgoingRequestHook: request => { + if (request.headers?.['user-agent'] != null) { + return `${request.headers['user-agent']}`.match('ignored-string') != null; + } + return false; + }, applyCustomAttributesOnSpan: customAttributeFunction, requestHook: requestHookFunction, responseHook: responseHookFunction, @@ -447,7 +467,7 @@ describe('HttpInstrumentation', () => { }); for (const ignored of ['string', 'function', 'regexp']) { - it(`should not trace ignored requests (client and server side) with type ${ignored}`, async () => { + it(`should not trace ignored requests with paths (client and server side) with type ${ignored}`, async () => { const testPath = `/ignored/${ignored}`; await httpRequest.get( @@ -458,6 +478,44 @@ describe('HttpInstrumentation', () => { }); } + it('should not trace ignored requests with headers (client and server side)', async () => { + const testValue = 'ignored-string'; + + await Promise.all([ + httpRequest.get( + `${protocol}://${hostname}:${serverPort}`, + { + headers: { + 'user-agent': testValue + } + } + ), + httpRequest.get( + `${protocol}://${hostname}:${serverPort}`, + { + headers: { + 'uSeR-aGeNt': testValue + } + } + ), + ]); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 0); + }); + + it('should trace not ignored requests with headers (client and server side)', async () => { + await httpRequest.get( + `${protocol}://${hostname}:${serverPort}`, + { + headers: { + 'user-agent': 'test-bot', + } + } + ); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 2); + }); + for (const arg of ['string', {}, new Date()]) { it(`should be tracable and not throw exception in ${protocol} instrumentation when passing the following argument ${JSON.stringify( arg diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts index 46bf516e13..2611642b4c 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts @@ -112,11 +112,17 @@ describe('HttpsInstrumentation', () => { throw new Error('bad ignoreIncomingPaths function'); }, ], + ignoreIncomingRequestHook: _request => { + throw new Error('bad ignoreIncomingRequestHook function'); + }, ignoreOutgoingUrls: [ (url: string) => { throw new Error('bad ignoreOutgoingUrls function'); }, ], + ignoreOutgoingRequestHook: _request => { + throw new Error('bad ignoreOutgoingRequestHook function'); + }, applyCustomAttributesOnSpan: () => { throw new Error(applyCustomAttributesOnSpanErrorMessage); }, @@ -142,7 +148,12 @@ describe('HttpsInstrumentation', () => { it('should generate valid spans (client side and server side)', async () => { const result = await httpsRequest.get( - `${protocol}://${hostname}:${serverPort}${pathname}` + `${protocol}://${hostname}:${serverPort}${pathname}`, + { + headers: { + 'user-agent': 'tester' + } + } ); const spans = memoryExporter.getFinishedSpans(); const [incomingSpan, outgoingSpan] = spans; @@ -181,11 +192,20 @@ describe('HttpsInstrumentation', () => { /\/ignored\/regexp$/i, (url: string) => url.endsWith('/ignored/function'), ], + ignoreIncomingRequestHook: request => { + return request.headers['user-agent']?.match('ignored-string') != null; + }, ignoreOutgoingUrls: [ `${protocol}://${hostname}:${serverPort}/ignored/string`, /\/ignored\/regexp$/i, (url: string) => url.endsWith('/ignored/function'), ], + ignoreOutgoingRequestHook: request => { + if (request.headers?.['user-agent'] != null) { + return `${request.headers['user-agent']}`.match('ignored-string') != null; + } + return false; + }, applyCustomAttributesOnSpan: customAttributeFunction, serverName, }); @@ -412,7 +432,7 @@ describe('HttpsInstrumentation', () => { }); for (const ignored of ['string', 'function', 'regexp']) { - it(`should not trace ignored requests (client and server side) with type ${ignored}`, async () => { + it(`should not trace ignored requests with paths (client and server side) with type ${ignored}`, async () => { const testPath = `/ignored/${ignored}`; await httpsRequest.get( @@ -423,6 +443,31 @@ describe('HttpsInstrumentation', () => { }); } + it('should not trace ignored requests with headers (client and server side)', async () => { + const testValue = 'ignored-string'; + + await Promise.all([ + httpsRequest.get( + `${protocol}://${hostname}:${serverPort}`, + { + headers: { + 'user-agent': testValue + } + } + ), + httpsRequest.get( + `${protocol}://${hostname}:${serverPort}`, + { + headers: { + 'uSeR-aGeNt': testValue + } + } + ) + ]); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 0); + }); + for (const arg of ['string', {}, new Date()]) { it(`should be tracable and not throw exception in ${protocol} instrumentation when passing the following argument ${JSON.stringify( arg diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts index e4837ab082..aa1715a5a0 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/utils.test.ts @@ -24,7 +24,6 @@ import { import { BasicTracerProvider, Span } from '@opentelemetry/sdk-trace-base'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import * as assert from 'assert'; -import * as http from 'http'; import { IncomingMessage, ServerResponse } from 'http'; import { Socket } from 'net'; import * as sinon from 'sinon'; @@ -58,28 +57,6 @@ describe('Utility', () => { } }); }); - describe('hasExpectHeader()', () => { - it('should throw if no option', () => { - try { - utils.hasExpectHeader('' as http.RequestOptions); - assert.fail(); - } catch (ignore) {} - }); - - it('should not throw if no headers', () => { - const result = utils.hasExpectHeader({} as http.RequestOptions); - assert.strictEqual(result, false); - }); - - it('should return true on Expect (no case sensitive)', () => { - for (const headers of [{ Expect: 1 }, { expect: 1 }, { ExPect: 1 }]) { - const result = utils.hasExpectHeader({ - headers, - } as http.RequestOptions); - assert.strictEqual(result, true); - } - }); - }); describe('getRequestInfo()', () => { it('should get options object', () => { @@ -170,7 +147,7 @@ describe('Utility', () => { }); it('should not re-throw when function throws an exception', () => { - const onException = (e: Error) => { + const onException = (e: unknown) => { // Do nothing }; for (const callback of [undefined, onException]) { From 206a1c3c1a2d20aa40abb3484b907e995cb3ef24 Mon Sep 17 00:00:00 2001 From: legendecas Date: Wed, 19 Jan 2022 00:04:21 +0800 Subject: [PATCH 13/16] test(sdk-metrics): browser compatibility tests (#2709) --- .../karma.conf.js | 24 ++++++++++ .../package.json | 8 ++++ .../PeriodicExportingMetricReader.test.ts | 27 +++++------ .../test/index-webpack.ts | 21 +++++++++ .../test/test-utils.ts | 45 +++++++++++++++++++ .../opentelemetry-core/test/test-utils.ts | 17 +++++-- 6 files changed, 126 insertions(+), 16 deletions(-) create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/karma.conf.js create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/index-webpack.ts create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/test-utils.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/karma.conf.js b/experimental/packages/opentelemetry-sdk-metrics-base/karma.conf.js new file mode 100644 index 0000000000..6174839d65 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/karma.conf.js @@ -0,0 +1,24 @@ +/*! + * 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 + })) +}; diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/package.json b/experimental/packages/opentelemetry-sdk-metrics-base/package.json index ce653a0f4c..9f3105d4c1 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/package.json +++ b/experimental/packages/opentelemetry-sdk-metrics-base/package.json @@ -12,7 +12,9 @@ "compile": "tsc --build tsconfig.all.json", "clean": "tsc --build --clean tsconfig.all.json", "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", + "test:browser": "nyc karma start --single-run", "tdd": "npm run test -- --watch-extensions ts --watch", + "tdd:browser": "karma start", "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", @@ -57,6 +59,12 @@ "@types/node": "14.17.33", "@types/sinon": "10.0.6", "codecov": "3.8.3", + "karma": "6.3.8", + "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", diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts index 90962c8ca2..4950f1cadc 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/export/PeriodicExportingMetricReader.test.ts @@ -22,6 +22,7 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; import { MetricProducer } from '../../src/export/MetricProducer'; import { TimeoutError } from '../../src/utils'; +import { assertRejects } from '../test-utils'; const MAX_32_BIT_INT = 2 ** 31 - 1; @@ -102,7 +103,7 @@ describe('PeriodicExportingMetricReader', () => { exporter: exporter, exportIntervalMillis: 0, exportTimeoutMillis: 0 - }), new Error('exportIntervalMillis must be greater than 0')); + }), /exportIntervalMillis must be greater than 0/); }); it('should throw when timeout less or equal to 0', () => { @@ -111,7 +112,7 @@ describe('PeriodicExportingMetricReader', () => { exporter: exporter, exportIntervalMillis: 1, exportTimeoutMillis: 0 - }), new Error('exportTimeoutMillis must be greater than 0')); + }), /exportTimeoutMillis must be greater than 0/); }); it('should throw when timeout less or equal to interval', () => { @@ -120,7 +121,7 @@ describe('PeriodicExportingMetricReader', () => { exporter: exporter, exportIntervalMillis: 100, exportTimeoutMillis: 200 - }), new Error('exportIntervalMillis must be greater than or equal to exportTimeoutMillis')); + }), /exportIntervalMillis must be greater than or equal to exportTimeoutMillis/); }); it('should not start exporting', async () => { @@ -151,7 +152,7 @@ describe('PeriodicExportingMetricReader', () => { reader.setMetricProducer(new TestMetricProducer()); const result = await exporter.waitForNumberOfExports(2); - assert.deepEqual(result, [[], []]); + assert.deepStrictEqual(result, [[], []]); await reader.shutdown(); }); }); @@ -169,7 +170,7 @@ describe('PeriodicExportingMetricReader', () => { reader.setMetricProducer(new TestMetricProducer()); const result = await exporter.waitForNumberOfExports(2); - assert.deepEqual(result, [[], []]); + assert.deepStrictEqual(result, [[], []]); exporter.throwException = false; await reader.shutdown(); @@ -188,7 +189,7 @@ describe('PeriodicExportingMetricReader', () => { reader.setMetricProducer(new TestMetricProducer()); const result = await exporter.waitForNumberOfExports(2); - assert.deepEqual(result, [[], []]); + assert.deepStrictEqual(result, [[], []]); exporter.throwException = false; await reader.shutdown(); @@ -227,7 +228,7 @@ describe('PeriodicExportingMetricReader', () => { }); reader.setMetricProducer(new TestMetricProducer()); - await assert.rejects(() => reader.forceFlush({ timeoutMillis: 20 }), + await assertRejects(() => reader.forceFlush({ timeoutMillis: 20 }), TimeoutError); await reader.shutdown(); }); @@ -241,7 +242,7 @@ describe('PeriodicExportingMetricReader', () => { exportTimeoutMillis: 80, }); - await assert.rejects(() => reader.forceFlush()); + await assertRejects(() => reader.forceFlush(), /Error during forceFlush/); }); it('should not forceFlush exporter after shutdown', async () => { @@ -294,7 +295,7 @@ describe('PeriodicExportingMetricReader', () => { }); reader.setMetricProducer(new TestMetricProducer()); - await assert.rejects(() => reader.shutdown({ timeoutMillis: 20 }), + await assertRejects(() => reader.shutdown({ timeoutMillis: 20 }), TimeoutError); }); @@ -326,7 +327,7 @@ describe('PeriodicExportingMetricReader', () => { exportTimeoutMillis: 80, }); - await assert.rejects(() => reader.shutdown()); + await assertRejects(() => reader.shutdown(), /Error during forceFlush/); }); }) ; @@ -340,7 +341,7 @@ describe('PeriodicExportingMetricReader', () => { exportTimeoutMillis: 80, }); - await assert.rejects(() => reader.collect()); + await assertRejects(() => reader.collect(), /MetricReader is not bound to a MetricProducer/); }); it('should return empty on shut-down instance', async () => { @@ -354,7 +355,7 @@ describe('PeriodicExportingMetricReader', () => { reader.setMetricProducer(new TestMetricProducer()); await reader.shutdown(); - assert.deepEqual([], await reader.collect()); + assert.deepStrictEqual([], await reader.collect()); }); it('should time out when timeoutMillis is set', async () => { @@ -368,7 +369,7 @@ describe('PeriodicExportingMetricReader', () => { producer.collectionTime = 40; reader.setMetricProducer(producer); - await assert.rejects( + await assertRejects( () => reader.collect({ timeoutMillis: 20 }), TimeoutError ); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/index-webpack.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/index-webpack.ts new file mode 100644 index 0000000000..9cfc10baa1 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/index-webpack.ts @@ -0,0 +1,21 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const testsContext = require.context('.', true, /test$/); +testsContext.keys().forEach(testsContext); + +const srcContext = require.context('.', true, /src$/); +srcContext.keys().forEach(srcContext); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/test-utils.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/test-utils.ts new file mode 100644 index 0000000000..82533608cd --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/test-utils.ts @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/** + * Changes to this file should be applied to opentelemetry-core/test/test-utils.ts too. + */ + +import * as assert from 'assert'; + +interface ErrorLikeConstructor { + new(): Error; +} + +/** + * Node.js v8.x and browser compatible `assert.rejects`. + */ +export async function assertRejects(actual: any, expected: RegExp | ErrorLikeConstructor) { + let rejected; + try { + if (typeof actual === 'function') { + await actual(); + } else { + await actual; + } + } catch (err) { + rejected = true; + assert.throws(() => { + throw err; + }, expected); + } + assert(rejected, 'Promise not rejected'); +} diff --git a/packages/opentelemetry-core/test/test-utils.ts b/packages/opentelemetry-core/test/test-utils.ts index 72ec427730..002945691d 100644 --- a/packages/opentelemetry-core/test/test-utils.ts +++ b/packages/opentelemetry-core/test/test-utils.ts @@ -16,15 +16,26 @@ import * as assert from 'assert'; +interface ErrorLikeConstructor { + new(): Error; +} + /** * Node.js v8.x and browser compatible `assert.rejects`. */ -export async function assertRejects(promise: any, expect: any) { +export async function assertRejects(actual: any, expected: RegExp | ErrorLikeConstructor) { + let rejected; try { - await promise; + if (typeof actual === 'function') { + await actual(); + } else { + await actual; + } } catch (err) { + rejected = true; assert.throws(() => { throw err; - }, expect); + }, expected); } + assert(rejected, 'Promise not rejected'); } From 395fb0428bfbd523f6bfb8b26c3973d5c08371c4 Mon Sep 17 00:00:00 2001 From: Yaniv Davidi Date: Tue, 18 Jan 2022 18:50:56 +0200 Subject: [PATCH 14/16] docs: document node v10 EOL (#2720) Co-authored-by: Valentin Marchaud --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18d6cbf629..ef5a1fd417 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ If you are a library author looking to build OpenTelemetry into your library, pl ### Node Support Automated tests are run using the latest release of each currently active version of Node.JS. -While Node.JS v8 is no longer supported by the Node.JS team, the latest version of Node.JS v8 is still included in our testing suite. +While Node.JS v8 and v10 are no longer supported by the Node.JS team, the latest versions of Node.JS v8 and v10 are still included in our testing suite. Please note that versions of Node.JS v8 prior to `v8.5.0` will NOT work, because OpenTelemetry Node depends on the `perf_hooks` module introduced in `v8.5.0` ### Browser Support From 1577f3536f2cf370e2d4763b0918b56b5b8d366a Mon Sep 17 00:00:00 2001 From: legendecas Date: Wed, 19 Jan 2022 23:31:28 +0800 Subject: [PATCH 15/16] feat(sdk-metrics-base): implement async instruments support (#2686) Co-authored-by: Daniel Dyla --- .../src/Meter.ts | 37 ++-- .../src/ObservableResult.ts | 26 +++ .../src/state/AsyncMetricStorage.ts | 100 +++++++++ .../src/state/DeltaMetricProcessor.ts | 24 ++- .../src/state/HashMap.ts | 8 +- .../src/state/SyncMetricStorage.ts | 6 +- .../src/state/TemporalMetricProcessor.ts | 2 +- .../src/view/AttributesProcessor.ts | 11 +- .../test/Meter.test.ts | 24 +++ .../test/ObservableResult.test.ts | 42 ++++ .../test/state/AsyncMetricStorage.test.ts | 198 ++++++++++++++++++ .../test/state/DeltaMetricProcessor.test.ts | 69 +++++- .../test/state/HashMap.test.ts | 17 ++ 13 files changed, 533 insertions(+), 31 deletions(-) create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/ObservableResult.test.ts create mode 100644 experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts index a9a3beb556..7808db28e2 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/Meter.ts @@ -26,6 +26,7 @@ import { MetricData } from './export/MetricData'; import { isNotNullish } from './utils'; import { MetricCollectorHandle } from './state/MetricCollector'; import { HrTime } from '@opentelemetry/api'; +import { AsyncMetricStorage } from './state/AsyncMetricStorage'; // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#meter @@ -62,27 +63,30 @@ export class Meter implements metrics.Meter { } createObservableGauge( - _name: string, - _callback: metrics.ObservableCallback, - _options?: metrics.ObservableGaugeOptions, + name: string, + callback: metrics.ObservableCallback, + options?: metrics.ObservableGaugeOptions, ): void { - throw new Error('Method not implemented.'); + const descriptor = createInstrumentDescriptor(name, InstrumentType.OBSERVABLE_GAUGE, options); + this._registerAsyncMetricStorage(descriptor, callback); } createObservableCounter( - _name: string, - _callback: metrics.ObservableCallback, - _options?: metrics.ObservableCounterOptions, + name: string, + callback: metrics.ObservableCallback, + options?: metrics.ObservableCounterOptions, ): void { - throw new Error('Method not implemented.'); + const descriptor = createInstrumentDescriptor(name, InstrumentType.OBSERVABLE_COUNTER, options); + this._registerAsyncMetricStorage(descriptor, callback); } createObservableUpDownCounter( - _name: string, - _callback: metrics.ObservableCallback, - _options?: metrics.ObservableUpDownCounterOptions, + name: string, + callback: metrics.ObservableCallback, + options?: metrics.ObservableUpDownCounterOptions, ): void { - throw new Error('Method not implemented.'); + const descriptor = createInstrumentDescriptor(name, InstrumentType.OBSERVABLE_UP_DOWN_COUNTER, options); + this._registerAsyncMetricStorage(descriptor, callback); } private _registerMetricStorage(descriptor: InstrumentDescriptor) { @@ -99,6 +103,15 @@ export class Meter implements metrics.Meter { return new MultiMetricStorage(storages); } + private _registerAsyncMetricStorage(descriptor: InstrumentDescriptor, callback: metrics.ObservableCallback) { + const views = this._meterProviderSharedState.viewRegistry.findViews(descriptor, this._instrumentationLibrary); + views.forEach(view => { + const storage = AsyncMetricStorage.create(view, descriptor, callback); + // TODO: handle conflicts + this._metricStorageRegistry.set(descriptor.name, storage); + }); + } + async collect(collector: MetricCollectorHandle, collectionTime: HrTime): Promise { const result = await Promise.all(Array.from(this._metricStorageRegistry.values()).map(metricStorage => { return metricStorage.collect( diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts new file mode 100644 index 0000000000..c10bf7514e --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/ObservableResult.ts @@ -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 + * + * 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 metrics from '@opentelemetry/api-metrics-wip'; +import { AttributeHashMap } from './state/HashMap'; + +export class ObservableResult implements metrics.ObservableResult { + buffer = new AttributeHashMap(); + + observe(value: number, attributes: metrics.Attributes = {}): void { + this.buffer.set(attributes, value); + } +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts new file mode 100644 index 0000000000..d98ececf7f --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/AsyncMetricStorage.ts @@ -0,0 +1,100 @@ +/* + * 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 { HrTime } from '@opentelemetry/api'; +import { ObservableCallback } from '@opentelemetry/api-metrics-wip'; +import { Accumulation, Aggregator } from '../aggregator/types'; +import { View } from '../view/View'; +import { createInstrumentDescriptorWithView, InstrumentDescriptor } from '../InstrumentDescriptor'; +import { AttributesProcessor } from '../view/AttributesProcessor'; +import { MetricStorage } from './MetricStorage'; +import { InstrumentationLibrary } from '@opentelemetry/core'; +import { Resource } from '@opentelemetry/resources'; +import { MetricData } from '../export/MetricData'; +import { DeltaMetricProcessor } from './DeltaMetricProcessor'; +import { TemporalMetricProcessor } from './TemporalMetricProcessor'; +import { Maybe } from '../utils'; +import { MetricCollectorHandle } from './MetricCollector'; +import { ObservableResult } from '../ObservableResult'; +import { AttributeHashMap } from './HashMap'; + +/** + * Internal interface. + * + * Stores and aggregates {@link MetricData} for asynchronous instruments. + */ +export class AsyncMetricStorage> implements MetricStorage { + private _deltaMetricStorage: DeltaMetricProcessor; + private _temporalMetricStorage: TemporalMetricProcessor; + + constructor( + private _instrumentDescriptor: InstrumentDescriptor, + aggregator: Aggregator, + private _attributesProcessor: AttributesProcessor, + private _callback: ObservableCallback + ) { + this._deltaMetricStorage = new DeltaMetricProcessor(aggregator); + this._temporalMetricStorage = new TemporalMetricProcessor(aggregator); + } + + private _record(measurements: AttributeHashMap) { + const processed = new AttributeHashMap(); + Array.from(measurements.entries()).forEach(([attributes, value]) => { + processed.set(this._attributesProcessor.process(attributes), value); + }); + this._deltaMetricStorage.batchCumulate(processed); + } + + /** + * Collects the metrics from this storage. The ObservableCallback is invoked + * during the collection. + * + * Note: This is a stateful operation and may reset any interval-related + * state for the MetricCollector. + */ + async collect( + collector: MetricCollectorHandle, + collectors: MetricCollectorHandle[], + resource: Resource, + instrumentationLibrary: InstrumentationLibrary, + sdkStartTime: HrTime, + collectionTime: HrTime, + ): Promise> { + const observableResult = new ObservableResult(); + // TODO: timeout with callback + await this._callback(observableResult); + this._record(observableResult.buffer); + + const accumulations = this._deltaMetricStorage.collect(); + + return this._temporalMetricStorage.buildMetrics( + collector, + collectors, + resource, + instrumentationLibrary, + this._instrumentDescriptor, + accumulations, + sdkStartTime, + collectionTime + ); + } + + static create(view: View, instrument: InstrumentDescriptor, callback: ObservableCallback): AsyncMetricStorage> { + instrument = createInstrumentDescriptorWithView(view, instrument); + const aggregator = view.aggregation.createAggregator(instrument); + return new AsyncMetricStorage(instrument, aggregator, view.attributesProcessor, callback); + } +} diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/DeltaMetricProcessor.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/DeltaMetricProcessor.ts index 0e1325ee71..590a78521e 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/DeltaMetricProcessor.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/DeltaMetricProcessor.ts @@ -28,11 +28,12 @@ import { AttributeHashMap } from './HashMap'; * recording to delta data points. */ export class DeltaMetricProcessor> { - private _activeCollectionStorage: AttributeHashMap; + private _activeCollectionStorage = new AttributeHashMap(); + // TODO: find a reasonable mean to clean the memo; + // https://github.com/open-telemetry/opentelemetry-specification/pull/2208 + private _cumulativeMemoStorage = new AttributeHashMap(); - constructor(private _aggregator: Aggregator) { - this._activeCollectionStorage = new AttributeHashMap(); - } + constructor(private _aggregator: Aggregator) {} /** Bind an efficient storage handle for a set of attributes. */ private bind(attributes: Attributes) { @@ -44,6 +45,21 @@ export class DeltaMetricProcessor> { accumulation?.record(value); } + batchCumulate(measurements: AttributeHashMap) { + Array.from(measurements.entries()).forEach(([attributes, value, hashCode]) => { + let accumulation = this._aggregator.createAccumulation(); + accumulation?.record(value); + if (this._cumulativeMemoStorage.has(attributes, hashCode)) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const previous = this._cumulativeMemoStorage.get(attributes, hashCode)!; + accumulation = this._aggregator.diff(previous, accumulation); + } + + this._cumulativeMemoStorage.set(attributes, accumulation, hashCode); + this._activeCollectionStorage.set(attributes, accumulation, hashCode); + }); + } + collect() { const unreportedDelta = this._activeCollectionStorage; this._activeCollectionStorage = new AttributeHashMap(); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/HashMap.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/HashMap.ts index fb8bd4a85a..879e5db737 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/HashMap.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/HashMap.ts @@ -53,11 +53,17 @@ export class HashMap { this._valueMap.set(hashCode, value); } + has(key: KeyType, hashCode?: HashCodeType) { + hashCode ??= this._hash(key); + return this._valueMap.has(hashCode); + } + *entries(): IterableIterator<[KeyType, ValueType, HashCodeType]> { const valueIterator = this._valueMap.entries(); let next = valueIterator.next(); while (next.done !== true) { - /** next.value[0] here can not be undefined */ + // next.value[0] here can not be undefined + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion yield [ this._keyMap.get(next.value[0])!, next.value[1], next.value[0]]; next = valueIterator.next(); } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts index cdc1e72b1a..609f0fc585 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/SyncMetricStorage.ts @@ -39,7 +39,11 @@ export class SyncMetricStorage> implements Writabl private _deltaMetricStorage: DeltaMetricProcessor; private _temporalMetricStorage: TemporalMetricProcessor; - constructor(private _instrumentDescriptor: InstrumentDescriptor, aggregator: Aggregator, private _attributesProcessor: AttributesProcessor) { + constructor( + private _instrumentDescriptor: InstrumentDescriptor, + aggregator: Aggregator, + private _attributesProcessor: AttributesProcessor + ) { this._deltaMetricStorage = new DeltaMetricProcessor(aggregator); this._temporalMetricStorage = new TemporalMetricProcessor(aggregator); } diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts index 1853adc8e5..9c4936de39 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/state/TemporalMetricProcessor.ts @@ -61,7 +61,7 @@ export class TemporalMetricProcessor { * @param currentAccumulations The current accumulation of metric data from instruments. * @param sdkStartTime The sdk start timestamp. * @param collectionTime The current collection timestamp. - * @returns The {@link MetricData} points or {@code null}. + * @returns The {@link MetricData} points or `null`. */ buildMetrics( collector: MetricCollectorHandle, diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/AttributesProcessor.ts b/experimental/packages/opentelemetry-sdk-metrics-base/src/view/AttributesProcessor.ts index 15b46f53e0..5ed8d2c0ab 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/src/view/AttributesProcessor.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/src/view/AttributesProcessor.ts @@ -23,7 +23,14 @@ import { Attributes } from '@opentelemetry/api-metrics-wip'; * additional dimension(s) from the {@link Context}. */ export abstract class AttributesProcessor { - abstract process(incoming: Attributes, context: Context): Attributes; + /** + * Process the metric instrument attributes. + * + * @param incoming The metric instrument attributes. + * @param context The active context when the instrument is synchronous. + * `undefined` otherwise. + */ + abstract process(incoming: Attributes, context?: Context): Attributes; static Noop() { return NOOP; @@ -31,7 +38,7 @@ export abstract class AttributesProcessor { } export class NoopAttributesProcessor extends AttributesProcessor { - process(incoming: Attributes, _context: Context) { + process(incoming: Attributes, _context?: Context) { return incoming; } } 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 785d0b5635..fbb1b3b991 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/Meter.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/Meter.test.ts @@ -14,12 +14,15 @@ * limitations under the License. */ +import { ObservableCallback } from '@opentelemetry/api-metrics-wip'; import * as assert from 'assert'; import { Counter, Histogram, UpDownCounter } from '../src/Instruments'; import { Meter } from '../src/Meter'; import { MeterProviderSharedState } from '../src/state/MeterProviderSharedState'; import { defaultInstrumentationLibrary, defaultResource } from './util'; +const noopObservableCallback: ObservableCallback = _observableResult => {}; + describe('Meter', () => { describe('createCounter', () => { it('should create counter', () => { @@ -44,4 +47,25 @@ describe('Meter', () => { assert(counter instanceof Histogram); }); }); + + describe('createObservableGauge', () => { + it('should create observable gauge', () => { + const meter = new Meter(new MeterProviderSharedState(defaultResource), defaultInstrumentationLibrary); + meter.createObservableGauge('foobar', noopObservableCallback); + }); + }); + + describe('createObservableCounter', () => { + it('should create observable counter', () => { + const meter = new Meter(new MeterProviderSharedState(defaultResource), defaultInstrumentationLibrary); + meter.createObservableCounter('foobar', noopObservableCallback); + }); + }); + + describe('createObservableUpDownCounter', () => { + it('should create observable up-down-counter', () => { + const meter = new Meter(new MeterProviderSharedState(defaultResource), defaultInstrumentationLibrary); + meter.createObservableUpDownCounter('foobar', noopObservableCallback); + }); + }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/ObservableResult.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/ObservableResult.test.ts new file mode 100644 index 0000000000..741ee28c55 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/ObservableResult.test.ts @@ -0,0 +1,42 @@ +/* + * 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 { ObservableResult } from '../src/ObservableResult'; +import { commonAttributes, commonValues } from './util'; + +describe('ObservableResult', () => { + describe('observe', () => { + it('should observe', () => { + const observableResult = new ObservableResult(); + for (const value of commonValues) { + for (const attributes of commonAttributes) { + observableResult.observe(value, attributes); + } + } + }); + + it('should deduplicate observations', () => { + const observableResult = new ObservableResult(); + observableResult.observe(1, {}); + observableResult.observe(2, {}); + + assert.strictEqual(observableResult.buffer.size, 1); + assert(observableResult.buffer.has({})); + assert.strictEqual(observableResult.buffer.get({}), 2); + }); + }); +}); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts new file mode 100644 index 0000000000..555d1f5049 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/AsyncMetricStorage.test.ts @@ -0,0 +1,198 @@ +/* + * 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 { hrTime } from '@opentelemetry/core'; +import * as assert from 'assert'; + +import { SumAggregator } from '../../src/aggregator'; +import { AggregationTemporality } from '../../src/export/AggregationTemporality'; +import { PointDataType } from '../../src/export/MetricData'; +import { MetricCollectorHandle } from '../../src/state/MetricCollector'; +import { AsyncMetricStorage } from '../../src/state/AsyncMetricStorage'; +import { NoopAttributesProcessor } from '../../src/view/AttributesProcessor'; +import { assertMetricData, assertPointData, defaultInstrumentationLibrary, defaultInstrumentDescriptor, defaultResource } from '../util'; +import { ObservableCallback } from '@opentelemetry/api-metrics-wip'; + +const deltaCollector: MetricCollectorHandle = { + aggregatorTemporality: AggregationTemporality.DELTA, +}; + +const cumulativeCollector: MetricCollectorHandle = { + aggregatorTemporality: AggregationTemporality.CUMULATIVE, +}; + +const sdkStartTime = hrTime(); + +class ObservableCallbackDelegate { + private _delegate?: ObservableCallback; + setDelegate(delegate: ObservableCallback) { + this._delegate = delegate; + } + + getCallback(): ObservableCallback { + return observableResult => { + this._delegate?.(observableResult); + }; + } +} + +describe('AsyncMetricStorage', () => { + describe('collect', () => { + describe('Delta Collector', () => { + const collectors = [deltaCollector]; + it('should collect and reset memos', async () => { + const delegate = new ObservableCallbackDelegate(); + const metricStorage = new AsyncMetricStorage( + defaultInstrumentDescriptor, + new SumAggregator(), + new NoopAttributesProcessor(), + delegate.getCallback(), + ); + + delegate.setDelegate(observableResult => { + observableResult.observe(1, { key: '1' }); + observableResult.observe(2, { key: '2' }); + observableResult.observe(3, { key: '3' }); + }); + { + const metric = await metricStorage.collect( + deltaCollector, + collectors, + defaultResource, + defaultInstrumentationLibrary, + sdkStartTime, + hrTime()); + + assertMetricData(metric, PointDataType.SINGULAR); + assert.strictEqual(metric.pointData.length, 3); + assertPointData(metric.pointData[0], { key: '1' }, 1); + assertPointData(metric.pointData[1], { key: '2' }, 2); + assertPointData(metric.pointData[2], { key: '3' }, 3); + } + + delegate.setDelegate(observableResult => {}); + // The attributes should not be memorized if no measurement was reported. + { + const metric = await metricStorage.collect( + deltaCollector, + collectors, + defaultResource, + defaultInstrumentationLibrary, + sdkStartTime, + hrTime()); + + assertMetricData(metric, PointDataType.SINGULAR); + assert.strictEqual(metric.pointData.length, 0); + } + + delegate.setDelegate(observableResult => { + observableResult.observe(4, { key: '1' }); + observableResult.observe(5, { key: '2' }); + observableResult.observe(6, { key: '3' }); + }); + { + const metric = await metricStorage.collect( + deltaCollector, + [deltaCollector], + defaultResource, + defaultInstrumentationLibrary, + sdkStartTime, + hrTime()); + + assertMetricData(metric, PointDataType.SINGULAR); + assert.strictEqual(metric.pointData.length, 3); + // all values were diffed. + assertPointData(metric.pointData[0], { key: '1' }, 3); + assertPointData(metric.pointData[1], { key: '2' }, 3); + assertPointData(metric.pointData[2], { key: '3' }, 3); + } + }); + }); + + describe('Cumulative Collector', () => { + const collectors = [cumulativeCollector]; + it('should collect cumulative metrics', async () => { + const delegate = new ObservableCallbackDelegate(); + const metricStorage = new AsyncMetricStorage( + defaultInstrumentDescriptor, + new SumAggregator(), + new NoopAttributesProcessor(), + delegate.getCallback(), + ); + + delegate.setDelegate(observableResult => { + observableResult.observe(1, { key: '1' }); + observableResult.observe(2, { key: '2' }); + observableResult.observe(3, { key: '3' }); + }); + { + const metric = await metricStorage.collect( + cumulativeCollector, + collectors, + defaultResource, + defaultInstrumentationLibrary, + sdkStartTime, + hrTime()); + + assertMetricData(metric, PointDataType.SINGULAR); + assert.strictEqual(metric.pointData.length, 3); + assertPointData(metric.pointData[0], { key: '1' }, 1); + assertPointData(metric.pointData[1], { key: '2' }, 2); + assertPointData(metric.pointData[2], { key: '3' }, 3); + } + + delegate.setDelegate(observableResult => {}); + // The attributes should be memorized even if no measurement was reported. + { + const metric = await metricStorage.collect( + cumulativeCollector, + collectors, + defaultResource, + defaultInstrumentationLibrary, + sdkStartTime, + hrTime()); + + assertMetricData(metric, PointDataType.SINGULAR); + assert.strictEqual(metric.pointData.length, 3); + assertPointData(metric.pointData[0], { key: '1' }, 1); + assertPointData(metric.pointData[1], { key: '2' }, 2); + assertPointData(metric.pointData[2], { key: '3' }, 3); + } + + delegate.setDelegate(observableResult => { + observableResult.observe(4, { key: '1' }); + observableResult.observe(5, { key: '2' }); + observableResult.observe(6, { key: '3' }); + }); + { + const metric = await metricStorage.collect( + cumulativeCollector, + collectors, + defaultResource, + defaultInstrumentationLibrary, + sdkStartTime, + hrTime()); + + assertMetricData(metric, PointDataType.SINGULAR); + assert.strictEqual(metric.pointData.length, 3); + assertPointData(metric.pointData[0], { key: '1' }, 4); + assertPointData(metric.pointData[1], { key: '2' }, 5); + assertPointData(metric.pointData[2], { key: '3' }, 6); + } + }); + }); + }); +}); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/DeltaMetricProcessor.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/DeltaMetricProcessor.test.ts index 8d606d64b9..73aa735c05 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/DeltaMetricProcessor.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/DeltaMetricProcessor.test.ts @@ -18,40 +18,89 @@ import * as api from '@opentelemetry/api'; import * as assert from 'assert'; import { DropAggregator, SumAggregator } from '../../src/aggregator'; import { DeltaMetricProcessor } from '../../src/state/DeltaMetricProcessor'; +import { AttributeHashMap } from '../../src/state/HashMap'; import { commonAttributes, commonValues } from '../util'; describe('DeltaMetricProcessor', () => { describe('record', () => { it('no exceptions on record with DropAggregator', () => { - const metricStorage = new DeltaMetricProcessor(new DropAggregator()); + const metricProcessor = new DeltaMetricProcessor(new DropAggregator()); for (const value of commonValues) { for (const attributes of commonAttributes) { - metricStorage.record(value, attributes, api.context.active()); + metricProcessor.record(value, attributes, api.context.active()); } } }); it('no exceptions on record with no-drop aggregator', () => { - const metricStorage = new DeltaMetricProcessor(new SumAggregator()); + const metricProcessor = new DeltaMetricProcessor(new SumAggregator()); for (const value of commonValues) { for (const attributes of commonAttributes) { - metricStorage.record(value, attributes, api.context.active()); + metricProcessor.record(value, attributes, api.context.active()); } } }); }); + describe('batchCumulate', () => { + it('no exceptions on batchCumulate with DropAggregator', () => { + const metricProcessor = new DeltaMetricProcessor(new DropAggregator()); + + const measurements = new AttributeHashMap(); + for (const value of commonValues) { + for (const attributes of commonAttributes) { + measurements.set(attributes, value); + } + } + metricProcessor.batchCumulate(measurements); + }); + + it('no exceptions on record with no-drop aggregator', () => { + const metricProcessor = new DeltaMetricProcessor(new SumAggregator()); + + const measurements = new AttributeHashMap(); + for (const value of commonValues) { + for (const attributes of commonAttributes) { + measurements.set(attributes, value); + } + } + metricProcessor.batchCumulate(measurements); + }); + + it('should compute the diff of accumulations', () => { + const metricProcessor = new DeltaMetricProcessor(new SumAggregator()); + + { + const measurements = new AttributeHashMap(); + measurements.set({}, 10); + metricProcessor.batchCumulate(measurements); + const accumulations = metricProcessor.collect(); + const accumulation = accumulations.get({}); + assert.strictEqual(accumulation?.toPoint(), 10); + } + + { + const measurements = new AttributeHashMap(); + measurements.set({}, 21); + metricProcessor.batchCumulate(measurements); + const accumulations = metricProcessor.collect(); + const accumulation = accumulations.get({}); + assert.strictEqual(accumulation?.toPoint(), 11); + } + }); + }); + describe('collect', () => { it('should export', () => { - const metricStorage = new DeltaMetricProcessor(new SumAggregator()); + const metricProcessor = new DeltaMetricProcessor(new SumAggregator()); - metricStorage.record(1, { attribute: '1' }, api.ROOT_CONTEXT); - metricStorage.record(2, { attribute: '1' }, api.ROOT_CONTEXT); - metricStorage.record(1, { attribute: '2' }, api.ROOT_CONTEXT); + metricProcessor.record(1, { attribute: '1' }, api.ROOT_CONTEXT); + metricProcessor.record(2, { attribute: '1' }, api.ROOT_CONTEXT); + metricProcessor.record(1, { attribute: '2' }, api.ROOT_CONTEXT); - let accumulations = metricStorage.collect(); + let accumulations = metricProcessor.collect(); assert.strictEqual(accumulations.size, 2); { const accumulation = accumulations.get({ attribute: '1' }); @@ -63,7 +112,7 @@ describe('DeltaMetricProcessor', () => { } /** the accumulations shall be reset. */ - accumulations = metricStorage.collect(); + accumulations = metricProcessor.collect(); assert.strictEqual(accumulations.size, 0); }); }); diff --git a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/HashMap.test.ts b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/HashMap.test.ts index 84224f3d94..94d399d5ab 100644 --- a/experimental/packages/opentelemetry-sdk-metrics-base/test/state/HashMap.test.ts +++ b/experimental/packages/opentelemetry-sdk-metrics-base/test/state/HashMap.test.ts @@ -39,6 +39,23 @@ describe('HashMap', () => { }); }); + describe('has', () => { + it('should return if the key exists in the value map', () => { + const map = new HashMap(hashAttributes); + const hash = hashAttributes({ foo: 'bar' }); + + // with pinned hash code + assert.strictEqual(map.has({}, hash), false); + assert.strictEqual(map.has({ foo: 'bar' }, hash), false); + + map.set({ foo: 'bar' }, 1); + // with pinned hash code + assert.strictEqual(map.has({}, hash), true); + // with attributes object. + assert.strictEqual(map.has({ foo: 'bar' }), true); + }); + }); + describe('entries', () => { it('iterating with entries', () => { const map = new HashMap(hashAttributes); From 8bda25ca9e1e543a1710076495b774a0e6ad11dd Mon Sep 17 00:00:00 2001 From: legendecas Date: Thu, 20 Jan 2022 00:30:14 +0800 Subject: [PATCH 16/16] docs(api-metrics): add notes on ObservableResult.observe (#2712) Co-authored-by: Valentin Marchaud Co-authored-by: Daniel Dyla --- .../src/types/ObservableResult.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/experimental/packages/opentelemetry-api-metrics/src/types/ObservableResult.ts b/experimental/packages/opentelemetry-api-metrics/src/types/ObservableResult.ts index 35298c6d2f..3803a633ff 100644 --- a/experimental/packages/opentelemetry-api-metrics/src/types/ObservableResult.ts +++ b/experimental/packages/opentelemetry-api-metrics/src/types/ObservableResult.ts @@ -20,5 +20,13 @@ import { Attributes } from './Metric'; * Interface that is being used in callback function for Observable Metric */ export interface ObservableResult { + /** + * Observe a measurement of the value associated with the given attributes. + * + * @param value The value to be observed. + * @param attributes The attributes associated with the value. If more than + * one values associated with the same attributes values, SDK may pick the + * last one or simply drop the entire observable result. + */ observe(value: number, attributes?: Attributes): void; }