Show the resolved default settings path in --help; add Prometheus/OpenMetrics polling
--settings-path's help text now names the actual resolved default path (computed once via LazyLock) instead of only describing where to look for one. Also adds an optional --metrics-url flag that polls a Prometheus/ OpenMetrics-compatible endpoint on an interval, pushing samples straight into a metric's bucket (bypassing log-line regex matching) so they're queryable via PromQL/dashboards alongside log-derived metrics. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
18c2d72d22
commit
12381545c8
@@ -23,6 +23,15 @@ pub struct IngestedLine {
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
/// One sample scraped from a Prometheus/OpenMetrics endpoint, pushed straight into a metric's bucket
|
||||
/// without going through log-line regex matching — see `crate::ingest::run_metrics_poll`.
|
||||
pub struct MetricSample {
|
||||
pub metric_name: String,
|
||||
pub labels: BTreeMap<String, String>,
|
||||
pub value: f64,
|
||||
pub timestamp: Timestamp,
|
||||
}
|
||||
|
||||
/// Also the request body for `POST /api/params` — `Deserialize` is derived directly here rather than adding a separate DTO, since the shape already matches.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct DeclareParamRequest {
|
||||
@@ -69,6 +78,7 @@ pub enum EngineQuery {
|
||||
#[allow(dead_code)]
|
||||
pub enum EngineMessage {
|
||||
Ingest(IngestedLine),
|
||||
IngestMetricSample(MetricSample),
|
||||
DeclareParam {
|
||||
request: DeclareParamRequest,
|
||||
respond_to: oneshot::Sender<Result<(), String>>,
|
||||
@@ -114,6 +124,8 @@ pub async fn run(mut rx: mpsc::Receiver<EngineMessage>, settings: SettingsHandle
|
||||
let mut index: BTreeMap<IndexKey, DataValue> = BTreeMap::new();
|
||||
let mut max_logs: Option<usize> = None;
|
||||
let mut log_count: usize = 0;
|
||||
// Its own counter, independent of log `sequence` — scraped samples aren't tied to any ingested line.
|
||||
let mut metric_sample_sequence: u64 = 0;
|
||||
// Per-rule rolling windows/seen-value sets, keyed by rule id; lives only as long as this loop (no restart persistence).
|
||||
let mut alert_states: HashMap<String, AlertRuntimeState> = HashMap::new();
|
||||
|
||||
@@ -139,6 +151,22 @@ pub async fn run(mut rx: mpsc::Receiver<EngineMessage>, settings: SettingsHandle
|
||||
tokio::spawn(alerts::deliver_for_rule(rule.name, message, ntfy_topic.clone(), ntfy_server.clone()));
|
||||
}
|
||||
}
|
||||
EngineMessage::IngestMetricSample(sample) => {
|
||||
let labels = sample
|
||||
.labels
|
||||
.into_iter()
|
||||
.map(|(name, value)| (name, MetricPrimitive::String(value)))
|
||||
.collect();
|
||||
push_bucket_value(
|
||||
&mut index,
|
||||
&sample.metric_name,
|
||||
labels,
|
||||
metric_sample_sequence,
|
||||
sample.timestamp,
|
||||
MetricPrimitive::Number(Number::Float(sample.value)),
|
||||
);
|
||||
metric_sample_sequence += 1;
|
||||
}
|
||||
EngineMessage::SetMaxLogs(new_max) => {
|
||||
max_logs = new_max;
|
||||
evict_excess_logs(&mut index, &mut log_count, max_logs);
|
||||
|
||||
Reference in New Issue
Block a user