Skip to content

Commit 02ab539

Browse files
committed
FullFormatter outputs key-values
1 parent 846e917 commit 02ab539

File tree

3 files changed

+88
-9
lines changed

3 files changed

+88
-9
lines changed

spdlog/src/formatter/full_formatter.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ impl FullFormatter {
9494
dest.write_str("] ")?;
9595
dest.write_str(record.payload())?;
9696

97+
let kvs = record.key_values();
98+
if !kvs.is_empty() {
99+
dest.write_str(" { ")?;
100+
101+
let mut iter = kvs.peekable();
102+
while let Some((key, value)) = iter.next() {
103+
dest.write_str(key.as_str())?;
104+
dest.write_str("=")?;
105+
write!(dest, "{}", value)?;
106+
if iter.peek().is_some() {
107+
dest.write_str(", ")?;
108+
}
109+
}
110+
dest.write_str(" }")?;
111+
}
112+
97113
if self.with_eol {
98114
dest.write_str(__EOL)?;
99115
}
@@ -126,11 +142,15 @@ mod tests {
126142
use chrono::prelude::*;
127143

128144
use super::*;
129-
use crate::{Level, __EOL};
145+
use crate::{kv, Level, __EOL};
130146

131147
#[test]
132148
fn format() {
133-
let record = Record::new(Level::Warn, "test log content", None, None, &[]);
149+
let kvs = [
150+
(kv::Key::__from_static_str("k1"), kv::Value::from(114)),
151+
(kv::Key::__from_static_str("k2"), kv::Value::from("514")),
152+
];
153+
let record = Record::new(Level::Warn, "test log content", None, None, &kvs);
134154
let mut buf = StringBuf::new();
135155
let mut ctx = FormatterContext::new();
136156
FullFormatter::new()
@@ -140,7 +160,7 @@ mod tests {
140160
let local_time: DateTime<Local> = record.time().into();
141161
assert_eq!(
142162
format!(
143-
"[{}] [warn] test log content{}",
163+
"[{}] [warn] test log content {{ k1=114, k2=514 }}{}",
144164
local_time.format("%Y-%m-%d %H:%M:%S.%3f"),
145165
__EOL
146166
),

spdlog/src/kv.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::borrow::Cow;
1+
use std::{borrow::Cow, marker::PhantomData};
22

33
use value_bag::{OwnedValueBag, ValueBag};
44

@@ -14,6 +14,15 @@ pub(crate) enum KeyInner<'a> {
1414
#[derive(Debug, Clone)]
1515
pub struct Key<'a>(KeyInner<'a>);
1616

17+
impl<'a> Key<'a> {
18+
pub fn as_str(&self) -> &str {
19+
match &self.0 {
20+
KeyInner::Str(s) => s,
21+
KeyInner::StaticStr(s) => s,
22+
}
23+
}
24+
}
25+
1726
impl<'a> Key<'a> {
1827
#[doc(hidden)]
1928
pub fn __from_static_str(key: &'static str) -> Self {
@@ -61,6 +70,50 @@ impl KeyOwned {
6170
pub type Value<'a> = ValueBag<'a>;
6271
pub(crate) type ValueOwned = OwnedValueBag;
6372

73+
pub struct KeyValuesIter<'a, I> {
74+
iter: I,
75+
len: usize,
76+
phantom: PhantomData<&'a ()>,
77+
}
78+
79+
impl<I> KeyValuesIter<'_, I> {
80+
pub fn len(&self) -> usize {
81+
self.len
82+
}
83+
84+
pub fn is_empty(&self) -> bool {
85+
self.len == 0
86+
}
87+
}
88+
89+
impl<'a, I> KeyValuesIter<'a, I>
90+
where
91+
I: Iterator<Item = (Key<'a>, Value<'a>)>,
92+
{
93+
pub(crate) fn new(iter: I, len: usize) -> Self {
94+
Self {
95+
iter,
96+
len,
97+
phantom: PhantomData,
98+
}
99+
}
100+
}
101+
102+
impl<'a, I> Iterator for KeyValuesIter<'a, I>
103+
where
104+
I: Iterator<Item = (Key<'a>, Value<'a>)>,
105+
{
106+
type Item = I::Item;
107+
108+
fn next(&mut self) -> Option<Self::Item> {
109+
self.iter.next()
110+
}
111+
112+
fn size_hint(&self) -> (usize, Option<usize>) {
113+
self.iter.size_hint()
114+
}
115+
}
116+
64117
pub(crate) type Pair<'a> = (Key<'a>, Value<'a>);
65118

66119
#[cfg(feature = "log")]

spdlog/src/record.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,12 @@ impl<'a> Record<'a> {
110110
}
111111

112112
#[must_use]
113-
pub fn key_values(&self) -> impl IntoIterator<Item = (kv::Key, kv::Value)> {
114-
// The 2 clones should be cheap
115-
self.kvs.iter().map(|(k, v)| (k.clone(), v.clone()))
113+
pub fn key_values(&self) -> kv::KeyValuesIter<impl Iterator<Item = (kv::Key, kv::Value)>> {
114+
kv::KeyValuesIter::new(
115+
// The 2 clones should be cheap
116+
self.kvs.iter().map(|(k, v)| (k.clone(), v.clone())),
117+
self.kvs.len(),
118+
)
116119
}
117120

118121
// When adding more getters, also add to `RecordOwned`
@@ -239,8 +242,11 @@ impl RecordOwned {
239242
}
240243

241244
#[must_use]
242-
pub fn key_values(&self) -> impl IntoIterator<Item = (kv::Key, kv::Value)> {
243-
self.kvs.iter().map(|(k, v)| (k.as_ref(), v.by_ref()))
245+
pub fn key_values(&self) -> kv::KeyValuesIter<impl Iterator<Item = (kv::Key, kv::Value)>> {
246+
kv::KeyValuesIter::new(
247+
self.kvs.iter().map(|(k, v)| (k.as_ref(), v.by_ref())),
248+
self.kvs.len(),
249+
)
244250
}
245251

246252
// When adding more getters, also add to `Record`

0 commit comments

Comments
 (0)