Improve logging and trace listeners
This commit is contained in:
		
							parent
							
								
									8caa569fb1
								
							
						
					
					
						commit
						6e49d0f849
					
				| @ -36,7 +36,7 @@ fn main() -> Result<()> { | ||||
| 
 | ||||
|     let sections = query_sections(&conn)?; | ||||
|     for sec in sections { | ||||
|         info!("section: {:?}", sec); | ||||
|         info!(section = debug(&sec), "read section"); | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
|  | ||||
| @ -3,7 +3,7 @@ use rusqlite::{params, Connection}; | ||||
| use std::collections::BTreeMap; | ||||
| use std::ops::Bound::{Excluded, Unbounded}; | ||||
| use thiserror::Error; | ||||
| use tracing::{debug, trace}; | ||||
| use tracing::{debug, trace, info}; | ||||
| 
 | ||||
| #[derive(Debug, Error)] | ||||
| pub enum MigrationError { | ||||
| @ -144,6 +144,7 @@ impl Migrations { | ||||
|             last_ver = *ver; | ||||
|         } | ||||
|         if last_ver != NO_MIGRATIONS { | ||||
|             info!(old_version = db_version, new_version = last_ver, "applied database migrations"); | ||||
|             set_db_version(&trans, last_ver)?; | ||||
|         } | ||||
|         trans.commit()?; | ||||
|  | ||||
| @ -117,17 +117,22 @@ impl SectionRunner { | ||||
| mod test { | ||||
|     use super::*; | ||||
|     use crate::section_interface::MockSectionInterface; | ||||
|     use tracing_subscriber::prelude::*; | ||||
|     use crate::trace_listeners::{EventListener, Filters, SpanFilters, SpanListener}; | ||||
|     use tracing_subscriber::prelude::*; | ||||
| 
 | ||||
|     #[tokio::test] | ||||
|     async fn test_quit() { | ||||
|         let quit_msg = EventListener::new( | ||||
|             Filters::new() | ||||
|                 .filter_message("runner_task recv") | ||||
|                 .filter_field_value("msg", "Quit"), | ||||
|                 .target("sprinklers_rs::section_runner") | ||||
|                 .message("runner_task recv") | ||||
|                 .field_value("msg", "Quit"), | ||||
|         ); | ||||
|         let task_span = SpanListener::new( | ||||
|             SpanFilters::new() | ||||
|                 .target("sprinklers_rs::section_runner") | ||||
|                 .name("runner_task"), | ||||
|         ); | ||||
|         let task_span = SpanListener::new(SpanFilters::new().filter_name("runner_task")); | ||||
|         let subscriber = tracing_subscriber::registry() | ||||
|             .with(quit_msg.clone()) | ||||
|             .with(task_span.clone()); | ||||
|  | ||||
| @ -11,6 +11,8 @@ use tracing_subscriber::{ | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct Filters { | ||||
|     filter_target: Option<String>, | ||||
|     filter_name: Option<String>, | ||||
|     filter_message: Option<String>, | ||||
|     filter_field: Option<String>, | ||||
|     filter_field_value: Option<String>, | ||||
| @ -19,27 +21,53 @@ pub struct Filters { | ||||
| impl Filters { | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             filter_target: None, | ||||
|             filter_name: None, | ||||
|             filter_message: None, | ||||
|             filter_field: None, | ||||
|             filter_field_value: None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn filter_message(mut self, message: impl ToString) -> Self { | ||||
|     pub fn target(mut self, target: impl ToString) -> Self { | ||||
|         self.filter_target = Some(target.to_string()); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn name(mut self, name: impl ToString) -> Self { | ||||
|         self.filter_name = Some(name.to_string()); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn message(mut self, message: impl ToString) -> Self { | ||||
|         self.filter_message = Some(message.to_string()); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn filter_field(mut self, field: impl ToString) -> Self { | ||||
|     pub fn field(mut self, field: impl ToString) -> Self { | ||||
|         self.filter_field = Some(field.to_string()); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn filter_field_value(mut self, field: impl ToString, value: impl ToString) -> Self { | ||||
|     pub fn field_value(mut self, field: impl ToString, value: impl ToString) -> Self { | ||||
|         self.filter_field = Some(field.to_string()); | ||||
|         self.filter_field_value = Some(value.to_string()); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     fn matches_metadata(&self, metadata: &tracing::Metadata) -> bool { | ||||
|         if let Some(target) = &self.filter_target { | ||||
|             if metadata.target() != target { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         if let Some(name) = &self.filter_name { | ||||
|             if metadata.name() != name { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         true | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct TraceListenerVisitor<'a> { | ||||
| @ -104,6 +132,10 @@ impl EventListener { | ||||
| } | ||||
| impl<S: Subscriber> Layer<S> for EventListener { | ||||
|     fn on_event(&self, ev: &tracing::Event, _: Context<S>) { | ||||
|         println!("event name: {}", ev.metadata().name()); | ||||
|         if !self.filters.matches_metadata(ev.metadata()) { | ||||
|             return; | ||||
|         } | ||||
|         let mut visit = TraceListenerVisitor::new(&self.filters); | ||||
|         ev.record(&mut visit); | ||||
|         if visit.did_match() { | ||||
| @ -115,19 +147,36 @@ impl<S: Subscriber> Layer<S> for EventListener { | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct SpanFilters { | ||||
|     filters: Filters, | ||||
|     filter_name: Option<String>, | ||||
| } | ||||
| 
 | ||||
| impl SpanFilters { | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             filters: Filters::new(), | ||||
|             filter_name: None, | ||||
|         } | ||||
|     } | ||||
|     pub fn target(mut self, target: impl ToString) -> Self { | ||||
|         self.filters = self.filters.target(target); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn filter_name(mut self, name: impl ToString) -> Self { | ||||
|         self.filter_name = Some(name.to_string()); | ||||
|     pub fn name(mut self, name: impl ToString) -> Self { | ||||
|         self.filters = self.filters.name(name); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn message(mut self, message: impl ToString) -> Self { | ||||
|         self.filters = self.filters.message(message); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn field(mut self, field: impl ToString) -> Self { | ||||
|         self.filters = self.filters.field(field); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn field_value(mut self, field: impl ToString, value: impl ToString) -> Self { | ||||
|         self.filters = self.filters.field_value(field, value); | ||||
|         self | ||||
|     } | ||||
| } | ||||
| @ -137,10 +186,8 @@ impl SpanFilters { | ||||
|     where | ||||
|         S: Subscriber + for<'lookup> LookupSpan<'lookup>, | ||||
|     { | ||||
|         if let Some(name) = &self.filter_name { | ||||
|             if span.name() != name { | ||||
|                 return false; | ||||
|             } | ||||
|         if !self.filters.matches_metadata(span.metadata()) { | ||||
|             return false; | ||||
|         } | ||||
|         true | ||||
|     } | ||||
| @ -212,15 +259,16 @@ mod test { | ||||
| 
 | ||||
|     #[test] | ||||
|     fn test_event_listener() { | ||||
|         let all_listener = EventListener::new(Filters::new()); | ||||
|         let msg_listener = EventListener::new(Filters::new().filter_message("filter message")); | ||||
|         let field_listener = EventListener::new(Filters::new().filter_field("field")); | ||||
|         let none_listener = EventListener::new(Filters::new().target("not my module path")); | ||||
|         let all_listener = EventListener::new(Filters::new().target(std::module_path!())); | ||||
|         let msg_listener = EventListener::new(Filters::new().message("filter message")); | ||||
|         let field_listener = EventListener::new(Filters::new().field("field")); | ||||
|         let field_value_listener = | ||||
|             EventListener::new(Filters::new().filter_field_value("field", 1234)); | ||||
|             EventListener::new(Filters::new().field_value("field", 1234)); | ||||
|         let msg_field_value_listener = EventListener::new( | ||||
|             Filters::new() | ||||
|                 .filter_message("filter message") | ||||
|                 .filter_field_value("field", 1234), | ||||
|                 .message("filter message") | ||||
|                 .field_value("field", 1234), | ||||
|         ); | ||||
|         let subscriber = tracing_subscriber::registry() | ||||
|             .with(all_listener.clone()) | ||||
| @ -230,6 +278,7 @@ mod test { | ||||
|             .with(msg_field_value_listener.clone()); | ||||
|         let _sub = tracing::subscriber::set_default(subscriber); | ||||
| 
 | ||||
|         assert_eq!(none_listener.get_count(), 0); | ||||
|         assert_eq!(all_listener.get_count(), 0); | ||||
|         assert_eq!(msg_listener.get_count(), 0); | ||||
|         assert_eq!(field_listener.get_count(), 0); | ||||
| @ -270,6 +319,7 @@ mod test { | ||||
| 
 | ||||
|         info!(field = 1234, "filter message"); | ||||
| 
 | ||||
|         assert_eq!(none_listener.get_count(), 0); | ||||
|         assert_eq!(all_listener.get_count(), 5); | ||||
|         assert_eq!(msg_listener.get_count(), 2); | ||||
|         assert_eq!(field_listener.get_count(), 3); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user