diff --git a/CHANGELOG.md b/CHANGELOG.md index 9941efcd2b0..0d629c233a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,15 +15,22 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/ ### :bug: (Bug Fix) +* fix: avoid grpc types dependency [#3551](https://github.com/open-telemetry/opentelemetry-js/pull/3551) @flarna +* 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) +* chore: fix cross project links and missing implicitly exported types [#3533](https://github.com/open-telemetry/opentelemetry-js/pull/3533) @legendecas + ## 1.9.0 ### :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) @@ -33,8 +40,10 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/ * `telemetry.sdk.name` * `telemetry.sdk.language` * `telemetry.sdk.version` +* fix(sdk-metrics): use Date.now() for instrument recording timestamps [#3514](https://github.com/open-telemetry/opentelemetry-js/pull/3514) @MisterSquishy * fix(sdk-trace): make spans resilient to clock drift [#3434](https://github.com/open-telemetry/opentelemetry-js/pull/3434) @dyladan * fix(selenium-tests): updated webpack version for selenium test issue [#3456](https://github.com/open-telemetry/opentelemetry-js/issues/3456) @SaumyaBhushan +* fix(sdk-metrics): collect metrics when periodic exporting metric reader flushes [#3517](https://github.com/open-telemetry/opentelemetry-js/pull/3517) @legendecas * fix(sdk-metrics): fix duplicated registration of metrics for collectors [#3488](https://github.com/open-telemetry/opentelemetry-js/pull/3488) @legendecas * fix(core): fix precision loss in numberToHrtime [#3480](https://github.com/open-telemetry/opentelemetry-js/pull/3480) @legendecas diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index d802680d8f5..cc96483c766 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## Unreleased + +### :bug: (Bug Fix) + +* fix(metrics): export `MetricsAPI` type [#3535](https://github.com/open-telemetry/opentelemetry-js/pull/3535) + ## 1.4.0 ### :rocket: (Enhancement) diff --git a/api/src/index.ts b/api/src/index.ts index 4b71551bcaa..2326aba9dcc 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -58,6 +58,7 @@ export { BatchObservableResult, ObservableResult, } from './metrics/ObservableResult'; +export type { MetricsAPI } from './api/metrics'; // Propagation APIs export { 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 00000000000..160a6bd38b7 --- /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 00000000000..9a9e85184cd --- /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 34afeb6bd45..42f011e15c8 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 c3045d79c19..6d3be1090b1 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 2eb7d783c1c..96f7d69af29 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 00000000000..4c60b54edba --- /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 1a7d0ed244e..1bea38c34f4 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 761e8a92624..f0dc6b55e3c 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 00000000000..890268333fa --- /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 00000000000..74d90ff34c0 --- /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 00000000000..f6ecd3a34f1 --- /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 00000000000..254ac931a50 --- /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 00000000000..e8187e72960 --- /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 00000000000..ae7d4b5a9dd --- /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 924c6b4b313..64f0e40ea0e 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 00000000000..ae474033346 --- /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 00000000000..5f6cf572d5a --- /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/opentelemetry-exporter-prometheus/test/util.ts b/experimental/packages/opentelemetry-exporter-prometheus/test/util.ts index be07dd3d8cc..2af8aa7f56c 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/test/util.ts +++ b/experimental/packages/opentelemetry-exporter-prometheus/test/util.ts @@ -15,17 +15,13 @@ */ import * as sinon from 'sinon'; -import * as perf_hooks from 'perf_hooks'; import { Resource } from '@opentelemetry/resources'; import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; export const mockedHrTimeMs = 1586347902211; export function mockHrTime() { - // We cannot stub core.now or core.timeOrigin since a property of - // ModuleNamespace can not be reconfigured.ß - sinon.stub(perf_hooks.performance, 'timeOrigin').value(0); - sinon.stub(perf_hooks.performance, 'now').returns(mockedHrTimeMs); + sinon.useFakeTimers(mockedHrTimeMs); } export const serviceName = Resource.default() diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts index 050eee24b1c..8c98a109368 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts @@ -33,7 +33,7 @@ import { CALL_SPAN_ENDED } from './serverUtils'; import { EventEmitter } from 'events'; import { AttributeNames } from '../enums/AttributeNames'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; -import { metadataCaptureType } from '../types'; +import { metadataCaptureType } from '../internal-types'; import { GRPC_STATUS_CODE_OK } from '../status-code'; /** diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts index 9147f455a04..2e5c833b193 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts @@ -20,7 +20,8 @@ import { isWrapped, } from '@opentelemetry/instrumentation'; import { InstrumentationBase } from '@opentelemetry/instrumentation'; -import { GrpcInstrumentationConfig, metadataCaptureType } from '../types'; +import { GrpcInstrumentationConfig } from '../types'; +import { metadataCaptureType } from '../internal-types'; import { ServerCallWithMeta, SendUnaryDataCallback, diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/clientUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/clientUtils.ts index 47de2ecf342..af56330a853 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/clientUtils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/clientUtils.ts @@ -25,7 +25,7 @@ import { findIndex, } from '../utils'; import { AttributeNames } from '../enums/AttributeNames'; -import { metadataCaptureType } from '../types'; +import { metadataCaptureType } from '../internal-types'; import { GRPC_STATUS_CODE_OK } from '../status-code'; /** diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts index 436e04ada4b..4df381eb668 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts @@ -27,7 +27,8 @@ import { SendUnaryDataCallback, GrpcClientFunc, } from './types'; -import { GrpcInstrumentationConfig, metadataCaptureType } from '../types'; +import { GrpcInstrumentationConfig } from '../types'; +import { metadataCaptureType } from '../internal-types'; import { context, propagation, diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/internal-types.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/internal-types.ts new file mode 100644 index 00000000000..d0052f7643e --- /dev/null +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/internal-types.ts @@ -0,0 +1,32 @@ +/* + * 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 { Span } from '@opentelemetry/api'; +import type * as grpcJsTypes from '@grpc/grpc-js'; +import type * as grpcTypes from 'grpc'; + +export type metadataCaptureType = { + client: { + captureRequestMetadata: ( + span: Span, + metadata: grpcJsTypes.Metadata | grpcTypes.Metadata + ) => void; + captureResponseMetadata: ( + span: Span, + metadata: grpcJsTypes.Metadata | grpcTypes.Metadata + ) => void; + }; +}; diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/types.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/types.ts index 67940a48e0a..dd08d8224b8 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/types.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/types.ts @@ -15,9 +15,6 @@ */ import { InstrumentationConfig } from '@opentelemetry/instrumentation'; -import { Span } from '@opentelemetry/api'; -import type * as grpcJsTypes from '@grpc/grpc-js'; -import type * as grpcTypes from 'grpc'; export type IgnoreMatcher = string | RegExp | ((str: string) => boolean); @@ -34,16 +31,3 @@ export interface GrpcInstrumentationConfig extends InstrumentationConfig { }; }; } - -export type metadataCaptureType = { - client: { - captureRequestMetadata: ( - span: Span, - metadata: grpcJsTypes.Metadata | grpcTypes.Metadata - ) => void; - captureResponseMetadata: ( - span: Span, - metadata: grpcJsTypes.Metadata | grpcTypes.Metadata - ) => void; - }; -}; diff --git a/experimental/packages/otlp-exporter-base/src/index.ts b/experimental/packages/otlp-exporter-base/src/index.ts index e1149d2add1..9ded1037826 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 c9678a80178..58b8777a97e 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 8c311fe0ed1..a271a3bf5ff 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 86a320fde66..fc857a58020 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 8a75162ea2d..b8b13bda202 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 c1903cd935b..c65efc58018 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/scripts/protos.js b/experimental/packages/otlp-proto-exporter-base/scripts/protos.js index e06cc9db444..3f3fbd6c0c0 100644 --- a/experimental/packages/otlp-proto-exporter-base/scripts/protos.js +++ b/experimental/packages/otlp-proto-exporter-base/scripts/protos.js @@ -45,6 +45,7 @@ async function pbjs(files) { const outFile = path.join(generatedPath, 'root.js'); const pbjsOptions = [ '-t', 'static-module', + '-p', protosPath, '-w', 'commonjs', '--null-defaults', '-o', outFile, diff --git a/experimental/packages/otlp-proto-exporter-base/src/index.ts b/experimental/packages/otlp-proto-exporter-base/src/index.ts index e2cc1ee65c7..e76b3a35937 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 00000000000..4e9f95d5c0d --- /dev/null +++ b/experimental/packages/otlp-proto-exporter-base/src/platform/browser/OTLPProtoExporterBrowserBase.ts @@ -0,0 +1,94 @@ +/* + * 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', + Accept: '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 00000000000..26765ea51f8 --- /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 00000000000..22efeb03093 --- /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 1d458c5cf6c..c0ff4b6b391 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 00000000000..c9c84bdac3f --- /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 1d262cd74b5..5cdbfa396d1 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 00000000000..ce8637cb82d --- /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 00000000000..4a1cb2c30b7 --- /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" + } + ] +} diff --git a/experimental/packages/otlp-transformer/package.json b/experimental/packages/otlp-transformer/package.json index ba4462f5c53..cd1641edccb 100644 --- a/experimental/packages/otlp-transformer/package.json +++ b/experimental/packages/otlp-transformer/package.json @@ -66,7 +66,7 @@ "karma-mocha": "2.0.1", "karma-spec-reporter": "0.0.32", "karma-webpack": "4.0.2", - "mkdirp": "1.0.4", + "mkdirp": "2.1.3", "mocha": "10.0.0", "nyc": "15.1.0", "rimraf": "3.0.2", diff --git a/package.json b/package.json index b2da03723ef..0bec743a3bc 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,9 @@ "markdownlint-cli": "0.32.2", "prettier": "2.8.0", "semver": "7.3.5", - "typedoc": "0.22.10", + "typedoc": "0.22.18", + "typedoc-plugin-missing-exports": "1.0.0", + "typedoc-plugin-resolve-crossmodule-references": "0.2.2", "typescript": "4.4.4" }, "changelog": { diff --git a/packages/opentelemetry-resources/src/Resource.ts b/packages/opentelemetry-resources/src/Resource.ts index ac368d812ee..0dc2072a2f9 100644 --- a/packages/opentelemetry-resources/src/Resource.ts +++ b/packages/opentelemetry-resources/src/Resource.ts @@ -34,7 +34,7 @@ export class Resource { } /** - * Returns a Resource that indentifies the SDK in use. + * Returns a Resource that identifies the SDK in use. */ static default(): Resource { return new Resource({ diff --git a/packages/sdk-metrics/src/Instruments.ts b/packages/sdk-metrics/src/Instruments.ts index 09e849cc323..d99c621c0b3 100644 --- a/packages/sdk-metrics/src/Instruments.ts +++ b/packages/sdk-metrics/src/Instruments.ts @@ -29,7 +29,7 @@ import { ObservableGauge, ObservableUpDownCounter, } from '@opentelemetry/api'; -import { hrTime } from '@opentelemetry/core'; +import { millisToHrTime } from '@opentelemetry/core'; import { InstrumentDescriptor } from './InstrumentDescriptor'; import { ObservableRegistry } from './state/ObservableRegistry'; import { @@ -57,7 +57,12 @@ export class SyncInstrument { ); value = Math.trunc(value); } - this._writableMetricStorage.record(value, attributes, context, hrTime()); + this._writableMetricStorage.record( + value, + attributes, + context, + millisToHrTime(Date.now()) + ); } } diff --git a/packages/sdk-metrics/src/aggregator/LastValue.ts b/packages/sdk-metrics/src/aggregator/LastValue.ts index e9e85b36bdb..9c627130f65 100644 --- a/packages/sdk-metrics/src/aggregator/LastValue.ts +++ b/packages/sdk-metrics/src/aggregator/LastValue.ts @@ -22,7 +22,7 @@ import { LastValue, } from './types'; import { HrTime } from '@opentelemetry/api'; -import { hrTime, hrTimeToMicroseconds } from '@opentelemetry/core'; +import { millisToHrTime, hrTimeToMicroseconds } from '@opentelemetry/core'; import { DataPointType, GaugeMetricData } from '../export/MetricData'; import { InstrumentDescriptor } from '../InstrumentDescriptor'; import { Maybe } from '../utils'; @@ -37,7 +37,7 @@ export class LastValueAccumulation implements Accumulation { record(value: number): void { this._current = value; - this.sampleTime = hrTime(); + this.sampleTime = millisToHrTime(Date.now()); } setStartTime(startTime: HrTime): void { diff --git a/packages/sdk-metrics/src/export/PeriodicExportingMetricReader.ts b/packages/sdk-metrics/src/export/PeriodicExportingMetricReader.ts index e9da187a457..c156e883adf 100644 --- a/packages/sdk-metrics/src/export/PeriodicExportingMetricReader.ts +++ b/packages/sdk-metrics/src/export/PeriodicExportingMetricReader.ts @@ -90,7 +90,25 @@ export class PeriodicExportingMetricReader extends MetricReader { } private async _runOnce(): Promise { - const { resourceMetrics, errors } = await this.collect({}); + try { + await callWithTimeout(this._doRun(), this._exportTimeout); + } catch (err) { + if (err instanceof TimeoutError) { + api.diag.error( + 'Export took longer than %s milliseconds and timed out.', + this._exportTimeout + ); + return; + } + + globalErrorHandler(err); + } + } + + private async _doRun(): Promise { + const { resourceMetrics, errors } = await this.collect({ + timeoutMillis: this._exportTimeout, + }); if (errors.length > 0) { api.diag.error( @@ -109,25 +127,15 @@ export class PeriodicExportingMetricReader extends MetricReader { protected override onInitialized(): void { // start running the interval as soon as this reader is initialized and keep handle for shutdown. - this._interval = setInterval(async () => { - try { - await callWithTimeout(this._runOnce(), this._exportTimeout); - } catch (err) { - if (err instanceof TimeoutError) { - api.diag.error( - 'Export took longer than %s milliseconds and timed out.', - this._exportTimeout - ); - return; - } - - globalErrorHandler(err); - } + this._interval = setInterval(() => { + // this._runOnce never rejects. Using void operator to suppress @typescript-eslint/no-floating-promises. + void this._runOnce(); }, this._exportInterval); unrefTimer(this._interval); } protected async onForceFlush(): Promise { + await this._runOnce(); await this._exporter.forceFlush(); } diff --git a/packages/sdk-metrics/src/state/MetricCollector.ts b/packages/sdk-metrics/src/state/MetricCollector.ts index 95fe8d4e148..3f17a0d5b9a 100644 --- a/packages/sdk-metrics/src/state/MetricCollector.ts +++ b/packages/sdk-metrics/src/state/MetricCollector.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { hrTime } from '@opentelemetry/core'; +import { millisToHrTime } from '@opentelemetry/core'; import { AggregationTemporalitySelector } from '../export/AggregationSelector'; import { CollectionResult } from '../export/MetricData'; import { MetricProducer, MetricCollectOptions } from '../export/MetricProducer'; @@ -36,7 +36,7 @@ export class MetricCollector implements MetricProducer { ) {} async collect(options?: MetricCollectOptions): Promise { - const collectionTime = hrTime(); + const collectionTime = millisToHrTime(Date.now()); const meterCollectionPromises = Array.from( this._sharedState.meterSharedStates.values() ).map(meterSharedState => diff --git a/packages/sdk-metrics/test/export/PeriodicExportingMetricReader.test.ts b/packages/sdk-metrics/test/export/PeriodicExportingMetricReader.test.ts index d6fa69df9d6..d5ab5531267 100644 --- a/packages/sdk-metrics/test/export/PeriodicExportingMetricReader.test.ts +++ b/packages/sdk-metrics/test/export/PeriodicExportingMetricReader.test.ts @@ -38,8 +38,9 @@ const MAX_32_BIT_INT = 2 ** 31 - 1; class TestMetricExporter implements PushMetricExporter { public exportTime = 0; public forceFlushTime = 0; - public throwException = false; - public failureResult = false; + public throwExport = false; + public throwFlush = false; + public rejectExport = false; private _batches: ResourceMetrics[] = []; private _shutdown: boolean = false; @@ -49,11 +50,11 @@ class TestMetricExporter implements PushMetricExporter { ): void { this._batches.push(metrics); - if (this.throwException) { + if (this.throwExport) { throw new Error('Error during export'); } setTimeout(() => { - if (this.failureResult) { + if (this.rejectExport) { resultCallback({ code: ExportResultCode.FAILED, error: new Error('some error'), @@ -72,7 +73,7 @@ class TestMetricExporter implements PushMetricExporter { } async forceFlush(): Promise { - if (this.throwException) { + if (this.throwFlush) { throw new Error('Error during forceFlush'); } @@ -91,6 +92,10 @@ class TestMetricExporter implements PushMetricExporter { } return this._batches.slice(0, numberOfExports); } + + getExports(): ResourceMetrics[] { + return this._batches.slice(0); + } } class TestDeltaMetricExporter extends TestMetricExporter { @@ -203,7 +208,7 @@ describe('PeriodicExportingMetricReader', () => { describe('periodic export', () => { it('should keep running on export errors', async () => { const exporter = new TestMetricExporter(); - exporter.throwException = true; + exporter.throwExport = true; const reader = new PeriodicExportingMetricReader({ exporter: exporter, exportIntervalMillis: 30, @@ -218,13 +223,13 @@ describe('PeriodicExportingMetricReader', () => { emptyResourceMetrics, ]); - exporter.throwException = false; + exporter.throwExport = false; await reader.shutdown(); }); it('should keep running on export failure', async () => { const exporter = new TestMetricExporter(); - exporter.failureResult = true; + exporter.rejectExport = true; const reader = new PeriodicExportingMetricReader({ exporter: exporter, exportIntervalMillis: 30, @@ -239,7 +244,7 @@ describe('PeriodicExportingMetricReader', () => { emptyResourceMetrics, ]); - exporter.failureResult = false; + exporter.rejectExport = false; await reader.shutdown(); }); @@ -261,7 +266,7 @@ describe('PeriodicExportingMetricReader', () => { emptyResourceMetrics, ]); - exporter.throwException = false; + exporter.throwExport = false; await reader.shutdown(); }); }); @@ -271,7 +276,7 @@ describe('PeriodicExportingMetricReader', () => { sinon.restore(); }); - it('should forceFlush exporter', async () => { + it('should collect and forceFlush exporter', async () => { const exporter = new TestMetricExporter(); const exporterMock = sinon.mock(exporter); exporterMock.expects('forceFlush').calledOnceWithExactly(); @@ -284,6 +289,10 @@ describe('PeriodicExportingMetricReader', () => { reader.setMetricProducer(new TestMetricProducer()); await reader.forceFlush(); exporterMock.verify(); + + const exports = exporter.getExports(); + assert.strictEqual(exports.length, 1); + await reader.shutdown(); }); @@ -307,12 +316,13 @@ describe('PeriodicExportingMetricReader', () => { it('should throw when exporter throws', async () => { const exporter = new TestMetricExporter(); - exporter.throwException = true; + exporter.throwFlush = true; const reader = new PeriodicExportingMetricReader({ exporter: exporter, exportIntervalMillis: MAX_32_BIT_INT, exportTimeoutMillis: 80, }); + reader.setMetricProducer(new TestMetricProducer()); await assertRejects(() => reader.forceFlush(), /Error during forceFlush/); }); @@ -454,7 +464,7 @@ describe('PeriodicExportingMetricReader', () => { it('should throw on non-initialized instance.', async () => { const exporter = new TestMetricExporter(); - exporter.throwException = true; + exporter.throwFlush = true; const reader = new PeriodicExportingMetricReader({ exporter: exporter, exportIntervalMillis: MAX_32_BIT_INT,