diff --git a/packages/opentelemetry-exporter-zipkin/src/zipkin.ts b/packages/opentelemetry-exporter-zipkin/src/zipkin.ts index ea8be143b6..ee44926c8a 100644 --- a/packages/opentelemetry-exporter-zipkin/src/zipkin.ts +++ b/packages/opentelemetry-exporter-zipkin/src/zipkin.ts @@ -59,7 +59,10 @@ export class ZipkinExporter implements SpanExporter { resultCallback: (result: ExportResult) => void ) { if (typeof this._serviceName !== 'string') { - this._serviceName = this.DEFAULT_SERVICE_NAME; + this._serviceName = String( + spans[0].resource.attributes[SERVICE_RESOURCE.NAME] || + this.DEFAULT_SERVICE_NAME + ); } this._logger.debug('Zipkin exporter export'); if (this._isShutdown) { diff --git a/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts b/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts index aa2e357b71..422ba8a879 100644 --- a/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts +++ b/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts @@ -482,6 +482,183 @@ describe('Zipkin Exporter - node', () => { }); }); }); + + it('should set serviceName per-span if resource has one', () => { + const resource_service_name = 'resource_service_name'; + const resource_service_name_prime = 'resource_service_name_prime'; + + let requestBody: any; + const scope = nock('http://localhost:9411') + .post('/api/v2/spans', body => { + requestBody = body; + return true; + }) + .replyWithError(new Error('My Socket Error')); + + const parentSpanId = '5c1c63257de34c67'; + const startTime = 1566156729709; + const duration = 2000; + + const span1: ReadableSpan = { + name: 'my-span', + kind: api.SpanKind.INTERNAL, + parentSpanId, + spanContext: { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.NONE, + }, + startTime: [startTime, 0], + endTime: [startTime + duration, 0], + ended: true, + duration: [duration, 0], + status: { + code: api.StatusCode.OK, + }, + attributes: { + key1: 'value1', + key2: 'value2', + }, + links: [], + events: [ + { + name: 'my-event', + time: [startTime + 10, 0], + attributes: { key3: 'value3' }, + }, + ], + resource: new Resource({ + [SERVICE_RESOURCE.NAME]: resource_service_name, + }), + instrumentationLibrary: { name: 'default', version: '0.0.1' }, + }; + const span2: ReadableSpan = { + name: 'my-span', + kind: api.SpanKind.SERVER, + spanContext: { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.NONE, + }, + startTime: [startTime, 0], + endTime: [startTime + duration, 0], + ended: true, + duration: [duration, 0], + status: { + code: api.StatusCode.OK, + }, + attributes: {}, + links: [], + events: [], + resource: new Resource({ + [SERVICE_RESOURCE.NAME]: resource_service_name_prime, + }), + instrumentationLibrary: { name: 'default', version: '0.0.1' }, + }; + + const exporter = new ZipkinExporter({}); + + exporter.export([span1, span2], (result: ExportResult) => { + requestBody; + scope.done(); + assert.equal( + requestBody[0].localEndpoint.serviceName, + resource_service_name + ); + assert.equal( + requestBody[1].localEndpoint.serviceName, + resource_service_name_prime + ); + }); + }); + + it('should set serviceName per-span if span has attribute', () => { + const span_service_name = 'span_service_name'; + const span_service_name_prime = 'span_service_name_prime'; + + let requestBody: any; + const scope = nock('http://localhost:9411') + .post('/api/v2/spans', body => { + requestBody = body; + return true; + }) + .replyWithError(new Error('My Socket Error')); + + const parentSpanId = '5c1c63257de34c67'; + const startTime = 1566156729709; + const duration = 2000; + + const span1: ReadableSpan = { + name: 'my-span', + kind: api.SpanKind.INTERNAL, + parentSpanId, + spanContext: { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.NONE, + }, + startTime: [startTime, 0], + endTime: [startTime + duration, 0], + ended: true, + duration: [duration, 0], + status: { + code: api.StatusCode.OK, + }, + attributes: { + key1: 'value1', + key2: 'value2', + [SERVICE_RESOURCE.NAME]: span_service_name, + }, + links: [], + events: [ + { + name: 'my-event', + time: [startTime + 10, 0], + attributes: { key3: 'value3' }, + }, + ], + resource: Resource.empty(), + instrumentationLibrary: { name: 'default', version: '0.0.1' }, + }; + const span2: ReadableSpan = { + name: 'my-span', + kind: api.SpanKind.SERVER, + spanContext: { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.NONE, + }, + startTime: [startTime, 0], + endTime: [startTime + duration, 0], + ended: true, + duration: [duration, 0], + status: { + code: api.StatusCode.OK, + }, + attributes: { + [SERVICE_RESOURCE.NAME]: span_service_name_prime, + }, + links: [], + events: [], + resource: Resource.empty(), + instrumentationLibrary: { name: 'default', version: '0.0.1' }, + }; + + const exporter = new ZipkinExporter({}); + + exporter.export([span1, span2], (result: ExportResult) => { + requestBody; + scope.done(); + assert.equal( + requestBody[0].localEndpoint.serviceName, + span_service_name + ); + assert.equal( + requestBody[1].localEndpoint.serviceName, + span_service_name_prime + ); + }); + }); }); describe('shutdown', () => {