bevy_remote_devtools_plugin/tracing_tracking/
events.rs

1use std::{
2    collections::{HashMap, VecDeque},
3    marker::PhantomData,
4    sync::Mutex,
5    time::SystemTime,
6};
7
8use bevy::{log::Level, utils::tracing::Subscriber};
9use chrono::{DateTime, Utc};
10use rweb::Schema;
11use serde::Serialize;
12use tracing_subscriber::{field::Visit, registry::LookupSpan, Layer};
13
14pub struct EventLayer<S>
15where
16    S: Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
17{
18    _inner: PhantomData<S>,
19}
20
21impl<S> EventLayer<S>
22where
23    S: Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
24{
25    pub fn new() -> Self {
26        Self {
27            _inner: PhantomData,
28        }
29    }
30}
31
32impl<S> Layer<S> for EventLayer<S>
33where
34    S: Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
35{
36    fn on_event(
37        &self,
38        event: &bevy::utils::tracing::Event<'_>,
39        _ctx: tracing_subscriber::layer::Context<'_, S>,
40    ) {
41        if event.metadata().target().contains("wgpu")
42            || event.metadata().target().contains("warp")
43            || event.metadata().target().contains("hyper")
44            || event.metadata().target().contains("draw_state")
45            || event.metadata().target().contains("diagnostic")
46            || *event.metadata().level() == Level::TRACE
47        {
48            return;
49        }
50
51        if let Ok(mut events) = STORED_EVENTS.lock() {
52            if events.len() == MAX_EVENTS {
53                events.pop_back();
54            }
55            let mut record = StoredRecord::new();
56            event.record(&mut record);
57            events.push_front(StoredEvent {
58                target: event.metadata().target().to_string(),
59                time: SystemTime::now().into(),
60                record,
61            });
62        }
63    }
64}
65
66const MAX_EVENTS: usize = 300;
67
68lazy_static::lazy_static! {
69  pub(crate) static ref STORED_EVENTS: Mutex<VecDeque<StoredEvent>> = {
70    Mutex::new(VecDeque::with_capacity(MAX_EVENTS))
71  };
72}
73
74#[derive(Serialize, Debug, Schema, Clone)]
75pub(crate) struct StoredEvent {
76    target: String,
77    time: DateTime<Utc>,
78    record: StoredRecord,
79}
80#[derive(Serialize, Debug, Schema, Clone)]
81pub(crate) struct StoredRecord {
82    properties: HashMap<String, String>,
83}
84
85impl StoredRecord {
86    fn new() -> Self {
87        Self {
88            properties: HashMap::new(),
89        }
90    }
91}
92
93impl Visit for StoredRecord {
94    fn record_debug(
95        &mut self,
96        field: &bevy::utils::tracing::field::Field,
97        value: &dyn std::fmt::Debug,
98    ) {
99        self.properties
100            .insert(field.to_string(), format!("{:#?}", value));
101    }
102    fn record_str(&mut self, field: &bevy::utils::tracing::field::Field, value: &str) {
103        self.properties.insert(field.to_string(), value.to_string());
104    }
105}