-
Couldn't load subscription status.
- Fork 1.4k
Description
I'm trying to integrate a timer metric that should track the duration of a effect in my system so I can visualize it in Grafana.
The code to create a timer is Metric is this:
/**
* Creates a timer metric, based on a histogram, which keeps track of
* durations in the specified unit of time (milliseconds, seconds, etc.). The
* unit of time will automatically be added to the metric as a tag
* ("time_unit: milliseconds").
*/
def timer(
name: String,
chronoUnit: ChronoUnit
): Metric[MetricKeyType.Histogram, Duration, MetricState.Histogram] = {
val boundaries = Histogram.Boundaries.exponential(1.0, 2.0, 100)
val base = histogram(name, boundaries).tagged(MetricLabel("time_unit", chronoUnit.toString.toLowerCase()))
base.contramap[Duration] { (duration: Duration) =>
duration.get(chronoUnit).toDouble
}
}I want to create a timer that is tracking the durations in milliseconds, so naturally I am creating it like this:
private type M = Metric[MetricKeyType.Histogram, zio.Duration, MetricState.Histogram]
val loadingMDS: M = Metric.timer("rtd_loading_mds", ChronoUnit.MILLIS) The problem now is the line
duration.get(chronoUnit).toDoublebecause duration.get(chronounit) does not convert the duration to the requested unit but it does try to access a field in the duration.
//-----------------------------------------------------------------------
/**
* Gets the value of the requested unit.
* <p>
* This returns a value for each of the two supported units,
* {@link ChronoUnit#SECONDS SECONDS} and {@link ChronoUnit#NANOS NANOS}.
* All other units throw an exception.
*
* @param unit the {@code TemporalUnit} for which to return the value
* @return the long value of the unit
* @throws DateTimeException if the unit is not supported
* @throws UnsupportedTemporalTypeException if the unit is not supported
*/
@Override
public long get(TemporalUnit unit) {
if (unit == SECONDS) {
return seconds;
} else if (unit == NANOS) {
return nanos;
} else {
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
}So any usage of Metric.timer(name, chronounit) with a ChronoUnit different from ChronoUnit.SECONDS or ChronoUnit.NANOS will throw the UnsupportedTemporalTypeException resulting in errors like this:
[info] {"@timestamp":"2023-01-13T16:32:23.335+01:00","@version":"1","message":"Fiber zio-fiber-352 did not handle an error","logger_name":"com.acme.myproject.masterdata.rtd.controllers.hlvis.RunRTDNextController","thread_name":"ZScheduler-Worker-15","level":"DEBUG","level_value":10000,
"stack_trace":"zio.FiberFailure: Unsupported unit: Millis
\tat java.base/java.time.Duration.get(Duration.java:552)
\tat com.acme.myproject.mypackage.modul0_load.LoadDataServiceLive.loadData(LoadDataService.scala:41)
\tat com.acme.myproject.mypackage.modul0_load.LoadDataServiceLive.loadData(LoadDataService.scala:38)
\tat com.acme.myproject.mypackage.RTDOrchestrationLive.runRTD.result(RTDOrchestration.scala:170)
\tat com.acme.myproject.mypackage.RTDOrchestrationLive.runRTD.result(RTDOrchestration.scala:171)
\tat com.acme.myproject.mypackage.RTDOrchestrationLive.runRTD.result(RTDOrchestration.scala:172)
\tat com.acme.myproject.mypackage.RTDOrchestrationLive.runRTD.result(RTDOrchestration.scala:173)
\tat com.acme.myproject.mypackage.RTDOrchestrationLive.runRTD.result(RTDOrchestration.scala:168)
\tat com.acme.myproject.mypackage.RTDOrchestrationLive.runRTD.resultStream(RTDOrchestration.scala:308)
\tat com.acme.myproject.mypackage.RTDOrchestrationLive.runRTD(RTDOrchestration.scala:149)
Caused by: java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Millis
\tat java.base/java.time.Duration.get(Duration.java:552)
\tat zio.metrics.Metric$.$anonfun$timer$1(Metric.scala:539)
\tat zio.metrics.Metric$.$anonfun$timer$1$adapted(Metric.scala:538)
\tat zio.metrics.Metric$$anon$1$$anon$2.update(Metric.scala:73)
\tat zio.metrics.Metric$$anon$13.$anonfun$apply$8(Metric.scala:265)
\tat zio.ZIO.$anonfun$map$1(ZIO.scala:959)
\tat zio.internal.FiberRuntime.runLoop(FiberRuntime.scala:1127)
\tat zio.internal.FiberRuntime.evaluateEffect(FiberRuntime.scala:385)
\tat zio.internal.FiberRuntime.evaluateMessageWhileSuspended(FiberRuntime.scala:508)
\tat zio.internal.FiberRuntime.drainQueueOnCurrentThread(FiberRuntime.scala:225)
\tat zio.internal.FiberRuntime.run(FiberRuntime.scala:138)
\tat zio.internal.ZScheduler$$anon$4.run(ZScheduler.scala:476)
",
I'm calling the metric like this:
for {
...
_ <- myEffect @@ loadingMDS.trackDuration
...