aptos_logger_link/
kv.rs

1// Copyright (c) Aptos
2// SPDX-License-Identifier: Apache-2.0
3
4//! Key-Value definitions for macros
5//!
6//! Example:
7//! ```
8//! use aptos_logger::info;
9//! info!(
10//!   key = "value"
11//! );
12//! ```
13
14use serde::Serialize;
15use std::{
16    borrow::{Borrow, Cow},
17    fmt,
18};
19
20/// The key part of a logging key value pair e.g. `info!(key = value)`
21#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)]
22pub struct Key(Cow<'static, str>);
23
24impl Key {
25    pub fn new(s: &'static str) -> Self {
26        Self(Cow::Borrowed(s))
27    }
28
29    pub fn new_owned(s: String) -> Self {
30        Self(Cow::Owned(s))
31    }
32
33    pub fn as_str(&self) -> &'_ Self {
34        self.borrow()
35    }
36}
37
38/// The value part of a logging key value pair e.g. `info!(key = value)`
39#[derive(Clone, Copy)]
40pub enum Value<'v> {
41    Debug(&'v (dyn fmt::Debug)),
42    Display(&'v (dyn fmt::Display)),
43    Serde(&'v (dyn erased_serde::Serialize)),
44}
45
46impl<'v> fmt::Debug for Value<'v> {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        match &self {
49            Value::Debug(d) => fmt::Debug::fmt(d, f),
50            Value::Display(d) => fmt::Display::fmt(d, f),
51            Value::Serde(s) => {
52                fmt::Debug::fmt(&serde_json::to_value(s).map_err(|_| fmt::Error)?, f)
53            }
54        }
55    }
56}
57
58impl<'v> Value<'v> {
59    /// Get a value from a debuggable type.
60    pub fn from_serde<T: serde::Serialize>(value: &'v T) -> Self {
61        Value::Serde(value)
62    }
63
64    /// Get a value from a debuggable type.
65    pub fn from_debug<T: fmt::Debug>(value: &'v T) -> Self {
66        Value::Debug(value)
67    }
68
69    /// Get a value from a displayable type.
70    pub fn from_display<T: fmt::Display>(value: &'v T) -> Self {
71        Value::Display(value)
72    }
73}
74
75/// The logging key value pair e.g. `info!(key = value)`
76#[derive(Clone, Debug)]
77pub struct KeyValue<'v> {
78    key: Key,
79    value: Value<'v>,
80}
81
82impl<'v> KeyValue<'v> {
83    pub fn new(key: &'static str, value: Value<'v>) -> Self {
84        Self {
85            key: Key::new(key),
86            value,
87        }
88    }
89}
90
91impl<'v> Schema for KeyValue<'v> {
92    fn visit(&self, visitor: &mut dyn Visitor) {
93        visitor.visit_pair(self.key.clone(), self.value)
94    }
95}
96
97/// A schema of key-value pairs.
98///
99/// The schema may be a single pair, a set of pairs, or a filter over a set of pairs.
100/// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data
101/// in a schema.
102pub trait Schema {
103    /// Visit key-value pairs.
104    fn visit(&self, visitor: &mut dyn Visitor);
105}
106
107/// A visitor for the key-value pairs in a [`Schema`](trait.Schema.html).
108pub trait Visitor {
109    /// Visit a key-value pair.
110    fn visit_pair(&mut self, key: Key, value: Value<'_>);
111}
112
113impl<'a, 'b: 'a> Visitor for fmt::DebugMap<'a, 'b> {
114    fn visit_pair(&mut self, key: Key, value: Value<'_>) {
115        self.entry(&key, &value);
116    }
117}