use std::time::{Duration, Instant};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TransformSignal {
Logs,
Traces,
Metrics,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum TransformPhase {
ProtobufDecode,
JsonDecode,
JsonlDecode,
RowCount,
BuilderInit,
ResourceLogsBuild,
ResourceSpansBuild,
ResourceMetricsBuild,
ResourceContextBuild,
ResourceAttributesJson,
ScopeLogsBuild,
ScopeSpansBuild,
ScopeMetricsBuild,
ScopeContextBuild,
ScopeAttributesJson,
LogRecordBuild,
SpanBuild,
MetricBuild,
ArrowAppend,
BodyAppend,
ResourceAttributesAppend,
ScopeAttributesAppend,
LogAttributesJson,
SpanAttributesJson,
MetricAttributesJson,
EventsJson,
LinksJson,
ExemplarsJson,
MetricArrayJson,
MetricsCapacity,
ArrowFinalize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum TransformCounter {
OutputRows,
ResourceContextDuplicateHit,
ResourceContextDuplicateMiss,
ScopeContextDuplicateHit,
ScopeContextDuplicateMiss,
ResourceAttributesRowCopies,
ResourceAttributesRowCopyBytes,
ScopeAttributesRowCopies,
ScopeAttributesRowCopyBytes,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TransformPhaseTiming {
pub signal: TransformSignal,
pub phase: TransformPhase,
pub elapsed: Duration,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TransformCounterValue {
pub signal: TransformSignal,
pub counter: TransformCounter,
pub value: u64,
}
pub trait TransformObserver {
fn on_phase(&mut self, timing: TransformPhaseTiming);
fn on_counter(&mut self, _counter: TransformCounterValue) {}
}
pub(crate) fn observe_phase(
observer: &mut Option<&mut dyn TransformObserver>,
signal: TransformSignal,
phase: TransformPhase,
elapsed: Duration,
) {
if let Some(observer) = observer.as_deref_mut() {
observer.on_phase(TransformPhaseTiming {
signal,
phase,
elapsed,
});
}
}
pub(crate) fn observe_counter(
observer: &mut Option<&mut dyn TransformObserver>,
signal: TransformSignal,
counter: TransformCounter,
value: u64,
) {
if value == 0 {
return;
}
if let Some(observer) = observer.as_deref_mut() {
observer.on_counter(TransformCounterValue {
signal,
counter,
value,
});
}
}
pub(crate) fn phase_start(observer: &Option<&mut dyn TransformObserver>) -> Option<Instant> {
observer.is_some().then(Instant::now)
}
pub(crate) fn finish_phase(
observer: &mut Option<&mut dyn TransformObserver>,
signal: TransformSignal,
phase: TransformPhase,
start: Option<Instant>,
) {
if let Some(start) = start {
observe_phase(observer, signal, phase, start.elapsed());
}
}
pub(crate) fn measure_phase<T, F>(
observer: &mut Option<&mut dyn TransformObserver>,
signal: TransformSignal,
phase: TransformPhase,
f: F,
) -> T
where
F: FnOnce() -> T,
{
if observer.is_some() {
let start = Instant::now();
let value = f();
observe_phase(observer, signal, phase, start.elapsed());
value
} else {
f()
}
}
pub(crate) fn measure_result<T, E, F>(
observer: &mut Option<&mut dyn TransformObserver>,
signal: TransformSignal,
phase: TransformPhase,
f: F,
) -> std::result::Result<T, E>
where
F: FnOnce() -> std::result::Result<T, E>,
{
if observer.is_some() {
let start = Instant::now();
let value = f();
observe_phase(observer, signal, phase, start.elapsed());
value
} else {
f()
}
}