Skip to content

Commit 93377a8

Browse files
committed
Implement RuntimePattern
1 parent d60315a commit 93377a8

File tree

10 files changed

+749
-342
lines changed

10 files changed

+749
-342
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
fail-fast: false
4444
matrix:
4545
os: ['ubuntu-latest', 'windows-latest', 'macos-latest']
46-
fn_features: ['', 'log native libsystemd multi-thread']
46+
fn_features: ['', 'log native libsystemd multi-thread runtime-pattern']
4747
cfg_feature: ['', 'flexible-string', 'source-location']
4848
runs-on: ${{ matrix.os }}
4949
steps:

spdlog/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,21 @@ source-location = []
3636
native = []
3737
libsystemd = ["libsystemd-sys"]
3838
multi-thread = ["crossbeam"]
39+
runtime-pattern = ["spdlog-internal"]
3940

4041
[dependencies]
4142
arc-swap = "1.5.1"
4243
atomic = "0.5.1"
4344
cfg-if = "1.0.0"
4445
chrono = "0.4.22"
4546
crossbeam = { version = "0.8.2", optional = true }
47+
dyn-clone = "1.0.14"
4648
flexible-string = { version = "0.1.0", optional = true }
4749
if_chain = "1.0.2"
4850
is-terminal = "0.4"
4951
log = { version = "0.4.8", optional = true }
5052
once_cell = "1.16.0"
53+
spdlog-internal = { version = "=0.1.0", path = "../spdlog-internal", optional = true }
5154
spdlog-macros = { version = "0.1.0", path = "../spdlog-macros" }
5255
spin = "0.9.8"
5356
thiserror = "1.0.37"
@@ -76,6 +79,7 @@ flexi_logger = "=0.24.1"
7679
tracing = "=0.1.37"
7780
tracing-subscriber = "=0.3.16"
7881
tracing-appender = "=0.2.2"
82+
paste = "1.0.14"
7983

8084
[build-dependencies]
8185
rustc_version = "0.4.0"

spdlog/benches/pattern.rs

Lines changed: 75 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ extern crate test;
44

55
use std::{cell::RefCell, sync::Arc};
66

