use serde::{Deserialize, Serialize};
use tokio::sync::broadcast;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InternalEvent {
pub source: String,
pub event_type: String,
pub region: String,
pub account_id: String,
pub detail: serde_json::Value,
}
pub const API_CALL_EVENT_TYPE: &str = "awsim:ApiCall";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiCallDetail {
pub event_id: String,
pub event_source: String,
pub event_name: String,
pub event_time_epoch: f64,
pub source_ip: Option<String>,
pub user_agent: Option<String>,
pub user_identity_arn: Option<String>,
pub user_identity_account: Option<String>,
pub request_parameters: Option<serde_json::Value>,
pub response_elements: Option<serde_json::Value>,
pub error_code: Option<String>,
pub error_message: Option<String>,
pub http_status: u16,
}
#[derive(Clone, Debug)]
pub struct EventBus {
sender: broadcast::Sender<InternalEvent>,
}
impl EventBus {
pub fn new() -> Self {
let (sender, _) = broadcast::channel(1024);
Self { sender }
}
pub fn publish(&self, event: InternalEvent) {
let _ = self.sender.send(event);
}
pub fn publish_api_call(&self, region: String, account_id: String, detail: ApiCallDetail) {
let payload = match serde_json::to_value(&detail) {
Ok(v) => v,
Err(_) => return,
};
self.publish(InternalEvent {
source: detail.event_source.clone(),
event_type: API_CALL_EVENT_TYPE.to_string(),
region,
account_id,
detail: payload,
});
}
pub fn subscribe(&self) -> broadcast::Receiver<InternalEvent> {
self.sender.subscribe()
}
pub fn subscriber_count(&self) -> usize {
self.sender.receiver_count()
}
}
impl Default for EventBus {
fn default() -> Self {
Self::new()
}
}