From 4947c2d6a4d33343194879c3b3eb18040eb9683b Mon Sep 17 00:00:00 2001 From: David Luna Date: Fri, 4 Oct 2024 10:42:35 +0200 Subject: [PATCH] chore(exporter-zipkin): remove usages of Span constructor (#5030) Co-authored-by: Marc Pichler --- CHANGELOG.md | 1 + .../test/common/transform.test.ts | 229 +++++++++--------- 2 files changed, 109 insertions(+), 121 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e42a90f7c..7ad9ff304d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ For semantic convention package changes, see the [semconv CHANGELOG](packages/se [#4992](https://github.com/open-telemetry/opentelemetry-js/pull/4992) * refactor(sdk-metrics): replace `MetricsAttributes` with `Attributes` [#5021](https://github.com/open-telemetry/opentelemetry-js/pull/5021) @david-luna * refactor(instrumentation-http): replace `SpanAttributes` and `MetricsAttributes` with `Attributes` [#5023](https://github.com/open-telemetry/opentelemetry-js/pull/5023) @david-luna +* chore(exporter-zipkin): remove usages of Span constructor [#5030](https://github.com/open-telemetry/opentelemetry-js/pull/5030) @david-luna * test(instrumentation-http): remove usages of `new Span` in tests [#5035](https://github.com/open-telemetry/opentelemetry-js/pull/5035) @david-luna ## 1.26.0 diff --git a/packages/opentelemetry-exporter-zipkin/test/common/transform.test.ts b/packages/opentelemetry-exporter-zipkin/test/common/transform.test.ts index 223257c45a..0c78dbbcf8 100644 --- a/packages/opentelemetry-exporter-zipkin/test/common/transform.test.ts +++ b/packages/opentelemetry-exporter-zipkin/test/common/transform.test.ts @@ -16,17 +16,16 @@ import * as api from '@opentelemetry/api'; import { + hrTime, hrTimeDuration, hrTimeToMicroseconds, + millisToHrTime, VERSION, } from '@opentelemetry/core'; -import { Resource } from '@opentelemetry/resources'; -import { BasicTracerProvider, Span } from '@opentelemetry/sdk-trace-base'; +import { IResource } from '@opentelemetry/resources'; +import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; -import { - SEMRESATTRS_SERVICE_NAME, - SEMRESATTRS_TELEMETRY_SDK_LANGUAGE, -} from '@opentelemetry/semantic-conventions'; +import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions'; import { defaultStatusCodeTagName, defaultStatusErrorTagName, @@ -35,43 +34,69 @@ import { _toZipkinTags, } from '../../src/transform'; import * as zipkinTypes from '../../src/types'; -const tracer = new BasicTracerProvider({ - resource: Resource.default().merge( - new Resource({ - [SEMRESATTRS_SERVICE_NAME]: 'zipkin-test', - cost: '112.12', - service: 'ui', - version: '1', - }) - ), -}).getTracer('default'); - -const language = tracer.resource.attributes[SEMRESATTRS_TELEMETRY_SDK_LANGUAGE]; +const resource = { + attributes: { + [SEMRESATTRS_SERVICE_NAME]: 'zipkin-test', + cost: '112.12', + service: 'ui', + version: '1', + 'telemetry.sdk.language': 'nodejs', + 'telemetry.sdk.name': 'opentelemetry', + 'telemetry.sdk.version': VERSION, + }, +} as unknown as IResource; const parentId = '5c1c63257de34c67'; const spanContext: api.SpanContext = { traceId: 'd4cda95b652f4a1592b449d5929fda1b', spanId: '6e0c63257de34c92', traceFlags: api.TraceFlags.SAMPLED, }; +const currentTime = Date.now(); +const durationMs = 10; +const startTime = hrTime(currentTime - durationMs); +const endTime = hrTime(currentTime); +const duration = millisToHrTime(durationMs); + +function getSpan(options: Partial): ReadableSpan { + const span = { + name: options.name || 'my-span', + kind: typeof options.kind === 'number' ? options.kind : api.SpanKind.SERVER, + startTime: options.startTime || startTime, + endTime: options.endTime || endTime, + duration: options.duration || duration, + spanContext: () => spanContext, + parentSpanId: options.parentSpanId || parentId, + attributes: options.attributes || {}, + events: options.events || [], + status: options.status || { code: api.SpanStatusCode.UNSET }, + resource, + } as ReadableSpan; + + // Expicit `undefined` properties in options will be removed from the + // result span. + Object.keys(options).forEach(k => { + if (options[k as keyof ReadableSpan] === undefined) { + delete span[k as keyof ReadableSpan]; + } + }); + + return span; +} describe('transform', () => { describe('toZipkinSpan', () => { it('should convert an OpenTelemetry span to a Zipkin span', () => { - const span = new Span( - tracer, - api.ROOT_CONTEXT, - 'my-span', - spanContext, - api.SpanKind.SERVER, - parentId - ); - span.setAttributes({ - key1: 'value1', - key2: 'value2', + const span = getSpan({ + attributes: { key1: 'value1', key2: 'value2' }, + events: [ + { + name: 'my-event', + time: hrTime(Date.now() + 5), + attributes: { key3: 'value 3' }, + }, + ], }); - span.addEvent('my-event', { key3: 'value3' }); - span.end(); const zipkinSpan = toZipkinSpan( span, @@ -103,7 +128,7 @@ describe('transform', () => { cost: '112.12', service: 'ui', version: '1', - 'telemetry.sdk.language': language, + 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': VERSION, }, @@ -112,14 +137,9 @@ describe('transform', () => { }); }); it("should skip parentSpanId if doesn't exist", () => { - const span = new Span( - tracer, - api.ROOT_CONTEXT, - 'my-span', - spanContext, - api.SpanKind.SERVER - ); - span.end(); + const span = getSpan({ + parentSpanId: undefined, + }); const zipkinSpan = toZipkinSpan( span, @@ -144,7 +164,7 @@ describe('transform', () => { cost: '112.12', service: 'ui', version: '1', - 'telemetry.sdk.language': language, + 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': VERSION, }, @@ -163,15 +183,10 @@ describe('transform', () => { it(`should map OpenTelemetry SpanKind ${ api.SpanKind[item.ot] } to Zipkin ${item.zipkin}`, () => { - const span = new Span( - tracer, - api.ROOT_CONTEXT, - 'my-span', - spanContext, - item.ot - ); - span.end(); - + const span = getSpan({ + kind: item.ot, + parentSpanId: undefined, + }); const zipkinSpan = toZipkinSpan( span, 'my-service', @@ -195,7 +210,7 @@ describe('transform', () => { cost: '112.12', service: 'ui', version: '1', - 'telemetry.sdk.language': language, + 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': VERSION, }, @@ -208,17 +223,12 @@ describe('transform', () => { describe('_toZipkinTags', () => { it('should convert OpenTelemetry attributes to Zipkin tags', () => { - const span = new Span( - tracer, - api.ROOT_CONTEXT, - 'my-span', - spanContext, - api.SpanKind.SERVER, - parentId - ); - span.setAttributes({ - key1: 'value1', - key2: 'value2', + const span = getSpan({ + parentSpanId: undefined, + attributes: { + key1: 'value1', + key2: 'value2', + }, }); const tags: zipkinTypes.Tags = _toZipkinTags( span, @@ -230,7 +240,7 @@ describe('transform', () => { key1: 'value1', key2: 'value2', [SEMRESATTRS_SERVICE_NAME]: 'zipkin-test', - 'telemetry.sdk.language': language, + 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': VERSION, cost: '112.12', @@ -239,21 +249,14 @@ describe('transform', () => { }); }); it('should map OpenTelemetry constructor attributes to a Zipkin tag', () => { - const span = new Span( - tracer, - api.ROOT_CONTEXT, - 'my-span', - spanContext, - api.SpanKind.SERVER, - parentId, - [], - undefined, - undefined, - { + const span = getSpan({ + parentSpanId: undefined, + attributes: { key1: 'value1', key2: 'value2', - } - ); + }, + }); + const tags: zipkinTypes.Tags = _toZipkinTags( span, defaultStatusCodeTagName, @@ -264,7 +267,7 @@ describe('transform', () => { key1: 'value1', key2: 'value2', [SEMRESATTRS_SERVICE_NAME]: 'zipkin-test', - 'telemetry.sdk.language': language, + 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': VERSION, cost: '112.12', @@ -273,21 +276,13 @@ describe('transform', () => { }); }); it('should map OpenTelemetry SpanStatus.code to a Zipkin tag', () => { - const span = new Span( - tracer, - api.ROOT_CONTEXT, - 'my-span', - spanContext, - api.SpanKind.SERVER, - parentId - ); - const status: api.SpanStatus = { - code: api.SpanStatusCode.ERROR, - }; - span.setStatus(status); - span.setAttributes({ - key1: 'value1', - key2: 'value2', + const span = getSpan({ + parentSpanId: undefined, + attributes: { + key1: 'value1', + key2: 'value2', + }, + status: { code: api.SpanStatusCode.ERROR }, }); const tags: zipkinTypes.Tags = _toZipkinTags( span, @@ -300,7 +295,7 @@ describe('transform', () => { key2: 'value2', [defaultStatusCodeTagName]: 'ERROR', [SEMRESATTRS_SERVICE_NAME]: 'zipkin-test', - 'telemetry.sdk.language': language, + 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': VERSION, cost: '112.12', @@ -309,22 +304,13 @@ describe('transform', () => { }); }); it('should map OpenTelemetry SpanStatus.message to a Zipkin tag', () => { - const span = new Span( - tracer, - api.ROOT_CONTEXT, - 'my-span', - spanContext, - api.SpanKind.SERVER, - parentId - ); - const status: api.SpanStatus = { - code: api.SpanStatusCode.ERROR, - message: 'my-message', - }; - span.setStatus(status); - span.setAttributes({ - key1: 'value1', - key2: 'value2', + const span = getSpan({ + parentSpanId: undefined, + attributes: { + key1: 'value1', + key2: 'value2', + }, + status: { code: api.SpanStatusCode.ERROR, message: 'my-message' }, }); const tags: zipkinTypes.Tags = _toZipkinTags( span, @@ -336,9 +322,9 @@ describe('transform', () => { key1: 'value1', key2: 'value2', [defaultStatusCodeTagName]: 'ERROR', - [defaultStatusErrorTagName]: status.message, + [defaultStatusErrorTagName]: 'my-message', [SEMRESATTRS_SERVICE_NAME]: 'zipkin-test', - 'telemetry.sdk.language': language, + 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': VERSION, cost: '112.12', @@ -350,16 +336,17 @@ describe('transform', () => { describe('_toZipkinAnnotations', () => { it('should convert OpenTelemetry events to Zipkin annotations', () => { - const span = new Span( - tracer, - api.ROOT_CONTEXT, - 'my-span', - spanContext, - api.SpanKind.SERVER, - parentId - ); - span.addEvent('my-event1'); - span.addEvent('my-event2', { key1: 'value1' }); + const span = getSpan({ + parentSpanId: undefined, + events: [ + { name: 'my-event1', time: hrTime(Date.now()) }, + { + name: 'my-event2', + time: hrTime(Date.now()), + attributes: { key1: 'value1' }, + }, + ], + }); const annotations = _toZipkinAnnotations(span.events); assert.deepStrictEqual(annotations, [