diem_logger/
lib.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8//! This crates provides an API for logging in diem.
9//! # Instrumenting with Logs
10//! ## Basic instrumenting with Logs
11//!
12//! A set of logging macros (`info!`, `error!`, `warn!`, `debug!`, and `trace!`)
13//! is provided for emitting logs at different levels. All of these macros
14//! support the addition of providing structured data along with a formatted
15//! text message.  For guidelines on which level to use, see the [coding guidelines](https://developers.diem.com/docs/core/coding-guidelines#logging).
16//!
17//! The below examples do no type checking for structured log fields, and
18//! instead just serialize whatever is given.
19//! ```
20//! use diem_logger::info;
21//!
22//! let world = "world!";
23//!
24//! // Formatted message, similar to `printf!`
25//! info!("hello {}", world);
26//! // => '{"level":"info", "message": "hello world!"}'
27//!
28//! // Structured data can be logged using the format 'key = value'
29//! // where value implements Serialize.  This can be used for indexing and search later.
30//! let value1 = 5;
31//! info!(key1 = value1);
32//! // => '{"level":"info", "data": {"key1": 5}}'
33//!
34//! // You can even set multiple key/value pairs and a format message together
35//! let value2 = false;
36//! info!(key1 = value1, key2 = value2, "hello {}", world);
37//! // => '{"level":"info", "data": {"key1": 5, "key2": false}, "message": "hello world!"}'
38//!
39//! // Structured data can also use `Display` or `Debug` outputs instead.
40//! // Using the sigil `?` for debug and `%` for display.
41//! let value1 = 5;
42//! info!(debug_key = ?value1, display_key = %value1);
43//! // => '{"level":"info", "data": {"display_key": 5, "debug_key": 5}}'
44//! ```
45//!
46//! ### Note
47//!
48//! Arguments used in a formatted message are **not** captured and included as
49//! structured data. Everything after the format string literal e.g. `"hello
50//! {}"` are only used in the format string.
51//!
52//! ## Preferred instrumenting with Logs (Typed Schemas)
53//!
54//! The `Schema` trait can be used to implement typed logging schemas. This can
55//! either be implemented by hand or derived using the `Schema` derive
56//! proc-macro, implementing the `Schema` trait for the struct as well as
57//! providing setters for all fields.
58//!
59//! ```
60//! use diem_logger::{info, Schema};
61//!
62//! #[derive(Schema)]
63//! struct LogSchema<'a> {
64//!     // Log using this type's Serialize impl
65//!     a: usize,
66//!     // Log using this type's Debug impl
67//!     #[schema(debug)]
68//!     b: Option<Vec<bool>>,
69//!     // Log using this type's Display impl
70//!     #[schema(display)]
71//!     c: Option<&'a str>,
72//! }
73//!
74//! let log = LogSchema {
75//!     a: 5,
76//!     b: None,
77//!     c: None,
78//! };
79//!
80//! // Automatic setters are named based on the field names, and handle `Option`
81//! // None fields will be ignored
82//! info!(log.c("radiant"));
83//! // => '{"level":"info", "data": { "a": 5, "c": "radiant"}}'
84//!
85//! #[derive(Schema)]
86//! struct OtherSchema<'a> {
87//!     val: Option<&'a str>,
88//! }
89//!
90//! let log = LogSchema {
91//!     a: 5,
92//!     b: None,
93//!     c: None,
94//! };
95//! let other = OtherSchema { val: None };
96//!
97//! // Schemas can be combined
98//! info!(
99//!     other.val("awesome"), // First schema
100//!     log                   // Second schema has fields added to it all
101//! );
102//! // => '{"level":"info", "data": { "a": 5, "val":"awesome"}}'
103//!
104//! let log = LogSchema {
105//!     a: 5,
106//!     b: None,
107//!     c: None,
108//! };
109//! let other = OtherSchema { val: None };
110//!
111//! // Schemas can be combined with one off fields and messages like above
112//! info!(
113//!     other.val("awesome"), // First schema
114//!     log,                  // Second schema has fields added to it all
115//!     new_field = "new",    // Basic structured fields
116//!     "Message: {}",        // Format messages
117//!     "Some message" // Format message fields (not added to indexed fields)
118//! );
119//! // => {"level":"info", "message": "Message: Some message",
120//! //     "data": { "a": 5, "val":"awesome", "new_field": "new"}}'
121//! ```
122//!
123//! ## Sampling logs
124//!
125//! Sometimes logging a large amount of data is expensive.  In order to log
126//! information only part of the time, we've added a `sample!` macro that's
127//! configurable on how often we want to execute some code.
128//!
129//! `SampleRate` determines how often the sampled statement will occur.
130//!
131//! ```ignore
132//! use diem_logger::{
133//!     info,
134//!     sample::{self, SampleRate, Sampling},
135//! };
136//! use std::time::Duration;
137//!
138//! // Sampled based on frequency of events, log only every 2 logs
139//! sample!(SampleRate::Frequency(2), info!("Long log"));
140//!
141//! // Sampled based on time passed, log at most once a minute
142//! sample!(
143//!     SampleRate::Duration(Duration::from_secs(60)),
144//!     info!("Long log")
145//! );
146//! ```
147//! # Configuration
148//!
149//! In order for logs to be captured and emitted a Logger needs to be
150//! instantiated. This can be done by using the `Logger` type:
151//!
152//! ```
153//! use diem_logger::{Level, Logger};
154//!
155//! Logger::builder().level(Level::Info).build();
156//! ```
157
158#![forbid(unsafe_code)]
159
160pub mod prelude {
161    pub use crate::{
162        debug as diem_debug,
163        diem_logger::{FileWriter, RollingFileWriter},
164        error as diem_error, event, info as diem_info, sample as diem_sample,
165        sample::{SampleRate, Sampling},
166        security::SecurityEvent,
167        trace as diem_trace, warn as diem_warn,
168    };
169}
170pub mod json_log;
171
172mod diem_logger;
173mod event;
174mod filter;
175mod kv;
176mod logger;
177mod macros;
178mod metadata;
179pub mod sample;
180
181mod security;
182mod struct_log;
183
184pub use crate::diem_logger::{
185    DiemLogger, DiemLogger as Logger, DiemLoggerBuilder, Writer, CHANNEL_SIZE,
186};
187pub use event::Event;
188pub use filter::{Filter, LevelFilter};
189pub use logger::flush;
190pub use metadata::{Level, Metadata};
191
192pub use diem_log_derive::Schema;
193pub use kv::{Key, KeyValue, Schema, Value, Visitor};
194pub use security::SecurityEvent;
195
196mod counters;