use std::cell::Cell;
use tracing_subscriber::registry::{LookupSpan, SpanRef};
use crate::field_mapping::{ExtractedFields, FieldExtractor};
use crate::tracing_field::get_tracing_fields;
thread_local! {
pub(crate) static SELF_RECORDING: Cell<bool> = const { Cell::new(false) };
}
pub(crate) fn extract_span_fields<S>(
attrs: &tracing_core::span::Attributes<'_>,
span: &SpanRef<'_, S>,
) where
S: for<'a> LookupSpan<'a>,
{
let metadata_fields = get_tracing_fields();
let extract_names: Vec<&'static str> = metadata_fields
.iter()
.filter(|e| e.extract.is_some())
.map(|e| e.span_field)
.collect();
let record_fields: Vec<&'static str> = metadata_fields
.iter()
.filter(|e| e.span_fmt_fn.is_some())
.map(|e| e.record_field)
.collect();
if extract_names.is_empty() && record_fields.is_empty() {
return;
}
let all_target: Vec<&'static str> = extract_names
.iter()
.chain(record_fields.iter())
.copied()
.collect();
let mut extractor = FieldExtractor::new(&all_target);
attrs.record(&mut extractor);
for &rf in &record_fields {
if extractor.extracted.string_values.contains_key(rf)
|| extractor.extracted.u64_values.contains_key(rf)
|| extractor.extracted.i64_values.contains_key(rf)
|| extractor.extracted.bool_values.contains_key(rf)
{
extractor.extracted.mark_user_set(rf);
}
}
if !extractor.extracted.is_empty() || !extractor.extracted.user_set_fields.is_empty() {
let mut extensions = span.extensions_mut();
extensions.insert(extractor.extracted);
}
}
pub(crate) fn merge_recorded_fields<S>(
values: &tracing_core::span::Record<'_>,
span: &SpanRef<'_, S>,
) where
S: for<'a> LookupSpan<'a>,
{
if SELF_RECORDING.with(|f| f.get()) {
return;
}
let metadata_fields = get_tracing_fields();
let extract_names: Vec<&'static str> = metadata_fields
.iter()
.filter(|e| e.extract.is_some())
.map(|e| e.span_field)
.collect();
let record_fields: Vec<&'static str> = metadata_fields
.iter()
.filter(|e| e.span_fmt_fn.is_some())
.map(|e| e.record_field)
.collect();
if extract_names.is_empty() && record_fields.is_empty() {
return;
}
let all_target: Vec<&'static str> = extract_names
.iter()
.chain(record_fields.iter())
.copied()
.collect();
let mut extractor = FieldExtractor::new(&all_target);
values.record(&mut extractor);
if !extractor.extracted.is_empty() {
let mut extensions = span.extensions_mut();
for &rf in &record_fields {
if extractor.extracted.string_values.contains_key(rf)
|| extractor.extracted.u64_values.contains_key(rf)
|| extractor.extracted.i64_values.contains_key(rf)
|| extractor.extracted.bool_values.contains_key(rf)
{
extractor.extracted.mark_user_set(rf);
}
}
if let Some(existing) = extensions.get_mut::<ExtractedFields>() {
existing
.string_values
.extend(extractor.extracted.string_values);
existing.u64_values.extend(extractor.extracted.u64_values);
existing.i64_values.extend(extractor.extracted.i64_values);
existing.bool_values.extend(extractor.extracted.bool_values);
existing
.user_set_fields
.extend(extractor.extracted.user_set_fields);
} else {
extensions.insert(extractor.extracted);
}
}
}