From 969925d9b6a1c58af12cb2e7a728a57273b1d6eb Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Thu, 27 Jun 2019 17:43:54 -0700 Subject: [PATCH] Resource API (#59) * Resource: Add merge function * Add merge operation on Resource * use shorthand syntax --- packages/opentelemetry-core/package.json | 4 +- packages/opentelemetry-core/src/index.ts | 2 + .../src/resources/Resource.ts | 32 ++++++++ .../opentelemetry-core/test/resource.test.ts | 78 +++++++++++++++++++ packages/opentelemetry-types/src/index.ts | 1 + .../src/resources/Resource.ts | 15 +++- 6 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 packages/opentelemetry-core/src/resources/Resource.ts create mode 100644 packages/opentelemetry-core/test/resource.test.ts diff --git a/packages/opentelemetry-core/package.json b/packages/opentelemetry-core/package.json index 394f0165e64..9cdda8c95a4 100644 --- a/packages/opentelemetry-core/package.json +++ b/packages/opentelemetry-core/package.json @@ -49,5 +49,7 @@ "ts-node": "^8.0.0", "typescript": "^3.4.5" }, - "dependencies": {} + "dependencies": { + "@opentelemetry/types": "^0.0.1" + } } diff --git a/packages/opentelemetry-core/src/index.ts b/packages/opentelemetry-core/src/index.ts index 6acf3afa4e0..ec4b4d63350 100644 --- a/packages/opentelemetry-core/src/index.ts +++ b/packages/opentelemetry-core/src/index.ts @@ -13,3 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +export * from './resources/Resource'; diff --git a/packages/opentelemetry-core/src/resources/Resource.ts b/packages/opentelemetry-core/src/resources/Resource.ts new file mode 100644 index 00000000000..2b58e4b0a84 --- /dev/null +++ b/packages/opentelemetry-core/src/resources/Resource.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2019, 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 types from '@opentelemetry/types'; + +export class Resource implements types.Resource { + constructor( + // TODO: Consider to add check/validation on labels. + readonly labels: { [key: string]: string } + ) {} + + merge(other: types.Resource | null): types.Resource { + if (!other || !Object.keys(other.labels).length) return this; + + // Labels from resource overwrite labels from other resource. + const mergedLabels = Object.assign({}, other.labels, this.labels); + return new Resource(mergedLabels); + } +} diff --git a/packages/opentelemetry-core/test/resource.test.ts b/packages/opentelemetry-core/test/resource.test.ts new file mode 100644 index 00000000000..7e4fe87dbab --- /dev/null +++ b/packages/opentelemetry-core/test/resource.test.ts @@ -0,0 +1,78 @@ +/** + * Copyright 2019, 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 { Resource } from '../src/resources/Resource'; + +describe('Resource', () => { + const resource1 = new Resource({ + 'k8s.io/container/name': 'c1', + 'k8s.io/namespace/name': 'default', + 'k8s.io/pod/name': 'pod-xyz-123', + }); + const resource2 = new Resource({ + 'k8s.io/zone': 'zone1', + 'k8s.io/location': 'location', + }); + const resource3 = new Resource({ + 'k8s.io/container/name': 'c2', + 'k8s.io/location': 'location1', + }); + const emptyResource = new Resource({}); + + it('should return merged resource', () => { + const expectedResource = new Resource({ + 'k8s.io/container/name': 'c1', + 'k8s.io/namespace/name': 'default', + 'k8s.io/pod/name': 'pod-xyz-123', + 'k8s.io/zone': 'zone1', + 'k8s.io/location': 'location', + }); + const actualResource = resource1.merge(resource2); + assert.strictEqual(Object.keys(actualResource.labels).length, 5); + assert.deepStrictEqual(actualResource, expectedResource); + }); + + it('should return merged resource when collision in labels', () => { + const expectedResource = new Resource({ + 'k8s.io/container/name': 'c1', + 'k8s.io/namespace/name': 'default', + 'k8s.io/pod/name': 'pod-xyz-123', + 'k8s.io/location': 'location1', + }); + const actualResource = resource1.merge(resource3); + assert.strictEqual(Object.keys(actualResource.labels).length, 4); + assert.deepStrictEqual(actualResource, expectedResource); + }); + + it('should return merged resource when first resource is empty', () => { + const actualResource = emptyResource.merge(resource2); + assert.strictEqual(Object.keys(actualResource.labels).length, 2); + assert.deepStrictEqual(actualResource, resource2); + }); + + it('should return merged resource when other resource is empty', () => { + const actualResource = resource1.merge(emptyResource); + assert.strictEqual(Object.keys(actualResource.labels).length, 3); + assert.deepStrictEqual(actualResource, resource1); + }); + + it('should return merged resource when other resource is null', () => { + const actualResource = resource1.merge(null); + assert.strictEqual(Object.keys(actualResource.labels).length, 3); + assert.deepStrictEqual(actualResource, resource1); + }); +}); diff --git a/packages/opentelemetry-types/src/index.ts b/packages/opentelemetry-types/src/index.ts index 9f68cbb66f7..17c558c2f46 100644 --- a/packages/opentelemetry-types/src/index.ts +++ b/packages/opentelemetry-types/src/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +export * from './resources/Resource'; export * from './trace/span'; export * from './trace/span_context'; export * from './trace/span_kind'; diff --git a/packages/opentelemetry-types/src/resources/Resource.ts b/packages/opentelemetry-types/src/resources/Resource.ts index ca325d395bf..a4ef363f409 100644 --- a/packages/opentelemetry-types/src/resources/Resource.ts +++ b/packages/opentelemetry-types/src/resources/Resource.ts @@ -14,11 +14,24 @@ * limitations under the License. */ -/** A Resource describes the entity for which a signal was collected. */ +/** + * A Resource describes the entity for which a signals (metrics or trace) are + * collected. + */ export interface Resource { /** * A dictionary of labels with string keys and values that provide information * about the entity. */ readonly labels: { [key: string]: string }; + + /** + * Returns a new, merged {@link Resource} by merging the current Resource + * with the other Resource. In case of a collision, current Resource takes + * precedence. + * + * @param other the Resource that will be merged with this. + * @returns the newly merged Resource. + */ + merge(other: Resource | null): Resource; }