opentelemetry-js icon indicating copy to clipboard operation
opentelemetry-js copied to clipboard

Customizable Clock API

Open GasimGasimzada opened this issue 5 years ago • 1 comments
trafficstars

Is your feature request related to a problem? Please describe.

We are currently using opentracing (not opentelemetry) and we are looking at migrating to opentelemetry for both server and client-side tracing. In our current implementation, we have a custom implementation for setting the clock (start and finish times) that is based on performance.now() and a custom time origin that is coming from server. The reason for it is that, the browser can have different time (not necessarily timezone but the actual clock) than the server and we do not have control over on how the end user's machine handles time. So, sending a custom time origin that starts in server and adding it to the relative time in the browser allows us to easily synchronize this time.

Describe the solution you'd like

Currently, OpenTelemetry JS has an internal clock api that is called for setting times internally. An easy solution for this would be exposing these clock functions with a specified interface. Here is an example gist:

interface ClockInterface {
  absNow(): HrTime
}

// Provided by OpenTelemetry
class BrowserPerformanceClock implements ClockInterface {

  timeOrigin() {
     let timeOrigin = performance.timeOrigin;
     if (typeof timeOrigin !== 'number') {
      const perf: TimeOriginLegacy = (performance as unknown) as TimeOriginLegacy;
      timeOrigin = perf.timing && perf.timing.fetchStart;
    }
    return timeOrigin;
  }
  absNow() {
    // this function is just a utilize to make it easier to convert a number
    // to HRTime
    const [seconds, nanos] = convertToHrTime(timeOrigin() + performance.now());
    return [seconds, nanos];
  }
}

class CustomPerformanceClock implements ClockInterface {
  absNow() {
    // this function is just a utilize to make it easier to convert a number
    // to HRTime
    const [seconds, nanos] = convertToHrTime(window.myConfig.tracing.startTime + performance.now());
    return [seconds, nanos];
  }
}

The clock can be passed to the Tracer from the Provider (default being PerformanceClock). Then, the Span can use this for getting startTime:

class Span { 
  ...

  constructor(tracer, ..., startTime) {
     // ...
     if (!startTime) startTime = tracer.clock.absNow();
     // ...
   }

If anyone needs to provide a custom clock (maybe something different in the node provider or browser provider), they can do so easily:

const tracerProvider = new WebTracerProvider({
  clock: new CustomPerformanceClock(); // default is BrowserPerformanceClock
});

Describe alternatives you've considered

We have tried alternatives with things such as clock skewing (this is provided by our vendor implementation of opentracing) but none of them helped us and due to that reason based on end-user's machine, the start time in the client can be lower than start time in server. This results in spans being ordered in correctly or not collected at all.

GasimGasimzada avatar Nov 05 '20 13:11 GasimGasimzada

I have an even more extreme version of this problem: I am attempting to log events in a simulation environment where I am testing with a non-realtime simulation clock.

It would help a lot for me to be able to customize the emitted telemetry to use this non-realtime clock so I can produce realistic spans and events from my simulation environment.

psigen avatar Oct 30 '22 17:10 psigen