tracing_ecs/attribute_mapper.rs
1use std::{borrow::Cow, collections::HashMap, ops::Deref};
2
3/// This span_name is used when calling the current `AttributeMapper` while
4/// processing event attributes.
5pub const EVENT_SPAN_NAME: &str = "__EVENT__";
6
7/// Map span attributes name to ECS field name
8///
9/// # Trait implementations
10///
11/// This trait is implemented on `HashMap<String, String>` and `HashMap<&'static str, &'static str>`
12/// to allow a direct mapping from a map.
13///
14/// Example
15///
16/// ```rust
17/// use tracing_ecs::ECSLayerBuilder;
18/// use maplit::hashmap;
19///
20/// ECSLayerBuilder::default()
21/// .with_attribute_mapper(hashmap!(
22/// "txid" => "transaction.id",
23/// "request_ip" => "source.ip",
24/// )).stdout().install().unwrap();
25/// ```
26///
27/// It is also implemented on `HashMap<String, HashMap<String, String>>` and
28/// `HashMap<&'static str, HashMap<&'static str, &'static str>>`. In this case, the first map level
29/// maps span names and the second attribute names.
30///
31/// Example
32///
33/// ```rust
34/// use tracing_ecs::ECSLayerBuilder;
35/// use maplit::hashmap;
36///
37/// ECSLayerBuilder::default()
38/// .with_attribute_mapper(hashmap!(
39/// "request" => hashmap!(
40/// "method" => "http.request.method",
41/// "request_ip" => "source.ip",
42/// ),
43/// "cron" => hashmap!(
44/// "request_ip" => "cron.source.ip",
45/// ),
46/// )).stdout().install().unwrap();
47/// ```
48///
49///
50pub trait AttributeMapper: Send + Sync + 'static {
51 /// Given a span name and the name of an attribute,
52 /// return the mapped attribute name
53 fn map(&self, span_name: &str, name: Cow<'static, str>) -> Cow<'static, str>;
54}
55
56impl<F> AttributeMapper for F
57where
58 F: for<'a> Fn(&'a str, Cow<'static, str>) -> Cow<'static, str> + Send + Sync + 'static,
59{
60 fn map(&self, span_name: &str, name: Cow<'static, str>) -> Cow<'static, str> {
61 self(span_name, name)
62 }
63}
64
65impl AttributeMapper for HashMap<String, String> {
66 fn map(&self, _span_name: &str, name: Cow<'static, str>) -> Cow<'static, str> {
67 self.get(name.deref())
68 .cloned()
69 .map(Cow::from)
70 .unwrap_or(name)
71 }
72}
73
74impl AttributeMapper for HashMap<&'static str, &'static str> {
75 fn map(&self, _span_name: &str, name: Cow<'static, str>) -> Cow<'static, str> {
76 self.get(name.deref())
77 .copied()
78 .map(Cow::from)
79 .unwrap_or(name)
80 }
81}
82
83impl AttributeMapper for HashMap<String, HashMap<String, String>> {
84 fn map(&self, span_name: &str, name: Cow<'static, str>) -> Cow<'static, str> {
85 self.get(span_name)
86 .and_then(|span_map| span_map.get(name.deref()).cloned().map(Cow::from))
87 .unwrap_or(name)
88 }
89}
90
91impl AttributeMapper for HashMap<&'static str, HashMap<&'static str, &'static str>> {
92 fn map(&self, span_name: &str, name: Cow<'static, str>) -> Cow<'static, str> {
93 self.get(span_name)
94 .and_then(|span_map| span_map.get(name.deref()).copied().map(Cow::from))
95 .unwrap_or(name)
96 }
97}