我在项目中使用跟踪库,但有一件事我无法弄清楚:如何访问我的 中的值(我在创建它时在跨度中设置的值)Layer?
我的图层看起来像这样:
impl<S> Layer<S> for CustomLayer where S: Subscriber {
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
Interest::sometimes() //hardcoding so enabled() will be called everytime a span is created
}
fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool {
if metadata.is_span() {
// How do I access value of key here?
if value == X {
true
} else if value == Y {
false
}
}
true // default
}
}
Run Code Online (Sandbox Code Playgroud)
Span如果您有权访问 a 中的数据ValueSet(如在new_span()或on_new_span()via中找到Attributes)或其Record条目(如在record()或中找到on_record()),则可以访问 a 中的数据。这样您就可以使用访客模式来查找您想要的信息。这是一个简单的实现,用于检查字段是否存在及其值是否是匹配的字符串:
use std::fmt::Debug;
use tracing::field::{ValueSet, Visit, Field};
use tracing::span::Record;
struct MatchStrVisitor<'a> {
field: &'a str,
value: &'a str,
matched: bool,
}
impl Visit for MatchStrVisitor<'_> {
fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {}
fn record_str(&mut self, field: &Field, value: &str) {
if field.name() == self.field && value == self.value {
self.matched = true;
}
}
}
fn value_in_valueset(valueset: &ValueSet<'_>, field: &str, value: &str) -> bool {
let mut visitor = MatchStrVisitor { field, value, matched: false };
valueset.record(&mut visitor);
visitor.matched
}
fn value_in_record(record: &Record<'_>, field: &str, value: &str) -> bool {
let mut visitor = MatchStrVisitor { field, value, matched: false };
record.record(&mut visitor);
visitor.matched
}
Run Code Online (Sandbox Code Playgroud)
这是相当初级的,但希望能展示什么是可能的。需要注意的一件事是,存储的“值”要么是原始值(i64、u64、bool、str等),要么是通过 类型擦除的形式&dyn Debug。这些是您可以从访问者那里收到的唯一类型的值。
特别针对 OP 的情况,如本期所述,您无法在方法中访问此信息enabled(),因为这是在记录任何值之前发生的。您需要在new_span()方法中做出决定,并通过注册表使用跨度扩展来跟踪您是否认为该跨度在其他方法中“启用”。
这是另一个基本示例:
use tracing::span::Attributes;
use tracing::{Subscriber, Metadata, Id, Event};
use tracing::subscriber::Interest;
use tracing_subscriber::layer::{Context, Layer};
use tracing_subscriber::registry::LookupSpan;
struct CustomLayer;
struct CustomLayerEnabled;
impl<S> Layer<S> for CustomLayer where S: Subscriber + for <'a> LookupSpan<'a> {
fn register_callsite(&self, _metadata: &'static Metadata<'static>) -> Interest {
Interest::sometimes()
}
fn enabled(&self, metadata: &Metadata<'_>, _ctx: Context<'_, S>) -> bool {
metadata.is_span()
}
fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
if value_in_valueset(attrs.values(), "myfield", "myvalue") {
ctx.span(id).unwrap().extensions_mut().insert(CustomLayerEnabled);
}
}
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
let span_id = event.parent().unwrap();
if let None = ctx.span(span_id).unwrap().extensions().get::<CustomLayerEnabled>() {
return;
}
// ... rest of your logic
}
}
Run Code Online (Sandbox Code Playgroud)
注意:我已经完全重写了这个答案,从评论和我新发现的经验中获取信息。
| 归档时间: |
|
| 查看次数: |
1931 次 |
| 最近记录: |