Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tracing metrics layer for dependency logging #4979

Merged
merged 19 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 120 additions & 59 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ tempfile = "3"
tokio = { version = "1", features = ["rt-multi-thread", "sync", "signal"] }
tokio-stream = { version = "0.1", features = ["sync"] }
tokio-util = { version = "0.6", features = ["codec", "compat", "time"] }
tracing-core = "0.1"
tracing-log = "0.2"
tracing-subscriber = "0.3"
tree_hash = "0.5"
tree_hash_derive = "0.5"
url = "2"
Expand Down
4 changes: 2 additions & 2 deletions book/src/help_general.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ FLAGS:
--disable-malloc-tuning If present, do not configure the system allocator. Providing this flag will
generally increase memory usage, it should only be provided when debugging
specific memory allocation issues.
-l Enables environment logging giving access to sub-protocol logs such as discv5
and libp2p
-l DEPRECATED Enables environment logging giving access to sub-protocol logs such
as discv5 and libp2p
-h, --help Prints help information
--log-color Force outputting colors when emitting logs to the terminal.
--logfile-compress If present, compress old log files. This can help reduce the space needed to
Expand Down
5 changes: 1 addition & 4 deletions boot_node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,8 @@ pub fn run(
log::Level::Error => drain.filter_level(Level::Error),
};

let logger = Logger::root(drain.fuse(), o!());
let _scope_guard = slog_scope::set_global_logger(logger);
slog_stdlog::init_with_level(debug_level).unwrap();
let log = Logger::root(drain.fuse(), o!());
Copy link
Collaborator Author

@divagant-martian divagant-martian Dec 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AgeManning had to remove this to make the bootnode logging not panic. It seems to work alright, any idea why the rest of the lines were here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they needed to be there in order to get the logs out to display inside slog.

If you run a boot node, do we still get logs to the terminal?

Copy link
Collaborator Author

@divagant-martian divagant-martian Dec 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I get them alright. Sample:

Dec 12 23:23:45.909 INFO Executing bootstrap query...
2023-12-12T23:23:45.909324Z  INFO discv5::service: Discv5 Service started
2023-12-12T23:23:45.909386Z  INFO discv5::service: Ip4
Dec 12 23:23:50.126 INFO Server metrics                          unreachable_nodes: 0, ipv6_and_ipv4_nodes: 0, ipv6_nodes: 0, ipv4_nodes: 18, requests/s: 0.00, active_sessions: 33, connected_peers: 18

first and last are slog ones, middle ones are tracing ones


let log = slog_scope::logger();
// Run the main function emitting any errors
if let Err(e) = match eth_spec_id {
EthSpecId::Minimal => {
Expand Down
19 changes: 11 additions & 8 deletions common/logging/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ edition = { workspace = true }
test_logger = [] # Print log output to stderr when running tests instead of dropping it

[dependencies]
slog = { workspace = true }
slog-term = { workspace = true }
tokio = { workspace = true }
lighthouse_metrics = { workspace = true }
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
lazy_static = { workspace = true }
sloggers = { workspace = true }
slog-async = { workspace = true }
take_mut = "0.2.2"
lighthouse_metrics = { workspace = true }
parking_lot = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
slog = { workspace = true }
slog-async = { workspace = true }
slog-term = { workspace = true }
sloggers = { workspace = true }
take_mut = "0.2.2"
tokio = { workspace = true }
tracing-core = { workspace = true }
tracing-log = { workspace = true }
tracing-subscriber = { workspace = true }
3 changes: 3 additions & 0 deletions common/logging/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ pub const MAX_MESSAGE_WIDTH: usize = 40;

pub mod async_record;
mod sse_logging_components;
mod tracing_metrics_layer;

pub use sse_logging_components::SSELoggingComponents;
pub use tracing_metrics_layer::MetricsLayer;

/// The minimum interval between log messages indicating that a queue is full.
const LOG_DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30);
Expand Down
63 changes: 63 additions & 0 deletions common/logging/src/tracing_metrics_layer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! Exposes [`MetricsLayer`]: A tracing layer that registers metrics of logging events.

use lighthouse_metrics as metrics;
use tracing_log::NormalizeEvent;

lazy_static! {
/// Count of `INFO` logs registered per enabled dependency.
pub static ref DEP_INFOS_TOTAL: metrics::Result<metrics::IntCounterVec> =
metrics::try_create_int_counter_vec(
"dep_info_total",
"Count of infos logged per enabled dependency",
&["target"]
);
/// Count of `WARN` logs registered per enabled dependency.
pub static ref DEP_WARNS_TOTAL: metrics::Result<metrics::IntCounterVec> =
metrics::try_create_int_counter_vec(
"dep_warn_total",
"Count of warns logged per enabled dependency",
&["target"]
);
/// Count of `ERROR` logs registered per enabled dependency.
pub static ref DEP_ERRORS_TOTAL: metrics::Result<metrics::IntCounterVec> =
metrics::try_create_int_counter_vec(
"dep_error_total",
"Count of errors logged per enabled dependency",
&["target"]
);
}

/// Layer that registers Prometheus metrics for `INFO`, `WARN` and `ERROR` logs emitted per dependency.
/// Dependencies are enabled via the `RUST_LOG` env flag.
pub struct MetricsLayer;

impl<S: tracing_core::Subscriber> tracing_subscriber::layer::Layer<S> for MetricsLayer {
fn on_event(
&self,
event: &tracing_core::Event<'_>,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
// get the event's normalized metadata
// this is necessary to get the correct module path for libp2p events
let normalized_meta = event.normalized_metadata();
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());

if !meta.is_event() {
// ignore tracing span events
return;
}

let full_target = meta.module_path().unwrap_or_else(|| meta.target());
let target = full_target
.split_once("::")
.map(|(name, _rest)| name)
.unwrap_or(full_target);
let target = &[target];
match *meta.level() {
tracing_core::Level::INFO => metrics::inc_counter_vec(&DEP_INFOS_TOTAL, target),
tracing_core::Level::WARN => metrics::inc_counter_vec(&DEP_WARNS_TOTAL, target),
tracing_core::Level::ERROR => metrics::inc_counter_vec(&DEP_ERRORS_TOTAL, target),
_ => {}
}
}
}
3 changes: 2 additions & 1 deletion lighthouse/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ types = { workspace = true }
bls = { workspace = true }
ethereum_hashing = { workspace = true }
clap = { workspace = true }
env_logger = { workspace = true }
environment = { workspace = true }
boot_node = { path = "../boot_node" }
futures = { workspace = true }
Expand All @@ -57,6 +56,8 @@ unused_port = { workspace = true }
database_manager = { path = "../database_manager" }
slasher = { workspace = true }
validator_manager = { path = "../validator_manager" }
tracing-subscriber = { workspace = true }
logging = { workspace = true }

