mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-03 00:31:50 +00:00
Logging via the HTTP API (#4074)
This PR adds the ability to read the Lighthouse logs from the HTTP API for both the BN and the VC. This is done in such a way to as minimize any kind of performance hit by adding this feature. The current design creates a tokio broadcast channel and mixes is into a form of slog drain that combines with our main global logger drain, only if the http api is enabled. The drain gets the logs, checks the log level and drops them if they are below INFO. If they are INFO or higher, it sends them via a broadcast channel only if there are users subscribed to the HTTP API channel. If not, it drops the logs. If there are more than one subscriber, the channel clones the log records and converts them to json in their independent HTTP API tasks. Co-authored-by: Michael Sproul <micsproul@gmail.com>
This commit is contained in:
@@ -36,11 +36,11 @@ tree_hash = "0.5.0"
|
||||
sysinfo = "0.26.5"
|
||||
system_health = { path = "../../common/system_health" }
|
||||
directory = { path = "../../common/directory" }
|
||||
logging = { path = "../../common/logging" }
|
||||
ethereum_serde_utils = "0.5.0"
|
||||
operation_pool = { path = "../operation_pool" }
|
||||
sensitive_url = { path = "../../common/sensitive_url" }
|
||||
unused_port = {path = "../../common/unused_port"}
|
||||
logging = { path = "../../common/logging" }
|
||||
store = { path = "../store" }
|
||||
|
||||
[dev-dependencies]
|
||||
@@ -51,4 +51,4 @@ genesis = { path = "../genesis" }
|
||||
|
||||
[[test]]
|
||||
name = "bn_http_api_tests"
|
||||
path = "tests/main.rs"
|
||||
path = "tests/main.rs"
|
||||
@@ -36,6 +36,7 @@ use eth2::types::{
|
||||
};
|
||||
use lighthouse_network::{types::SyncState, EnrExt, NetworkGlobals, PeerId, PubsubMessage};
|
||||
use lighthouse_version::version_with_platform;
|
||||
use logging::SSELoggingComponents;
|
||||
use network::{NetworkMessage, NetworkSenders, ValidatorSubscriptionMessage};
|
||||
use operation_pool::ReceivedPreCapella;
|
||||
use parking_lot::RwLock;
|
||||
@@ -108,6 +109,7 @@ pub struct Context<T: BeaconChainTypes> {
|
||||
pub network_senders: Option<NetworkSenders<T::EthSpec>>,
|
||||
pub network_globals: Option<Arc<NetworkGlobals<T::EthSpec>>>,
|
||||
pub eth1_service: Option<eth1::Service>,
|
||||
pub sse_logging_components: Option<SSELoggingComponents>,
|
||||
pub log: Logger,
|
||||
}
|
||||
|
||||
@@ -448,6 +450,9 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
let inner_ctx = ctx.clone();
|
||||
let log_filter = warp::any().map(move || inner_ctx.log.clone());
|
||||
|
||||
let inner_components = ctx.sse_logging_components.clone();
|
||||
let sse_component_filter = warp::any().map(move || inner_components.clone());
|
||||
|
||||
// Create a `warp` filter that provides access to local system information.
|
||||
let system_info = Arc::new(RwLock::new(sysinfo::System::new()));
|
||||
{
|
||||
@@ -3729,6 +3734,44 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
},
|
||||
);
|
||||
|
||||
// Subscribe to logs via Server Side Events
|
||||
// /lighthouse/logs
|
||||
let lighthouse_log_events = warp::path("lighthouse")
|
||||
.and(warp::path("logs"))
|
||||
.and(warp::path::end())
|
||||
.and(sse_component_filter)
|
||||
.and_then(|sse_component: Option<SSELoggingComponents>| {
|
||||
blocking_response_task(move || {
|
||||
if let Some(logging_components) = sse_component {
|
||||
// Build a JSON stream
|
||||
let s =
|
||||
BroadcastStream::new(logging_components.sender.subscribe()).map(|msg| {
|
||||
match msg {
|
||||
Ok(data) => {
|
||||
// Serialize to json
|
||||
match data.to_json_string() {
|
||||
// Send the json as a Server Side Event
|
||||
Ok(json) => Ok(Event::default().data(json)),
|
||||
Err(e) => Err(warp_utils::reject::server_sent_event_error(
|
||||
format!("Unable to serialize to JSON {}", e),
|
||||
)),
|
||||
}
|
||||
}
|
||||
Err(e) => Err(warp_utils::reject::server_sent_event_error(
|
||||
format!("Unable to receive event {}", e),
|
||||
)),
|
||||
}
|
||||
});
|
||||
|
||||
Ok::<_, warp::Rejection>(warp::sse::reply(warp::sse::keep_alive().stream(s)))
|
||||
} else {
|
||||
Err(warp_utils::reject::custom_server_error(
|
||||
"SSE Logging is not enabled".to_string(),
|
||||
))
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Define the ultimate set of routes that will be provided to the server.
|
||||
// Use `uor` rather than `or` in order to simplify types (see `UnifyingOrFilter`).
|
||||
let routes = warp::get()
|
||||
@@ -3796,6 +3839,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.uor(get_lighthouse_block_packing_efficiency)
|
||||
.uor(get_lighthouse_merge_readiness)
|
||||
.uor(get_events)
|
||||
.uor(lighthouse_log_events.boxed())
|
||||
.recover(warp_utils::reject::handle_rejection),
|
||||
)
|
||||
.boxed()
|
||||
|
||||
@@ -198,6 +198,7 @@ pub async fn create_api_server_on_port<T: BeaconChainTypes>(
|
||||
network_senders: Some(network_senders),
|
||||
network_globals: Some(network_globals),
|
||||
eth1_service: Some(eth1_service),
|
||||
sse_logging_components: None,
|
||||
log,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user