use obs_proto::obs::v1::{ObsEnvelope, Severity, Tier};
use crate::{observer::observer, self_event::self_event};
pub(crate) fn emit_registry_initialized(schema_count: u64, arrow_assembly_ns: u64) {
let mut env = base("obs.runtime.v1.ObsRegistryInitialized", Severity::Debug);
env.labels
.insert("schema_count".to_string(), schema_count.to_string());
env.labels.insert(
"arrow_assembly_ns".to_string(),
arrow_assembly_ns.to_string(),
);
emit_self(env);
}
pub(crate) fn emit_config_reloaded(config_hash: u64) {
let mut env = base("obs.runtime.v1.ObsConfigReloaded", Severity::Info);
env.labels
.insert("config_hash".to_string(), format!("{config_hash:016x}"));
emit_self(env);
}
pub(crate) fn emit_config_reload_failed(reason: &str) {
let mut env = base("obs.runtime.v1.ObsConfigReloadFailed", Severity::Warn);
env.labels
.insert("reason".to_string(), truncate(reason, 512));
emit_self(env);
}
#[allow(dead_code)]
pub(crate) fn emit_schema_unknown(sink: &str, full_name: &str) {
let mut env = base("obs.runtime.v1.ObsSchemaUnknown", Severity::Debug);
env.labels.insert("sink".to_string(), sink.to_string());
env.labels
.insert("full_name".to_string(), full_name.to_string());
emit_self(env);
}
pub(crate) fn emit_audit_spooled(full_name: &str) {
let mut env = base("obs.runtime.v1.ObsAuditSpooled", Severity::Warn);
env.labels
.insert("full_name".to_string(), full_name.to_string());
emit_self(env);
}
pub(crate) fn emit_audit_spool_failed(reason: &str) {
let mut env = base("obs.runtime.v1.ObsAuditSpoolFailed", Severity::Fatal);
env.labels
.insert("reason".to_string(), truncate(reason, 512));
emit_self(env);
}
pub(crate) fn emit_sink_dropped(tier: &str, reason: &str) {
let mut env = base("obs.runtime.v1.ObsSinkDropped", Severity::Warn);
env.labels.insert("tier".to_string(), tier.to_string());
env.labels.insert("reason".to_string(), reason.to_string());
emit_self(env);
}
pub fn emit_callsite_hash_collision_pub(hash: u64, first: &str, second: &str) {
let mut env = base("obs.runtime.v1.ObsCallsiteHashCollision", Severity::Warn);
env.labels
.insert("schema_hash".to_string(), format!("{hash:016x}"));
env.labels.insert("first".to_string(), first.to_string());
env.labels.insert("second".to_string(), second.to_string());
emit_self(env);
}
pub fn emit_span_pair_orphaned_pub(full_name: &str) {
let mut env = base("obs.runtime.v1.ObsSpanPairOrphaned", Severity::Debug);
env.labels
.insert("full_name".to_string(), full_name.to_string());
emit_self(env);
}
pub fn emit_label_cardinality_high_pub(full_name: &str, label_key: &str, estimated_distinct: u64) {
let mut env = base("obs.runtime.v1.ObsLabelCardinalityHigh", Severity::Warn);
env.labels
.insert("full_name".to_string(), full_name.to_string());
env.labels
.insert("label_key".to_string(), label_key.to_string());
env.labels.insert(
"estimated_distinct".to_string(),
estimated_distinct.to_string(),
);
emit_self(env);
}
pub(crate) fn emit_oversized_dropped(full_name: &str, size_bytes: u64) {
let mut env = base("obs.runtime.v1.ObsOversizedDropped", Severity::Warn);
env.labels
.insert("full_name".to_string(), full_name.to_string());
env.labels
.insert("size_bytes".to_string(), size_bytes.to_string());
emit_self(env);
}
pub(crate) fn emit_oversized_label_dropped(full_name: &str, label_name: &str, size_bytes: u64) {
let mut env = base("obs.runtime.v1.ObsOversizedDropped", Severity::Warn);
env.labels
.insert("full_name".to_string(), full_name.to_string());
env.labels
.insert("label_name".to_string(), label_name.to_string());
env.labels
.insert("size_bytes".to_string(), size_bytes.to_string());
env.labels.insert("reason".to_string(), "label".to_string());
emit_self(env);
}
pub fn emit_oversized_label_dropped_pub(field: &str, original_size: u64, capped_size: u64) {
let mut env = base("obs.runtime.v1.ObsLabelOversized", Severity::Warn);
env.labels.insert("field".to_string(), field.to_string());
env.labels
.insert("original_size".to_string(), original_size.to_string());
env.labels
.insert("capped_size".to_string(), capped_size.to_string());
emit_self(env);
}
fn base(full_name: &str, sev: Severity) -> ObsEnvelope {
self_event(full_name, Tier::Log, sev)
}
fn truncate(s: &str, max: usize) -> String {
if s.len() <= max {
return s.to_string();
}
let mut out = s.chars().take(max).collect::<String>();
out.push('…');
out
}
fn emit_self(env: ObsEnvelope) {
observer().emit_envelope(env);
}