use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::RwLock;
use windows::Win32::System::Diagnostics::Etw;
use crate::native::etw_types::event_record::EventRecord;
use crate::provider::Provider;
use crate::schema_locator::SchemaLocator;
use crate::trace::RealTimeTraceTrait;
use crate::EtwCallback;
#[derive(Debug)]
pub enum CallbackData {
RealTime(RealTimeCallbackData),
FromFile(CallbackDataFromFile),
}
#[derive(Debug)]
pub struct RealTimeCallbackData {
events_handled: AtomicUsize,
schema_locator: SchemaLocator,
providers: Vec<Provider>,
}
pub struct CallbackDataFromFile {
events_handled: AtomicUsize,
schema_locator: SchemaLocator,
callback: RwLock<EtwCallback>,
}
impl CallbackData {
pub fn on_event(&self, record: &EventRecord) {
match self {
CallbackData::RealTime(rt_cb) => rt_cb.on_event(record),
CallbackData::FromFile(f_cb) => f_cb.on_event(record),
}
}
pub fn events_handled(&self) -> usize {
match self {
CallbackData::RealTime(rt_cb) => rt_cb.events_handled(),
CallbackData::FromFile(f_cb) => f_cb.events_handled(),
}
}
}
impl std::default::Default for RealTimeCallbackData {
fn default() -> Self {
Self {
events_handled: AtomicUsize::new(0),
schema_locator: SchemaLocator::new(),
providers: Vec::new(),
}
}
}
impl RealTimeCallbackData {
pub fn new() -> Self {
Default::default()
}
pub fn add_provider(&mut self, provider: Provider) {
self.providers.push(provider)
}
pub fn providers(&self) -> &[Provider] {
&self.providers
}
pub fn events_handled(&self) -> usize {
self.events_handled.load(Ordering::Relaxed)
}
pub fn provider_flags<T: RealTimeTraceTrait>(&self) -> Etw::EVENT_TRACE_FLAG {
Etw::EVENT_TRACE_FLAG(T::enable_flags(&self.providers))
}
pub fn on_event(&self, record: &EventRecord) {
self.events_handled.fetch_add(1, Ordering::Relaxed);
for prov in &self.providers {
if prov.guid() == record.provider_id() {
prov.on_event(record, &self.schema_locator);
}
}
}
}
impl CallbackDataFromFile {
pub fn new(callback: EtwCallback) -> Self {
Self {
events_handled: AtomicUsize::new(0),
schema_locator: SchemaLocator::new(),
callback: RwLock::new(callback),
}
}
pub fn events_handled(&self) -> usize {
self.events_handled.load(Ordering::Relaxed)
}
pub fn on_event(&self, record: &EventRecord) {
self.events_handled.fetch_add(1, Ordering::Relaxed);
if let Ok(mut cb) = self.callback.write() {
cb(record, &self.schema_locator);
}
}
}
impl std::fmt::Debug for CallbackDataFromFile {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CallbackDataFromFile")
.field("events_handled", &self.events_handled)
.field("schema_locator", &self.schema_locator)
.finish()
}
}