clnrm_core/validation/common.rs
1//! Common validation utilities shared across validators
2//!
3//! This module provides shared functionality to eliminate duplication
4//! in validation logic, error creation, and span processing.
5
6use crate::validation::span_validator::SpanData;
7
8/// Check if span is an error span
9///
10/// Checks multiple attributes to determine if a span represents an error:
11/// - `otel.status_code` == "ERROR"
12/// - `error` == true
13///
14/// # Arguments
15/// * `span` - The span to check
16///
17/// # Returns
18/// * `bool` - True if span represents an error
19pub fn is_error_span(span: &SpanData) -> bool {
20 span.attributes
21 .get("otel.status_code")
22 .and_then(|v| v.as_str())
23 .map(|s| s == "ERROR")
24 .unwrap_or(false)
25 || span
26 .attributes
27 .get("error")
28 .and_then(|v| v.as_bool())
29 .unwrap_or(false)
30}
31
32/// Get span status code
33///
34/// Extracts the OTEL status code from span attributes.
35/// Checks multiple attribute keys and defaults to "UNSET" if not found.
36///
37/// # Arguments
38/// * `span` - The span to extract status from
39///
40/// # Returns
41/// * `String` - Status code (UNSET, OK, or ERROR)
42pub fn get_span_status(span: &SpanData) -> String {
43 span.attributes
44 .get("otel.status_code")
45 .and_then(|v| v.as_str())
46 .map(|s| s.to_string())
47 .or_else(|| {
48 span.attributes
49 .get("status")
50 .and_then(|v| v.as_str())
51 .map(|s| s.to_string())
52 })
53 .unwrap_or_else(|| "UNSET".to_string())
54}
55
56/// Count spans by name
57///
58/// # Arguments
59/// * `spans` - Slice of spans to count
60/// * `name` - Name to count
61///
62/// # Returns
63/// * `usize` - Count of matching spans
64pub fn count_spans_by_name(spans: &[SpanData], name: &str) -> usize {
65 spans.iter().filter(|s| s.name == name).count()
66}
67
68/// Count error spans
69///
70/// # Arguments
71/// * `spans` - Slice of spans to count
72///
73/// # Returns
74/// * `usize` - Count of error spans
75pub fn count_error_spans(spans: &[SpanData]) -> usize {
76 spans.iter().filter(|s| is_error_span(s)).count()
77}