1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
use super::grammar;
/// Default fields that represent the search path when a Datadog tag/facet is not provided.
static DEFAULT_FIELDS: &[&str] = &[
"message",
"custom.error.message",
"custom.error.stack",
"custom.title",
"_default_",
];
/// Attributes that represent special fields in Datadog.
static RESERVED_ATTRIBUTES: &[&str] = &[
"host",
"source",
"status",
"service",
"trace_id",
"message",
"timestamp",
"tags",
];
/// Describes a field to search on.
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub enum Field {
/// Default field (when tag/facet isn't provided)
Default(String),
/// Reserved field that receives special treatment in Datadog.
Reserved(String),
/// A facet -- i.e. started with `@`, transformed to `custom.*`
Facet(String),
/// Tag type - i.e. search in the `tags` field.
Tag(String),
}
impl Field {
pub fn as_str(&self) -> &str {
match self {
Self::Default(ref s) => s,
Self::Reserved(ref s) => s,
Self::Facet(ref s) => s,
Self::Tag(ref s) => s,
}
}
}
/// Converts a field/facet name to the VRL equivalent. Datadog payloads have a `message` field
/// (which is used whenever the default field is encountered. Facets are hosted on .custom.*.
pub fn normalize_fields<T: AsRef<str>>(value: T) -> Vec<Field> {
let value = value.as_ref();
if value.eq(grammar::DEFAULT_FIELD) {
return DEFAULT_FIELDS
.iter()
.map(|s| Field::Default((*s).to_owned()))
.collect();
}
let field = match value.replace('@', "custom.") {
v if value.starts_with('@') => Field::Facet(v),
v if DEFAULT_FIELDS.contains(&v.as_ref()) => Field::Default(v),
v if RESERVED_ATTRIBUTES.contains(&v.as_ref()) => Field::Reserved(v),
v => Field::Tag(v),
};
vec![field]
}