///|
/// Observe package for M3-TRACE-REPLAY.

///|
pub fn package_id() -> String {
  "lockwire/observe"
}

///|
pub(all) struct MetricPoint {
  name : String
  vtime : @core.VTime
  value : Int64
  unit : String
} derive(Eq, Debug)

///|
pub fn MetricPoint::make(
  name~ : String,
  vtime~ : @core.VTime,
  value~ : Int64,
  unit~ : String,
) -> MetricPoint {
  { name, vtime, value, unit }
}

///|
pub(open) trait TraceSink {
  fn write(Self, @trace.TraceEvent) -> Unit
}

///|
pub(open) trait MetricSink {
  fn emit(Self, MetricPoint) -> Unit
}

///|
pub(open) trait Probe {
  fn on_trace(Self, @trace.TraceEvent) -> Unit
  fn on_metric(Self, MetricPoint) -> Unit
}

///|
pub(all) struct TimelineProbe {
  events : Array[@trace.TraceEvent]
  metrics : Array[MetricPoint]
} derive(Debug)

///|
pub fn TimelineProbe::new() -> TimelineProbe {
  { events: [], metrics: [] }
}

///|
pub fn TimelineProbe::event_count(self : TimelineProbe) -> Int {
  self.events.length()
}

///|
pub fn TimelineProbe::metric_count(self : TimelineProbe) -> Int {
  self.metrics.length()
}

///|
pub fn TimelineProbe::record_trace(
  self : TimelineProbe,
  event : @trace.TraceEvent,
) -> Unit {
  self.events.push(event)
}

///|
pub fn TimelineProbe::record_metric(
  self : TimelineProbe,
  metric : MetricPoint,
) -> Unit {
  self.metrics.push(metric)
}

///|
pub impl TraceSink for TimelineProbe with fn write(self, event) {
  self.record_trace(event)
}

///|
pub impl MetricSink for TimelineProbe with fn emit(self, metric) {
  self.record_metric(metric)
}

///|
pub impl Probe for TimelineProbe with fn on_trace(self, event) {
  self.write(event)
}

///|
pub impl Probe for TimelineProbe with fn on_metric(self, metric) {
  self.emit(metric)
}