pub use crate::dispatcher::set_sink;
pub fn try_record_counter(name: &str, labels: &[(&str, &str)], delta: i64) {
if reject_invalid_ident(name) {
return;
}
if !crate::emit_buffer::is_replaying() && crate::gate::drop_counter(name, labels) {
return;
}
if crate::emit_buffer::push_counter(name, labels, delta) {
return;
}
crate::dispatcher::enter_dispatch_counter(name, |sink| {
sink.record_counter(name, labels, delta)
});
}
pub fn try_record_gauge(name: &str, labels: &[(&str, &str)], value: f64) {
if reject_invalid_ident(name) {
return;
}
if !crate::emit_buffer::is_replaying() && crate::gate::drop_gauge(name, labels, value) {
return;
}
if crate::emit_buffer::push_gauge(name, labels, value) {
return;
}
crate::dispatcher::enter_dispatch_gauge(name, |sink| sink.record_gauge(name, labels, value));
}
pub fn try_log_event(table: &str, fields: &serde_json::Value) {
if reject_invalid_ident(table) {
return;
}
if !crate::emit_buffer::is_replaying() && crate::gate::drop_event(table) {
return;
}
if crate::emit_buffer::push_event(table, fields) {
return;
}
crate::dispatcher::enter_dispatch_event(table, |sink| sink.log_event(table, fields));
}
pub fn try_record_counter_now(name: &str, labels: &[(&str, &str)], delta: i64) {
if reject_invalid_ident(name) {
return;
}
if crate::gate::drop_counter(name, labels) {
return;
}
crate::dispatcher::enter_dispatch_counter(name, |sink| {
sink.record_counter(name, labels, delta)
});
}
pub fn try_record_gauge_now(name: &str, labels: &[(&str, &str)], value: f64) {
if reject_invalid_ident(name) {
return;
}
if crate::gate::drop_gauge(name, labels, value) {
return;
}
crate::dispatcher::enter_dispatch_gauge(name, |sink| sink.record_gauge(name, labels, value));
}
pub fn try_log_event_now(table: &str, fields: &serde_json::Value) {
if reject_invalid_ident(table) {
return;
}
if crate::gate::drop_event(table) {
return;
}
crate::dispatcher::enter_dispatch_event(table, |sink| sink.log_event(table, fields));
}
fn reject_invalid_ident(name: &str) -> bool {
if crate::validate::is_valid_spectra_ident(name) {
return false;
}
tracing::debug!(
operation = "emit",
reason = "invalid_ident",
"dropping emit with invalid metric/table name"
);
true
}
pub fn try_record_counter_at(
name: &str,
labels: &[(&str, &str)],
delta: i64,
ts: chrono::DateTime<chrono::Utc>,
) {
crate::emit_buffer::with_emit_ts(ts, || try_record_counter_now(name, labels, delta));
}
pub fn try_record_gauge_at(
name: &str,
labels: &[(&str, &str)],
value: f64,
ts: chrono::DateTime<chrono::Utc>,
) {
crate::emit_buffer::with_emit_ts(ts, || try_record_gauge_now(name, labels, value));
}
pub fn try_log_event_at(
table: &str,
fields: &serde_json::Value,
ts: chrono::DateTime<chrono::Utc>,
) {
crate::emit_buffer::with_emit_ts(ts, || try_log_event_now(table, fields));
}
#[cfg(test)]
mod tests {
use super::*;
use crate::sinks::NoOpSink;
use crate::{RecordingSink, SpectraSink};
use std::sync::Arc;
#[tokio::test]
async fn drops_emit_with_invalid_metric_name() {
let _g = crate::test_util::GLOBAL_TEST_LOCK.lock().await;
crate::test_util::reset_gate_disabled();
let recording = Arc::new(RecordingSink::new());
set_sink(Arc::clone(&recording) as Arc<dyn SpectraSink>);
try_record_counter("evil; DROP", &[], 1);
assert!(recording
.recorded_counters_matching("evil; DROP", &[])
.is_empty());
try_record_counter("cache_hits", &[], 1);
assert_eq!(
recording
.recorded_counters_matching("cache_hits", &[])
.len(),
1
);
set_sink(Arc::new(NoOpSink));
crate::config::reset_config_for_test();
}
}