ironpost_core/
metrics.rs

1//! 메트릭 상수 및 설명 등록
2//!
3//! 모든 Prometheus 메트릭의 이름과 설명을 중앙에서 정의합니다.
4//! 각 모듈은 이 상수를 사용하여 `metrics::counter!()`, `metrics::gauge!()`,
5//! `metrics::histogram!()` 매크로를 호출합니다.
6//!
7//! # 네이밍 컨벤션
8//!
9//! - 접두어: `ironpost_`
10//! - 모듈명: `ebpf_`, `log_pipeline_`, `container_guard_`, `sbom_scanner_`
11//! - 접미어: `_total` (counter), `_seconds` (histogram/latency), 없음 (gauge)
12//!
13//! # 사용 예시
14//!
15//! ```ignore
16//! use ironpost_core::metrics;
17//! use metrics::counter;
18//!
19//! counter!(ironpost_core::metrics::LOG_PIPELINE_LOGS_PROCESSED_TOTAL).increment(1);
20//! ```
21
22// ─── 레이블 키 상수 ────────────────────────────────────────────────
23
24/// 프로토콜 레이블 키 (TCP, UDP, ICMP, other)
25pub const LABEL_PROTOCOL: &str = "protocol";
26
27/// 심각도 레이블 키 (info, low, medium, high, critical)
28pub const LABEL_SEVERITY: &str = "severity";
29
30/// 모듈 레이블 키
31pub const LABEL_MODULE: &str = "module";
32
33/// 파서 형식 레이블 키 (syslog, json)
34pub const LABEL_PARSER_FORMAT: &str = "format";
35
36/// 격리 액션 레이블 키 (disconnect, pause, stop)
37pub const LABEL_ACTION: &str = "action";
38
39/// 에코시스템 레이블 키 (cargo, npm)
40pub const LABEL_ECOSYSTEM: &str = "ecosystem";
41
42/// 결과 레이블 키 (success, failure)
43pub const LABEL_RESULT: &str = "result";
44
45// ─── eBPF Engine 메트릭 ────────────────────────────────────────────
46
47/// eBPF: 처리된 전체 패킷 수 (counter)
48pub const EBPF_PACKETS_TOTAL: &str = "ironpost_ebpf_packets_total";
49
50/// eBPF: 차단된 패킷 수 (counter)
51pub const EBPF_PACKETS_BLOCKED_TOTAL: &str = "ironpost_ebpf_packets_blocked_total";
52
53/// eBPF: 전송 바이트 수 (counter)
54pub const EBPF_BYTES_TOTAL: &str = "ironpost_ebpf_bytes_total";
55
56/// eBPF: XDP 처리 지연 시간 (histogram, 초)
57pub const EBPF_XDP_PROCESSING_DURATION_SECONDS: &str =
58    "ironpost_ebpf_xdp_processing_duration_seconds";
59
60/// eBPF: 프로토콜별 패킷 수 (counter, label: protocol)
61pub const EBPF_PROTOCOL_PACKETS_TOTAL: &str = "ironpost_ebpf_protocol_packets_total";
62
63/// eBPF: 초당 패킷 처리량 (gauge)
64pub const EBPF_PACKETS_PER_SECOND: &str = "ironpost_ebpf_packets_per_second";
65
66/// eBPF: 초당 비트 처리량 (gauge)
67pub const EBPF_BITS_PER_SECOND: &str = "ironpost_ebpf_bits_per_second";
68
69// ─── Log Pipeline 메트릭 ────────────────────────────────────────────
70
71/// Log Pipeline: 수집된 전체 로그 수 (counter)
72pub const LOG_PIPELINE_LOGS_COLLECTED_TOTAL: &str = "ironpost_log_pipeline_logs_collected_total";
73
74/// Log Pipeline: 처리된 로그 수 (counter)
75pub const LOG_PIPELINE_LOGS_PROCESSED_TOTAL: &str = "ironpost_log_pipeline_logs_processed_total";
76
77/// Log Pipeline: 파싱 에러 수 (counter)
78pub const LOG_PIPELINE_PARSE_ERRORS_TOTAL: &str = "ironpost_log_pipeline_parse_errors_total";
79
80/// Log Pipeline: 규칙 매칭 수 (counter)
81pub const LOG_PIPELINE_RULE_MATCHES_TOTAL: &str = "ironpost_log_pipeline_rule_matches_total";
82
83/// Log Pipeline: 전송된 알림 수 (counter)
84pub const LOG_PIPELINE_ALERTS_SENT_TOTAL: &str = "ironpost_log_pipeline_alerts_sent_total";
85
86/// Log Pipeline: 로그 처리 지연 시간 (histogram, 초)
87pub const LOG_PIPELINE_PROCESSING_DURATION_SECONDS: &str =
88    "ironpost_log_pipeline_processing_duration_seconds";
89
90/// Log Pipeline: 버퍼 내 로그 수 (gauge)
91pub const LOG_PIPELINE_BUFFER_SIZE: &str = "ironpost_log_pipeline_buffer_size";
92
93/// Log Pipeline: 드롭된 로그 수 (counter)
94pub const LOG_PIPELINE_LOGS_DROPPED_TOTAL: &str = "ironpost_log_pipeline_logs_dropped_total";
95
96// ─── Container Guard 메트릭 ─────────────────────────────────────────
97
98/// Container Guard: 모니터링 중인 컨테이너 수 (gauge)
99pub const CONTAINER_GUARD_MONITORED_CONTAINERS: &str =
100    "ironpost_container_guard_monitored_containers";
101
102/// Container Guard: 정책 위반 수 (counter)
103pub const CONTAINER_GUARD_POLICY_VIOLATIONS_TOTAL: &str =
104    "ironpost_container_guard_policy_violations_total";
105
106/// Container Guard: 격리 실행 수 (counter)
107pub const CONTAINER_GUARD_ISOLATIONS_TOTAL: &str = "ironpost_container_guard_isolations_total";
108
109/// Container Guard: 격리 실패 수 (counter)
110pub const CONTAINER_GUARD_ISOLATION_FAILURES_TOTAL: &str =
111    "ironpost_container_guard_isolation_failures_total";
112
113/// Container Guard: 처리된 알림 수 (counter)
114pub const CONTAINER_GUARD_ALERTS_PROCESSED_TOTAL: &str =
115    "ironpost_container_guard_alerts_processed_total";
116
117/// Container Guard: 로드된 정책 수 (gauge)
118pub const CONTAINER_GUARD_POLICIES_LOADED: &str = "ironpost_container_guard_policies_loaded";
119
120// ─── SBOM Scanner 메트릭 ────────────────────────────────────────────
121
122/// SBOM Scanner: 완료된 스캔 수 (counter)
123pub const SBOM_SCANNER_SCANS_COMPLETED_TOTAL: &str = "ironpost_sbom_scanner_scans_completed_total";
124
125/// SBOM Scanner: 발견된 CVE 수 (gauge, label: severity)
126pub const SBOM_SCANNER_CVES_FOUND: &str = "ironpost_sbom_scanner_cves_found";
127
128/// SBOM Scanner: 스캔 소요 시간 (histogram, 초)
129pub const SBOM_SCANNER_SCAN_DURATION_SECONDS: &str = "ironpost_sbom_scanner_scan_duration_seconds";
130
131/// SBOM Scanner: 스캔된 패키지 수 (counter)
132pub const SBOM_SCANNER_PACKAGES_SCANNED_TOTAL: &str =
133    "ironpost_sbom_scanner_packages_scanned_total";
134
135/// SBOM Scanner: 취약점 DB 마지막 업데이트 시각 (gauge, Unix epoch)
136pub const SBOM_SCANNER_VULNDB_LAST_UPDATE: &str =
137    "ironpost_sbom_scanner_vulndb_last_update_timestamp";
138
139// ─── Daemon 메트릭 ──────────────────────────────────────────────────
140
141/// Daemon: 가동 시간 (gauge, 초)
142pub const DAEMON_UPTIME_SECONDS: &str = "ironpost_daemon_uptime_seconds";
143
144/// Daemon: 등록된 플러그인 수 (gauge)
145pub const DAEMON_PLUGINS_REGISTERED: &str = "ironpost_daemon_plugins_registered";
146
147/// Daemon: 빌드 정보 (gauge, 항상 1, labels: version, commit, rust_version)
148pub const DAEMON_BUILD_INFO: &str = "ironpost_daemon_build_info";
149
150// ─── 히스토그램 버킷 정의 ────────────────────────────────────────────
151
152/// 로그 처리 지연 시간 히스토그램 버킷 (초)
153///
154/// 100us ~ 10s 범위, 로그 단위 분포
155pub const PROCESSING_DURATION_BUCKETS: [f64; 10] = [
156    0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 10.0,
157];
158
159/// 스캔 소요 시간 히스토그램 버킷 (초)
160///
161/// 100ms ~ 300s 범위 (SBOM 스캔은 디스크 I/O 포함)
162pub const SCAN_DURATION_BUCKETS: [f64; 9] = [0.1, 0.5, 1.0, 5.0, 10.0, 30.0, 60.0, 120.0, 300.0];
163
164// ─── 설명 등록 함수 ─────────────────────────────────────────────────
165
166/// 모든 메트릭의 설명(description)을 등록합니다.
167///
168/// `metrics::describe_counter!()`, `describe_gauge!()`, `describe_histogram!()`을
169/// 호출하여 Prometheus HELP 텍스트를 설정합니다.
170///
171/// 이 함수는 전역 레코더 설치 후 한 번만 호출해야 합니다.
172/// 일반적으로 `ironpost-daemon`의 시작 시점에서 호출합니다.
173pub fn describe_all() {
174    use metrics::{describe_counter, describe_gauge, describe_histogram};
175
176    // eBPF Engine
177    describe_counter!(
178        EBPF_PACKETS_TOTAL,
179        "Total number of packets processed by eBPF XDP"
180    );
181    describe_counter!(
182        EBPF_PACKETS_BLOCKED_TOTAL,
183        "Total number of packets blocked (XDP_DROP) by eBPF"
184    );
185    describe_counter!(EBPF_BYTES_TOTAL, "Total bytes processed by eBPF XDP");
186    describe_histogram!(
187        EBPF_XDP_PROCESSING_DURATION_SECONDS,
188        "XDP packet processing latency in seconds"
189    );
190    describe_counter!(
191        EBPF_PROTOCOL_PACKETS_TOTAL,
192        "Packets processed per protocol (TCP, UDP, ICMP, other)"
193    );
194    describe_gauge!(
195        EBPF_PACKETS_PER_SECOND,
196        "Current packet processing rate (packets/sec)"
197    );
198    describe_gauge!(EBPF_BITS_PER_SECOND, "Current throughput rate (bits/sec)");
199
200    // Log Pipeline
201    describe_counter!(
202        LOG_PIPELINE_LOGS_COLLECTED_TOTAL,
203        "Total number of raw log lines collected from all sources"
204    );
205    describe_counter!(
206        LOG_PIPELINE_LOGS_PROCESSED_TOTAL,
207        "Total number of log entries successfully parsed and processed"
208    );
209    describe_counter!(
210        LOG_PIPELINE_PARSE_ERRORS_TOTAL,
211        "Total number of log parsing failures"
212    );
213    describe_counter!(
214        LOG_PIPELINE_RULE_MATCHES_TOTAL,
215        "Total number of detection rule matches"
216    );
217    describe_counter!(
218        LOG_PIPELINE_ALERTS_SENT_TOTAL,
219        "Total number of alert events sent to downstream consumers"
220    );
221    describe_histogram!(
222        LOG_PIPELINE_PROCESSING_DURATION_SECONDS,
223        "Time to process a single log batch in seconds"
224    );
225    describe_gauge!(
226        LOG_PIPELINE_BUFFER_SIZE,
227        "Current number of log entries in the processing buffer"
228    );
229    describe_counter!(
230        LOG_PIPELINE_LOGS_DROPPED_TOTAL,
231        "Total number of log entries dropped due to buffer overflow"
232    );
233
234    // Container Guard
235    describe_gauge!(
236        CONTAINER_GUARD_MONITORED_CONTAINERS,
237        "Number of containers currently being monitored"
238    );
239    describe_counter!(
240        CONTAINER_GUARD_POLICY_VIOLATIONS_TOTAL,
241        "Total number of security policy violations detected"
242    );
243    describe_counter!(
244        CONTAINER_GUARD_ISOLATIONS_TOTAL,
245        "Total number of container isolation actions executed"
246    );
247    describe_counter!(
248        CONTAINER_GUARD_ISOLATION_FAILURES_TOTAL,
249        "Total number of failed container isolation attempts"
250    );
251    describe_counter!(
252        CONTAINER_GUARD_ALERTS_PROCESSED_TOTAL,
253        "Total number of alert events processed by container guard"
254    );
255    describe_gauge!(
256        CONTAINER_GUARD_POLICIES_LOADED,
257        "Number of security policies currently loaded"
258    );
259
260    // SBOM Scanner
261    describe_counter!(
262        SBOM_SCANNER_SCANS_COMPLETED_TOTAL,
263        "Total number of SBOM scans completed"
264    );
265    describe_gauge!(
266        SBOM_SCANNER_CVES_FOUND,
267        "Number of CVEs found by severity level"
268    );
269    describe_histogram!(
270        SBOM_SCANNER_SCAN_DURATION_SECONDS,
271        "Time to complete a single SBOM scan in seconds"
272    );
273    describe_counter!(
274        SBOM_SCANNER_PACKAGES_SCANNED_TOTAL,
275        "Total number of packages scanned across all SBOM scans"
276    );
277    describe_gauge!(
278        SBOM_SCANNER_VULNDB_LAST_UPDATE,
279        "Unix timestamp of the last vulnerability database update"
280    );
281
282    // Daemon
283    describe_gauge!(DAEMON_UPTIME_SECONDS, "Ironpost daemon uptime in seconds");
284    describe_gauge!(
285        DAEMON_PLUGINS_REGISTERED,
286        "Number of plugins registered in the daemon"
287    );
288    describe_gauge!(
289        DAEMON_BUILD_INFO,
290        "Build information (always 1, with version/commit labels)"
291    );
292}
293
294#[cfg(test)]
295mod tests {
296    use super::*;
297
298    // メトリック名の一覧(テスト用)
299    const ALL_METRIC_NAMES: &[&str] = &[
300        EBPF_PACKETS_TOTAL,
301        EBPF_PACKETS_BLOCKED_TOTAL,
302        EBPF_BYTES_TOTAL,
303        EBPF_XDP_PROCESSING_DURATION_SECONDS,
304        EBPF_PROTOCOL_PACKETS_TOTAL,
305        EBPF_PACKETS_PER_SECOND,
306        EBPF_BITS_PER_SECOND,
307        LOG_PIPELINE_LOGS_COLLECTED_TOTAL,
308        LOG_PIPELINE_LOGS_PROCESSED_TOTAL,
309        LOG_PIPELINE_PARSE_ERRORS_TOTAL,
310        LOG_PIPELINE_RULE_MATCHES_TOTAL,
311        LOG_PIPELINE_ALERTS_SENT_TOTAL,
312        LOG_PIPELINE_PROCESSING_DURATION_SECONDS,
313        LOG_PIPELINE_BUFFER_SIZE,
314        LOG_PIPELINE_LOGS_DROPPED_TOTAL,
315        CONTAINER_GUARD_MONITORED_CONTAINERS,
316        CONTAINER_GUARD_POLICY_VIOLATIONS_TOTAL,
317        CONTAINER_GUARD_ISOLATIONS_TOTAL,
318        CONTAINER_GUARD_ISOLATION_FAILURES_TOTAL,
319        CONTAINER_GUARD_ALERTS_PROCESSED_TOTAL,
320        CONTAINER_GUARD_POLICIES_LOADED,
321        SBOM_SCANNER_SCANS_COMPLETED_TOTAL,
322        SBOM_SCANNER_CVES_FOUND,
323        SBOM_SCANNER_SCAN_DURATION_SECONDS,
324        SBOM_SCANNER_PACKAGES_SCANNED_TOTAL,
325        SBOM_SCANNER_VULNDB_LAST_UPDATE,
326        DAEMON_UPTIME_SECONDS,
327        DAEMON_PLUGINS_REGISTERED,
328        DAEMON_BUILD_INFO,
329    ];
330
331    #[test]
332    fn all_metrics_start_with_ironpost_prefix() {
333        for name in ALL_METRIC_NAMES {
334            assert!(
335                name.starts_with("ironpost_"),
336                "Metric '{}' does not start with 'ironpost_' prefix",
337                name
338            );
339        }
340    }
341
342    #[test]
343    fn all_metrics_have_29_entries() {
344        // Design document mentions 28 but actually defines 29 metrics
345        // (7 eBPF + 8 Log Pipeline + 6 Container Guard + 5 SBOM Scanner + 3 Daemon)
346        assert_eq!(
347            ALL_METRIC_NAMES.len(),
348            29,
349            "Expected 29 metrics (7 eBPF + 8 Log Pipeline + 6 Container Guard + 5 SBOM + 3 Daemon)"
350        );
351    }
352
353    #[test]
354    fn describe_all_does_not_panic() {
355        // describe_all() should not panic even without a recorder installed
356        describe_all();
357    }
358
359    #[test]
360    fn label_keys_are_lowercase() {
361        let labels = [
362            LABEL_PROTOCOL,
363            LABEL_SEVERITY,
364            LABEL_MODULE,
365            LABEL_PARSER_FORMAT,
366            LABEL_ACTION,
367            LABEL_ECOSYSTEM,
368            LABEL_RESULT,
369        ];
370        for label in &labels {
371            assert_eq!(
372                label.to_lowercase(),
373                *label,
374                "Label key '{}' should be lowercase",
375                label
376            );
377        }
378    }
379
380    #[test]
381    fn processing_duration_buckets_are_sorted() {
382        let buckets = PROCESSING_DURATION_BUCKETS;
383        for i in 1..buckets.len() {
384            assert!(
385                buckets[i] > buckets[i - 1],
386                "Bucket values must be in ascending order"
387            );
388        }
389    }
390
391    #[test]
392    fn scan_duration_buckets_are_sorted() {
393        let buckets = SCAN_DURATION_BUCKETS;
394        for i in 1..buckets.len() {
395            assert!(
396                buckets[i] > buckets[i - 1],
397                "Bucket values must be in ascending order"
398            );
399        }
400    }
401}