|
1 | | -use tracing::{Metadata, Subscriber}; |
2 | | -use tracing_subscriber::layer::{Context, Filter}; |
| 1 | +use tracing::Subscriber; |
3 | 2 |
|
4 | 3 | /// DA checker spans |
5 | 4 | pub const SPAN_PENDING_COMPONENTS: &str = "pending_components"; |
@@ -51,28 +50,112 @@ pub const LH_BN_ROOT_SPAN_NAMES: &[&str] = &[ |
51 | 50 | SPAN_HANDLE_LIGHT_CLIENT_FINALITY_UPDATE, |
52 | 51 | ]; |
53 | 52 |
|
54 | | -/// Filter that only allows spans that either: |
55 | | -/// - Have a parent span, or |
56 | | -/// - Are root spans with names matching the predefined allowed list |
57 | | -pub struct AllowedRootSpanFilter(&'static [&'static str]); |
| 53 | +use std::collections::HashSet; |
| 54 | +use tracing::span::Id; |
| 55 | +use tracing_subscriber::Layer; |
58 | 56 |
|
59 | | -impl AllowedRootSpanFilter { |
60 | | - pub fn new(allowed_names: &'static [&'static str]) -> Self { |
61 | | - AllowedRootSpanFilter(allowed_names) |
| 57 | +/// A filtering layer that wraps another layer and only forwards spans from allowed root spans and their descendants |
| 58 | +pub struct AllowedRootSpanLayer<L> { |
| 59 | + inner: L, |
| 60 | + allowed_names: &'static [&'static str], |
| 61 | + allowed_spans: std::sync::Mutex<HashSet<Id>>, |
| 62 | +} |
| 63 | + |
| 64 | +impl<L> AllowedRootSpanLayer<L> { |
| 65 | + pub fn new(inner: L, allowed_names: &'static [&'static str]) -> Self { |
| 66 | + AllowedRootSpanLayer { |
| 67 | + inner, |
| 68 | + allowed_names, |
| 69 | + allowed_spans: std::sync::Mutex::new(HashSet::new()), |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + fn is_span_allowed(&self, span_id: &Id) -> bool { |
| 74 | + self.allowed_spans.lock().unwrap().contains(span_id) |
| 75 | + } |
| 76 | + |
| 77 | + fn mark_span_allowed(&self, span_id: Id) { |
| 78 | + self.allowed_spans.lock().unwrap().insert(span_id); |
| 79 | + } |
| 80 | + |
| 81 | + fn remove_span(&self, span_id: &Id) { |
| 82 | + self.allowed_spans.lock().unwrap().remove(span_id); |
62 | 83 | } |
63 | 84 | } |
64 | 85 |
|
65 | | -impl<S> Filter<S> for AllowedRootSpanFilter |
| 86 | +impl<S, L> Layer<S> for AllowedRootSpanLayer<L> |
66 | 87 | where |
67 | | - S: Subscriber, |
| 88 | + S: Subscriber + for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>, |
| 89 | + L: Layer<S>, |
68 | 90 | { |
69 | | - fn enabled(&self, metadata: &Metadata<'_>, ctx: &Context<'_, S>) -> bool { |
70 | | - // Has a parent span: allow |
71 | | - if ctx.current_span().id().is_some() { |
72 | | - return true; |
| 91 | + fn on_new_span( |
| 92 | + &self, |
| 93 | + attrs: &tracing::span::Attributes<'_>, |
| 94 | + id: &Id, |
| 95 | + ctx: tracing_subscriber::layer::Context<'_, S>, |
| 96 | + ) { |
| 97 | + let should_allow = if let Some(parent_id) = ctx.current_span().id() { |
| 98 | + // This span has a parent - allow it if the parent is allowed |
| 99 | + self.is_span_allowed(parent_id) |
| 100 | + } else { |
| 101 | + // This is a root span - allow it if it's in the allowed list |
| 102 | + self.allowed_names.contains(&attrs.metadata().name()) |
| 103 | + }; |
| 104 | + |
| 105 | + if should_allow { |
| 106 | + self.mark_span_allowed(id.clone()); |
| 107 | + self.inner.on_new_span(attrs, id, ctx); |
73 | 108 | } |
| 109 | + } |
| 110 | + |
| 111 | + fn on_record( |
| 112 | + &self, |
| 113 | + span: &Id, |
| 114 | + values: &tracing::span::Record<'_>, |
| 115 | + ctx: tracing_subscriber::layer::Context<'_, S>, |
| 116 | + ) { |
| 117 | + if self.is_span_allowed(span) { |
| 118 | + self.inner.on_record(span, values, ctx); |
| 119 | + } |
| 120 | + } |
74 | 121 |
|
75 | | - // Root span: only allow if in allowed list |
76 | | - self.0.contains(&metadata.name()) |
| 122 | + fn on_follows_from( |
| 123 | + &self, |
| 124 | + span: &Id, |
| 125 | + follows: &Id, |
| 126 | + ctx: tracing_subscriber::layer::Context<'_, S>, |
| 127 | + ) { |
| 128 | + if self.is_span_allowed(span) { |
| 129 | + self.inner.on_follows_from(span, follows, ctx); |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + fn on_event(&self, event: &tracing::Event<'_>, ctx: tracing_subscriber::layer::Context<'_, S>) { |
| 134 | + // Check if we're in an allowed span context |
| 135 | + if let Some(current_span_id) = ctx.current_span().id() |
| 136 | + && self.is_span_allowed(current_span_id) |
| 137 | + { |
| 138 | + self.inner.on_event(event, ctx); |
| 139 | + } |
| 140 | + // If no current span, we could choose to allow or disallow events - for now, disallow |
| 141 | + } |
| 142 | + |
| 143 | + fn on_enter(&self, id: &Id, ctx: tracing_subscriber::layer::Context<'_, S>) { |
| 144 | + if self.is_span_allowed(id) { |
| 145 | + self.inner.on_enter(id, ctx); |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + fn on_exit(&self, id: &Id, ctx: tracing_subscriber::layer::Context<'_, S>) { |
| 150 | + if self.is_span_allowed(id) { |
| 151 | + self.inner.on_exit(id, ctx); |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + fn on_close(&self, id: Id, ctx: tracing_subscriber::layer::Context<'_, S>) { |
| 156 | + if self.is_span_allowed(&id) { |
| 157 | + self.inner.on_close(id.clone(), ctx); |
| 158 | + } |
| 159 | + self.remove_span(&id); |
77 | 160 | } |
78 | 161 | } |
0 commit comments