Skip to content

Commit 5f24f65

Browse files
committed
A working version
1 parent 4da3351 commit 5f24f65

File tree

15 files changed

+172
-35
lines changed

15 files changed

+172
-35
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

beacon_node/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ serde = "1.0.116"
3535
clap_utils = { path = "../common/clap_utils" }
3636
hyper = "0.14.4"
3737
lighthouse_version = { path = "../common/lighthouse_version" }
38-
logging = { path = "../common/logging" }
3938
hex = "0.4.2"
4039
slasher = { path = "../slasher", default-features = false }
4140
monitoring_api = { path = "../common/monitoring_api" }

beacon_node/client/src/builder.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use eth2::{
1919
types::{BlockId, StateId},
2020
BeaconNodeHttpClient, Error as ApiError, Timeouts,
2121
};
22-
use logging::SSELoggingComponents;
2322
use execution_layer::ExecutionLayer;
2423
use genesis::{interop_genesis_state, Eth1GenesisService, DEFAULT_ETH1_BLOCK_HASH};
2524
use lighthouse_network::{prometheus_client::registry::Registry, NetworkGlobals};
@@ -73,7 +72,6 @@ pub struct ClientBuilder<T: BeaconChainTypes> {
7372
http_metrics_config: http_metrics::Config,
7473
slasher: Option<Arc<Slasher<T::EthSpec>>>,
7574
eth_spec_instance: T::EthSpec,
76-
sse_logging_components: Option<SSELoggingComponents>,
7775

7876
}
7977

@@ -89,7 +87,7 @@ where
8987
/// Instantiates a new, empty builder.
9088
///
9189
/// The `eth_spec_instance` parameter is used to concretize `TEthSpec`.
92-
pub fn new(eth_spec_instance: TEthSpec, sse_logging_components: Option<SSELoggingComponents>) -> Self {
90+
pub fn new(eth_spec_instance: TEthSpec) -> Self {
9391
Self {
9492
slot_clock: None,
9593
store: None,
@@ -107,7 +105,6 @@ where
107105
http_metrics_config: <_>::default(),
108106
slasher: None,
109107
eth_spec_instance,
110-
sse_logging_components,
111108
}
112109
}
113110

@@ -476,7 +473,7 @@ where
476473
network_globals: None,
477474
eth1_service: Some(genesis_service.eth1_service.clone()),
478475
log: context.log().clone(),
479-
sse_logging_components: self.sse_logging_components.take(),
476+
sse_logging_components: runtime_context.sse_logging_components.clone(),
480477
});
481478

482479
// Discard the error from the oneshot.
@@ -601,12 +598,6 @@ where
601598
self
602599
}
603600

604-
/// Adds SSE Logging components to the builder if they exist.
605-
pub fn sse_logging_comonents(mut self, components: Option<SSELoggingComponents>) -> Self {
606-
self.sse_logging_components = components;
607-
self
608-
}
609-
610601
/// Provides configuration for the HTTP server that serves Prometheus metrics.
611602
pub fn http_metrics_config(mut self, config: http_metrics::Config) -> Self {
612603
self.http_metrics_config = config;
@@ -703,7 +694,7 @@ where
703694
network_senders: self.network_senders.clone(),
704695
network_globals: self.network_globals.clone(),
705696
eth1_service: self.eth1_service.clone(),
706-
sse_logging_components: self.sse_logging_components.take(),
697+
sse_logging_components: runtime_context.sse_logging_components.clone(),
707698
log: log.clone(),
708699
});
709700

beacon_node/src/lib.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use slog::{info, warn};
2121
use std::ops::{Deref, DerefMut};
2222
use std::sync::Arc;
2323
use types::EthSpec;
24-
use logging::SSELoggingComponents;
2524

