spdlog/formatter/
full_formatter.rs1use std::fmt::{self, Write};
4
5use cfg_if::cfg_if;
6
7use crate::{
8 formatter::{fmt_with_time, Formatter, FormatterContext, TimeDate},
9 Error, Record, StringBuf, __EOL,
10};
11
12#[rustfmt::skip]
13#[derive(Clone)]
37pub struct FullFormatter {
38 with_eol: bool,
39}
40
41impl FullFormatter {
42 #[must_use]
44 pub fn new() -> FullFormatter {
45 FullFormatter { with_eol: true }
46 }
47
48 #[must_use]
49 pub(crate) fn without_eol() -> Self {
50 Self { with_eol: false }
51 }
52
53 fn format_impl(
54 &self,
55 record: &Record,
56 dest: &mut StringBuf,
57 ctx: &mut FormatterContext,
58 ) -> Result<(), fmt::Error> {
59 cfg_if! {
60 if #[cfg(not(feature = "flexible-string"))] {
61 dest.reserve(crate::string_buf::RESERVE_SIZE);
62 }
63 }
64
65 fmt_with_time(ctx, record, |mut time: TimeDate| {
66 dest.write_str("[")?;
67 dest.write_str(time.full_second_str())?;
68 dest.write_str(".")?;
69 write!(dest, "{:03}", time.millisecond())?;
70 dest.write_str("] [")?;
71 Ok(())
72 })?;
73
74 if let Some(logger_name) = record.logger_name() {
75 dest.write_str(logger_name)?;
76 dest.write_str("] [")?;
77 }
78
79 let style_range_begin = dest.len();
80
81 dest.write_str(record.level().as_str())?;
82
83 let style_range_end = dest.len();
84
85 if let Some(srcloc) = record.source_location() {
86 dest.write_str("] [")?;
87 dest.write_str(srcloc.module_path())?;
88 dest.write_str(", ")?;
89 dest.write_str(srcloc.file())?;
90 dest.write_str(":")?;
91 write!(dest, "{}", srcloc.line())?;
92 }
93
94 dest.write_str("] ")?;
95 dest.write_str(record.payload())?;
96
97 if self.with_eol {
98 dest.write_str(__EOL)?;
99 }
100
101 ctx.set_style_range(Some(style_range_begin..style_range_end));
102 Ok(())
103 }
104}
105
106impl Formatter for FullFormatter {
107 fn format(
108 &self,
109 record: &Record,
110 dest: &mut StringBuf,
111 ctx: &mut FormatterContext,
112 ) -> crate::Result<()> {
113 self.format_impl(record, dest, ctx)
114 .map_err(Error::FormatRecord)
115 }
116}
117
118impl Default for FullFormatter {
119 fn default() -> FullFormatter {
120 FullFormatter::new()
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use chrono::prelude::*;
127
128 use super::*;
129 use crate::{Level, __EOL};
130
131 #[test]
132 fn format() {
133 let record = Record::new(Level::Warn, "test log content", None, None);
134 let mut buf = StringBuf::new();
135 let mut ctx = FormatterContext::new();
136 FullFormatter::new()
137 .format(&record, &mut buf, &mut ctx)
138 .unwrap();
139
140 let local_time: DateTime<Local> = record.time().into();
141 assert_eq!(
142 format!(
143 "[{}] [warn] test log content{}",
144 local_time.format("%Y-%m-%d %H:%M:%S.%3f"),
145 __EOL
146 ),
147 buf
148 );
149 assert_eq!(Some(27..31), ctx.style_range());
150 }
151}