From c398601cc182ccc4af1144445e0ea9b797ff4426 Mon Sep 17 00:00:00 2001 From: Rajat Khanna Date: Fri, 23 Aug 2024 15:06:51 +0530 Subject: [PATCH] feat(jaeger-remote-sampler): Implement jaeger remote sampler (#4589) Co-authored-by: Marc Pichler Co-authored-by: Trent Mick --- experimental/CHANGELOG.md | 1 + .../sampler-jaeger-remote/.eslintignore | 1 + .../sampler-jaeger-remote/.eslintrc.js | 8 + .../packages/sampler-jaeger-remote/.npmignore | 4 + .../packages/sampler-jaeger-remote/LICENSE | 201 ++++ .../packages/sampler-jaeger-remote/README.md | 66 ++ .../sampler-jaeger-remote/package.json | 69 ++ .../src/JaegerRemoteSampler.ts | 137 +++ .../src/PerOperationSampler.ts | 82 ++ .../sampler-jaeger-remote/src/index.ts | 18 + .../sampler-jaeger-remote/src/types.ts | 67 ++ .../test/JaegerRemoteSampler.test.ts | 511 ++++++++++ .../test/PerOperationSampler.test.ts | 52 + .../sampler-jaeger-remote/test/utils.ts | 20 + .../sampler-jaeger-remote/tsconfig.json | 19 + package-lock.json | 914 ++++++++++++++++++ tsconfig.json | 4 + 17 files changed, 2174 insertions(+) create mode 100644 experimental/packages/sampler-jaeger-remote/.eslintignore create mode 100644 experimental/packages/sampler-jaeger-remote/.eslintrc.js create mode 100644 experimental/packages/sampler-jaeger-remote/.npmignore create mode 100644 experimental/packages/sampler-jaeger-remote/LICENSE create mode 100644 experimental/packages/sampler-jaeger-remote/README.md create mode 100644 experimental/packages/sampler-jaeger-remote/package.json create mode 100644 experimental/packages/sampler-jaeger-remote/src/JaegerRemoteSampler.ts create mode 100644 experimental/packages/sampler-jaeger-remote/src/PerOperationSampler.ts create mode 100644 experimental/packages/sampler-jaeger-remote/src/index.ts create mode 100644 experimental/packages/sampler-jaeger-remote/src/types.ts create mode 100644 experimental/packages/sampler-jaeger-remote/test/JaegerRemoteSampler.test.ts create mode 100644 experimental/packages/sampler-jaeger-remote/test/PerOperationSampler.test.ts create mode 100644 experimental/packages/sampler-jaeger-remote/test/utils.ts create mode 100644 experimental/packages/sampler-jaeger-remote/tsconfig.json diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 796d00e393..7b48d64b50 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to experimental packages in this project will be documented * feat(otlp-transformer): Do not limit @opentelemetry/api upper range peerDependency [#4816](https://github.com/open-telemetry/opentelemetry-js/pull/4816) @mydea * feat(instrumentation-http): Allow to opt-out of instrumenting incoming/outgoing requests [#4643](https://github.com/open-telemetry/opentelemetry-js/pull/4643) @mydea +* feat(sampler-jaeger-remote): added support of jaeger-remote-sampler according to this [spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#jaegerremotesampler) [#4534](https://github.com/open-telemetry/opentelemetry-js/pull/4589) @legalimpurity ### :bug: (Bug Fix) diff --git a/experimental/packages/sampler-jaeger-remote/.eslintignore b/experimental/packages/sampler-jaeger-remote/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/.eslintignore @@ -0,0 +1 @@ +build diff --git a/experimental/packages/sampler-jaeger-remote/.eslintrc.js b/experimental/packages/sampler-jaeger-remote/.eslintrc.js new file mode 100644 index 0000000000..9cfb3fd423 --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + "env": { + "mocha": true, + "commonjs": true, + "node": true, + }, + ...require('../../../eslint.base.js') +} diff --git a/experimental/packages/sampler-jaeger-remote/.npmignore b/experimental/packages/sampler-jaeger-remote/.npmignore new file mode 100644 index 0000000000..9505ba9450 --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/.npmignore @@ -0,0 +1,4 @@ +/bin +/coverage +/doc +/test diff --git a/experimental/packages/sampler-jaeger-remote/LICENSE b/experimental/packages/sampler-jaeger-remote/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/experimental/packages/sampler-jaeger-remote/README.md b/experimental/packages/sampler-jaeger-remote/README.md new file mode 100644 index 0000000000..ef6727a688 --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/README.md @@ -0,0 +1,66 @@ +# Jaeger Remote Sampler + +[![NPM Published Version][npm-img]][npm-url] +[![Apache License][license-image]][license-image] + +**Note: This is an experimental package under active development. Minor releases may include breaking changes.** + +The Jaeger Remote Sampler package is designed for OpenTelemetry to dynamically fetch and update sampling strategies from a Jaeger agent or collector. This enables applications to adjust their sampling strategies based on the current configuration provided by Jaeger, optimizing for both performance and observability. + +## Installation + +```bash +npm install --save @opentelemetry/sampler-jaeger-remote +``` + +## Usage + +To integrate the Jaeger Remote Sampler with your application, configure it with the endpoint of your Jaeger agent or collector. The sampler can be set up as follows: + +```javascript +const { JaegerRemoteSampler } = require('@opentelemetry/sampler-jaeger-remote'); +const { Resource } = require('@opentelemetry/resources'); +const { NodeTracerProvider } = require('@opentelemetry/node'); + +// Jaeger agent endpoint +const sampler = new JaegerRemoteSampler({ + endpoint: 'http://your-jaeger-agent:14268/api/sampling', + serviceName: 'your-service-name', + initialSampler: new AlwaysOnSampler(), + poolingInterval: 60000 // 60 seconds +}); +const provider = new NodeTracerProvider({ + resource: Resource.default().merge(new Resource({ + 'service.name': 'your-service-name' + })), + sampler +}); + +provider.register(); +``` + +## Supported Configuration Options + +The Jaeger Remote Sampler supports the following sampling strategies based on the configuration received from the remote endpoint: + +1. **Per-Operation Sampling**: If the remote configuration includes `operationSampling` with `perOperationStrategies`, it creates a `PerOperationSampler`. This allows for different sampling rates for different operations. + +2. **Probabilistic Sampling**: If the remote configuration specifies `StrategyType.PROBABILISTIC`, it creates a `TraceIdRatioBasedSampler`. This samples a percentage of traces based on the trace ID. + +3. **Default Sampling**: If none of the above apply, it falls back to the initial sampler provided in the constructor. + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us in [GitHub Discussions][discussions-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions +[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[npm-url]: https://www.npmjs.com/package/@opentelemetry/sampler-jaeger-remote +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fsampler-jaeger-remote.svg diff --git a/experimental/packages/sampler-jaeger-remote/package.json b/experimental/packages/sampler-jaeger-remote/package.json new file mode 100644 index 0000000000..b0f7112817 --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/package.json @@ -0,0 +1,69 @@ +{ + "name": "@opentelemetry/sampler-jaeger-remote", + "version": "0.52.1", + "description": "Jaeger Remote Sampler", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js", + "scripts": { + "prepublishOnly": "npm run compile", + "compile": "tsc --build", + "clean": "tsc --build --clean", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "tdd": "npm run test -- --watch-extensions ts --watch", + "test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'", + "version": "node ../../../scripts/version-update.js", + "watch": "tsc -w", + "precompile": "cross-var lerna run version --scope $npm_package_name --include-dependencies", + "prewatch": "npm run precompile", + "peer-api-check": "node ../../../scripts/peer-api-check.js", + "align-api-deps": "node ../../../scripts/align-api-deps.js", + "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../../" + }, + "keywords": [ + "opentelemetry", + "nodejs", + "metrics", + "stats" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.js.map", + "build/src/**/*.d.ts", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@opentelemetry/sdk-trace-base": "1.25.1" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "devDependencies": { + "@types/mocha": "10.0.6", + "@types/node": "18.6.5", + "@types/sinon": "17.0.3", + "codecov": "3.8.3", + "cross-var": "1.1.0", + "eslint-plugin-header": "^3.1.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.1.3", + "lerna": "6.6.2", + "mocha": "10.2.0", + "nyc": "15.1.0", + "sinon": "15.1.2", + "ts-loader": "8.4.0", + "typescript": "4.4.4" + }, + "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/sampler-jaeger-remote", + "sideEffects": false +} diff --git a/experimental/packages/sampler-jaeger-remote/src/JaegerRemoteSampler.ts b/experimental/packages/sampler-jaeger-remote/src/JaegerRemoteSampler.ts new file mode 100644 index 0000000000..e662287934 --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/src/JaegerRemoteSampler.ts @@ -0,0 +1,137 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Link, SpanKind, Attributes, diag, Context } from '@opentelemetry/api'; +import { + Sampler, + SamplingResult, + ParentBasedSampler, + TraceIdRatioBasedSampler, +} from '@opentelemetry/sdk-trace-base'; +import axios from 'axios'; +import { PerOperationSampler } from './PerOperationSampler'; +import { SamplingStrategyResponse, StrategyType } from './types'; + +interface JaegerRemoteSamplerOptions { + /** Address of a service that implements the Remote Sampling API, such as Jaeger Collector or OpenTelemetry Collector */ + endpoint: string; + /** Service name for Remote Sampling API */ + serviceName?: string; + /** Polling interval for getting configuration from remote */ + poolingInterval: number; + /** Initial sampler that is used before the first configuration is fetched */ + initialSampler: Sampler; +} + +/** JaegerRemoteSampler */ +export class JaegerRemoteSampler implements Sampler { + private _endpoint: string; + private _serviceName?: string; + private _poolingInterval: number; + private _sampler: Sampler; + private _syncingConfig: boolean; + + constructor(config: JaegerRemoteSamplerOptions) { + this._endpoint = config.endpoint; + this._serviceName = config.serviceName; + this._poolingInterval = config.poolingInterval; + this._sampler = config.initialSampler; + this._syncingConfig = false; + + setInterval(async () => { + if (this._syncingConfig) { + return; + } + this._syncingConfig = true; + try { + await this.getAndUpdateSampler(); + } finally { + this._syncingConfig = false; + } + }, this._poolingInterval); + } + + shouldSample( + context: Context, + traceId: string, + spanName: string, + spanKind: SpanKind, + attributes: Attributes, + links: Link[] + ): SamplingResult { + return this._sampler.shouldSample( + context, + traceId, + spanName, + spanKind, + attributes, + links + ); + } + + toString(): string { + return `JaegerRemoteSampler{endpoint=${this._endpoint},${ + this._serviceName && ` serviceName=${this._serviceName},` + } poolingInterval=${this._poolingInterval}, sampler=${this._sampler}}`; + } + + private async getAndUpdateSampler() { + const newConfig = await this.getSamplerConfig(this._serviceName); + this._sampler = await this.convertSamplingResponseToSampler(newConfig); + } + + private convertSamplingResponseToSampler( + newConfig: SamplingStrategyResponse + ): Sampler { + const perOperationStrategies = + newConfig.operationSampling?.perOperationStrategies; + if ( + newConfig.operationSampling && + perOperationStrategies && + perOperationStrategies.length > 0 + ) { + const defaultSampler: Sampler = new TraceIdRatioBasedSampler( + newConfig.operationSampling.defaultSamplingProbability + ); + return new ParentBasedSampler({ + root: new PerOperationSampler({ + defaultSampler, + perOperationStrategies, + }), + }); + } + switch (newConfig.strategyType) { + case StrategyType.PROBABILISTIC: + return new ParentBasedSampler({ + root: new TraceIdRatioBasedSampler( + newConfig.probabilisticSampling.samplingRate + ), + }); + default: + diag.warn(`Strategy ${newConfig.strategyType} not supported.`); + return this._sampler; + } + } + + private async getSamplerConfig( + serviceName?: string + ): Promise { + const response = await axios.get( + `${this._endpoint}/sampling?service=${serviceName ?? ''}` + ); + return response.data; + } +} diff --git a/experimental/packages/sampler-jaeger-remote/src/PerOperationSampler.ts b/experimental/packages/sampler-jaeger-remote/src/PerOperationSampler.ts new file mode 100644 index 0000000000..3588782aaa --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/src/PerOperationSampler.ts @@ -0,0 +1,82 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Context, SpanKind, Link, SpanAttributes } from '@opentelemetry/api'; +import { + Sampler, + SamplingResult, + TraceIdRatioBasedSampler, +} from '@opentelemetry/sdk-trace-base'; +import { PerOperationStrategy } from './types'; + +interface PerOperationSamplerOptions { + /** The default sampler to use in case span does not have a custom strategy. */ + defaultSampler: Sampler; + /** Stores strategies for every custom span. */ + perOperationStrategies: PerOperationStrategy[]; +} + +/** PerOperationSampler to be used from JaegerRemoteSampler */ +export class PerOperationSampler implements Sampler { + private _defaultSampler: Sampler; + private _perOperationSampler: Map; + + constructor(config: PerOperationSamplerOptions) { + this._defaultSampler = config.defaultSampler; + this._perOperationSampler = new Map( + config.perOperationStrategies.map(perOperationStrategy => [ + perOperationStrategy.operation, + new TraceIdRatioBasedSampler( + perOperationStrategy.probabilisticSampling.samplingRate + ), + ]) + ); + } + + private getSamplerForOperation(spanName: string): Sampler { + let resultantSampler = this._perOperationSampler.get(spanName); + if (resultantSampler == null) { + resultantSampler = this._defaultSampler; + } + return resultantSampler; + } + + shouldSample( + context: Context, + traceId: string, + spanName: string, + spanKind: SpanKind, + attributes: SpanAttributes, + links: Link[] + ): SamplingResult { + return this.getSamplerForOperation(spanName).shouldSample( + context, + traceId, + spanName, + spanKind, + attributes, + links + ); + } + + toString(): string { + return `PerOperationSampler{default=${ + this._defaultSampler + }, perOperationSamplers={${Array.from(this._perOperationSampler).map( + ([key, value]) => `${key}=${value}` + )}}}`; + } +} diff --git a/experimental/packages/sampler-jaeger-remote/src/index.ts b/experimental/packages/sampler-jaeger-remote/src/index.ts new file mode 100644 index 0000000000..dbededc69c --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { JaegerRemoteSampler } from './JaegerRemoteSampler'; +export { StrategyType, ProbabilisticSamplingOptions } from './types'; diff --git a/experimental/packages/sampler-jaeger-remote/src/types.ts b/experimental/packages/sampler-jaeger-remote/src/types.ts new file mode 100644 index 0000000000..76eac5f7fb --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/src/types.ts @@ -0,0 +1,67 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Enum representing different types of sampling strategies. + */ +export enum StrategyType { + /** Constant sampling strategy */ + CONST = 'CONST', + /** Probabilistic sampling strategy */ + PROBABILISTIC = 'PROBABILISTIC', + /** Rate-limiting sampling strategy */ + RATELIMITING = 'RATELIMITING', + /** Remote sampling strategy */ + REMOTE = 'REMOTE', +} + +/** + * Interface for probabilistic sampling options. + */ +export interface ProbabilisticSamplingOptions { + /** The sampling rate, typically a number between 0 and 1 */ + samplingRate: number; +} + +/** + * Interface representing a per-operation sampling strategy. + */ +export interface PerOperationStrategy { + /** The name or identifier of the operation */ + operation: string; + /** The probabilistic sampling options for this operation */ + probabilisticSampling: ProbabilisticSamplingOptions; +} + +/** + * Interface representing the response of a sampling strategy. + */ +export interface SamplingStrategyResponse { + /** The type of sampling strategy being used */ + strategyType: StrategyType; + /** The probabilistic sampling options */ + probabilisticSampling: ProbabilisticSamplingOptions; + /** Optional operation-specific sampling configuration */ + operationSampling?: { + /** The default sampling probability for operations */ + defaultSamplingProbability: number; + /** The default lower bound of traces per second */ + defaultLowerBoundTracesPerSecond: number; + /** Array of per-operation sampling strategies */ + perOperationStrategies: PerOperationStrategy[]; + /** The default upper bound of traces per second */ + defaultUpperBoundTracesPerSecond: number; + }; +} diff --git a/experimental/packages/sampler-jaeger-remote/test/JaegerRemoteSampler.test.ts b/experimental/packages/sampler-jaeger-remote/test/JaegerRemoteSampler.test.ts new file mode 100644 index 0000000000..b675032e71 --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/test/JaegerRemoteSampler.test.ts @@ -0,0 +1,511 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AlwaysOffSampler, + AlwaysOnSampler, + ParentBasedSampler, + SamplingDecision, + TraceIdRatioBasedSampler, +} from '@opentelemetry/sdk-trace-base'; +import * as api from '@opentelemetry/api'; +import { JaegerRemoteSampler } from '../src'; +import * as sinon from 'sinon'; +import * as assert from 'assert'; +import { SpanKind } from '@opentelemetry/api'; +import { SamplingStrategyResponse, StrategyType } from '../src/types'; +import { PerOperationSampler } from '../src/PerOperationSampler'; +import { randomSamplingProability } from './utils'; +import axios from 'axios'; + +describe('JaegerRemoteSampler', () => { + const endpoint = 'http://localhost:5778'; + const serviceName = 'foo'; + const alwaysOnSampler = new AlwaysOnSampler(); + const alwaysOffSampler = new AlwaysOffSampler(); + const numberOfIterations = Math.floor((Math.random() + 0.01) * 100); + const poolingInterval = Math.floor((Math.random() + 0.01) * 5 * 1000); + + let clock: sinon.SinonFakeTimers; + + beforeEach(() => { + clock = sinon.useFakeTimers(Date.now()); + }); + + afterEach(() => { + clock.restore(); + }); + + describe('constructor', () => { + let getAndUpdateSamplerStub: sinon.SinonStub; + + beforeEach(() => { + getAndUpdateSamplerStub = sinon + .stub(JaegerRemoteSampler.prototype, 'getAndUpdateSampler' as any) + .resolves(); + }); + + afterEach(() => { + getAndUpdateSamplerStub.restore(); + }); + + it('Test Sampler to run at fixed poolingInterval', async () => { + new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval * numberOfIterations); + sinon.assert.callCount(getAndUpdateSamplerStub, numberOfIterations); + }); + + it('Dont try to sync if already syncing.', async () => { + getAndUpdateSamplerStub.callsFake( + async () => + new Promise(resolve => setTimeout(resolve, poolingInterval + 1000)) + ); + new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval * 2); + sinon.assert.callCount(getAndUpdateSamplerStub, 1); + }); + }); + + describe('shouldSample', () => { + let samplerStubInstance: sinon.SinonStubbedInstance; + + beforeEach(() => { + samplerStubInstance = sinon.createStubInstance(AlwaysOnSampler); + samplerStubInstance.shouldSample.returns({ + decision: SamplingDecision.RECORD, + }); + }); + + it('Should return SamplingDecision.RECORD decision provided by the current sampler set in it.', async () => { + const jaegerRemoteSampler = new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: samplerStubInstance, + }); + + assert.equal( + jaegerRemoteSampler.shouldSample( + api.ROOT_CONTEXT, + '', + '', + SpanKind.CLIENT, + {}, + [] + ).decision, + SamplingDecision.RECORD + ); + }); + }); + + describe('getAndUpdateSampler', () => { + let getSamplerConfigStub: sinon.SinonStub; + let convertSamplingResponseToSamplerStub: sinon.SinonStub; + + const sampleSamplingStrategyResponse: SamplingStrategyResponse = { + strategyType: StrategyType.PROBABILISTIC, + probabilisticSampling: { + samplingRate: 0, + }, + operationSampling: { + defaultSamplingProbability: 0, + defaultLowerBoundTracesPerSecond: 0, + perOperationStrategies: [], + defaultUpperBoundTracesPerSecond: 0, + }, + }; + + beforeEach(() => { + getSamplerConfigStub = sinon + .stub(JaegerRemoteSampler.prototype, 'getSamplerConfig' as any) + .resolves(sampleSamplingStrategyResponse); + convertSamplingResponseToSamplerStub = sinon + .stub( + JaegerRemoteSampler.prototype, + 'convertSamplingResponseToSampler' as any + ) + .resolves(alwaysOffSampler); + }); + + afterEach(() => { + getSamplerConfigStub.restore(); + convertSamplingResponseToSamplerStub.restore(); + }); + + it('getSamplerConfig is called with service name set in the constructor.', async () => { + new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + sinon.assert.calledWithExactly(getSamplerConfigStub, serviceName); + }); + + it('convertSamplingResponseToSampler is passed config provided by getSamplerConfig.', async () => { + new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + sinon.assert.calledWithExactly( + convertSamplingResponseToSamplerStub, + sampleSamplingStrategyResponse + ); + }); + + it('internal sampler is set to sampler returned by convertSamplingResponseToSampler.', async () => { + const jaegerRemoteSampler = new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + assert.equal(jaegerRemoteSampler['_sampler'], alwaysOffSampler); + }); + }); + + describe('convertSamplingResponseToSampler', () => { + let getSamplerConfigStub: sinon.SinonStub; + + beforeEach(() => { + getSamplerConfigStub = sinon.stub( + JaegerRemoteSampler.prototype, + 'getSamplerConfig' as any + ); + }); + + afterEach(() => { + getSamplerConfigStub.restore(); + }); + + describe('defaultStrategy', () => { + it('Use root level samplingRate when operationSampling object is null.', async () => { + const samplingRate = randomSamplingProability(); + + const samplingStrategyResponseWithoutPerOperationStrategies: SamplingStrategyResponse = + { + strategyType: StrategyType.PROBABILISTIC, + probabilisticSampling: { + samplingRate, + }, + }; + + getSamplerConfigStub.resolves( + samplingStrategyResponseWithoutPerOperationStrategies + ); + + const jaegerRemoteSampler = new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + const jaegerCurrentSampler = jaegerRemoteSampler['_sampler']; + assert.equal(jaegerCurrentSampler instanceof ParentBasedSampler, true); + const parentBasedRootSampler = ( + jaegerCurrentSampler as ParentBasedSampler + )['_root']; + assert.equal( + parentBasedRootSampler instanceof TraceIdRatioBasedSampler, + true + ); + const internalTraceIdRatioBasedSamplerRatio = ( + parentBasedRootSampler as TraceIdRatioBasedSampler + )['_ratio']; + assert.equal(internalTraceIdRatioBasedSamplerRatio, samplingRate); + }); + + it('Use root level samplingRate perOperation Strategies is a empty array.', async () => { + const samplingRate = randomSamplingProability(); + + const samplingStrategyResponseWithoutPerOperationStrategies: SamplingStrategyResponse = + { + strategyType: StrategyType.PROBABILISTIC, + probabilisticSampling: { + samplingRate, + }, + operationSampling: { + defaultSamplingProbability: 1.5, + defaultLowerBoundTracesPerSecond: 1.6, + perOperationStrategies: [], + defaultUpperBoundTracesPerSecond: 18, + }, + }; + + getSamplerConfigStub.resolves( + samplingStrategyResponseWithoutPerOperationStrategies + ); + + const jaegerRemoteSampler = new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + const jaegerCurrentSampler = jaegerRemoteSampler['_sampler']; + assert.equal(jaegerCurrentSampler instanceof ParentBasedSampler, true); + const parentBasedRootSampler = ( + jaegerCurrentSampler as ParentBasedSampler + )['_root']; + assert.equal( + parentBasedRootSampler instanceof TraceIdRatioBasedSampler, + true + ); + const internalTraceIdRatioBasedSamplerRatio = ( + parentBasedRootSampler as TraceIdRatioBasedSampler + )['_ratio']; + assert.equal(internalTraceIdRatioBasedSamplerRatio, samplingRate); + }); + }); + + describe('perOperationStrategy', () => { + const defaultSamplingProbability = randomSamplingProability(); + const op1SamplingRate = randomSamplingProability(); + const op2SamplingRate = randomSamplingProability(); + const op1 = 'op1'; + const op2 = 'op2'; + + const samplingStrategyResponseWithPerOperationStrategies: SamplingStrategyResponse = + { + strategyType: StrategyType.PROBABILISTIC, + probabilisticSampling: { + samplingRate: 1.5, + }, + operationSampling: { + defaultSamplingProbability, + defaultLowerBoundTracesPerSecond: 1.6, + perOperationStrategies: [ + { + operation: op1, + probabilisticSampling: { + samplingRate: op1SamplingRate, + }, + }, + { + operation: op2, + probabilisticSampling: { + samplingRate: op2SamplingRate, + }, + }, + ], + defaultUpperBoundTracesPerSecond: 1.8, + }, + }; + + beforeEach(() => { + getSamplerConfigStub.resolves( + samplingStrategyResponseWithPerOperationStrategies + ); + }); + + it('Use default probability from inside operationSampling object and perOperationStrategies values for specific operations.', async () => { + const jaegerRemoteSampler = new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + const jaegerCurrentSampler = jaegerRemoteSampler['_sampler']; + assert.equal(jaegerCurrentSampler instanceof ParentBasedSampler, true); + const parentBasedRootSampler = ( + jaegerCurrentSampler as ParentBasedSampler + )['_root']; + assert.equal( + parentBasedRootSampler instanceof PerOperationSampler, + true + ); + const perOperationSampler = + parentBasedRootSampler as PerOperationSampler; + + const defaultSampler = + perOperationSampler['getSamplerForOperation'](''); + assert.equal(defaultSampler instanceof TraceIdRatioBasedSampler, true); + + const defautRatio = (defaultSampler as TraceIdRatioBasedSampler)[ + '_ratio' + ]; + assert.equal(defaultSamplingProbability, defautRatio); + + const op1Sampler = perOperationSampler['getSamplerForOperation'](op1); + assert.equal(op1Sampler instanceof TraceIdRatioBasedSampler, true); + + const op1Ratio = (op1Sampler as TraceIdRatioBasedSampler)['_ratio']; + assert.equal(op1SamplingRate, op1Ratio); + + const op2Sampler = perOperationSampler['getSamplerForOperation'](op2); + assert.equal(op2Sampler instanceof TraceIdRatioBasedSampler, true); + + const op2Ratio = (op2Sampler as TraceIdRatioBasedSampler)['_ratio']; + assert.equal(op2SamplingRate, op2Ratio); + }); + }); + + describe('errorCase', () => { + let diagWarnStub: sinon.SinonStub; + const invalidStrategyType = 'ANY_TEXT'; + const errorSamplingStrategyResponse = { + strategyType: invalidStrategyType, + probabilisticSampling: { + samplingRate: 0, + }, + operationSampling: { + defaultSamplingProbability: 0, + defaultLowerBoundTracesPerSecond: 0, + perOperationStrategies: [], + defaultUpperBoundTracesPerSecond: 0, + }, + }; + + beforeEach(() => { + getSamplerConfigStub.resolves(errorSamplingStrategyResponse); + diagWarnStub = sinon.stub(api.diag, 'warn'); + }); + + it('Throw error when unsupported strategy type is sent by api.', async () => { + new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + sinon.assert.calledOnceWithExactly( + diagWarnStub, + `Strategy ${invalidStrategyType} not supported.` + ); + }); + }); + }); + + describe('toString', () => { + let getSamplerConfigStub: sinon.SinonStub; + + const defaultSamplingProbability = randomSamplingProability(); + const op1SamplingRate = randomSamplingProability(); + const op1 = 'op1'; + + const samplingStrategyResponseWithPerOperationStrategies: SamplingStrategyResponse = + { + strategyType: StrategyType.PROBABILISTIC, + probabilisticSampling: { + samplingRate: 1.5, + }, + operationSampling: { + defaultSamplingProbability, + defaultLowerBoundTracesPerSecond: 1.6, + perOperationStrategies: [ + { + operation: op1, + probabilisticSampling: { + samplingRate: op1SamplingRate, + }, + }, + ], + defaultUpperBoundTracesPerSecond: 1.8, + }, + }; + + beforeEach(() => { + getSamplerConfigStub = sinon.stub( + JaegerRemoteSampler.prototype, + 'getSamplerConfig' as any + ); + }); + + afterEach(() => { + getSamplerConfigStub.restore(); + }); + + beforeEach(() => { + getSamplerConfigStub.resolves( + samplingStrategyResponseWithPerOperationStrategies + ); + }); + + it('Should reflect sampler name with current sampler runninng in it', async () => { + const jaegerRemoteSampler = new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + const jaegerCurrentSampler = jaegerRemoteSampler.toString(); + assert.equal( + jaegerCurrentSampler, + `JaegerRemoteSampler{endpoint=${endpoint}, serviceName=${serviceName}, poolingInterval=${poolingInterval}, sampler=ParentBased{root=PerOperationSampler{default=TraceIdRatioBased{${defaultSamplingProbability}}, perOperationSamplers={${op1}=TraceIdRatioBased{${op1SamplingRate}}}}, remoteParentSampled=AlwaysOnSampler, remoteParentNotSampled=AlwaysOffSampler, localParentSampled=AlwaysOnSampler, localParentNotSampled=AlwaysOffSampler}}` + ); + }); + }); + + describe('getSamplerConfig', () => { + let axiosGetStub: sinon.SinonStub; + + beforeEach(() => { + axiosGetStub = sinon.stub(axios, 'get'); + }); + + afterEach(() => { + axiosGetStub.restore(); + }); + + it('Should pass endpoint and service name.', async () => { + new JaegerRemoteSampler({ + endpoint, + serviceName, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + sinon.assert.calledOnceWithExactly( + axiosGetStub, + `${endpoint}/sampling?service=${serviceName}` + ); + }); + + it('Should pass endpoint and blank service name if nothing is provided.', async () => { + new JaegerRemoteSampler({ + endpoint, + serviceName: undefined, + poolingInterval, + initialSampler: alwaysOnSampler, + }); + await clock.tickAsync(poolingInterval); + sinon.assert.calledOnceWithExactly( + axiosGetStub, + `${endpoint}/sampling?service=` + ); + }); + }); +}); diff --git a/experimental/packages/sampler-jaeger-remote/test/PerOperationSampler.test.ts b/experimental/packages/sampler-jaeger-remote/test/PerOperationSampler.test.ts new file mode 100644 index 0000000000..d80c39692b --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/test/PerOperationSampler.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + AlwaysOnSampler, + SamplingDecision, +} from '@opentelemetry/sdk-trace-base'; +import { PerOperationSampler } from '../src/PerOperationSampler'; +import sinon = require('sinon'); +import * as api from '@opentelemetry/api'; + +describe('PerOPerationSampler', () => { + describe('shouldSample', () => { + let samplerStubInstance1: sinon.SinonStubbedInstance; + + beforeEach(() => { + samplerStubInstance1 = sinon.createStubInstance(AlwaysOnSampler); + samplerStubInstance1.shouldSample.returns({ + decision: SamplingDecision.RECORD, + }); + }); + + it('Should return samplingDecision decision provided by default sampler.', async () => { + const perOperationSampler = new PerOperationSampler({ + defaultSampler: samplerStubInstance1, + perOperationStrategies: [], + }); + + perOperationSampler.shouldSample( + api.ROOT_CONTEXT, + '', + '', + api.SpanKind.CLIENT, + {}, + [] + ); + sinon.assert.callCount(samplerStubInstance1.shouldSample, 1); + }); + }); +}); diff --git a/experimental/packages/sampler-jaeger-remote/test/utils.ts b/experimental/packages/sampler-jaeger-remote/test/utils.ts new file mode 100644 index 0000000000..df1e72510f --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/test/utils.ts @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const randomSamplingProability = () => { + const rand = Math.random() + 0.01; + return rand > 1 ? rand - 0.01 : rand; +}; diff --git a/experimental/packages/sampler-jaeger-remote/tsconfig.json b/experimental/packages/sampler-jaeger-remote/tsconfig.json new file mode 100644 index 0000000000..a20e8572d1 --- /dev/null +++ b/experimental/packages/sampler-jaeger-remote/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "build", + "rootDir": "." + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ], + "references": [ + { + "path": "../../../api" + }, + { + "path": "../../../packages/opentelemetry-sdk-trace-base" + } + ] +} diff --git a/package-lock.json b/package-lock.json index 57af242385..a353599ce2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1937,6 +1937,513 @@ "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, + "experimental/packages/sampler-jaeger-remote": { + "version": "0.52.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/sdk-trace-base": "1.25.1" + }, + "devDependencies": { + "@types/mocha": "10.0.6", + "@types/node": "18.6.5", + "@types/sinon": "17.0.3", + "codecov": "3.8.3", + "cross-var": "1.1.0", + "eslint-plugin-header": "^3.1.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.1.3", + "lerna": "6.6.2", + "mocha": "10.2.0", + "nyc": "15.1.0", + "sinon": "15.1.2", + "ts-loader": "8.4.0", + "typescript": "4.4.4" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/@types/mocha": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true + }, + "experimental/packages/sampler-jaeger-remote/node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "experimental/packages/sampler-jaeger-remote/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "experimental/packages/sampler-jaeger-remote/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "experimental/packages/sampler-jaeger-remote/node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/ts-loader": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz", + "integrity": "sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^2.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "*" + } + }, + "experimental/packages/sampler-jaeger-remote/node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "experimental/packages/sampler-jaeger-remote/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, "experimental/packages/sdk-events": { "name": "@opentelemetry/sdk-events", "version": "0.52.1", @@ -6695,6 +7202,10 @@ "resolved": "packages/opentelemetry-resources", "link": true }, + "node_modules/@opentelemetry/sampler-jaeger-remote": { + "resolved": "experimental/packages/sampler-jaeger-remote", + "link": true + }, "node_modules/@opentelemetry/sdk-events": { "resolved": "experimental/packages/sdk-events", "link": true @@ -13109,6 +13620,18 @@ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, "node_modules/error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", @@ -19648,6 +20171,19 @@ "node": ">= 4.0.0" } }, + "node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, "node_modules/meow": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", @@ -24004,6 +24540,12 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true + }, "node_modules/ps-tree": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", @@ -35580,6 +36122,353 @@ } } }, + "@opentelemetry/sampler-jaeger-remote": { + "version": "file:experimental/packages/sampler-jaeger-remote", + "requires": { + "@opentelemetry/sdk-trace-base": "1.25.1", + "@types/mocha": "10.0.6", + "@types/node": "18.6.5", + "@types/sinon": "17.0.3", + "codecov": "3.8.3", + "cross-var": "1.1.0", + "eslint-plugin-header": "^3.1.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.1.3", + "lerna": "6.6.2", + "mocha": "10.2.0", + "nyc": "15.1.0", + "sinon": "15.1.2", + "ts-loader": "8.4.0", + "typescript": "4.4.4" + }, + "dependencies": { + "@types/mocha": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dev": true, + "requires": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "dev": true, + "requires": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "ts-loader": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz", + "integrity": "sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^2.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + } + }, + "workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } + } + }, "@opentelemetry/sdk-events": { "version": "file:experimental/packages/sdk-events", "requires": { @@ -41513,6 +42402,15 @@ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, "error": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", @@ -46452,6 +47350,16 @@ "fs-monkey": "^1.0.4" } }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, "meow": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", @@ -49740,6 +50648,12 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true + }, "ps-tree": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", diff --git a/tsconfig.json b/tsconfig.json index 6ecaefc224..eaada3447e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,6 +28,7 @@ "experimental/packages/otlp-grpc-exporter-base", "experimental/packages/otlp-transformer", "experimental/packages/propagator-aws-xray-lambda", + "experimental/packages/sampler-jaeger-remote", "experimental/packages/sdk-events", "experimental/packages/sdk-logs", "experimental/packages/shim-opencensus", @@ -131,6 +132,9 @@ { "path": "experimental/packages/propagator-aws-xray-lambda" }, + { + "path": "experimental/packages/sampler-jaeger-remote" + }, { "path": "experimental/packages/sdk-events" },