tangle_indexer


git clone https://radroots.dev/git/tangle_indexer.git
Log | Files | Refs | Submodules | LICENSE

commit a5d14ecf48f13307bf88ec3f8d50aa4a7c51b673
parent 4818ad787b21a02ba582c54b2e456c1afbbfdb4e
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Fri,  8 Aug 2025 18:14:55 +0000

Edit `indexer` adding audit feature to enable events logging.

Diffstat:
Mcrates/indexer/Cargo.toml | 7+++++--
Acrates/indexer/src/audit.rs | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/indexer/src/domain/indexer/models/listing.rs | 2++
Mcrates/indexer/src/domain/indexer/models/metadata.rs | 2++
Mcrates/indexer/src/lib.rs | 12++++++++++++
Mcrates/indexer/src/telemetry.rs | 29++++++++++++++++++++++++-----
6 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/crates/indexer/Cargo.toml b/crates/indexer/Cargo.toml @@ -18,4 +18,8 @@ thiserror = "1.0" tokio = { version = "1", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] } -tracing-appender = "0.2" -\ No newline at end of file +tracing-appender = "0.2" + +[features] +default = [] +audit = [] diff --git a/crates/indexer/src/audit.rs b/crates/indexer/src/audit.rs @@ -0,0 +1,74 @@ +#![cfg(feature = "audit")] + +use tracing::info; + +use crate::relay::event::RelayIndexerEvent; +use radroots_common::models::events::{RadrootsListingEvent, RadrootsMetadataEvent}; + +static AUDIT_PUBLIC_KEY: Option<&'static str> = option_env!("AUDIT_PUBLIC_KEY"); + +#[inline] +fn matches(pk: &str) -> bool { + match AUDIT_PUBLIC_KEY { + Some(w) => pk == w, + None => false, + } +} + +#[inline] +pub fn log_indexer_event(idx: &RelayIndexerEvent) { + if !matches(&idx.author) { + return; + } + + let tags_json = match serde_json::to_string(&idx.tags) { + Ok(json) => json, + Err(_) => String::from("Error serializing tags"), + }; + info!( + target: "audit", + kind = idx.kind.as_u64(), + id = %idx.id, + author = %idx.author, + created_at = idx.created_at, + tags = %tags_json, + content = %idx.content, + "AUDIT: relay indexer event" + ); +} + +#[inline] +pub fn log_metadata_event(evt: &RadrootsMetadataEvent) { + if !matches(&evt.event.author) { + return; + } + if let Ok(json) = serde_json::to_string(evt) { + info!( + target = "audit", + kind = evt.event.kind, + id = %evt.event.id, + author = %evt.event.author, + created_at = evt.event.created_at, + processed_json = %json, + "AUDIT: processed metadata" + ); + } +} + +#[inline] +pub fn log_listing_event(evt: &RadrootsListingEvent) { + if !matches(&evt.event.author) { + return; + } + if let Ok(json) = serde_json::to_string(evt) { + info!( + target = "audit", + kind = evt.event.kind, + id = %evt.event.id, + author = %evt.event.author, + created_at = evt.event.created_at, + processed_json = %json, + "AUDIT: processed listing" + ); + } +} diff --git a/crates/indexer/src/domain/indexer/models/listing.rs b/crates/indexer/src/domain/indexer/models/listing.rs @@ -11,6 +11,7 @@ use std::{collections::BTreeMap, fs, path::PathBuf}; use tracing::{instrument, warn}; use crate::{ + audit, domain::{ events::ToRadrootsListingEvent, indexer::{ @@ -69,6 +70,7 @@ impl EventIndexes for EventListingIndexes { for raw in raw_events { match raw.clone().to_radroots_listing_event() { Ok(evt) => { + audit::log_listing_event(&evt); let id = evt.event.id.clone(); let country_code = evt.data.location_country.to_lowercase(); diff --git a/crates/indexer/src/domain/indexer/models/metadata.rs b/crates/indexer/src/domain/indexer/models/metadata.rs @@ -9,6 +9,7 @@ use std::{collections::BTreeMap, fs, path::PathBuf}; use tracing::{instrument, warn}; use crate::{ + audit, domain::{ events::ToRadrootsMetadataEvent, indexer::{ @@ -68,6 +69,7 @@ impl EventIndexes for EventMetadataIndexes { for raw in raw_events { match raw.clone().to_radroots_metadata_event() { Ok(evt) => { + audit::log_metadata_event(&evt); let id = evt.event.id.clone(); let author = evt.event.author.clone(); events.push(evt.clone()); diff --git a/crates/indexer/src/lib.rs b/crates/indexer/src/lib.rs @@ -20,6 +20,17 @@ pub mod relay { pub mod event; pub mod record; } + +#[cfg(feature = "audit")] +pub mod audit; + +#[cfg(not(feature = "audit"))] +pub mod audit { + pub fn log_indexer_event(_: &crate::relay::event::RelayIndexerEvent) {} + pub fn log_metadata_event(_: &radroots_common::models::events::RadrootsMetadataEvent) {} + pub fn log_listing_event(_: &radroots_common::models::events::RadrootsListingEvent) {} +} + use crate::{ domain::indexer::{ kind::IndexerEventKind, @@ -78,6 +89,7 @@ pub async fn run(settings: Settings) -> Result<()> { let mut records_kind: HashMap<IndexerEventKind, Vec<RelayIndexerEvent>> = HashMap::new(); for rec in records.into_iter() { let iev = RelayIndexerEvent::try_from(rec)?; + audit::log_indexer_event(&iev); records_kind.entry(iev.kind).or_default().push(iev); } diff --git a/crates/indexer/src/telemetry.rs b/crates/indexer/src/telemetry.rs @@ -1,9 +1,12 @@ use std::path::Path; use tracing_appender::rolling; -use tracing_subscriber::{fmt, prelude::*, registry::Registry, EnvFilter}; +use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; + +#[cfg(feature = "audit")] +use tracing_subscriber::filter::Targets; pub fn init(logs_dir: impl AsRef<Path>) { - let file_appender = rolling::daily(logs_dir, concat!(env!("CARGO_PKG_NAME"), ".log")); + let file_appender = rolling::daily(&logs_dir, concat!(env!("CARGO_PKG_NAME"), ".log")); let (file_writer, guard) = tracing_appender::non_blocking(file_appender); std::mem::forget(guard); @@ -14,9 +17,25 @@ pub fn init(logs_dir: impl AsRef<Path>) { .with_ansi(false) .with_target(false); - Registry::default() + let subscriber = Registry::default() .with(EnvFilter::from_default_env()) .with(stdout_layer) - .with(file_layer) - .init(); + .with(file_layer); + + #[cfg(feature = "audit")] + let subscriber = { + let audit_app = rolling::daily(&logs_dir, "audit.log"); + let (audit_writer, audit_guard) = tracing_appender::non_blocking(audit_app); + std::mem::forget(audit_guard); + + let audit_layer = fmt::layer() + .with_writer(audit_writer) + .with_ansi(false) + .with_target(true) + .with_filter(Targets::new().with_target("audit", tracing::Level::INFO)); + + subscriber.with(audit_layer) + }; + + subscriber.init(); }