7+
use paste::paste;
78
use spdlog::{
8-
formatter::{pattern, Formatter, FullFormatter, Pattern, PatternFormatter},
9+
formatter::{pattern, Formatter, FullFormatter, Pattern, PatternFormatter, RuntimePattern},
910
prelude::*,
1011
sink::Sink,
1112
Record, StringBuf,
@@ -76,15 +77,7 @@ fn bench_pattern(bencher: &mut Bencher, pattern: impl Pattern + Clone + 'static)
7677
bench_formatter(bencher, PatternFormatter::new(pattern));
7778
}
7879

79-
#[bench]
80-
fn bench_1_full_formatter(bencher: &mut Bencher) {
81-
bench_formatter(bencher, FullFormatter::new())
82-
}
83-
84-
#[bench]
85-
fn bench_2_full_pattern(bencher: &mut Bencher) {
86-
let pattern = pattern!("[{date} {time}.{millisecond}] [{level}] {payload}{eol}");
87-
80+
fn bench_full_pattern(bencher: &mut Bencher, pattern: impl Pattern + Clone + 'static) {
8881
let full_formatter = Arc::new(StringSink::with(|b| {
8982
b.formatter(Box::new(FullFormatter::new()))
9083
}));
@@ -103,192 +96,81 @@ fn bench_2_full_pattern(bencher: &mut Bencher) {
10396
bench_pattern(bencher, pattern)
10497
}
10598

106-
#[bench]
107-
fn bench_weekday_name(bencher: &mut Bencher) {
108-
bench_pattern(bencher, pattern!("{weekday_name}"))
109-
}
110-
111-
#[bench]
112-
fn bench_weekday_name_full(bencher: &mut Bencher) {
113-
bench_pattern(bencher, pattern!("{weekday_name_full}"))
114-
}
115-
116-
#[bench]
117-
fn bench_month_name(bencher: &mut Bencher) {
118-
bench_pattern(bencher, pattern!("{month_name}"))
119-
}
120-
121-
#[bench]
122-
fn bench_month_name_full(bencher: &mut Bencher) {
123-
bench_pattern(bencher, pattern!("{month_name_full}"))
124-
}
125-
126-
#[bench]
127-
fn bench_datetime(bencher: &mut Bencher) {
128-
bench_pattern(bencher, pattern!("{datetime}"))
129-
}
130-
131-
#[bench]
132-
fn bench_year_short(bencher: &mut Bencher) {
133-
bench_pattern(bencher, pattern!("{year_short}"))
134-
}
135-
136-
#[bench]
137-
fn bench_year(bencher: &mut Bencher) {
138-
bench_pattern(bencher, pattern!("{year}"))
139-
}
140-
141-
#[bench]
142-
fn bench_date_short(bencher: &mut Bencher) {
143-
bench_pattern(bencher, pattern!("{date_short}"))
144-
}
145-
146-
#[bench]
147-
fn bench_date(bencher: &mut Bencher) {
148-
bench_pattern(bencher, pattern!("{date}"))
149-
}
150-
151-
#[bench]
152-
fn bench_month(bencher: &mut Bencher) {
153-
bench_pattern(bencher, pattern!("{month}"))
154-
}
155-
156-
#[bench]
157-
fn bench_day(bencher: &mut Bencher) {
158-
bench_pattern(bencher, pattern!("{day}"))
159-
}
160-
161-
#[bench]
162-
fn bench_hour(bencher: &mut Bencher) {
163-
bench_pattern(bencher, pattern!("{hour}"))
164-
}
165-
166-
#[bench]
167-
fn bench_hour_12(bencher: &mut Bencher) {
168-
bench_pattern(bencher, pattern!("{hour_12}"))
169-
}
170-
171-
#[bench]
172-
fn bench_minute(bencher: &mut Bencher) {
173-
bench_pattern(bencher, pattern!("{minute}"))
174-
}
175-
176-
#[bench]
177-
fn bench_second(bencher: &mut Bencher) {
178-
bench_pattern(bencher, pattern!("{second}"))
179-
}
180-
181-
#[bench]
182-
fn bench_millsecond(bencher: &mut Bencher) {
183-
bench_pattern(bencher, pattern!("{millisecond}"))
184-
}
185-
186-
#[bench]
187-
fn bench_microsecond(bencher: &mut Bencher) {
188-
bench_pattern(bencher, pattern!("{microsecond}"))
189-
}
190-
191-
#[bench]
192-
fn bench_nanosecond(bencher: &mut Bencher) {
193-
bench_pattern(bencher, pattern!("{nanosecond}"))
194-
}
195-
196-
#[bench]
197-
fn bench_am_pm(bencher: &mut Bencher) {
198-
bench_pattern(bencher, pattern!("{am_pm}"))
199-
}
200-
201-
#[bench]
202-
fn bench_time_12(bencher: &mut Bencher) {
203-
bench_pattern(bencher, pattern!("{time_12}"))
204-
}
205-
206-
#[bench]
207-
fn bench_time_short(bencher: &mut Bencher) {
208-
bench_pattern(bencher, pattern!("{time_short}"))
209-
}
210-
211-
#[bench]
212-
fn bench_time(bencher: &mut Bencher) {
213-
bench_pattern(bencher, pattern!("{time}"))
214-
}
215-
216-
#[bench]
217-
fn bench_tz_offset(bencher: &mut Bencher) {
218-
bench_pattern(bencher, pattern!("{tz_offset}"))
219-
}
220-
221-
#[bench]
222-
fn bench_unix_timestamp(bencher: &mut Bencher) {
223-
bench_pattern(bencher, pattern!("{unix_timestamp}"))
224-
}
225-
226-
#[bench]
227-
fn bench_full(bencher: &mut Bencher) {
228-
bench_pattern(bencher, pattern!("{full}"))
229-
}
230-
231-
#[bench]
232-
fn bench_level(bencher: &mut Bencher) {
233-
bench_pattern(bencher, pattern!("{level}"))
234-
}
235-
236-
#[bench]
237-
fn bench_level_short(bencher: &mut Bencher) {
238-
bench_pattern(bencher, pattern!("{level_short}"))
239-
}
99+
//
240100

241101
#[bench]
242-
fn bench_source(bencher: &mut Bencher) {
243-
bench_pattern(bencher, pattern!("{source}"))
244-
}
245-
246-
#[bench]
247-
fn bench_file_name(bencher: &mut Bencher) {
248-
bench_pattern(bencher, pattern!("{file_name}"))
249-
}
250-
251-
#[bench]
252-
fn bench_file(bencher: &mut Bencher) {
253-
bench_pattern(bencher, pattern!("{file}"))
254-
}
255-
256-
#[bench]
257-
fn bench_line(bencher: &mut Bencher) {
258-
bench_pattern(bencher, pattern!("{line}"))
259-
}
260-
261-
#[bench]
262-
fn bench_column(bencher: &mut Bencher) {
263-
bench_pattern(bencher, pattern!("{column}"))
264-
}
265-
266-
#[bench]
267-
fn bench_module_path(bencher: &mut Bencher) {
268-
bench_pattern(bencher, pattern!("{module_path}"))
269-
}
270-
271-
#[bench]
272-
fn bench_logger(bencher: &mut Bencher) {
273-
bench_pattern(bencher, pattern!("{logger}"))
274-
}
275-
276-
#[bench]
277-
fn bench_payload(bencher: &mut Bencher) {
278-
bench_pattern(bencher, pattern!("{payload}"))
279-
}
280-
281-
#[bench]
282-
fn bench_pid(bencher: &mut Bencher) {
283-
bench_pattern(bencher, pattern!("{pid}"))
284-
}
285-
286-
#[bench]
287-
fn bench_tid(bencher: &mut Bencher) {
288-
bench_pattern(bencher, pattern!("{tid}"))
102+
fn bench_1_full_formatter(bencher: &mut Bencher) {
103+
bench_formatter(bencher, FullFormatter::new())
289104
}
290105

291106
#[bench]
292-
fn bench_eol(bencher: &mut Bencher) {
293-
bench_pattern(bencher, pattern!("{eol}"))
107+
fn bench_2_full_pattern_ct(bencher: &mut Bencher) {
108+
bench_full_pattern(
109+
bencher,
110+
pattern!("[{date} {time}.{millisecond}] [{level}] {payload}{eol}"),
111+
)
112+
}
113+
114+
#[bench]
115+
fn bench_3_full_pattern_rt(bencher: &mut Bencher) {
116+
bench_full_pattern(
117+
bencher,
118+
RuntimePattern::new("[{date} {time}.{millisecond}] [{level}] {payload}{eol}").unwrap(),
119+
)
120+
}
121+
122+
macro_rules! bench_patterns {
123+
( $(($name:ident, $placeholder:literal)),+ $(,)? ) => {
124+
$(paste! {
125+
#[bench]
126+
fn [<bench_4_ct_ $name>](bencher: &mut Bencher) {
127+
bench_pattern(bencher, pattern!($placeholder))
128+
}
129+
#[bench]
130+
fn [<bench_5_rt_ $name>](bencher: &mut Bencher) {
131+
bench_pattern(bencher, RuntimePattern::new($placeholder).unwrap())
132+
}
133+
})+
134+
};
135+
}
136+
137+
bench_patterns! {
138+
(weekday_name, "{weekday_name}"),
139+
(weekday_name_full, "{weekday_name_full}"),
140+
(month_name, "{month_name}"),
141+
(month_name_full, "{month_name_full}"),
142+
(datetime, "{datetime}"),
143+
(year_short, "{year_short}"),
144+
(year, "{year}"),
145+
(date_short, "{date_short}"),
146+
(date, "{date}"),
147+
(month, "{month}"),
148+
(day, "{day}"),
149+
(hour, "{hour}"),
150+
(hour_12, "{hour_12}"),
151+
(minute, "{minute}"),
152+
(second, "{second}"),
153+
(millsecond, "{millisecond}"),
154+
(microsecond, "{microsecond}"),
155+
(nanosecond, "{nanosecond}"),
156+
(am_pm, "{am_pm}"),
157+
(time_12, "{time_12}"),
158+
(time_short, "{time_short}"),
159+
(time, "{time}"),
160+
(tz_offset, "{tz_offset}"),
161+
(unix_timestamp, "{unix_timestamp}"),
162+
(full, "{full}"),
163+
(level, "{level}"),
164+
(level_short, "{level_short}"),
165+
(source, "{source}"),
166+
(file_name, "{file_name}"),
167+
(file, "{file}"),
168+
(line, "{line}"),
169+
(column, "{column}"),
170+
(module_path, "{module_path}"),
171+
(logger, "{logger}"),
172+
(payload, "{payload}"),
173+
(pid, "{pid}"),
174+
(tid, "{tid}"),
175+
(eol, "{eol}"),
294176
}

spdlog/src/error.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ pub enum Error {
9292
#[error("failed to send message to channel: {0}")]
9393
SendToChannel(SendToChannelError, SendToChannelErrorDropped),
9494

95+
/// The variant returned by [`RuntimePatternBuilder::build`] when the
96+
/// pattern is failed to be built at runtime.
97+
///
98+
/// [`RuntimePatternBuilder::build`]: crate::formatter::RuntimePatternBuilder::build
99+
#[cfg(feature = "runtime-pattern")]
100+
#[error("failed to build pattern at runtime: {0}")]
101+
BuildPattern(BuildPatternError),
102+
95103
/// This variant returned when multiple errors occurred.
96104
#[error("{0:?}")]
97105
Multiple(Vec<Error>),
@@ -127,6 +135,16 @@ pub enum InvalidArgumentError {
127135
ThreadPoolCapacity(String),
128136
}
129137

138+
#[cfg(feature = "runtime-pattern")]
139+
impl Error {
140+
pub(crate) fn err_build_pattern(err: BuildPatternErrorInner) -> Self {
141+
Self::BuildPattern(BuildPatternError(err))
142+
}
143+
pub(crate) fn err_build_pattern_internal(err: spdlog_internal::pattern_parser::Error) -> Self {
144+
Self::BuildPattern(BuildPatternError(BuildPatternErrorInner::Internal(err)))
145+
}
146+
}
147+
130148
/// This error indicates that an invalid logger name was set.
131149
///
132150
/// See the documentation of [`LoggerBuilder::name`] for the name requirements.
@@ -242,6 +260,22 @@ impl SendToChannelErrorDropped {
242260
}
243261
}
244262

263+
/// This error indicates that an error occurred while building a pattern at
264+
/// compile-time.
265+
#[cfg(feature = "runtime-pattern")]
266+
#[derive(Error, Debug)]
267+
#[error("{0}")]
268+
pub struct BuildPatternError(BuildPatternErrorInner);
269+
270+
#[cfg(feature = "runtime-pattern")]
271+
#[derive(Error, Debug)]
272+
pub(crate) enum BuildPatternErrorInner {
273+
#[error("{0}")]
274+
Internal(spdlog_internal::pattern_parser::Error),
275+
#[error("invalid placeholder for custom pattern '{0}'")]
276+
InvalidCustomPlaceholder(String),
277+
}
278+
245279
/// The result type of this crate.
246280
pub type Result<T> = result::Result<T, Error>;
247281

0 commit comments

Comments
 (0)