Skip to content

Commit

Permalink
hack global dispatcher to handle both global and default. (#80)
Browse files Browse the repository at this point in the history
1. in post, with_default will override the global tracing to get information
2. I get the global subscriber in a hack way.
3. set the global subscriber in Extrinsic subscriber 
4. when meet global require, record to global, meet ExtrinsicSubscriber require, record to self.
  • Loading branch information
atenjin authored Jun 18, 2021
1 parent 8a4b305 commit 69bf195
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 63 deletions.
15 changes: 7 additions & 8 deletions client/basic-authorship/src/basic_authorship.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use std::marker::PhantomData;
use prometheus_endpoint::Registry as PrometheusRegistry;
use sc_proposer_metrics::MetricsLink as PrometheusMetrics;

use crate::block_tracing::{handle_dispatch, BlockSubscriber};
use crate::block_tracing::{hack_global_subscriber, handle_dispatch, ExtrinsicSubscriber};
use ec_client_api::statekv::{ClientStateKv, StateKv};

/// Default block size limit in bytes used by [`Proposer`].
Expand Down Expand Up @@ -348,17 +348,15 @@ where
let mut extrinsic_count = 0_u32;
let state_kv = self.client.state_kv();

let global_subscriber = hack_global_subscriber();
let targets = "state";

for inherent in block_builder.create_inherents(inherent_data)? {
let r = {
let dispatch = Dispatch::new(BlockSubscriber::new(targets));
let dispatch =
Dispatch::new(ExtrinsicSubscriber::new(targets, global_subscriber.clone()));
let r =
dispatcher::with_default(&dispatch, || -> Result<(), sp_blockchain::Error> {
let span = tracing::info_span!(
target: "block_trace",
"trace_block",
);
let _enter = span.enter();
// push and execute inherent
block_builder.push(inherent)
});
Expand Down Expand Up @@ -456,7 +454,8 @@ where
trace!("[{:?}] Pushing to the block.", pending_tx_hash);

let r = {
let dispatch = Dispatch::new(BlockSubscriber::new(targets));
let dispatch =
Dispatch::new(ExtrinsicSubscriber::new(targets, global_subscriber.clone()));
let r =
dispatcher::with_default(&dispatch, || -> Result<(), sp_blockchain::Error> {
let span = tracing::info_span!(
Expand Down
110 changes: 57 additions & 53 deletions client/basic-authorship/src/block_tracing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@

// Copyright 2020-2021 patract labs. Licensed under GPL-3.0.

use std::{
collections::HashMap,
sync::atomic::{AtomicU64, Ordering},
time::Instant,
};
use std::sync::atomic::AtomicU64;

use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
use tracing::{
dispatcher,
span::{Attributes, Id, Record},
warn, Dispatch, Level, Subscriber,
};

use sc_tracing::{SpanDatum, TraceEvent, Values};
use sc_tracing::{TraceEvent, Values};
use sp_runtime::{traits::Block as BlockT, SaturatedConversion};
use sp_tracing::WASM_TRACE_IDENTIFIER;

Expand All @@ -25,10 +22,10 @@ use std::sync::Arc;

mod parser;

pub struct BlockSubscriber {
pub struct ExtrinsicSubscriber {
pub global: Arc<dyn Subscriber + Send + Sync>,
pub targets: Vec<(String, Level)>,
pub next_id: AtomicU64,
pub spans: Mutex<HashMap<Id, SpanDatum>>,
pub events: Mutex<Vec<TraceEvent>>,
}

Expand All @@ -49,86 +46,93 @@ fn parse_target(s: &str) -> (String, Level) {
}
}

impl BlockSubscriber {
pub fn new(targets: &str) -> Self {
impl ExtrinsicSubscriber {
pub fn new(targets: &str, global: Arc<dyn Subscriber + Send + Sync>) -> Self {
let next_id = AtomicU64::new(1);
let mut targets: Vec<_> = targets.split(',').map(parse_target).collect();
// Ensure that WASM traces are always enabled
// Filtering happens when decoding the actual target / level
targets.push((WASM_TRACE_IDENTIFIER.to_owned(), Level::TRACE));
BlockSubscriber {
ExtrinsicSubscriber {
global,
targets,
next_id,
spans: Mutex::new(HashMap::new()),
events: Mutex::new(Vec::new()),
}
}
}

impl Subscriber for BlockSubscriber {
fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
impl ExtrinsicSubscriber {
fn self_enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
for (target, level) in &self.targets {
if metadata.level() <= level && metadata.target().starts_with(target) {
return true;
}
}
false
}
}

fn new_span(&self, attrs: &Attributes<'_>) -> Id {
let id = Id::from_u64(self.next_id.fetch_add(1, Ordering::Relaxed));
let mut values = Values::default();
attrs.record(&mut values);
let parent_id = attrs.parent().cloned();
let span = SpanDatum {
id: id.clone(),
parent_id,
name: attrs.metadata().name().to_owned(),
target: attrs.metadata().target().to_owned(),
level: *attrs.metadata().level(),
line: attrs.metadata().line().unwrap_or(0),
start_time: Instant::now(),
values,
overall_time: Default::default(),
};
impl Subscriber for ExtrinsicSubscriber {
fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
self.global.enabled(metadata) | self.self_enabled(metadata)
}

self.spans.lock().insert(id.clone(), span);
id
fn new_span(&self, attrs: &Attributes<'_>) -> Id {
self.global.new_span(attrs)
}

fn record(&self, span: &Id, values: &Record<'_>) {
let mut span_data = self.spans.lock();
if let Some(s) = span_data.get_mut(span) {
values.record(&mut s.values);
}
self.global.record(span, values)
}

fn record_follows_from(&self, _span: &Id, _follows: &Id) {
// Not currently used
unimplemented!("record_follows_from is not implemented");
fn record_follows_from(&self, span: &Id, follows: &Id) {
self.global.record_follows_from(span, follows)
}

fn event(&self, event: &tracing::Event<'_>) {
let mut values = Values::default();
event.record(&mut values);
let parent_id = event.parent().cloned();
let trace_event = TraceEvent {
name: event.metadata().name().to_owned(),
target: event.metadata().target().to_owned(),
level: *event.metadata().level(),
values,
parent_id,
};
self.events.lock().push(trace_event);
if self.self_enabled(event.metadata()) {
let mut values = Values::default();
event.record(&mut values);
let parent_id = event.parent().cloned();
let trace_event = TraceEvent {
name: event.metadata().name().to_owned(),
target: event.metadata().target().to_owned(),
level: *event.metadata().level(),
values,
parent_id,
};
self.events.lock().push(trace_event);
}
if self.global.enabled(event.metadata()) {
self.global.event(event)
}
}

fn enter(&self, id: &Id) {
self.global.enter(id)
}

fn enter(&self, _id: &Id) {}
fn exit(&self, _span: &Id) {
self.global.exit(_span)
}
}

fn exit(&self, _span: &Id) {}
pub fn hack_global_subscriber() -> Arc<dyn Subscriber + Send + Sync> {
dispatcher::get_default(|d| {
// a hack way to get private subscriber in Dispatch to public field.
pub struct PublicDispatch {
pub subscriber: Arc<dyn Subscriber + Send + Sync>,
}
let pub_dispatch: PublicDispatch = unsafe { std::mem::transmute(d.clone()) };
pub_dispatch.subscriber
})
}

pub fn parse(dispatch: Dispatch) -> Vec<Event> {
let block_subscriber = dispatch.downcast_ref::<BlockSubscriber>().expect("fxck");
let block_subscriber = dispatch
.downcast_ref::<ExtrinsicSubscriber>()
.expect("must be same subscriber");
let events: Vec<_> = block_subscriber.events.lock().drain(..).collect();

use std::collections::BTreeMap;
Expand Down
3 changes: 2 additions & 1 deletion client/basic-authorship/src/block_tracing/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,8 @@ mod tests {
}
}

let dispatch = Dispatch::new(BlockSubscriber::new("state"));
let global = hack_global_subscriber();
let dispatch = Dispatch::new(ExtrinsicSubscriber::new("state", global));
dispatcher::with_default(&dispatch, || -> Result<(), sp_blockchain::Error> {
let span = tracing::info_span!(
target: "block_trace",
Expand Down
2 changes: 1 addition & 1 deletion vendor/substrate

0 comments on commit 69bf195

Please sign in to comment.