use obs_proto::obs::v1::Severity;
use crate::{
callsite::ObsCallsite,
envelope::{EventSchema, build_envelope_at},
observer::{enter_emit_envelope, observer},
};
pub trait Emit: EventSchema + Sized {
fn emit(self) {
emit_inner::<Self>(&self, Self::DEFAULT_SEV)
}
fn emit_at(self, sev: Severity) {
emit_inner::<Self>(&self, sev)
}
}
impl<E: EventSchema + Sized> Emit for E {}
fn emit_inner<E: EventSchema>(event: &E, sev: Severity) {
let callsite = ObsCallsite::new(
E::FULL_NAME,
E::DEFAULT_SEV,
module_path!(),
file!(),
line!(),
);
emit_one::<E>(&callsite, event, sev);
}
#[doc(hidden)]
#[inline]
pub fn emit_with_callsite<E: EventSchema>(
callsite: &'static ObsCallsite,
event: &E,
sev: Severity,
) {
emit_one::<E>(callsite, event, sev)
}
#[inline]
fn emit_one<E: EventSchema>(callsite: &ObsCallsite, event: &E, sev: Severity) {
use crate::callsite::{EnabledOutcome, Interest};
let o = observer();
let cur_gen = o.generation();
let outcome = callsite.enabled(cur_gen);
let permitted = match outcome {
EnabledOutcome::AlwaysOn => true,
EnabledOutcome::Off => false,
EnabledOutcome::SometimesOn => o.enabled(callsite),
EnabledOutcome::ReProbe => {
let allowed = o.enabled(callsite);
callsite.cache(
if allowed {
Interest::Always
} else {
Interest::Never
},
cur_gen,
);
allowed
}
};
if !permitted {
return;
}
let mut env = build_envelope_at::<E>(callsite, event, sev);
event.project(&mut env);
enter_emit_envelope(&o, env);
}