diff --git a/packages/opentelemetry-exporter-jaeger/package.json b/packages/opentelemetry-exporter-jaeger/package.json index 2ac156ce11..914f1544a5 100644 --- a/packages/opentelemetry-exporter-jaeger/package.json +++ b/packages/opentelemetry-exporter-jaeger/package.json @@ -45,12 +45,14 @@ "@opentelemetry/resources": "^0.11.0", "@types/mocha": "8.0.2", "@types/node": "14.0.27", + "@types/sinon": "^9.0.8", "codecov": "3.7.2", "gts": "2.0.2", "mocha": "7.2.0", "nock": "12.0.3", "nyc": "15.1.0", "rimraf": "3.0.2", + "sinon": "^9.2.0", "ts-mocha": "7.0.0", "ts-node": "9.0.0", "typescript": "3.9.7" diff --git a/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts b/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts index 1018b78126..b74b1cd2d4 100644 --- a/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts +++ b/packages/opentelemetry-exporter-jaeger/test/jaeger.test.ts @@ -15,8 +15,14 @@ */ import * as assert from 'assert'; +import * as sinon from 'sinon'; import { JaegerExporter } from '../src'; -import { ExportResult, NoopLogger } from '@opentelemetry/core'; +import { + ExportResult, + loggingErrorHandler, + NoopLogger, + setGlobalErrorHandler, +} from '@opentelemetry/core'; import * as api from '@opentelemetry/api'; import { ThriftProcess } from '../src/types'; import { ReadableSpan } from '@opentelemetry/tracing'; @@ -106,7 +112,33 @@ describe('JaegerExporter', () => { }); describe('export', () => { + const readableSpan: ReadableSpan = { + name: 'my-span1', + kind: api.SpanKind.CLIENT, + spanContext: { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.NONE, + }, + startTime: [1566156729, 709], + endTime: [1566156731, 709], + ended: true, + status: { + code: api.CanonicalCode.DATA_LOSS, + }, + attributes: {}, + links: [], + events: [], + duration: [32, 800000000], + resource: Resource.empty(), + instrumentationLibrary: { + name: 'default', + version: '0.0.1', + }, + }; + let exporter: JaegerExporter; + beforeEach(() => { exporter = new JaegerExporter({ serviceName: 'opentelemetry', @@ -124,32 +156,6 @@ describe('JaegerExporter', () => { }); it('should send spans to Jaeger backend and return with Success', () => { - const spanContext = { - traceId: 'd4cda95b652f4a1592b449d5929fda1b', - spanId: '6e0c63257de34c92', - traceFlags: TraceFlags.NONE, - }; - const readableSpan: ReadableSpan = { - name: 'my-span1', - kind: api.SpanKind.CLIENT, - spanContext, - startTime: [1566156729, 709], - endTime: [1566156731, 709], - ended: true, - status: { - code: api.CanonicalCode.DATA_LOSS, - }, - attributes: {}, - links: [], - events: [], - duration: [32, 800000000], - resource: Resource.empty(), - instrumentationLibrary: { - name: 'default', - version: '0.0.1', - }, - }; - exporter.export([readableSpan], (result: ExportResult) => { assert.strictEqual(result, ExportResult.SUCCESS); }); @@ -172,32 +178,33 @@ describe('JaegerExporter', () => { endpoint: mockedEndpoint, }); assert.strictEqual(exporter['_sender'].constructor.name, 'HTTPSender'); - const spanContext = { - traceId: 'd4cda95b652f4a1592b449d5929fda1b', - spanId: '6e0c63257de34c92', - traceFlags: TraceFlags.NONE, - }; - const readableSpan: ReadableSpan = { - name: 'my-span1', - kind: api.SpanKind.CLIENT, - spanContext, - startTime: [1566156729, 709], - endTime: [1566156731, 709], - ended: true, - status: { - code: api.CanonicalCode.DATA_LOSS, - }, - attributes: {}, - links: [], - events: [], - duration: [32, 800000000], - resource: Resource.empty(), - instrumentationLibrary: { - name: 'default', - version: '0.0.1', - }, - }; exporter.export([readableSpan], () => {}); }); + + it('should call globalErrorHandler on error', () => { + nock.cleanAll(); + const errorHandlerSpy = sinon.spy(); + setGlobalErrorHandler(errorHandlerSpy); + const expectedError = new Error('whoops'); + const mockedEndpoint = 'http://testendpoint'; + const scope = nock(mockedEndpoint) + .post('/') + .replyWithError(expectedError); + const exporter = new JaegerExporter({ + serviceName: 'opentelemetry', + endpoint: mockedEndpoint, + }); + + exporter.export([readableSpan], () => { + scope.done(); + assert.strictEqual(errorHandlerSpy.callCount, 1); + + const [[error]] = errorHandlerSpy.args; + assert.strictEqual(error, expectedError); + }); + + // reset global error handler + setGlobalErrorHandler(loggingErrorHandler()); + }); }); }); diff --git a/packages/opentelemetry-exporter-zipkin/test/browser/zipkin.test.ts b/packages/opentelemetry-exporter-zipkin/test/browser/zipkin.test.ts index c47e69fa57..0ed5ca6b0c 100644 --- a/packages/opentelemetry-exporter-zipkin/test/browser/zipkin.test.ts +++ b/packages/opentelemetry-exporter-zipkin/test/browser/zipkin.test.ts @@ -14,7 +14,11 @@ * limitations under the License. */ -import { NoopLogger } from '@opentelemetry/core'; +import { + NoopLogger, + setGlobalErrorHandler, + loggingErrorHandler, +} from '@opentelemetry/core'; import { ReadableSpan } from '@opentelemetry/tracing'; import * as assert from 'assert'; import * as sinon from 'sinon'; @@ -132,6 +136,25 @@ describe('Zipkin Exporter - web', () => { done(); }); }); + + it('should call globalErrorHandler on error', () => { + const errorHandlerSpy = sinon.spy(); + setGlobalErrorHandler(errorHandlerSpy); + + zipkinExporter.export(spans, () => { + const [[error]] = errorHandlerSpy.args; + assert.strictEqual(errorHandlerSpy.callCount, 1); + assert.ok(error.message.includes('Zipkin request error')); + + //reset global error handler + setGlobalErrorHandler(loggingErrorHandler()); + }); + + setTimeout(() => { + const request = server.requests[0]; + request.respond(400); + }); + }); }); describe('when "sendBeacon" is NOT available', () => { @@ -152,6 +175,25 @@ describe('Zipkin Exporter - web', () => { done(); }); }); + + it('should call globalErrorHandler on error', () => { + const errorHandlerSpy = sinon.spy(); + setGlobalErrorHandler(errorHandlerSpy); + + zipkinExporter.export(spans, () => { + const [[error]] = errorHandlerSpy.args; + assert.strictEqual(errorHandlerSpy.callCount, 1); + assert.ok(error.message.includes('sendBeacon - cannot send')); + + //reset global error handler + setGlobalErrorHandler(loggingErrorHandler()); + }); + + setTimeout(() => { + const request = server.requests[0]; + request.respond(400); + }); + }); }); }); }); diff --git a/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts b/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts index df2604f532..298cd04f26 100644 --- a/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts +++ b/packages/opentelemetry-exporter-zipkin/test/node/zipkin.test.ts @@ -16,11 +16,14 @@ import * as assert from 'assert'; import * as nock from 'nock'; +import * as sinon from 'sinon'; import { ReadableSpan } from '@opentelemetry/tracing'; import { ExportResult, NoopLogger, hrTimeToMicroseconds, + setGlobalErrorHandler, + loggingErrorHandler, } from '@opentelemetry/core'; import * as api from '@opentelemetry/api'; import { Resource } from '@opentelemetry/resources'; @@ -463,6 +466,30 @@ describe('Zipkin Exporter - node', () => { assert.equal(exporter['_serviceName'], resource_service_name); }); }); + + it('should call globalErrorHandler on error', () => { + const errorHandlerSpy = sinon.spy(); + setGlobalErrorHandler(errorHandlerSpy); + const expectedError = new Error('Whoops'); + const scope = nock('http://localhost:9411') + .post('/api/v2/spans') + .replyWithError(expectedError); + + const exporter = new ZipkinExporter({ + serviceName: 'my-service', + logger: new NoopLogger(), + }); + + exporter.export([getReadableSpan()], (result: ExportResult) => { + scope.done(); + }); + + const [[error]] = errorHandlerSpy.args; + + assert.strictEqual(errorHandlerSpy.callCount, 1); + assert.strictEqual(error, expectedError); + setGlobalErrorHandler(loggingErrorHandler()); + }); }); });