2625
/// A type-alias to the tighten the definition of a production-intended `Client`.
2726
pub type ProductionClient<E> =
@@ -46,10 +45,9 @@ impl<E: EthSpec> ProductionBeaconNode<E> {
4645
pub async fn new_from_cli(
4746
context: RuntimeContext<E>,
4847
matches: ArgMatches<'static>,
49-
sse_log: Option<SSELoggingComponents>,
5048
) -> Result<Self, String> {
5149
let client_config = get_config::<E>(&matches, &context)?;
52-
Self::new(context, client_config, sse_log).await
50+
Self::new(context, client_config).await
5351
}
5452

5553
/// Starts a new beacon node `Client` in the given `environment`.
@@ -58,7 +56,6 @@ impl<E: EthSpec> ProductionBeaconNode<E> {
5856
pub async fn new(
5957
context: RuntimeContext<E>,
6058
mut client_config: ClientConfig,
61-
sse_logging_components: Option<SSELoggingComponents>,
6259
) -> Result<Self, String> {
6360
let spec = context.eth2_config().spec.clone();
6461
let client_genesis = client_config.genesis.clone();
@@ -83,7 +80,7 @@ impl<E: EthSpec> ProductionBeaconNode<E> {
8380
TimeoutRwLock::disable_timeouts()
8481
}
8582

86-
let builder = ClientBuilder::new(context.eth_spec_instance.clone(), sse_logging_components)
83+
let builder = ClientBuilder::new(context.eth_spec_instance.clone())
8784
.runtime_context(context)
8885
.chain_spec(spec)
8986
.http_api_config(client_config.http_api.clone())

book/src/api-lighthouse.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,3 +677,32 @@ Caveats:
677677
This is because the state _prior_ to the `start_epoch` needs to be loaded from the database, and
678678
loading a state on a boundary is most efficient.
679679

680+
681+
### `/lighthouse/logs`
682+
683+
This is a Server Side Event subscription endpoint. This allows a user to read
684+
the Lighthouse logs directly from the HTTP API endpoint. This currently
685+
exposes INFO and higher level logs.
686+
687+
Example:
688+
689+
```bash
690+
curl -N "http://localhost:5052/lighthouse/logs"
691+
```
692+
693+
Should provide an output that emits log events as they occur:
694+
```json
695+
{
696+
"data": {
697+
"time": "Mar 13 15:28:41",
698+
"level": "INFO",
699+
"msg": "Syncing",
700+
"service": "slot_notifier",
701+
"est_time": "1 hr 27 mins",
702+
"speed": "5.33 slots/sec",
703+
"distance": "28141 slots (3 days 21 hrs)",
704+
"peers": "8"
705+
}
706+
}
707+
```
708+

book/src/api-vc-endpoints.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,3 +578,33 @@ The following fields may be omitted or nullified to obtain default values:
578578
### Example Response Body
579579

580580
*No data is included in the response body.*
581+
582+
## `GET /lighthouse/logs`
583+
584+
Provides a subscription to receive logs as Server Side Events. Currently the
585+
logs emitted are INFO level or higher.
586+
587+
### HTTP Specification
588+
589+
| Property | Specification |
590+
|-------------------|--------------------------------------------|
591+
| Path | `/lighthouse/logs` |
592+
| Method | GET |
593+
| Required Headers | [`Authorization`](./api-vc-auth-header.md) |
594+
| Typical Responses | 200 |
595+
596+
### Example Response Body
597+
598+
```json
599+
{
600+
"data": {
601+
"time": "Mar 13 15:26:53",
602+
"level": "INFO",
603+
"msg": "Connected to beacon node(s)",
604+
"service": "notifier",
605+
"synced": 1,
606+
"available": 1,
607+
"total": 1
608+
}
609+
}
610+
```

common/logging/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ take_mut = "0.2.2"
1919
parking_lot = "0.12.1"
2020
serde = "1.0.153"
2121
serde_json = "1.0.94"
22+
chrono = "0.4.23"

common/logging/src/async_record.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,17 +158,27 @@ impl Serialize for AsyncRecord {
158158
where
159159
S: serde::Serializer,
160160
{
161+
// Get the current time
162+
let dt = chrono::Local::now().format("%b %e %T").to_string();
163+
161164
let rs = RecordStatic {
162165
location: &*self.location,
163166
level: self.level,
164167
tag: &self.tag,
165168
};
166169
let mut map_serializer = SerdeSerializer::new(serializer)?;
170+
171+
// Serialize the time and log level first
172+
map_serializer.serialize_entry("time", &dt)?;
173+
map_serializer.serialize_entry("level", &self.level.as_short_str())?;
174+
167175
let kv = self.kv.lock();
168176

169177
// Convoluted pattern to avoid binding `format_args!` to a temporary.
170178
// See: https://stackoverflow.com/questions/56304313/cannot-use-format-args-due-to-temporary-value-is-freed-at-the-end-of-this-state
171179
let mut f = |msg: std::fmt::Arguments| {
180+
map_serializer.serialize_entry("msg", &msg.to_string())?;
181+
172182
let record = Record::new(&rs, &msg, BorrowedKV(&(*kv)));
173183
self.logger_values
174184
.serialize(&record, &mut map_serializer)
@@ -179,7 +189,6 @@ impl Serialize for AsyncRecord {
179189
.map_err(serde::ser::Error::custom)
180190
};
181191
f(format_args!("{}", self.msg))?;
182-
183192
map_serializer.end()
184193
}
185194
}
@@ -195,6 +204,14 @@ impl<S: serde::Serializer> SerdeSerializer<S> {
195204
Ok(SerdeSerializer { ser_map })
196205
}
197206

207+
fn serialize_entry<K, V>(&mut self, key: K, value: V) -> Result<(), S::Error>
208+
where
209+
K: serde::Serialize,
210+
V: serde::Serialize,
211+
{
212+
self.ser_map.serialize_entry(&key, &value)
213+
}
214+
198215
/// Finish serialization, and return the serializer
199216
fn end(self) -> Result<S::Ok, S::Error> {
200217
self.ser_map.end()

common/logging/src/sse_logging_components.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ use std::panic::AssertUnwindSafe;
77
use std::sync::Arc;
88
use tokio::sync::broadcast::Sender;
99

10+
/// Default log level for SSE Events.
11+
// NOTE: Made this a constant. Debug level seems to be pretty intense. Can make this
12+
// configurable later if needed.
13+
const LOG_LEVEL: slog::Level = slog::Level::Info;
14+
1015
/// The components required in the HTTP API task to receive logged events.
1116
#[derive(Clone)]
1217
pub struct SSELoggingComponents {
@@ -29,10 +34,12 @@ impl Drain for SSELoggingComponents {
2934
type Err = &'static str;
3035

3136
fn log(&self, record: &Record, logger_values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
32-
// There are subscribers, attempt to send the logs
33-
match self.sender.send(AsyncRecord::from(record, logger_values)) {
34-
Ok(_num_sent) => {} // Everything got sent
35-
Err(_err) => {} // There are no subscribers, do nothing
37+
if record.level().is_at_least(LOG_LEVEL) {
38+
// There are subscribers, attempt to send the logs
39+
match self.sender.send(AsyncRecord::from(record, logger_values)) {
40+
Ok(_num_sent) => {} // Everything got sent
41+
Err(_err) => {} // There are no subscribers, do nothing
42+
}
3643
}
3744
Ok(())
3845
}

lighthouse/environment/src/lib.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub struct RuntimeContext<E: EthSpec> {
9090
pub eth_spec_instance: E,
9191
pub eth2_config: Eth2Config,
9292
pub eth2_network_config: Option<Arc<Eth2NetworkConfig>>,
93+
pub sse_logging_components: Option<SSELoggingComponents>,
9394
}
9495

9596
impl<E: EthSpec> RuntimeContext<E> {
@@ -102,6 +103,7 @@ impl<E: EthSpec> RuntimeContext<E> {
102103
eth_spec_instance: self.eth_spec_instance.clone(),
103104
eth2_config: self.eth2_config.clone(),
104105
eth2_network_config: self.eth2_network_config.clone(),
106+
sse_logging_components: self.sse_logging_components.clone(),
105107
}
106108
}
107109

@@ -325,6 +327,7 @@ impl<E: EthSpec> EnvironmentBuilder<E> {
325327

326328
log = Logger::root(Duplicate::new(log, sse_logger).fuse(), o!());
327329
}
330+
328331
self.log = Some(log);
329332

330333
Ok(self)
@@ -414,6 +417,7 @@ impl<E: EthSpec> Environment<E> {
414417
eth_spec_instance: self.eth_spec_instance.clone(),
415418
eth2_config: self.eth2_config.clone(),
416419
eth2_network_config: self.eth2_network_config.clone(),
420+
sse_logging_components: self.sse_logging_components.clone(),
417421
}
418422
}
419423

@@ -429,6 +433,7 @@ impl<E: EthSpec> Environment<E> {
429433
eth_spec_instance: self.eth_spec_instance.clone(),
430434
eth2_config: self.eth2_config.clone(),
431435
eth2_network_config: self.eth2_network_config.clone(),
436+
sse_logging_components: self.sse_logging_components.clone(),
432437
}
433438
}
434439

@@ -550,13 +555,6 @@ impl<E: EthSpec> Environment<E> {
550555
}
551556
}
552557

553-
/// Takes the receiver of the SSE Log components if one exists.
554-
/// This is used to obtain the receiver of the SSE log channel in order to pass it to the HTTP
555-
/// API.
556-
pub fn get_sse_log(&mut self) -> Option<SSELoggingComponents> {
557-
self.sse_logging_components.take()
558-
}
559-
560558
/// Fire exit signal which shuts down all spawned services
561559
pub fn fire_signal(&mut self) {
562560
if let Some(signal) = self.signal.take() {

0 commit comments

Comments
 (0)