bevy_remote_devtools_plugin/tracing_tracking/
events.rs1use 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}