vector/internal_events/
parser.rs

1use std::borrow::Cow;
2
3use metrics::counter;
4use vector_lib::internal_event::InternalEvent;
5use vector_lib::internal_event::{error_stage, error_type, ComponentEventsDropped, UNINTENTIONAL};
6
7fn truncate_string_at(s: &str, maxlen: usize) -> Cow<str> {
8    let ellipsis: &str = "[...]";
9    if s.len() >= maxlen {
10        let mut len = maxlen - ellipsis.len();
11        while !s.is_char_boundary(len) {
12            len -= 1;
13        }
14        format!("{}{}", &s[..len], ellipsis).into()
15    } else {
16        s.into()
17    }
18}
19
20#[derive(Debug)]
21pub struct ParserMatchError<'a> {
22    pub value: &'a [u8],
23}
24
25impl InternalEvent for ParserMatchError<'_> {
26    fn emit(self) {
27        error!(
28            message = "Pattern failed to match.",
29            error_code = "no_match_found",
30            error_type = error_type::CONDITION_FAILED,
31            stage = error_stage::PROCESSING,
32            field = &truncate_string_at(&String::from_utf8_lossy(self.value), 60)[..],
33            internal_log_rate_limit = true
34        );
35        counter!(
36            "component_errors_total",
37            "error_code" => "no_match_found",
38            "error_type" => error_type::CONDITION_FAILED,
39            "stage" => error_stage::PROCESSING,
40        )
41        .increment(1);
42    }
43}
44
45#[allow(dead_code)]
46pub const DROP_EVENT: bool = true;
47#[allow(dead_code)]
48pub const RETAIN_EVENT: bool = false;
49
50#[derive(Debug)]
51pub struct ParserMissingFieldError<'a, const DROP_EVENT: bool> {
52    pub field: &'a str,
53}
54
55impl<const DROP_EVENT: bool> InternalEvent for ParserMissingFieldError<'_, DROP_EVENT> {
56    fn emit(self) {
57        let reason = "Field does not exist.";
58        error!(
59            message = reason,
60            field = %self.field,
61            error_code = "field_not_found",
62            error_type = error_type::CONDITION_FAILED,
63            stage = error_stage::PROCESSING,
64            internal_log_rate_limit = true
65        );
66        counter!(
67            "component_errors_total",
68            "error_code" => "field_not_found",
69            "error_type" => error_type::CONDITION_FAILED,
70            "stage" => error_stage::PROCESSING,
71            "field" => self.field.to_string(),
72        )
73        .increment(1);
74
75        if DROP_EVENT {
76            emit!(ComponentEventsDropped::<UNINTENTIONAL> { count: 1, reason });
77        }
78    }
79}
80
81#[derive(Debug)]
82pub struct ParserConversionError<'a> {
83    pub name: &'a str,
84    pub error: crate::types::Error,
85}
86
87impl InternalEvent for ParserConversionError<'_> {
88    fn emit(self) {
89        error!(
90            message = "Could not convert types.",
91            name = %self.name,
92            error = ?self.error,
93            error_code = "type_conversion",
94            error_type = error_type::CONVERSION_FAILED,
95            stage = error_stage::PROCESSING,
96            internal_log_rate_limit = true
97        );
98        counter!(
99            "component_errors_total",
100            "error_code" => "type_conversion",
101            "error_type" => error_type::CONVERSION_FAILED,
102            "stage" => error_stage::PROCESSING,
103            "name" => self.name.to_string(),
104        )
105        .increment(1);
106    }
107}
108
109#[cfg(test)]
110mod test {
111    #[test]
112    fn truncate_utf8() {
113        let message = "Hello 😁 this is test.";
114        assert_eq!("Hello [...]", super::truncate_string_at(message, 13));
115    }
116}