[dev-dependencies]
tempfile = { workspace = true }
Expand Down
34 changes: 29 additions & 5 deletions lighthouse/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use beacon_node::ProductionBeaconNode;
use clap::{App, Arg, ArgMatches};
use clap_utils::{flags::DISABLE_MALLOC_TUNING_FLAG, get_eth2_network_config};
use directory::{parse_path_or_default, DEFAULT_BEACON_NODE_DIR, DEFAULT_VALIDATOR_DIR};
use env_logger::{Builder, Env};
use environment::{EnvironmentBuilder, LoggerConfig};
use eth2_network_config::{Eth2NetworkConfig, DEFAULT_HARDCODED_NETWORK, HARDCODED_NET_NAMES};
use ethereum_hashing::have_sha_extensions;
Expand All @@ -15,6 +14,7 @@ use slog::{crit, info};
use std::path::PathBuf;
use std::process::exit;
use task_executor::ShutdownReason;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use types::{EthSpec, EthSpecId};
use validator_client::ProductionValidatorClient;

Expand Down Expand Up @@ -84,7 +84,8 @@ fn main() {
.arg(
Arg::with_name("env_log")
.short("l")
.help("Enables environment logging giving access to sub-protocol logs such as discv5 and libp2p",
.help(
"DEPRECATED Enables environment logging giving access to sub-protocol logs such as discv5 and libp2p",
jimmygchen marked this conversation as resolved.
Show resolved Hide resolved
)
.takes_value(false),
)
Expand Down Expand Up @@ -364,9 +365,32 @@ fn main() {
}
}

// Debugging output for libp2p and external crates.
if matches.is_present("env_log") {
Builder::from_env(Env::default()).init();
// read the `RUST_LOG` statement
let filter_layer = match tracing_subscriber::EnvFilter::try_from_default_env()
.or_else(|_| tracing_subscriber::EnvFilter::try_new("debug"))
{
Ok(filter) => filter,
Err(e) => {
eprintln!("Failed to initialize dependency logging {e}");
exit(1)
}
};

let turn_on_terminal_logs = matches.is_present("env_log");

if let Err(e) = tracing_subscriber::fmt()
.with_env_filter(filter_layer)
.with_writer(move || {
tracing_subscriber::fmt::writer::OptionalWriter::<std::io::Stdout>::from(
turn_on_terminal_logs.then(std::io::stdout),
)
})
.finish()
.with(logging::MetricsLayer)
.try_init()
{
eprintln!("Failed to initialize dependency logging {e}");
exit(1)
}

let result = get_eth2_network_config(&matches).and_then(|eth2_network_config| {
Expand Down
Loading