tracing_human_layer/
style.rs1use std::fmt::Display;
2
3use owo_colors::Style as OwoStyle;
4use tracing::Level;
5
6use super::SpanInfo;
7
8#[derive(Debug)]
9pub struct Style {
10 indent_text: &'static str,
12
13 pub subsequent_indent: &'static str,
15
16 color: bool,
18
19 indent: OwoStyle,
21
22 text: OwoStyle,
24
25 field_name: OwoStyle,
27
28 field_value: OwoStyle,
30
31 span_name: OwoStyle,
33
34 span_in: OwoStyle,
36}
37
38impl Style {
39 pub fn new(level: Level, color: bool) -> Self {
40 let indent_text;
41 let span_in = OwoStyle::new().dimmed();
42 let mut indent = OwoStyle::new();
43 let mut text = OwoStyle::new();
44 let mut field_name = OwoStyle::new().bold();
45 let mut field_value = OwoStyle::new();
46 let mut span_name = OwoStyle::new();
47
48 match level {
49 Level::TRACE => {
50 indent_text = "TRACE ";
51 indent = indent.purple();
52 text = text.dimmed();
53 field_name = field_name.dimmed();
54 field_value = field_value.dimmed();
55 span_name = span_name.dimmed();
56 }
57 Level::DEBUG => {
58 indent_text = "DEBUG ";
59 indent = indent.blue();
60 text = text.dimmed();
61 field_name = field_name.dimmed();
62 field_value = field_value.dimmed();
63 span_name = span_name.dimmed();
64 }
65 Level::INFO => {
66 indent_text = "• ";
67 indent = indent.green();
68 }
69 Level::WARN => {
70 indent_text = "⚠ ";
71 indent = indent.yellow();
72 text = text.yellow();
73 }
74 Level::ERROR => {
75 indent_text = "⚠ ";
76 indent = indent.red();
77 text = text.red();
78 }
79 }
80
81 Self {
82 indent_text,
83 subsequent_indent: " ",
84 color,
85 indent,
86 text,
87 field_name,
88 field_value,
89 span_name,
90 span_in,
91 }
92 }
93
94 pub fn style_field(&self, name: &str, value: &str) -> String {
95 format!(
96 "{name}{value}",
97 name = name.colored(self.color, self.field_name),
98 value = format!("={value}").colored(self.color, self.field_value),
99 )
100 }
101
102 pub fn indent_colored(&self) -> String {
103 self.indent_text
104 .colored(self.color, self.indent)
105 .to_string()
106 }
107
108 pub fn style_message(&self, message: &str) -> String {
109 message.colored(self.color, self.text).to_string()
110 }
111
112 pub fn style_span_name(&self, name: &str) -> String {
113 name.colored(self.color, self.span_name).to_string()
114 }
115
116 pub fn style_span(&self, span: &SpanInfo) -> String {
117 format!(
118 "{in_}{name}{fields}",
119 in_ = "in ".colored(self.color, self.span_in),
120 name = span.name.colored(self.color, self.span_name),
121 fields = span.fields,
122 )
123 }
124}
125
126trait IntoConditionalColor: Display {
127 fn colored(&self, color: bool, style: OwoStyle) -> ConditionalColor<&Self> {
128 ConditionalColor::new(self).color(color).style(style)
129 }
130}
131
132impl<T> IntoConditionalColor for T where T: Display {}
133
134struct ConditionalColor<T> {
136 color: bool,
137 style: OwoStyle,
138 inner: T,
139}
140
141impl<T> ConditionalColor<T> {
142 pub fn new(inner: T) -> Self {
143 Self {
144 color: true,
145 style: OwoStyle::new(),
146 inner,
147 }
148 }
149
150 pub fn color(mut self, color: bool) -> Self {
151 self.color = color;
152 self
153 }
154
155 pub fn style(mut self, style: OwoStyle) -> Self {
156 self.style = style;
157 self
158 }
159}
160
161impl<T> Display for ConditionalColor<T>
162where
163 T: Display,
164{
165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166 if self.color {
167 self.style.style(&self.inner).fmt(f)
168 } else {
169 self.inner.fmt(f)
170 }
171 }
172}