Skip to content

Commit

Permalink
Fix Fetch and XHR instrumentation to use anchored clock
Browse files Browse the repository at this point in the history
  • Loading branch information
gregolsen committed Oct 12, 2022
1 parent ef6fcdc commit 19d855e
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 9 deletions.
6 changes: 5 additions & 1 deletion api/src/trace/NonRecordingSpan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import { Exception } from '../common/Exception';
import { TimeInput } from '../common/Time';
import { HrTime, TimeInput } from '../common/Time';
import { SpanAttributes } from './attributes';
import { INVALID_SPAN_CONTEXT } from './invalid-span-constants';
import { Span } from './span';
Expand Down Expand Up @@ -72,4 +72,8 @@ export class NonRecordingSpan implements Span {

// By default does nothing
recordException(_exception: Exception, _time?: TimeInput): void {}

currentTime(): HrTime {
return [0, 0];
}
}
8 changes: 7 additions & 1 deletion api/src/trace/span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import { Exception } from '../common/Exception';
import { TimeInput } from '../common/Time';
import { HrTime, TimeInput } from '../common/Time';
import { SpanAttributes, SpanAttributeValue } from './attributes';
import { SpanContext } from './span_context';
import { SpanStatus } from './status';
Expand Down Expand Up @@ -126,4 +126,10 @@ export interface Span {
* use the current time.
*/
recordException(exception: Exception, time?: TimeInput): void;

/**
* Returns current time based on the anchored clock.
* Used to snapshot time when the span has to be ended later.
*/
currentTime(): HrTime;
}
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export class FetchInstrumentation extends InstrumentationBase<Promise<Response>>
spanData: SpanData,
response: FetchResponse
) {
const endTime = core.hrTime();
const endTime = span.currentTime();
this._addFinalSpanAttributes(span, response);

setTimeout(() => {
Expand Down Expand Up @@ -308,7 +308,8 @@ export class FetchInstrumentation extends InstrumentationBase<Promise<Response>>
if (!createdSpan) {
return original.apply(this, args);
}
const spanData = plugin._prepareSpanData(url);
const startTime = createdSpan.currentTime();
const spanData = plugin._prepareSpanData(url, startTime);

function endSpanOnError(span: api.Span, error: FetchError) {
plugin._applyAttributesAfterFetch(span, options, error);
Expand Down Expand Up @@ -427,8 +428,7 @@ export class FetchInstrumentation extends InstrumentationBase<Promise<Response>>
* resources
* @param spanUrl
*/
private _prepareSpanData(spanUrl: string): SpanData {
const startTime = core.hrTime();
private _prepareSpanData(spanUrl: string, startTime: api.HrTime): SpanData {
const entries: PerformanceResourceTiming[] = [];
if (typeof PerformanceObserver !== 'function') {
return { entries, startTime, spanUrl };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
InstrumentationConfig,
safeExecuteInTheMiddle,
} from '@opentelemetry/instrumentation';
import { hrTime, isUrlIgnored, otperformance } from '@opentelemetry/core';
import { isUrlIgnored, otperformance } from '@opentelemetry/core';
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
import {
addSpanNetworkEvents,
Expand Down Expand Up @@ -431,7 +431,7 @@ export class XMLHttpRequestInstrumentation extends InstrumentationBase<XMLHttpRe
if (xhrMem.span) {
plugin._applyAttributesAfterXHR(xhrMem.span, xhr);
}
const endTime = hrTime();
const endTime = xhrMem.span?.currentTime();

// the timeout is needed as observer doesn't have yet information
// when event "load" is called. Also the time may differ depends on
Expand Down Expand Up @@ -486,7 +486,7 @@ export class XMLHttpRequestInstrumentation extends InstrumentationBase<XMLHttpRe
api.trace.setSpan(api.context.active(), currentSpan),
() => {
plugin._tasksCount++;
xhrMem.sendStartTime = hrTime();
xhrMem.sendStartTime = currentSpan.currentTime();
currentSpan.addEvent(EventNames.METHOD_SEND);

this.addEventListener('abort', onAbort);
Expand Down
4 changes: 4 additions & 0 deletions packages/opentelemetry-sdk-trace-base/src/Span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ export class Span implements api.Span, ReadableSpan {
return this._ended;
}

currentTime(): api.HrTime {
return timeInputToHrTime(this._clock.now());
}

private _isSpanEnded(): boolean {
if (this._ended) {
api.diag.warn(`Can not execute the operation on ended Span {traceId: ${this._spanContext.traceId}, spanId: ${this._spanContext.spanId}}`);
Expand Down

0 comments on commit 19d855e

Please sign in to comment.