rsocket-rpc-tracing
Version:
RSocket JavaScript RPC Tracing Support
118 lines (101 loc) • 2.42 kB
Flow
import {Single, IFutureSubscriber} from 'rsocket-flowable/build/Single';
import {Tracer, Span, SpanContext, FORMAT_TEXT_MAP} from 'opentracing';
export function createSpanSingle(
single: Single<T>,
tracer: Tracer,
name: string,
context?: SpanContext | Span,
metadata?: Object,
...tags: Object
) {
return new Single(subscriber => {
const spanSubscriber = new SpanSingleSubscriber(
subscriber,
tracer,
name,
context,
metadata,
...tags,
);
single.subscribe(spanSubscriber);
});
}
class SpanSingleSubscriber implements IFutureSubscriber<T> {
_span: Span;
_subscriber: IFutureSubscriber<T>;
_tracer: Tracer;
_cancel: () => void;
constructor(
subscriber: IFutureSubscriber<T>,
tracer: Tracer,
name: string,
context?: SpanContext | Span,
metadata?: Object,
...tags: Object
) {
this._subscriber = subscriber;
this._tracer = tracer;
let options = {};
if (context) {
options.childOf = context;
}
if (tags) {
const finalTags = {};
tags.forEach(tag => {
Object.keys(tag).forEach(key => {
finalTags[key] = tag[key];
});
});
options.tags = finalTags;
}
//Not supported at this time.
// if (references) {
// options.references = references;
// }
//
options.startTime = Date.now() * 1000;
this._span = this._tracer.startSpan(name, options);
this._tracer.inject(
this._span.context(),
FORMAT_TEXT_MAP,
metadata === undefined || metadata === null ? {} : metadata,
);
}
cleanup() {
this._span.finish();
}
onSubscribe(cancel?: () => void) {
this._cancel = cancel;
this._span.log('onSubscribe', timeInMicros());
this._subscriber.onSubscribe(() => {
this.cancel();
});
}
cancel() {
try {
this._span.log('cancel', timeInMicros());
this._cancel && this._cancel();
} finally {
this.cleanup();
}
}
onError(error: Error) {
try {
this._span.log('onError', timeInMicros());
this._subscriber.onError(error);
} finally {
this.cleanup();
}
}
onComplete(value: T) {
try {
this._span.log('onComplete', timeInMicros());
this._subscriber.onComplete(value);
} finally {
this.cleanup();
}
}
}
function timeInMicros() {
return Date.now() * 1000 /*microseconds*/;
}