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