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;