From 9589d541cef7c8d0227d66c0c4fc2ee32ac93dbe Mon Sep 17 00:00:00 2001 From: Purvi Kanal Date: Fri, 20 Jan 2023 01:12:20 -0500 Subject: [PATCH 1/2] feat: browser support for exporter-trace-otlp-proto (#3208) * add node & browser platform for exporter-trace-otlp-proto * add browser support for proto base exporter * add base browser class with xhr support * add browser class for proto trace exporter * slight tweaks to make it work * send data as blob to avoid making sync xhr requests * fix lint * remove console.logs and add browser proto example * cleanup and start adding tests * Undo formatting changes * exporter-trace-otlp-proto: fix compile errors * Misc updates from review comments * Adding changelog entry * Reverting format changes not needed * Moving the send function into the class for browser case. * Adjust indentation to fix lint errors * Remove template parameter that's not needed * Apply review changes * fix the import path * Addressing lint errors * Explicit imports for browser case * More explicit exports * Add missing exports * Address lint issues with export statements * Adding missing exports * Adding missing export * Using import from top level folder * Trigger Build * Update experimental/packages/exporter-trace-otlp-proto/test/browser/CollectorTraceExporter.test.ts Co-authored-by: Marc Pichler * Remove trailing comma * Remove blank line to fix lint error * Fixes based on testing opentelemetry-web/fetch-proto * Add additional missing export * Skip hex conversion of traceId for the protobuf * Add esm/esnext builds for the proto packages that will now be used for the browser case as well. * Trigger Build Co-authored-by: Santosh Cheler Co-authored-by: Santosh Cheler Co-authored-by: Marc Pichler Co-authored-by: Marc Pichler --- CHANGELOG.md | 1 + .../examples/fetch-proto/index.html | 20 +++++ .../examples/fetch-proto/index.js | 80 +++++++++++++++++ examples/opentelemetry-web/package.json | 1 + .../opentelemetry-web/webpack.dev.config.js | 3 +- .../opentelemetry-web/webpack.prod.config.js | 1 + .../exporter-trace-otlp-proto/karma.conf.js | 26 ++++++ .../exporter-trace-otlp-proto/package.json | 23 ++++- .../exporter-trace-otlp-proto/src/index.ts | 3 +- .../src/platform/browser/OTLPTraceExporter.ts | 72 +++++++++++++++ .../src/platform/browser/index.ts | 16 ++++ .../src/platform/index.ts | 16 ++++ .../{ => platform/node}/OTLPTraceExporter.ts | 0 .../src/platform/node/index.ts | 17 ++++ .../browser/CollectorTraceExporter.test.ts | 50 +++++++++++ .../test/browser/index-webpack.ts | 20 +++++ .../test/{ => node}/OTLPTraceExporter.test.ts | 4 +- .../tsconfig.esm.json | 19 ++++ .../tsconfig.esnext.json | 19 ++++ .../packages/otlp-exporter-base/src/index.ts | 16 +++- .../src/platform/browser/index.ts | 3 +- .../src/platform/browser/util.ts | 2 +- .../otlp-exporter-base/src/platform/index.ts | 12 ++- .../src/platform/node/index.ts | 6 +- .../otlp-proto-exporter-base/package.json | 20 ++++- .../otlp-proto-exporter-base/src/index.ts | 5 +- .../browser/OTLPProtoExporterBrowserBase.ts | 90 +++++++++++++++++++ .../src/platform/browser/index.ts | 17 ++++ .../src/platform/index.ts | 24 +++++ .../node}/OTLPProtoExporterNodeBase.ts | 2 +- .../src/platform/node/index.ts | 18 ++++ .../src/{ => platform/node}/util.ts | 4 +- .../src/{ => platform}/types.ts | 0 .../tsconfig.esm.json | 21 +++++ .../tsconfig.esnext.json | 21 +++++ 35 files changed, 623 insertions(+), 29 deletions(-) create mode 100644 examples/opentelemetry-web/examples/fetch-proto/index.html create mode 100644 examples/opentelemetry-web/examples/fetch-proto/index.js create mode 100644 experimental/packages/exporter-trace-otlp-proto/karma.conf.js create mode 100644 experimental/packages/exporter-trace-otlp-proto/src/platform/browser/OTLPTraceExporter.ts create mode 100644 experimental/packages/exporter-trace-otlp-proto/src/platform/browser/index.ts create mode 100644 experimental/packages/exporter-trace-otlp-proto/src/platform/index.ts rename experimental/packages/exporter-trace-otlp-proto/src/{ => platform/node}/OTLPTraceExporter.ts (100%) create mode 100644 experimental/packages/exporter-trace-otlp-proto/src/platform/node/index.ts create mode 100644 experimental/packages/exporter-trace-otlp-proto/test/browser/CollectorTraceExporter.test.ts create mode 100644 experimental/packages/exporter-trace-otlp-proto/test/browser/index-webpack.ts rename experimental/packages/exporter-trace-otlp-proto/test/{ => node}/OTLPTraceExporter.test.ts (99%) create mode 100644 experimental/packages/exporter-trace-otlp-proto/tsconfig.esm.json create mode 100644 experimental/packages/exporter-trace-otlp-proto/tsconfig.esnext.json create mode 100644 experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts create mode 100644 experimental/packages/otlp-proto-exporter-base/src/platform/browser/index.ts create mode 100644 experimental/packages/otlp-proto-exporter-base/src/platform/index.ts rename experimental/packages/otlp-proto-exporter-base/src/{ => platform/node}/OTLPProtoExporterNodeBase.ts (98%) create mode 100644 experimental/packages/otlp-proto-exporter-base/src/platform/node/index.ts rename experimental/packages/otlp-proto-exporter-base/src/{ => platform/node}/util.ts (96%) rename experimental/packages/otlp-proto-exporter-base/src/{ => platform}/types.ts (100%) create mode 100644 experimental/packages/otlp-proto-exporter-base/tsconfig.esm.json create mode 100644 experimental/packages/otlp-proto-exporter-base/tsconfig.esnext.json diff --git a/CHANGELOG.md b/CHANGELOG.md index d6385594f3..daa351e51d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/ ### :rocket: (Enhancement) * feat(instrumentation-grpc): set net.peer.name and net.peer.port on client spans [#3430](https://github.com/open-telemetry/opentelemetry-js/pull/3430) +* feat(exporter-trace-otlp-proto): Add protobuf otlp trace exporter support for browser [#3208](https://github.com/open-telemetry/opentelemetry-js/pull/3208) @pkanal ### :bug: (Bug Fix) diff --git a/examples/opentelemetry-web/examples/fetch-proto/index.html b/examples/opentelemetry-web/examples/fetch-proto/index.html new file mode 100644 index 0000000000..160a6bd38b --- /dev/null +++ b/examples/opentelemetry-web/examples/fetch-proto/index.html @@ -0,0 +1,20 @@ + + + + + + Fetch Plugin Example + + + + + + + Example of using Web Tracer with Fetch plugin with console exporter and proto exporter + +
+ + + + + diff --git a/examples/opentelemetry-web/examples/fetch-proto/index.js b/examples/opentelemetry-web/examples/fetch-proto/index.js new file mode 100644 index 0000000000..9a9e85184c --- /dev/null +++ b/examples/opentelemetry-web/examples/fetch-proto/index.js @@ -0,0 +1,80 @@ +const { context, trace } = require("@opentelemetry/api"); +const { ConsoleSpanExporter, SimpleSpanProcessor} = require("@opentelemetry/sdk-trace-base"); +const { WebTracerProvider } = require("@opentelemetry/sdk-trace-web"); +const { FetchInstrumentation } = require("@opentelemetry/instrumentation-fetch"); +const { ZoneContextManager } = require("@opentelemetry/context-zone"); +const { B3Propagator } = require("@opentelemetry/propagator-b3"); +const { registerInstrumentations } = require("@opentelemetry/instrumentation"); +const { OTLPTraceExporter: OTLPTraceExporterProto } = require("@opentelemetry/exporter-trace-otlp-proto"); + +const provider = new WebTracerProvider(); + +// Note: For production consider using the "BatchSpanProcessor" to reduce the number of requests +// to your exporter. Using the SimpleSpanProcessor here as it sends the spans immediately to the +// exporter without delay +provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); +provider.addSpanProcessor( + new SimpleSpanProcessor(new OTLPTraceExporterProto()) +); + +provider.register({ + contextManager: new ZoneContextManager(), + propagator: new B3Propagator(), +}); + +registerInstrumentations({ + instrumentations: [ + new FetchInstrumentation({ + ignoreUrls: [/localhost:8090\/sockjs-node/], + propagateTraceHeaderCorsUrls: [ + "https://cors-test.appspot.com/test", + "https://httpbin.org/get", + ], + clearTimingResources: true, + }), + ], +}); + +const webTracerWithZone = provider.getTracer("example-tracer-web"); + +const getData = (url) => + fetch(url, { + method: "GET", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }); + +// example of keeping track of context between async operations +const prepareClickEvent = () => { + const url = "https://httpbin.org/get"; + + const element = document.getElementById("button1"); + + const onClick = () => { + const singleSpan = webTracerWithZone.startSpan("files-series-info"); + context.with(trace.setSpan(context.active(), singleSpan), () => { + getData(url).then((_data) => { + trace + .getSpan(context.active()) + .addEvent("fetching-single-span-completed"); + singleSpan.end(); + }); + }); + for (let i = 0, j = 5; i < j; i += 1) { + const span = webTracerWithZone.startSpan(`files-series-info-${i}`); + context.with(trace.setSpan(context.active(), span), () => { + getData(url).then((_data) => { + trace + .getSpan(context.active()) + .addEvent(`fetching-span-${i}-completed`); + span.end(); + }); + }); + } + }; + element.addEventListener("click", onClick); +}; + +window.addEventListener("load", prepareClickEvent); diff --git a/examples/opentelemetry-web/package.json b/examples/opentelemetry-web/package.json index 34afeb6bd4..42f011e15c 100644 --- a/examples/opentelemetry-web/package.json +++ b/examples/opentelemetry-web/package.json @@ -47,6 +47,7 @@ "@opentelemetry/core": "1.9.0", "@opentelemetry/exporter-metrics-otlp-http": "0.35.0", "@opentelemetry/exporter-trace-otlp-http": "0.35.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.35.0", "@opentelemetry/exporter-zipkin": "1.9.0", "@opentelemetry/instrumentation": "0.35.0", "@opentelemetry/instrumentation-fetch": "0.35.0", diff --git a/examples/opentelemetry-web/webpack.dev.config.js b/examples/opentelemetry-web/webpack.dev.config.js index c3045d79c1..6d3be1090b 100644 --- a/examples/opentelemetry-web/webpack.dev.config.js +++ b/examples/opentelemetry-web/webpack.dev.config.js @@ -12,6 +12,7 @@ const common = { 'xml-http-request': 'examples/xml-http-request/index.js', fetchXhr: 'examples/fetchXhr/index.js', fetchXhrB3: 'examples/fetchXhrB3/index.js', + 'fetch-proto': 'examples/fetch-proto/index.js', zipkin: 'examples/zipkin/index.js', }, output: { @@ -41,7 +42,7 @@ const common = { resolve: { modules: [ path.resolve(directory), - 'node_modules', + 'node_modules' ], extensions: ['.ts', '.js', '.jsx', '.json'], }, diff --git a/examples/opentelemetry-web/webpack.prod.config.js b/examples/opentelemetry-web/webpack.prod.config.js index 2eb7d783c1..96f7d69af2 100644 --- a/examples/opentelemetry-web/webpack.prod.config.js +++ b/examples/opentelemetry-web/webpack.prod.config.js @@ -12,6 +12,7 @@ const common = { 'xml-http-request': 'examples/xml-http-request/index.js', fetchXhr: 'examples/fetchXhr/index.js', fetchXhrB3: 'examples/fetchXhrB3/index.js', + "fetch-proto": "examples/fetch-proto/index.js", zipkin: 'examples/zipkin/index.js', }, output: { diff --git a/experimental/packages/exporter-trace-otlp-proto/karma.conf.js b/experimental/packages/exporter-trace-otlp-proto/karma.conf.js new file mode 100644 index 0000000000..4c60b54edb --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/karma.conf.js @@ -0,0 +1,26 @@ +/*! + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const karmaWebpackConfig = require('../../../karma.webpack'); +const karmaBaseConfig = require('../../../karma.base'); + +module.exports = (config) => { + config.set(Object.assign({}, karmaBaseConfig, { + webpack: karmaWebpackConfig, + files: ['test/browser/index-webpack.ts'], + preprocessors: { 'test/browser/index-webpack.ts': ['webpack'] } + })) +}; diff --git a/experimental/packages/exporter-trace-otlp-proto/package.json b/experimental/packages/exporter-trace-otlp-proto/package.json index 1a7d0ed244..1bea38c34f 100644 --- a/experimental/packages/exporter-trace-otlp-proto/package.json +++ b/experimental/packages/exporter-trace-otlp-proto/package.json @@ -3,18 +3,27 @@ "version": "0.35.0", "description": "OpenTelemetry Collector Exporter allows user to send collected traces to the OpenTelemetry Collector using protobuf over HTTP", "main": "build/src/index.js", + "module": "build/esm/index.js", + "esnext": "build/esnext/index.js", "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js", + "browser": { + "./src/platform/index.ts": "./src/platform/browser/index.ts", + "./build/esm/platform/index.js": "./build/esm/platform/browser/index.js", + "./build/esnext/platform/index.js": "./build/esnext/platform/browser/index.js", + "./build/src/platform/index.js": "./build/src/platform/browser/index.js" + }, "scripts": { "prepublishOnly": "npm run compile", - "compile": "tsc --build", - "clean": "tsc --build --clean", + "compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json", + "clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "tdd": "npm run test -- --watch-extensions ts --watch", - "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'", + "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'", + "test:browser": "nyc karma start --single-run", "version": "node ../../../scripts/version-update.js", - "watch": "tsc --build --watch", + "watch": "tsc --build --watch tsconfig.json tsconfig.esm.json tsconfig.esnext.json", "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile", "peer-api-check": "node ../../../scripts/peer-api-check.js", @@ -35,6 +44,12 @@ "node": ">=14" }, "files": [ + "build/esm/**/*.js", + "build/esm/**/*.js.map", + "build/esm/**/*.d.ts", + "build/esnext/**/*.js", + "build/esnext/**/*.js.map", + "build/esnext/**/*.d.ts", "build/src/**/*.js", "build/src/**/*.js.map", "build/src/**/*.d.ts", diff --git a/experimental/packages/exporter-trace-otlp-proto/src/index.ts b/experimental/packages/exporter-trace-otlp-proto/src/index.ts index 761e8a9262..f0dc6b55e3 100644 --- a/experimental/packages/exporter-trace-otlp-proto/src/index.ts +++ b/experimental/packages/exporter-trace-otlp-proto/src/index.ts @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -export * from './OTLPTraceExporter'; +export { OTLPTraceExporter } from './platform'; diff --git a/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/OTLPTraceExporter.ts new file mode 100644 index 0000000000..890268333f --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/OTLPTraceExporter.ts @@ -0,0 +1,72 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; +import { + OTLPExporterConfigBase, + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded, +} from '@opentelemetry/otlp-exporter-base'; +import { + OTLPProtoExporterBrowserBase, + ServiceClientType, +} from '@opentelemetry/otlp-proto-exporter-base'; +import { + createExportTraceServiceRequest, + IExportTraceServiceRequest, +} from '@opentelemetry/otlp-transformer'; + +const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/traces'; +const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURCE_PATH}`; + +/** + * Collector Trace Exporter for Web + */ +export class OTLPTraceExporter + extends OTLPProtoExporterBrowserBase + implements SpanExporter +{ + constructor(config: OTLPExporterConfigBase = {}) { + super(config); + this._headers = Object.assign( + this._headers, + baggageUtils.parseKeyPairsIntoRecord( + getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS + ) + ); + } + convert(spans: ReadableSpan[]): IExportTraceServiceRequest { + return createExportTraceServiceRequest(spans); + } + + getDefaultUrl(config: OTLPExporterConfigBase): string { + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0 + ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? appendResourcePathToUrl( + getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, + DEFAULT_COLLECTOR_RESOURCE_PATH + ) + : DEFAULT_COLLECTOR_URL; + } + + getServiceClientType() { + return ServiceClientType.SPANS; + } +} diff --git a/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/index.ts b/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/index.ts new file mode 100644 index 0000000000..74d90ff34c --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/src/platform/browser/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { OTLPTraceExporter } from './OTLPTraceExporter'; diff --git a/experimental/packages/exporter-trace-otlp-proto/src/platform/index.ts b/experimental/packages/exporter-trace-otlp-proto/src/platform/index.ts new file mode 100644 index 0000000000..f6ecd3a34f --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/src/platform/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { OTLPTraceExporter } from './node'; diff --git a/experimental/packages/exporter-trace-otlp-proto/src/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-proto/src/platform/node/OTLPTraceExporter.ts similarity index 100% rename from experimental/packages/exporter-trace-otlp-proto/src/OTLPTraceExporter.ts rename to experimental/packages/exporter-trace-otlp-proto/src/platform/node/OTLPTraceExporter.ts diff --git a/experimental/packages/exporter-trace-otlp-proto/src/platform/node/index.ts b/experimental/packages/exporter-trace-otlp-proto/src/platform/node/index.ts new file mode 100644 index 0000000000..254ac931a5 --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/src/platform/node/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { OTLPTraceExporter } from './OTLPTraceExporter'; diff --git a/experimental/packages/exporter-trace-otlp-proto/test/browser/CollectorTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-proto/test/browser/CollectorTraceExporter.test.ts new file mode 100644 index 0000000000..e8187e7296 --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/test/browser/CollectorTraceExporter.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 * as sinon from 'sinon'; +import { OTLPTraceExporter } from '../../src/platform/browser/index'; + +describe('OTLPTraceExporter - web', () => { + let collectorTraceExporter: OTLPTraceExporter; + describe('constructor', () => { + let onInitSpy: any; + beforeEach(() => { + onInitSpy = sinon.stub(OTLPTraceExporter.prototype, 'onInit'); + const collectorExporterConfig = { + hostname: 'foo', + url: 'http://foo.bar.com', + }; + collectorTraceExporter = new OTLPTraceExporter(collectorExporterConfig); + }); + afterEach(() => { + sinon.restore(); + }); + it('should create an instance', () => { + assert.ok(typeof collectorTraceExporter !== 'undefined'); + }); + it('should call onInit', () => { + assert.strictEqual(onInitSpy.callCount, 1); + }); + it('should set hostname', () => { + assert.strictEqual(collectorTraceExporter.hostname, 'foo'); + }); + + it('should set url', () => { + assert.strictEqual(collectorTraceExporter.url, 'http://foo.bar.com'); + }); + }); +}); diff --git a/experimental/packages/exporter-trace-otlp-proto/test/browser/index-webpack.ts b/experimental/packages/exporter-trace-otlp-proto/test/browser/index-webpack.ts new file mode 100644 index 0000000000..ae7d4b5a9d --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/test/browser/index-webpack.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. + */ +const testsContext = require.context('../browser', true, /test$/); +testsContext.keys().forEach(testsContext); + +const srcContext = require.context('.', true, /src$/); +srcContext.keys().forEach(srcContext); diff --git a/experimental/packages/exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-proto/test/node/OTLPTraceExporter.test.ts similarity index 99% rename from experimental/packages/exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts rename to experimental/packages/exporter-trace-otlp-proto/test/node/OTLPTraceExporter.test.ts index 924c6b4b31..64f0e40ea0 100644 --- a/experimental/packages/exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts +++ b/experimental/packages/exporter-trace-otlp-proto/test/node/OTLPTraceExporter.test.ts @@ -22,13 +22,13 @@ import * as http from 'http'; import * as sinon from 'sinon'; import { Stream, PassThrough } from 'stream'; import * as zlib from 'zlib'; -import { OTLPTraceExporter } from '../src'; +import { OTLPTraceExporter } from '../../src'; import { ensureExportTraceServiceRequestIsSet, ensureProtoSpanIsCorrect, mockedReadableSpan, MockedResponse, -} from './traceHelper'; +} from '../traceHelper'; import { CompressionAlgorithm, OTLPExporterNodeConfigBase, diff --git a/experimental/packages/exporter-trace-otlp-proto/tsconfig.esm.json b/experimental/packages/exporter-trace-otlp-proto/tsconfig.esm.json new file mode 100644 index 0000000000..ae47403334 --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/tsconfig.esm.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.base.esm.json", + "compilerOptions": { + "outDir": "build/esm", + "rootDir": "src", + "tsBuildInfoFile": "build/esm/tsconfig.esm.tsbuildinfo" + }, + "include": [ + "src/**/*.ts" + ], + "references": [ + { + "path": "../../../api" + }, + { + "path": "../../../packages/opentelemetry-core" + } + ] +} diff --git a/experimental/packages/exporter-trace-otlp-proto/tsconfig.esnext.json b/experimental/packages/exporter-trace-otlp-proto/tsconfig.esnext.json new file mode 100644 index 0000000000..5f6cf572d5 --- /dev/null +++ b/experimental/packages/exporter-trace-otlp-proto/tsconfig.esnext.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.base.esnext.json", + "compilerOptions": { + "outDir": "build/esnext", + "rootDir": "src", + "tsBuildInfoFile": "build/esnext/tsconfig.esnext.tsbuildinfo" + }, + "include": [ + "src/**/*.ts" + ], + "references": [ + { + "path": "../../../api" + }, + { + "path": "../../../packages/opentelemetry-core" + } + ] +} diff --git a/experimental/packages/otlp-exporter-base/src/index.ts b/experimental/packages/otlp-exporter-base/src/index.ts index e1149d2add..9ded103782 100644 --- a/experimental/packages/otlp-exporter-base/src/index.ts +++ b/experimental/packages/otlp-exporter-base/src/index.ts @@ -13,7 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './OTLPExporterBase'; export * from './platform'; -export * from './types'; -export * from './util'; +export { OTLPExporterBase } from './OTLPExporterBase'; +export { + OTLPExporterError, + OTLPExporterConfigBase, + ExportServiceError, +} from './types'; +export { + parseHeaders, + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded, + configureExporterTimeout, + invalidTimeout, +} from './util'; diff --git a/experimental/packages/otlp-exporter-base/src/platform/browser/index.ts b/experimental/packages/otlp-exporter-base/src/platform/browser/index.ts index c9678a8017..58b8777a97 100644 --- a/experimental/packages/otlp-exporter-base/src/platform/browser/index.ts +++ b/experimental/packages/otlp-exporter-base/src/platform/browser/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ -export * from './OTLPExporterBrowserBase'; +export { OTLPExporterBrowserBase } from './OTLPExporterBrowserBase'; +export { sendWithXhr } from './util'; diff --git a/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts b/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts index 8c311fe0ed..a271a3bf5f 100644 --- a/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts +++ b/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts @@ -50,7 +50,7 @@ export function sendWithBeacon( * @param onError */ export function sendWithXhr( - body: string, + body: string | Blob, url: string, headers: Record, exporterTimeout: number, diff --git a/experimental/packages/otlp-exporter-base/src/platform/index.ts b/experimental/packages/otlp-exporter-base/src/platform/index.ts index 86a320fde6..fc857a5802 100644 --- a/experimental/packages/otlp-exporter-base/src/platform/index.ts +++ b/experimental/packages/otlp-exporter-base/src/platform/index.ts @@ -13,5 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './node'; -export { OTLPExporterBrowserBase } from './browser'; + +export { + OTLPExporterNodeBase, + sendWithHttp, + createHttpAgent, + configureCompression, + OTLPExporterNodeConfigBase, + CompressionAlgorithm, +} from './node'; +export { OTLPExporterBrowserBase, sendWithXhr } from './browser'; diff --git a/experimental/packages/otlp-exporter-base/src/platform/node/index.ts b/experimental/packages/otlp-exporter-base/src/platform/node/index.ts index 8a75162ea2..b8b13bda20 100644 --- a/experimental/packages/otlp-exporter-base/src/platform/node/index.ts +++ b/experimental/packages/otlp-exporter-base/src/platform/node/index.ts @@ -14,6 +14,6 @@ * limitations under the License. */ -export * from './OTLPExporterNodeBase'; -export * from './util'; -export * from './types'; +export { OTLPExporterNodeBase } from './OTLPExporterNodeBase'; +export { sendWithHttp, createHttpAgent, configureCompression } from './util'; +export { OTLPExporterNodeConfigBase, CompressionAlgorithm } from './types'; diff --git a/experimental/packages/otlp-proto-exporter-base/package.json b/experimental/packages/otlp-proto-exporter-base/package.json index c1903cd935..c65efc5801 100644 --- a/experimental/packages/otlp-proto-exporter-base/package.json +++ b/experimental/packages/otlp-proto-exporter-base/package.json @@ -3,18 +3,26 @@ "version": "0.35.0", "description": "OpenTelemetry OTLP-HTTP-protobuf Exporter base (for internal use only)", "main": "build/src/index.js", + "module": "build/esm/index.js", + "esnext": "build/esnext/index.js", "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js", + "browser": { + "./src/platform/index.ts": "./src/platform/browser/index.ts", + "./build/esm/platform/index.js": "./build/esm/platform/browser/index.js", + "./build/esnext/platform/index.js": "./build/esnext/platform/browser/index.js", + "./build/src/platform/index.js": "./build/src/platform/browser/index.js" + }, "scripts": { "prepublishOnly": "npm run compile", - "compile": "npm run protos && tsc --build", - "clean": "tsc --build --clean", + "compile": "npm run protos && tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json", + "clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "protos": "npm run submodule && node scripts/protos.js", "submodule": "git submodule sync --recursive && git submodule update --init --recursive", "version": "node ../../../scripts/version-update.js", - "watch": "npm run protos && tsc -w", + "watch": "npm run protos && tsc -w tsconfig.json tsconfig.esm.json tsconfig.esnext.json", "precompile": "lerna run version --scope $(npm pkg get name) --include-dependencies", "prewatch": "npm run precompile" }, @@ -33,6 +41,12 @@ "node": ">=14" }, "files": [ + "build/esm/**/*.js", + "build/esm/**/*.js.map", + "build/esm/**/*.d.ts", + "build/esnext/**/*.js", + "build/esnext/**/*.js.map", + "build/esnext/**/*.d.ts", "build/src/**/*.js", "build/src/**/*.js.map", "build/src/**/*.d.ts", diff --git a/experimental/packages/otlp-proto-exporter-base/src/index.ts b/experimental/packages/otlp-proto-exporter-base/src/index.ts index e2cc1ee65c..e76b3a3593 100644 --- a/experimental/packages/otlp-proto-exporter-base/src/index.ts +++ b/experimental/packages/otlp-proto-exporter-base/src/index.ts @@ -13,7 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -export { OTLPProtoExporterNodeBase } from './OTLPProtoExporterNodeBase'; -export * from './types'; -export * from './util'; +export * from './platform'; diff --git a/experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts b/experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts new file mode 100644 index 0000000000..1b386855e4 --- /dev/null +++ b/experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts @@ -0,0 +1,90 @@ +/* + * 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 { diag } from '@opentelemetry/api'; +import { ServiceClientType } from '../types'; +import { + OTLPExporterBrowserBase as OTLPExporterBaseMain, + OTLPExporterError, + OTLPExporterConfigBase, + sendWithXhr, +} from '@opentelemetry/otlp-exporter-base'; +import * as root from '../../generated/root'; + +interface ExportRequestType unknown }> { + create(properties?: T): R; + encode(message: T, writer?: protobuf.Writer): protobuf.Writer; + decode(reader: protobuf.Reader | Uint8Array, length?: number): R; +} + +/** + * Collector Exporter abstract base class + */ +export abstract class OTLPProtoExporterBrowserBase< + ExportItem, + ServiceRequest +> extends OTLPExporterBaseMain { + constructor(config: OTLPExporterConfigBase = {}) { + super(config); + } + + private _getExportRequestProto( + clientType: ServiceClientType + ): ExportRequestType { + if (clientType === ServiceClientType.SPANS) { + // eslint-disable-next-line + return root.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest as unknown as ExportRequestType; + } else { + // eslint-disable-next-line + return root.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest as unknown as ExportRequestType; + } + } + + override send( + objects: ExportItem[], + onSuccess: () => void, + onError: (error: OTLPExporterError) => void + ): void { + if (this._shutdownOnce.isCalled) { + diag.debug('Shutdown already started. Cannot send objects'); + return; + } + + const serviceRequest = this.convert(objects); + const exportRequestType = this._getExportRequestProto( + this.getServiceClientType() + ); + const message = exportRequestType.create(serviceRequest); + + if (message) { + const body = exportRequestType.encode(message).finish(); + if (body) { + sendWithXhr( + new Blob([body], { type: 'application/x-protobuf' }), + this.url, + { ...this._headers, 'Content-Type': 'application/x-protobuf' }, + this.timeoutMillis, + onSuccess, + onError + ); + } + } else { + onError(new OTLPExporterError('No proto')); + } + } + + abstract getServiceClientType(): ServiceClientType; +} diff --git a/experimental/packages/otlp-proto-exporter-base/src/platform/browser/index.ts b/experimental/packages/otlp-proto-exporter-base/src/platform/browser/index.ts new file mode 100644 index 0000000000..26765ea51f --- /dev/null +++ b/experimental/packages/otlp-proto-exporter-base/src/platform/browser/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { OTLPProtoExporterBrowserBase } from './OTLPProtoExporterBrowserBase'; +export { ServiceClientType } from '../types'; diff --git a/experimental/packages/otlp-proto-exporter-base/src/platform/index.ts b/experimental/packages/otlp-proto-exporter-base/src/platform/index.ts new file mode 100644 index 0000000000..22efeb0309 --- /dev/null +++ b/experimental/packages/otlp-proto-exporter-base/src/platform/index.ts @@ -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 + * + * 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 { + OTLPProtoExporterNodeBase, + ExportRequestType, + getExportRequestProto, + send, +} from './node'; +export { OTLPProtoExporterBrowserBase } from './browser'; +export { ServiceClientType } from './types'; diff --git a/experimental/packages/otlp-proto-exporter-base/src/OTLPProtoExporterNodeBase.ts b/experimental/packages/otlp-proto-exporter-base/src/platform/node/OTLPProtoExporterNodeBase.ts similarity index 98% rename from experimental/packages/otlp-proto-exporter-base/src/OTLPProtoExporterNodeBase.ts rename to experimental/packages/otlp-proto-exporter-base/src/platform/node/OTLPProtoExporterNodeBase.ts index 1d458c5cf6..c0ff4b6b39 100644 --- a/experimental/packages/otlp-proto-exporter-base/src/OTLPProtoExporterNodeBase.ts +++ b/experimental/packages/otlp-proto-exporter-base/src/platform/node/OTLPProtoExporterNodeBase.ts @@ -15,7 +15,7 @@ */ import { diag } from '@opentelemetry/api'; -import { ServiceClientType } from './types'; +import { ServiceClientType } from '../types'; import { OTLPExporterNodeBase as OTLPExporterBaseMain, CompressionAlgorithm, diff --git a/experimental/packages/otlp-proto-exporter-base/src/platform/node/index.ts b/experimental/packages/otlp-proto-exporter-base/src/platform/node/index.ts new file mode 100644 index 0000000000..c9c84bdac3 --- /dev/null +++ b/experimental/packages/otlp-proto-exporter-base/src/platform/node/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 { OTLPProtoExporterNodeBase } from './OTLPProtoExporterNodeBase'; +export { ExportRequestType, getExportRequestProto, send } from './util'; diff --git a/experimental/packages/otlp-proto-exporter-base/src/util.ts b/experimental/packages/otlp-proto-exporter-base/src/platform/node/util.ts similarity index 96% rename from experimental/packages/otlp-proto-exporter-base/src/util.ts rename to experimental/packages/otlp-proto-exporter-base/src/platform/node/util.ts index 1d262cd74b..5cdbfa396d 100644 --- a/experimental/packages/otlp-proto-exporter-base/src/util.ts +++ b/experimental/packages/otlp-proto-exporter-base/src/platform/node/util.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ServiceClientType } from './types'; +import { ServiceClientType } from '../types'; import { OTLPProtoExporterNodeBase } from './OTLPProtoExporterNodeBase'; import { CompressionAlgorithm, @@ -22,7 +22,7 @@ import { sendWithHttp, } from '@opentelemetry/otlp-exporter-base'; import type * as protobuf from 'protobufjs'; -import * as root from './generated/root'; +import * as root from '../../generated/root'; export interface ExportRequestType unknown }> { create(properties?: T): R; diff --git a/experimental/packages/otlp-proto-exporter-base/src/types.ts b/experimental/packages/otlp-proto-exporter-base/src/platform/types.ts similarity index 100% rename from experimental/packages/otlp-proto-exporter-base/src/types.ts rename to experimental/packages/otlp-proto-exporter-base/src/platform/types.ts diff --git a/experimental/packages/otlp-proto-exporter-base/tsconfig.esm.json b/experimental/packages/otlp-proto-exporter-base/tsconfig.esm.json new file mode 100644 index 0000000000..ce8637cb82 --- /dev/null +++ b/experimental/packages/otlp-proto-exporter-base/tsconfig.esm.json @@ -0,0 +1,21 @@ +{ + "extends": "../../../tsconfig.base.esm.json", + "compilerOptions": { + "allowJs": true, + "outDir": "build/esm", + "rootDir": "src", + "tsBuildInfoFile": "build/esm/tsconfig.esm.tsbuildinfo" + }, + "include": [ + "src/**/*.ts", + "src/generated/*.js" + ], + "references": [ + { + "path": "../../../api" + }, + { + "path": "../../../packages/opentelemetry-core" + } + ] +} diff --git a/experimental/packages/otlp-proto-exporter-base/tsconfig.esnext.json b/experimental/packages/otlp-proto-exporter-base/tsconfig.esnext.json new file mode 100644 index 0000000000..4a1cb2c30b --- /dev/null +++ b/experimental/packages/otlp-proto-exporter-base/tsconfig.esnext.json @@ -0,0 +1,21 @@ +{ + "extends": "../../../tsconfig.base.esnext.json", + "compilerOptions": { + "allowJs": true, + "outDir": "build/esnext", + "rootDir": "src", + "tsBuildInfoFile": "build/esnext/tsconfig.esnext.tsbuildinfo" + }, + "include": [ + "src/**/*.ts", + "src/generated/*.js", + ], + "references": [ + { + "path": "../../../api" + }, + { + "path": "../../../packages/opentelemetry-core" + } + ] +} From bcfb1b63d5eb9d10cc5ddcb9b3683a48cbdfb43b Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Tue, 24 Jan 2023 11:13:08 -0800 Subject: [PATCH 2/2] Match Accept header with Content-Type in the proto exporter (#3562) * Match Accept header with Content-Type in the proto exporter * Lint fixes * Add changelog entry --- CHANGELOG.md | 3 +++ .../src/platform/browser/OTLPProtoExporterBrowserBase.ts | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index daa351e51d..651c54da10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/ ### :bug: (Bug Fix) +* fix(otlp-proto-exporter-base): Match Accept header with Content-Type in the proto exporter + [#3562](https://github.com/open-telemetry/opentelemetry-js/pull/3562) @scheler + ### :books: (Refine Doc) ### :house: (Internal) diff --git a/experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts b/experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts index 1b386855e4..4e9f95d5c0 100644 --- a/experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts +++ b/experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts @@ -75,7 +75,11 @@ export abstract class OTLPProtoExporterBrowserBase< sendWithXhr( new Blob([body], { type: 'application/x-protobuf' }), this.url, - { ...this._headers, 'Content-Type': 'application/x-protobuf' }, + { + ...this._headers, + 'Content-Type': 'application/x-protobuf', + Accept: 'application/x-protobuf', + }, this.timeoutMillis, onSuccess, onError