From abd191bef366de8926f14701bf8b83df03b60d22 Mon Sep 17 00:00:00 2001 From: Matthew Wear Date: Wed, 11 Mar 2020 13:41:22 -0700 Subject: [PATCH] SDK Resource (#846) * feat: add Resource.empty() method * feat: add resource to BasicTracerProvider and assign to Spans * feat: add Resource.createLibraryResource method * refactor: rename LIBARY_RESOURCE -> TELEMETRY_SDK_RESOURCE * feat: add resource to ReadableSpan interface * feat: add Resource to NodeTracerProvider * feat: add Resource to WebTracerProvider * refactor: move resource-assertions * feat: add Resource to instruments * refactor: add SDK_INFO to core; simplify SDK resource creation * chore: docs and cleanup * docs: no need to update the copyright * chore: move resources to devDependencies where applicable * refactor: add resource to TraceConfig * refactor: add resource to MeterConfig * refactor: change resource visibility on Meter * refactor: move resource-assertions to test/util --- packages/opentelemetry-base/package.json | 4 +++ packages/opentelemetry-base/src/index.ts | 1 + .../src/platform/browser/constants.ts | 25 +++++++++++++++++++ .../src/platform/browser/index.ts | 17 +++++++++++++ .../opentelemetry-base/src/platform/index.ts | 20 +++++++++++++++ .../src/platform/node/constants.ts | 25 +++++++++++++++++++ .../src/platform/node/index.ts | 17 +++++++++++++ .../package.json | 1 + .../test/helper.ts | 2 ++ .../package.json | 1 + .../test/jaeger.test.ts | 2 ++ .../test/transform.test.ts | 5 ++++ .../package.json | 1 + .../test/exporter.test.ts | 5 ++++ .../test/transform.test.ts | 2 ++ .../package.json | 1 + .../test/zipkin.test.ts | 4 +++ packages/opentelemetry-metrics/package.json | 3 ++- packages/opentelemetry-metrics/src/Meter.ts | 14 ++++++++--- .../src/MeterProvider.ts | 2 ++ packages/opentelemetry-metrics/src/Metric.ts | 19 ++++++++------ packages/opentelemetry-metrics/src/types.ts | 4 +++ .../opentelemetry-metrics/test/Meter.test.ts | 16 ++++++++++++ packages/opentelemetry-node/package.json | 1 + .../test/NodeTracerProvider.test.ts | 14 +++++++++++ packages/opentelemetry-resources/package.json | 3 ++- .../opentelemetry-resources/src/Resource.ts | 23 +++++++++++++++++ .../opentelemetry-resources/src/constants.ts | 10 ++++---- .../test/Resource.test.ts | 24 ++++++++++++++++++ .../test/resource-assertions.test.ts | 25 +++++++++++-------- .../test/util/resource-assertions.ts | 22 ++++++++++------ packages/opentelemetry-tracing/package.json | 1 + .../src/BasicTracerProvider.ts | 3 +++ packages/opentelemetry-tracing/src/Span.ts | 3 +++ packages/opentelemetry-tracing/src/Tracer.ts | 3 +++ .../src/export/ReadableSpan.ts | 2 ++ packages/opentelemetry-tracing/src/types.ts | 4 +++ .../test/BasicTracerProvider.test.ts | 15 +++++++++++ packages/opentelemetry-web/package.json | 1 + .../test/WebTracerProvider.test.ts | 20 +++++++++++++-- 40 files changed, 329 insertions(+), 36 deletions(-) create mode 100644 packages/opentelemetry-base/src/platform/browser/constants.ts create mode 100644 packages/opentelemetry-base/src/platform/browser/index.ts create mode 100644 packages/opentelemetry-base/src/platform/index.ts create mode 100644 packages/opentelemetry-base/src/platform/node/constants.ts create mode 100644 packages/opentelemetry-base/src/platform/node/index.ts diff --git a/packages/opentelemetry-base/package.json b/packages/opentelemetry-base/package.json index 9c934bdab5..81eeccf4e7 100644 --- a/packages/opentelemetry-base/package.json +++ b/packages/opentelemetry-base/package.json @@ -3,6 +3,10 @@ "version": "0.4.0", "description": "OpenTelemetry base provides base code for the SDK packages", "main": "build/src/index.js", + "browser": { + "./src/platform/index.ts": "./src/platform/browser/index.ts", + "./build/src/platform/index.js": "./build/src/platform/browser/index.js" + }, "types": "build/src/index.d.ts", "repository": "open-telemetry/opentelemetry-js", "scripts": { diff --git a/packages/opentelemetry-base/src/index.ts b/packages/opentelemetry-base/src/index.ts index a6120e227b..1c2e67e6b7 100644 --- a/packages/opentelemetry-base/src/index.ts +++ b/packages/opentelemetry-base/src/index.ts @@ -15,3 +15,4 @@ */ export * from './ExportResult'; +export * from './platform'; diff --git a/packages/opentelemetry-base/src/platform/browser/constants.ts b/packages/opentelemetry-base/src/platform/browser/constants.ts new file mode 100644 index 0000000000..f37897b468 --- /dev/null +++ b/packages/opentelemetry-base/src/platform/browser/constants.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2020, 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 { VERSION } from '../../version'; + +/** Constants describing the SDK in use */ +export const SDK_INFO = { + NAME: 'opentelemetry', + RUNTIME: 'browser', + LANGUAGE: 'webjs', + VERSION: VERSION, +}; diff --git a/packages/opentelemetry-base/src/platform/browser/index.ts b/packages/opentelemetry-base/src/platform/browser/index.ts new file mode 100644 index 0000000000..953b08f4da --- /dev/null +++ b/packages/opentelemetry-base/src/platform/browser/index.ts @@ -0,0 +1,17 @@ +/*! + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './constants'; diff --git a/packages/opentelemetry-base/src/platform/index.ts b/packages/opentelemetry-base/src/platform/index.ts new file mode 100644 index 0000000000..6c6d039c91 --- /dev/null +++ b/packages/opentelemetry-base/src/platform/index.ts @@ -0,0 +1,20 @@ +/*! + * Copyright 2020, 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. + */ + +// Use the node platform by default. The "browser" field of package.json is used +// to override this file to use `./browser/index.ts` when packaged with +// webpack, Rollup, etc. +export * from './node'; diff --git a/packages/opentelemetry-base/src/platform/node/constants.ts b/packages/opentelemetry-base/src/platform/node/constants.ts new file mode 100644 index 0000000000..33c475d428 --- /dev/null +++ b/packages/opentelemetry-base/src/platform/node/constants.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2020, 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 { VERSION } from '../../version'; + +/** Constants describing the SDK in use */ +export const SDK_INFO = { + NAME: 'opentelemetry', + RUNTIME: 'node', + LANGUAGE: 'nodejs', + VERSION: VERSION, +}; diff --git a/packages/opentelemetry-base/src/platform/node/index.ts b/packages/opentelemetry-base/src/platform/node/index.ts new file mode 100644 index 0000000000..953b08f4da --- /dev/null +++ b/packages/opentelemetry-base/src/platform/node/index.ts @@ -0,0 +1,17 @@ +/*! + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './constants'; diff --git a/packages/opentelemetry-exporter-collector/package.json b/packages/opentelemetry-exporter-collector/package.json index 3edf900009..9ca0d23062 100644 --- a/packages/opentelemetry-exporter-collector/package.json +++ b/packages/opentelemetry-exporter-collector/package.json @@ -50,6 +50,7 @@ }, "devDependencies": { "@babel/core": "^7.6.0", + "@opentelemetry/resources": "^0.4.0", "@types/mocha": "^5.2.5", "@types/node": "^12.6.8", "@types/sinon": "^7.0.13", diff --git a/packages/opentelemetry-exporter-collector/test/helper.ts b/packages/opentelemetry-exporter-collector/test/helper.ts index e15e0ba7d5..750f32599b 100644 --- a/packages/opentelemetry-exporter-collector/test/helper.ts +++ b/packages/opentelemetry-exporter-collector/test/helper.ts @@ -17,6 +17,7 @@ import { TraceFlags } from '@opentelemetry/api'; import * as core from '@opentelemetry/core'; import { ReadableSpan } from '@opentelemetry/tracing'; +import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; import * as transform from '../src/transform'; import * as collectorTypes from '../src/types'; @@ -68,6 +69,7 @@ export const mockedReadableSpan: ReadableSpan = { }, ], duration: [0, 8885000], + resource: Resource.empty(), }; export function ensureSpanIsCorrect(span: collectorTypes.Span) { diff --git a/packages/opentelemetry-exporter-jaeger/package.json b/packages/opentelemetry-exporter-jaeger/package.json index 14f532a2b9..9ce236e458 100644 --- a/packages/opentelemetry-exporter-jaeger/package.json +++ b/packages/opentelemetry-exporter-jaeger/package.json @@ -40,6 +40,7 @@ "access": "public" }, "devDependencies": { + "@opentelemetry/resources": "^0.4.0", "@types/mocha": "^5.2.7", "@types/node": "^12.6.9", "codecov": "^3.6.1", diff --git a/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts b/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts index b24e6b4538..9b79bcc838 100644 --- a/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts +++ b/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts @@ -22,6 +22,7 @@ import { ThriftProcess } from '../src/types'; import { ReadableSpan } from '@opentelemetry/tracing'; import { ExportResult } from '@opentelemetry/base'; import { TraceFlags } from '@opentelemetry/api'; +import { Resource } from '@opentelemetry/resources'; describe('JaegerExporter', () => { describe('constructor', () => { @@ -127,6 +128,7 @@ describe('JaegerExporter', () => { links: [], events: [], duration: [32, 800000000], + resource: Resource.empty(), }; exporter.export([readableSpan], (result: ExportResult) => { diff --git a/packages/opentelemetry-exporter-jaeger/test/transform.test.ts b/packages/opentelemetry-exporter-jaeger/test/transform.test.ts index 5068ce7295..bc58b031aa 100644 --- a/packages/opentelemetry-exporter-jaeger/test/transform.test.ts +++ b/packages/opentelemetry-exporter-jaeger/test/transform.test.ts @@ -17,6 +17,7 @@ import * as assert from 'assert'; import { spanToThrift } from '../src/transform'; import { ReadableSpan } from '@opentelemetry/tracing'; +import { Resource } from '@opentelemetry/resources'; import * as types from '@opentelemetry/api'; import { ThriftUtils, Utils, ThriftReferenceType } from '../src/types'; import { hrTimeToMicroseconds } from '@opentelemetry/core'; @@ -69,6 +70,7 @@ describe('transform', () => { }, ], duration: [32, 800000000], + resource: Resource.empty(), }; const thriftSpan = spanToThrift(readableSpan); @@ -143,6 +145,7 @@ describe('transform', () => { links: [], events: [], duration: [32, 800000000], + resource: Resource.empty(), }; const thriftSpan = spanToThrift(readableSpan); @@ -207,6 +210,7 @@ describe('transform', () => { ], events: [], duration: [32, 800000000], + resource: Resource.empty(), }; const thriftSpan = spanToThrift(readableSpan); @@ -245,6 +249,7 @@ describe('transform', () => { links: [], events: [], duration: [32, 800000000], + resource: Resource.empty(), }; const thriftSpan = spanToThrift(readableSpan); diff --git a/packages/opentelemetry-exporter-stackdriver-trace/package.json b/packages/opentelemetry-exporter-stackdriver-trace/package.json index 98226eb0e6..f1de5af310 100644 --- a/packages/opentelemetry-exporter-stackdriver-trace/package.json +++ b/packages/opentelemetry-exporter-stackdriver-trace/package.json @@ -41,6 +41,7 @@ "access": "public" }, "devDependencies": { + "@opentelemetry/resources": "^0.4.0", "@types/mocha": "^5.2.7", "@types/nock": "^11.1.0", "@types/node": "^12.6.9", diff --git a/packages/opentelemetry-exporter-stackdriver-trace/test/exporter.test.ts b/packages/opentelemetry-exporter-stackdriver-trace/test/exporter.test.ts index 211fd46f2e..6d4321f52b 100644 --- a/packages/opentelemetry-exporter-stackdriver-trace/test/exporter.test.ts +++ b/packages/opentelemetry-exporter-stackdriver-trace/test/exporter.test.ts @@ -17,6 +17,7 @@ import { ExportResult } from '@opentelemetry/base'; import { ConsoleLogger, LogLevel } from '@opentelemetry/core'; import { ReadableSpan } from '@opentelemetry/tracing'; +import { Resource } from '@opentelemetry/resources'; import * as types from '@opentelemetry/api'; import * as assert from 'assert'; import * as nock from 'nock'; @@ -121,6 +122,7 @@ describe('Stackdriver Trace Exporter', () => { isRemote: true, }, status: { code: types.CanonicalCode.OK }, + resource: Resource.empty(), }; const result = await new Promise((resolve, reject) => { @@ -155,6 +157,7 @@ describe('Stackdriver Trace Exporter', () => { isRemote: true, }, status: { code: types.CanonicalCode.OK }, + resource: Resource.empty(), }; getClientShouldFail = true; @@ -188,6 +191,7 @@ describe('Stackdriver Trace Exporter', () => { isRemote: true, }, status: { code: types.CanonicalCode.OK }, + resource: Resource.empty(), }; batchWriteShouldFail = true; @@ -219,6 +223,7 @@ describe('Stackdriver Trace Exporter', () => { isRemote: true, }, status: { code: types.CanonicalCode.OK }, + resource: Resource.empty(), }; await exporter['_projectId']; diff --git a/packages/opentelemetry-exporter-stackdriver-trace/test/transform.test.ts b/packages/opentelemetry-exporter-stackdriver-trace/test/transform.test.ts index f79da9e353..32f7de8312 100644 --- a/packages/opentelemetry-exporter-stackdriver-trace/test/transform.test.ts +++ b/packages/opentelemetry-exporter-stackdriver-trace/test/transform.test.ts @@ -16,6 +16,7 @@ import { VERSION as CORE_VERSION } from '@opentelemetry/core'; import { ReadableSpan } from '@opentelemetry/tracing'; +import { Resource } from '@opentelemetry/resources'; import * as types from '@opentelemetry/api'; import * as assert from 'assert'; import { getReadableSpanTransformer } from '../src/transform'; @@ -50,6 +51,7 @@ describe('transform', () => { name: 'my-span', spanContext, status: { code: types.CanonicalCode.OK }, + resource: Resource.empty(), }; }); diff --git a/packages/opentelemetry-exporter-zipkin/package.json b/packages/opentelemetry-exporter-zipkin/package.json index 7ac477ce18..44788807a6 100644 --- a/packages/opentelemetry-exporter-zipkin/package.json +++ b/packages/opentelemetry-exporter-zipkin/package.json @@ -39,6 +39,7 @@ "access": "public" }, "devDependencies": { + "@opentelemetry/resources": "^0.4.0", "@types/mocha": "^5.2.7", "@types/nock": "^10.0.3", "@types/node": "^12.6.9", diff --git a/packages/opentelemetry-exporter-zipkin/test/zipkin.test.ts b/packages/opentelemetry-exporter-zipkin/test/zipkin.test.ts index 2cde0c5da8..bd0105e553 100644 --- a/packages/opentelemetry-exporter-zipkin/test/zipkin.test.ts +++ b/packages/opentelemetry-exporter-zipkin/test/zipkin.test.ts @@ -20,6 +20,7 @@ import { ReadableSpan } from '@opentelemetry/tracing'; import { ExportResult } from '@opentelemetry/base'; import { NoopLogger, hrTimeToMicroseconds } from '@opentelemetry/core'; import * as types from '@opentelemetry/api'; +import { Resource } from '@opentelemetry/resources'; import { ZipkinExporter } from '../src'; import * as zipkinTypes from '../src/types'; import { OT_REQUEST_HEADER } from '../src/utils'; @@ -48,6 +49,7 @@ function getReadableSpan() { attributes: {}, links: [], events: [], + resource: Resource.empty(), }; return readableSpan; } @@ -154,6 +156,7 @@ describe('ZipkinExporter', () => { attributes: { key3: 'value3' }, }, ], + resource: Resource.empty(), }; const span2: ReadableSpan = { name: 'my-span', @@ -173,6 +176,7 @@ describe('ZipkinExporter', () => { attributes: {}, links: [], events: [], + resource: Resource.empty(), }; const exporter = new ZipkinExporter({ diff --git a/packages/opentelemetry-metrics/package.json b/packages/opentelemetry-metrics/package.json index 6a7543fe1b..cc5f82af96 100644 --- a/packages/opentelemetry-metrics/package.json +++ b/packages/opentelemetry-metrics/package.json @@ -59,6 +59,7 @@ "dependencies": { "@opentelemetry/api": "^0.4.0", "@opentelemetry/base": "^0.4.0", - "@opentelemetry/core": "^0.4.0" + "@opentelemetry/core": "^0.4.0", + "@opentelemetry/resources": "^0.4.0" } } diff --git a/packages/opentelemetry-metrics/src/Meter.ts b/packages/opentelemetry-metrics/src/Meter.ts index 693aa450af..83e46291a1 100644 --- a/packages/opentelemetry-metrics/src/Meter.ts +++ b/packages/opentelemetry-metrics/src/Meter.ts @@ -16,6 +16,7 @@ import * as types from '@opentelemetry/api'; import { ConsoleLogger } from '@opentelemetry/core'; +import { Resource } from '@opentelemetry/resources'; import { BaseBoundInstrument } from './BoundInstrument'; import { Metric, CounterMetric, MeasureMetric, ObserverMetric } from './Metric'; import { @@ -36,6 +37,7 @@ export class Meter implements types.Meter { private readonly _logger: types.Logger; private readonly _metrics = new Map>(); private readonly _batcher: Batcher; + private readonly _resource: Resource; readonly labels = Meter.labels; /** @@ -44,6 +46,7 @@ export class Meter implements types.Meter { constructor(config: MeterConfig = DEFAULT_CONFIG) { this._logger = config.logger || new ConsoleLogger(config.logLevel); this._batcher = new UngroupedBatcher(); + this._resource = config.resource || Resource.createTelemetrySDKResource(); // start the push controller const exporter = config.exporter || new NoopExporter(); const interval = config.interval; @@ -73,7 +76,7 @@ export class Meter implements types.Meter { ...options, }; - const measure = new MeasureMetric(name, opt, this._batcher); + const measure = new MeasureMetric(name, opt, this._batcher, this._resource); this._registerMetric(name, measure); return measure; } @@ -102,7 +105,7 @@ export class Meter implements types.Meter { ...DEFAULT_METRIC_OPTIONS, ...options, }; - const counter = new CounterMetric(name, opt, this._batcher); + const counter = new CounterMetric(name, opt, this._batcher, this._resource); this._registerMetric(name, counter); return counter; } @@ -129,7 +132,12 @@ export class Meter implements types.Meter { ...DEFAULT_METRIC_OPTIONS, ...options, }; - const observer = new ObserverMetric(name, opt, this._batcher); + const observer = new ObserverMetric( + name, + opt, + this._batcher, + this._resource + ); this._registerMetric(name, observer); return observer; } diff --git a/packages/opentelemetry-metrics/src/MeterProvider.ts b/packages/opentelemetry-metrics/src/MeterProvider.ts index bb4410bb17..09bd9f8e66 100644 --- a/packages/opentelemetry-metrics/src/MeterProvider.ts +++ b/packages/opentelemetry-metrics/src/MeterProvider.ts @@ -16,6 +16,7 @@ import { ConsoleLogger } from '@opentelemetry/core'; import * as types from '@opentelemetry/api'; +import { Resource } from '@opentelemetry/resources'; import { Meter } from '.'; import { DEFAULT_CONFIG, MeterConfig } from './types'; @@ -24,6 +25,7 @@ import { DEFAULT_CONFIG, MeterConfig } from './types'; */ export class MeterProvider implements types.MeterProvider { private readonly _meters: Map = new Map(); + readonly resource: Resource = Resource.createTelemetrySDKResource(); readonly logger: types.Logger; constructor(private _config: MeterConfig = DEFAULT_CONFIG) { diff --git a/packages/opentelemetry-metrics/src/Metric.ts b/packages/opentelemetry-metrics/src/Metric.ts index 179a481828..f98a5a256e 100644 --- a/packages/opentelemetry-metrics/src/Metric.ts +++ b/packages/opentelemetry-metrics/src/Metric.ts @@ -15,6 +15,7 @@ */ import * as types from '@opentelemetry/api'; +import { Resource } from '@opentelemetry/resources'; import { BoundCounter, BaseBoundInstrument, @@ -39,7 +40,8 @@ export abstract class Metric constructor( private readonly _name: string, private readonly _options: MetricOptions, - private readonly _kind: MetricKind + private readonly _kind: MetricKind, + readonly resource: Resource ) { this._monotonic = _options.monotonic; this._disabled = _options.disabled; @@ -108,9 +110,10 @@ export class CounterMetric extends Metric constructor( name: string, options: MetricOptions, - private readonly _batcher: Batcher + private readonly _batcher: Batcher, + resource: Resource ) { - super(name, options, MetricKind.COUNTER); + super(name, options, MetricKind.COUNTER, resource); } protected _makeInstrument(labelSet: types.LabelSet): BoundCounter { return new BoundCounter( @@ -141,9 +144,10 @@ export class MeasureMetric extends Metric constructor( name: string, options: MetricOptions, - private readonly _batcher: Batcher + private readonly _batcher: Batcher, + resource: Resource ) { - super(name, options, MetricKind.MEASURE); + super(name, options, MetricKind.MEASURE, resource); this._absolute = options.absolute !== undefined ? options.absolute : true; // Absolute default is true } @@ -172,9 +176,10 @@ export class ObserverMetric extends Metric constructor( name: string, options: MetricOptions, - private readonly _batcher: Batcher + private readonly _batcher: Batcher, + resource: Resource ) { - super(name, options, MetricKind.OBSERVER); + super(name, options, MetricKind.OBSERVER, resource); } protected _makeInstrument(labelSet: types.LabelSet): BoundObserver { diff --git a/packages/opentelemetry-metrics/src/types.ts b/packages/opentelemetry-metrics/src/types.ts index 31a2a8e486..c444668ce3 100644 --- a/packages/opentelemetry-metrics/src/types.ts +++ b/packages/opentelemetry-metrics/src/types.ts @@ -17,6 +17,7 @@ import { LogLevel } from '@opentelemetry/core'; import { Logger, ValueType } from '@opentelemetry/api'; import { MetricExporter } from './export/types'; +import { Resource } from '@opentelemetry/resources'; /** Options needed for SDK metric creation. */ export interface MetricOptions { @@ -64,6 +65,9 @@ export interface MeterConfig { /** Metric collect interval */ interval?: number; + + /** Resource associated with metric telemetry */ + resource?: Resource; } /** Default Meter configuration. */ diff --git a/packages/opentelemetry-metrics/test/Meter.test.ts b/packages/opentelemetry-metrics/test/Meter.test.ts index 87ade69ce1..f0ed7b161d 100644 --- a/packages/opentelemetry-metrics/test/Meter.test.ts +++ b/packages/opentelemetry-metrics/test/Meter.test.ts @@ -35,6 +35,7 @@ import { ObserverAggregator, } from '../src/export/Aggregator'; import { ValueType } from '@opentelemetry/api'; +import { Resource } from '@opentelemetry/resources'; describe('Meter', () => { let meter: Meter; @@ -88,6 +89,11 @@ describe('Meter', () => { assert.strictEqual(record1.aggregator.value(), 20); }); + it('should return counter with resource', () => { + const counter = meter.createCounter('name') as CounterMetric; + assert.ok(counter.resource instanceof Resource); + }); + describe('.bind()', () => { it('should create a counter instrument', () => { const counter = meter.createCounter('name') as CounterMetric; @@ -275,6 +281,11 @@ describe('Meter', () => { assert.strictEqual((measure as MeasureMetric)['_absolute'], false); }); + it('should return a measure with resource', () => { + const measure = meter.createMeasure('name') as MeasureMetric; + assert.ok(measure.resource instanceof Resource); + }); + describe('names', () => { it('should return no op metric if name is an empty string', () => { const measure = meter.createMeasure(''); @@ -457,6 +468,11 @@ describe('Meter', () => { ensureMetric(metric3); ensureMetric(metric4); }); + + it('should return an observer with resource', () => { + const observer = meter.createObserver('name') as ObserverMetric; + assert.ok(observer.resource instanceof Resource); + }); }); describe('#getMetrics', () => { diff --git a/packages/opentelemetry-node/package.json b/packages/opentelemetry-node/package.json index 767c174e54..6e3f195755 100644 --- a/packages/opentelemetry-node/package.json +++ b/packages/opentelemetry-node/package.json @@ -41,6 +41,7 @@ "access": "public" }, "devDependencies": { + "@opentelemetry/resources": "^0.4.0", "@types/mocha": "^5.2.5", "@types/node": "^12.6.8", "@opentelemetry/scope-base": "^0.4.0", diff --git a/packages/opentelemetry-node/test/NodeTracerProvider.test.ts b/packages/opentelemetry-node/test/NodeTracerProvider.test.ts index c7ffba7565..8a098598f6 100644 --- a/packages/opentelemetry-node/test/NodeTracerProvider.test.ts +++ b/packages/opentelemetry-node/test/NodeTracerProvider.test.ts @@ -24,6 +24,7 @@ import { } from '@opentelemetry/core'; import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks'; import { Span } from '@opentelemetry/tracing'; +import { Resource, TELEMETRY_SDK_RESOURCE } from '@opentelemetry/resources'; import * as assert from 'assert'; import * as path from 'path'; import { ScopeManager } from '../../opentelemetry-scope-base/build/src'; @@ -158,6 +159,19 @@ describe('NodeTracerProvider', () => { assert.ok(span instanceof Span); assert.deepStrictEqual(span.attributes, defaultAttributes); }); + + it('should assign resource to span', () => { + provider = new NodeTracerProvider({ + logger: new NoopLogger(), + }); + const span = provider.getTracer('default').startSpan('my-span') as Span; + assert.ok(span); + assert.ok(span.resource instanceof Resource); + assert.equal( + span.resource.labels[TELEMETRY_SDK_RESOURCE.LANGUAGE], + 'nodejs' + ); + }); }); describe('.getCurrentSpan()', () => { diff --git a/packages/opentelemetry-resources/package.json b/packages/opentelemetry-resources/package.json index 33608a0599..834baefdaa 100644 --- a/packages/opentelemetry-resources/package.json +++ b/packages/opentelemetry-resources/package.json @@ -54,6 +54,7 @@ "typescript": "3.7.2" }, "dependencies": { - "@opentelemetry/api": "^0.4.0" + "@opentelemetry/api": "^0.4.0", + "@opentelemetry/base": "^0.4.0" } } diff --git a/packages/opentelemetry-resources/src/Resource.ts b/packages/opentelemetry-resources/src/Resource.ts index eb35658207..471e7a943a 100644 --- a/packages/opentelemetry-resources/src/Resource.ts +++ b/packages/opentelemetry-resources/src/Resource.ts @@ -14,11 +14,34 @@ * limitations under the License. */ +import { SDK_INFO } from '@opentelemetry/base'; +import { TELEMETRY_SDK_RESOURCE } from './constants'; + /** * A Resource describes the entity for which a signals (metrics or trace) are * collected. */ export class Resource { + static readonly EMPTY = new Resource({}); + + /** + * Returns an empty Resource + */ + static empty(): Resource { + return Resource.EMPTY; + } + + /** + * Returns a Resource that indentifies the SDK in use. + */ + static createTelemetrySDKResource(): Resource { + return new Resource({ + [TELEMETRY_SDK_RESOURCE.LANGUAGE]: SDK_INFO.LANGUAGE, + [TELEMETRY_SDK_RESOURCE.NAME]: SDK_INFO.NAME, + [TELEMETRY_SDK_RESOURCE.VERSION]: SDK_INFO.VERSION, + }); + } + constructor( /** * A dictionary of labels with string keys and values that provide information diff --git a/packages/opentelemetry-resources/src/constants.ts b/packages/opentelemetry-resources/src/constants.ts index 33a5639336..c6423777b3 100644 --- a/packages/opentelemetry-resources/src/constants.ts +++ b/packages/opentelemetry-resources/src/constants.ts @@ -98,15 +98,15 @@ export const K8S_RESOURCE = { }; /** Attributes describing the telemetry library. */ -export const LIBRARY_RESOURCE = { +export const TELEMETRY_SDK_RESOURCE = { /** The name of the telemetry library. */ - NAME: 'library.name', + NAME: 'telemetry.sdk.name', /** The language of telemetry library and of the code instrumented with it. */ - LANGUAGE: 'library.language', + LANGUAGE: 'telemetry.sdk.language', - /** The version string of the library. */ - VERSION: 'library.version', + /** The version string of the telemetry library */ + VERSION: 'telemetry.sdk.version', }; /** Attributes describing a service instance. */ diff --git a/packages/opentelemetry-resources/test/Resource.test.ts b/packages/opentelemetry-resources/test/Resource.test.ts index c15ba1c6cf..4dc63a9995 100644 --- a/packages/opentelemetry-resources/test/Resource.test.ts +++ b/packages/opentelemetry-resources/test/Resource.test.ts @@ -14,8 +14,10 @@ * limitations under the License. */ +import { SDK_INFO } from '@opentelemetry/base'; import * as assert from 'assert'; import { Resource } from '../src/Resource'; +import { assertTelemetrySDKResource } from './util/resource-assertions'; describe('Resource', () => { const resource1 = new Resource({ @@ -86,4 +88,26 @@ describe('Resource', () => { assert.equal(resource.labels['custom.number'], 42); assert.equal(resource.labels['custom.boolean'], true); }); + + describe('.empty()', () => { + it('should return an empty resource', () => { + const resource = Resource.empty(); + assert.equal(Object.entries(resource.labels), 0); + }); + + it('should return the same empty resource', () => { + assert.strictEqual(Resource.empty(), Resource.empty()); + }); + }); + + describe('.createTelemetrySDKResource()', () => { + it('should return a telemetry SDK resource', () => { + const resource = Resource.createTelemetrySDKResource(); + assertTelemetrySDKResource(resource, { + language: SDK_INFO.LANGUAGE, + name: SDK_INFO.NAME, + version: SDK_INFO.VERSION, + }); + }); + }); }); diff --git a/packages/opentelemetry-resources/test/resource-assertions.test.ts b/packages/opentelemetry-resources/test/resource-assertions.test.ts index 4101624054..d3b0e17957 100644 --- a/packages/opentelemetry-resources/test/resource-assertions.test.ts +++ b/packages/opentelemetry-resources/test/resource-assertions.test.ts @@ -14,13 +14,14 @@ * limitations under the License. */ +import { SDK_INFO } from '@opentelemetry/base'; import { Resource } from '../src/Resource'; import { CLOUD_RESOURCE, CONTAINER_RESOURCE, HOST_RESOURCE, K8S_RESOURCE, - LIBRARY_RESOURCE, + TELEMETRY_SDK_RESOURCE, SERVICE_RESOURCE, } from '../src/constants'; import { @@ -28,7 +29,7 @@ import { assertContainerResource, assertHostResource, assertK8sResource, - assertLibraryResource, + assertTelemetrySDKResource, assertServiceResource, } from './util/resource-assertions'; @@ -131,19 +132,23 @@ describe('assertK8sResource', () => { }); }); -describe('assertLibraryResource', () => { - it('requires one library label', () => { - const resource = new Resource({ [LIBRARY_RESOURCE.NAME]: 'opentelemetry' }); - assertLibraryResource(resource, {}); +describe('assertTelemetrySDKResource', () => { + it('uses default validations', () => { + const resource = new Resource({ + [TELEMETRY_SDK_RESOURCE.NAME]: SDK_INFO.NAME, + [TELEMETRY_SDK_RESOURCE.LANGUAGE]: SDK_INFO.LANGUAGE, + [TELEMETRY_SDK_RESOURCE.VERSION]: SDK_INFO.VERSION, + }); + assertTelemetrySDKResource(resource, {}); }); it('validates optional labels', () => { const resource = new Resource({ - [LIBRARY_RESOURCE.NAME]: 'opentelemetry', - [LIBRARY_RESOURCE.LANGUAGE]: 'nodejs', - [LIBRARY_RESOURCE.VERSION]: '0.1.0', + [TELEMETRY_SDK_RESOURCE.NAME]: 'opentelemetry', + [TELEMETRY_SDK_RESOURCE.LANGUAGE]: 'nodejs', + [TELEMETRY_SDK_RESOURCE.VERSION]: '0.1.0', }); - assertLibraryResource(resource, { + assertTelemetrySDKResource(resource, { name: 'opentelemetry', language: 'nodejs', version: '0.1.0', diff --git a/packages/opentelemetry-resources/test/util/resource-assertions.ts b/packages/opentelemetry-resources/test/util/resource-assertions.ts index d748229495..0401a8dd4f 100644 --- a/packages/opentelemetry-resources/test/util/resource-assertions.ts +++ b/packages/opentelemetry-resources/test/util/resource-assertions.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { SDK_INFO } from '@opentelemetry/base'; import * as assert from 'assert'; import { Resource } from '../../src/Resource'; import { @@ -21,9 +22,10 @@ import { CONTAINER_RESOURCE, HOST_RESOURCE, K8S_RESOURCE, - LIBRARY_RESOURCE, + TELEMETRY_SDK_RESOURCE, SERVICE_RESOURCE, } from '../../src/constants'; + /** * Test utility method to validate a cloud resource * @@ -180,12 +182,12 @@ export const assertK8sResource = ( }; /** - * Test utility method to validate a library resource + * Test utility method to validate a telemetry sdk resource * * @param resource the Resource to validate * @param validations validations for the resource labels */ -export const assertLibraryResource = ( +export const assertTelemetrySDKResource = ( resource: Resource, validations: { name?: string; @@ -193,20 +195,26 @@ export const assertLibraryResource = ( version?: string; } ) => { - assertHasOneLabel(LIBRARY_RESOURCE, resource); + const defaults = { + name: SDK_INFO.NAME, + language: SDK_INFO.LANGUAGE, + version: SDK_INFO.VERSION, + }; + validations = { ...defaults, ...validations }; + if (validations.name) assert.strictEqual( - resource.labels[LIBRARY_RESOURCE.NAME], + resource.labels[TELEMETRY_SDK_RESOURCE.NAME], validations.name ); if (validations.language) assert.strictEqual( - resource.labels[LIBRARY_RESOURCE.LANGUAGE], + resource.labels[TELEMETRY_SDK_RESOURCE.LANGUAGE], validations.language ); if (validations.version) assert.strictEqual( - resource.labels[LIBRARY_RESOURCE.VERSION], + resource.labels[TELEMETRY_SDK_RESOURCE.VERSION], validations.version ); }; diff --git a/packages/opentelemetry-tracing/package.json b/packages/opentelemetry-tracing/package.json index e67c54cfb6..4a59b40ba8 100644 --- a/packages/opentelemetry-tracing/package.json +++ b/packages/opentelemetry-tracing/package.json @@ -76,6 +76,7 @@ "@opentelemetry/api": "^0.4.0", "@opentelemetry/base": "^0.4.0", "@opentelemetry/core": "^0.4.0", + "@opentelemetry/resources": "^0.4.0", "@opentelemetry/scope-base": "^0.4.0" } } diff --git a/packages/opentelemetry-tracing/src/BasicTracerProvider.ts b/packages/opentelemetry-tracing/src/BasicTracerProvider.ts index a679200fc5..fe44199e61 100644 --- a/packages/opentelemetry-tracing/src/BasicTracerProvider.ts +++ b/packages/opentelemetry-tracing/src/BasicTracerProvider.ts @@ -21,6 +21,7 @@ import { DEFAULT_CONFIG } from './config'; import { MultiSpanProcessor } from './MultiSpanProcessor'; import { NoopSpanProcessor } from './NoopSpanProcessor'; import { SDKRegistrationConfig, TracerConfig } from './types'; +import { Resource } from '@opentelemetry/resources'; /** * This class represents a basic tracer provider which platform libraries can extend @@ -31,9 +32,11 @@ export class BasicTracerProvider implements api.TracerProvider { activeSpanProcessor = new NoopSpanProcessor(); readonly logger: api.Logger; + readonly resource: Resource; constructor(private _config: TracerConfig = DEFAULT_CONFIG) { this.logger = _config.logger || new ConsoleLogger(_config.logLevel); + this.resource = _config.resource || Resource.createTelemetrySDKResource(); } getTracer(name: string, version = '*', config?: TracerConfig): Tracer { diff --git a/packages/opentelemetry-tracing/src/Span.ts b/packages/opentelemetry-tracing/src/Span.ts index 7292cb43a6..4028564a4d 100644 --- a/packages/opentelemetry-tracing/src/Span.ts +++ b/packages/opentelemetry-tracing/src/Span.ts @@ -21,6 +21,7 @@ import { isTimeInput, timeInputToHrTime, } from '@opentelemetry/core'; +import { Resource } from '@opentelemetry/resources'; import { ReadableSpan } from './export/ReadableSpan'; import { Tracer } from './Tracer'; import { SpanProcessor } from './SpanProcessor'; @@ -39,6 +40,7 @@ export class Span implements types.Span, ReadableSpan { readonly links: types.Link[] = []; readonly events: types.TimedEvent[] = []; readonly startTime: types.HrTime; + readonly resource: Resource; name: string; status: types.Status = { code: types.CanonicalCode.OK, @@ -66,6 +68,7 @@ export class Span implements types.Span, ReadableSpan { this.kind = kind; this.links = links; this.startTime = timeInputToHrTime(startTime); + this.resource = parentTracer.resource; this._logger = parentTracer.logger; this._traceParams = parentTracer.getActiveTraceParams(); this._spanProcessor = parentTracer.getActiveSpanProcessor(); diff --git a/packages/opentelemetry-tracing/src/Tracer.ts b/packages/opentelemetry-tracing/src/Tracer.ts index 15fef62dd8..48871c52ed 100644 --- a/packages/opentelemetry-tracing/src/Tracer.ts +++ b/packages/opentelemetry-tracing/src/Tracer.ts @@ -25,6 +25,7 @@ import { randomTraceId, setActiveSpan, } from '@opentelemetry/core'; +import { Resource } from '@opentelemetry/resources'; import { BasicTracerProvider } from './BasicTracerProvider'; import { DEFAULT_CONFIG } from './config'; import { Span } from './Span'; @@ -38,6 +39,7 @@ export class Tracer implements api.Tracer { private readonly _defaultAttributes: api.Attributes; private readonly _sampler: api.Sampler; private readonly _traceParams: TraceParams; + readonly resource: Resource; readonly logger: api.Logger; /** @@ -51,6 +53,7 @@ export class Tracer implements api.Tracer { this._defaultAttributes = localConfig.defaultAttributes; this._sampler = localConfig.sampler; this._traceParams = localConfig.traceParams; + this.resource = _tracerProvider.resource; this.logger = config.logger || new ConsoleLogger(config.logLevel); } diff --git a/packages/opentelemetry-tracing/src/export/ReadableSpan.ts b/packages/opentelemetry-tracing/src/export/ReadableSpan.ts index 3d461d285d..93bf90ea5d 100644 --- a/packages/opentelemetry-tracing/src/export/ReadableSpan.ts +++ b/packages/opentelemetry-tracing/src/export/ReadableSpan.ts @@ -23,6 +23,7 @@ import { SpanContext, TimedEvent, } from '@opentelemetry/api'; +import { Resource } from '@opentelemetry/resources'; export interface ReadableSpan { readonly name: string; @@ -37,4 +38,5 @@ export interface ReadableSpan { readonly events: TimedEvent[]; readonly duration: HrTime; readonly ended: boolean; + readonly resource: Resource; } diff --git a/packages/opentelemetry-tracing/src/types.ts b/packages/opentelemetry-tracing/src/types.ts index 107f1f80ab..3d4ccb1123 100644 --- a/packages/opentelemetry-tracing/src/types.ts +++ b/packages/opentelemetry-tracing/src/types.ts @@ -22,6 +22,7 @@ import { } from '@opentelemetry/api'; import { LogLevel } from '@opentelemetry/core'; import { ScopeManager } from '@opentelemetry/scope-base'; +import { Resource } from '@opentelemetry/resources'; /** * TracerConfig provides an interface for configuring a Basic Tracer. @@ -48,6 +49,9 @@ export interface TracerConfig { /** Trace Parameters */ traceParams?: TraceParams; + + /** Resource associated with trace telemetry */ + resource?: Resource; } /** diff --git a/packages/opentelemetry-tracing/test/BasicTracerProvider.test.ts b/packages/opentelemetry-tracing/test/BasicTracerProvider.test.ts index 4c79b029d3..5fca2226c7 100644 --- a/packages/opentelemetry-tracing/test/BasicTracerProvider.test.ts +++ b/packages/opentelemetry-tracing/test/BasicTracerProvider.test.ts @@ -24,6 +24,7 @@ import { setExtractedSpanContext, TraceState, } from '@opentelemetry/core'; +import { Resource } from '@opentelemetry/resources'; import { NoopScopeManager, ScopeManager } from '@opentelemetry/scope-base'; import * as assert from 'assert'; import { BasicTracerProvider, Span } from '../src'; @@ -305,6 +306,13 @@ describe('BasicTracerProvider', () => { assert.ok(span instanceof Span); assert.deepStrictEqual(span.attributes, defaultAttributes); }); + + it('should assign a resource', () => { + const tracer = new BasicTracerProvider().getTracer('default'); + const span = tracer.startSpan('my-span') as Span; + assert.ok(span); + assert.ok(span.resource instanceof Resource); + }); }); describe('.getCurrentSpan()', () => { @@ -342,4 +350,11 @@ describe('BasicTracerProvider', () => { return patchedFn(); }); }); + + describe('.resource', () => { + it('should return a Resource', () => { + const tracerProvider = new BasicTracerProvider(); + assert.ok(tracerProvider.resource instanceof Resource); + }); + }); }); diff --git a/packages/opentelemetry-web/package.json b/packages/opentelemetry-web/package.json index bc0a2d8e22..794f41ab99 100644 --- a/packages/opentelemetry-web/package.json +++ b/packages/opentelemetry-web/package.json @@ -43,6 +43,7 @@ }, "devDependencies": { "@babel/core": "^7.6.0", + "@opentelemetry/resources": "^0.4.0", "@opentelemetry/scope-zone": "^0.4.0", "@types/jquery": "^3.3.31", "@types/mocha": "^5.2.5", diff --git a/packages/opentelemetry-web/test/WebTracerProvider.test.ts b/packages/opentelemetry-web/test/WebTracerProvider.test.ts index 248b516969..59e826adbf 100644 --- a/packages/opentelemetry-web/test/WebTracerProvider.test.ts +++ b/packages/opentelemetry-web/test/WebTracerProvider.test.ts @@ -15,10 +15,11 @@ */ import { context } from '@opentelemetry/api'; -import { BasePlugin } from '@opentelemetry/core'; +import { BasePlugin, NoopLogger } from '@opentelemetry/core'; import { ScopeManager } from '@opentelemetry/scope-base'; import { ZoneScopeManager } from '@opentelemetry/scope-zone'; -import { Tracer } from '@opentelemetry/tracing'; +import { Tracer, Span } from '@opentelemetry/tracing'; +import { Resource, TELEMETRY_SDK_RESOURCE } from '@opentelemetry/resources'; import * as assert from 'assert'; import * as sinon from 'sinon'; import { WebTracerConfig } from '../src'; @@ -116,5 +117,20 @@ describe('WebTracerProvider', () => { }); }); }); + + describe('.startSpan()', () => { + it('should assign resource to span', () => { + const provider = new WebTracerProvider({ + logger: new NoopLogger(), + }); + const span = provider.getTracer('default').startSpan('my-span') as Span; + assert.ok(span); + assert.ok(span.resource instanceof Resource); + assert.equal( + span.resource.labels[TELEMETRY_SDK_RESOURCE.LANGUAGE], + 'webjs' + ); + }); + }); }); });