@@ -20,7 +20,6 @@ import * as jaegerTypes from './types';
2020import { NoopLogger } from '@opentelemetry/core' ;
2121import * as types from '@opentelemetry/types' ;
2222import { spanToThrift } from './transform' ;
23- import { unrefTimer } from '@opentelemetry/core' ;
2423
2524/**
2625 * Format and sends span information to Jaeger Exporter.
@@ -29,77 +28,94 @@ export class JaegerExporter implements SpanExporter {
2928 private readonly _logger : types . Logger ;
3029 private readonly _process : jaegerTypes . ThriftProcess ;
3130 private readonly _sender : typeof jaegerTypes . UDPSender ;
32- private readonly _forceFlush : boolean = true ;
33- private readonly _flushTimeout : number ;
34- private _timer : NodeJS . Timeout ;
31+ private readonly _forceFlushOnShutdown : boolean = true ;
32+ private readonly _onShutdownFlushTimeout : number ;
3533
3634 constructor ( config : jaegerTypes . ExporterConfig ) {
3735 this . _logger = config . logger || new NoopLogger ( ) ;
3836 const tags : jaegerTypes . Tag [ ] = config . tags || [ ] ;
39- if ( config . forceFlush !== undefined ) {
40- this . _forceFlush = config . forceFlush ;
41- }
42- this . _flushTimeout = config . flushTimeout || 2000 ;
37+ this . _forceFlushOnShutdown =
38+ typeof config . forceFlush === 'boolean' ? config . forceFlush : true ;
39+ this . _onShutdownFlushTimeout =
40+ typeof config . flushTimeout === 'number' ? config . flushTimeout : 2000 ;
4341
4442 this . _sender = new jaegerTypes . UDPSender ( config ) ;
4543 this . _process = {
4644 serviceName : config . serviceName ,
4745 tags : jaegerTypes . ThriftUtils . getThriftTags ( tags ) ,
4846 } ;
4947 this . _sender . setProcess ( this . _process ) ;
50-
51- const flushInterval = config . flushInterval || 5000 ;
52- this . _timer = setInterval ( this . _flush . bind ( this ) , flushInterval ) ;
53- unrefTimer ( this . _timer ) ;
5448 }
5549
5650 /** Exports a list of spans to Jaeger. */
5751 export (
5852 spans : ReadableSpan [ ] ,
5953 resultCallback : ( result : ExportResult ) => void
6054 ) : void {
55+ if ( spans . length === 0 ) {
56+ return resultCallback ( ExportResult . SUCCESS ) ;
57+ }
6158 this . _logger . debug ( 'Jaeger exporter export' ) ;
62- return this . _sendSpans ( spans , resultCallback ) ;
59+ this . _sendSpans ( spans , resultCallback ) . catch ( err => {
60+ this . _logger . error ( `JaegerExporter failed to export: ${ err } ` ) ;
61+ } ) ;
6362 }
6463
6564 /** Shutdown exporter. */
6665 shutdown ( ) : void {
67- if ( ! this . _forceFlush ) return ;
66+ if ( ! this . _forceFlushOnShutdown ) return ;
6867 // Make an optimistic flush.
6968 this . _flush ( ) ;
7069 // Sleeping x seconds before closing the sender's connection to ensure
7170 // all spans are flushed.
7271 setTimeout ( ( ) => {
7372 this . _sender . close ( ) ;
74- } , this . _flushTimeout ) ;
73+ } , this . _onShutdownFlushTimeout ) ;
7574 }
7675
7776 /** Transform spans and sends to Jaeger service. */
78- private _sendSpans (
77+ private async _sendSpans (
7978 spans : ReadableSpan [ ] ,
8079 done ?: ( result : ExportResult ) => void
8180 ) {
8281 const thriftSpan = spans . map ( span => spanToThrift ( span ) ) ;
8382 for ( const span of thriftSpan ) {
84- this . _sender . append ( span , ( numSpans : number , err ?: string ) => {
85- if ( err ) {
86- // @todo : decide whether to break out the loop on first error.
87- this . _logger . error ( `failed to append span: ${ err } ` ) ;
88- if ( done ) return done ( ExportResult . FAILED_NOT_RETRYABLE ) ;
89- }
90- } ) ;
83+ try {
84+ await this . _append ( span ) ;
85+ } catch ( err ) {
86+ this . _logger . error ( `failed to append span: ${ err } ` ) ;
87+ // TODO right now we break out on first error, is that desirable?
88+ if ( done ) return done ( ExportResult . FAILED_NOT_RETRYABLE ) ;
89+ }
9190 }
92- // @todo : We should wait for all the callbacks of the append calls to
93- // complete before it calls done with success.
9491 this . _logger . debug ( 'successful append for : %s' , thriftSpan . length ) ;
92+
93+ // Flush all spans on each export. No-op if span buffer is empty
94+ await this . _flush ( ) ;
95+
9596 if ( done ) return done ( ExportResult . SUCCESS ) ;
9697 }
9798
98- private _flush ( ) : void {
99- this . _sender . flush ( ( numSpans : number , err ?: string ) => {
100- if ( err ) {
101- this . _logger . error ( `failed to flush ${ numSpans } spans: ${ err } ` ) ;
102- }
99+ private async _append ( span : jaegerTypes . ThriftSpan ) : Promise < number > {
100+ return new Promise ( ( resolve , reject ) => {
101+ this . _sender . append ( span , ( count : number , err ?: string ) => {
102+ if ( err ) {
103+ return reject ( new Error ( err ) ) ;
104+ }
105+ resolve ( count ) ;
106+ } ) ;
107+ } ) ;
108+ }
109+
110+ private async _flush ( ) : Promise < void > {
111+ await new Promise ( ( resolve , reject ) => {
112+ this . _sender . flush ( ( _count : number , err ?: string ) => {
113+ if ( err ) {
114+ return reject ( new Error ( err ) ) ;
115+ }
116+ this . _logger . debug ( 'successful flush for %s spans' , _count ) ;
117+ resolve ( ) ;
118+ } ) ;
103119 } ) ;
104120 }
105121}
0 commit comments