vector/internal_events/
parser.rs

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