| Crates.io | sentrystr-tracing |
| lib.rs | sentrystr-tracing |
| version | 0.1.2 |
| created_at | 2025-09-21 21:37:06.847969+00 |
| updated_at | 2025-09-22 21:21:07.375602+00 |
| description | A decentralized error tracking and alerting system using Nostr |
| homepage | |
| repository | https://github.com/9qeklajc/sentrystr |
| max_upload_size | |
| id | 1849223 |
| size | 89,087 |
A tracing integration for SentryStr that provides seamless logging and alerting through Nostr relays with optional direct messaging capabilities.
tracing ecosystemuse sentrystr_tracing::SentryStrTracingBuilder;
use tracing::{info, warn, error};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let relays = vec!["wss://relay.damus.io".to_string()];
SentryStrTracingBuilder::new()
.with_generated_keys_and_relays(relays)
.with_min_level(tracing::Level::INFO)
.init()
.await?;
info!("Application started");
warn!(cpu_usage = 85.5, "High CPU usage");
error!(error_code = 500, "Database connection failed");
Ok(())
}
use nostr::prelude::*;
use sentrystr_core::Level;
use sentrystr_tracing::{builder::DirectMessageConfig, SentryStrTracingBuilder};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let relays = vec!["wss://relay.damus.io".to_string()];
let recipient_pubkey = PublicKey::from_bech32("npub1...")?;
let dm_config = DirectMessageConfig::new(recipient_pubkey, relays.clone())
.with_min_level(Level::Error)
.with_nip17(true);
SentryStrTracingBuilder::new()
.with_generated_keys_and_relays(relays)
.with_direct_messaging(dm_config)
.init()
.await?;
// This will send both to Nostr and as a DM
error!("Critical system failure");
Ok(())
}
with_config(config) - Use existing SentryStr configwith_generated_keys_and_relays(relays) - Generate new keyswith_secret_key_and_relays(key, relays) - Use specific keywith_direct_messaging(dm_config) - Enable DM alertswith_min_level(level) - Set minimum tracing levelwith_fields(include) - Include/exclude custom fieldswith_metadata(include) - Include/exclude tracing metadatalet dm_config = DirectMessageConfig::new(recipient_pubkey, relays)
.with_min_level(Level::Warning) // Only warn+ events
.with_nip17(true); // Use NIP-17 encryption
Run the examples to see the integration in action:
# Basic tracing without DMs
cargo run --example basic_usage
# With direct message alerts
cargo run --example with_direct_messages
# Complex structured logging
cargo run --example custom_fields
# Integration test
cargo run --example integration_test
use axum::{routing::get, Router};
use sentrystr_tracing::SentryStrTracingBuilder;
use tracing::{info, error};
#[tokio::main]
async fn main() {
SentryStrTracingBuilder::new()
.with_generated_keys_and_relays(vec!["wss://relay.damus.io".to_string()])
.init_with_env_filter("info,axum=debug")
.await
.expect("Failed to initialize tracing");
let app = Router::new()
.route("/", get(|| async { "Hello, World!" }));
info!("Starting web server on port 3000");
// Server will automatically log requests through tracing
}
use sentrystr_tracing::SentryStrTracingBuilder;
use tracing::{info, warn, error, instrument};
#[instrument]
async fn process_job(job_id: u64) -> Result<(), Box<dyn std::error::Error>> {
info!(job_id = job_id, "Processing job");
// Simulate work
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
if job_id % 10 == 0 {
error!(job_id = job_id, "Job processing failed");
return Err("Processing failed".into());
}
info!(job_id = job_id, "Job completed successfully");
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
SentryStrTracingBuilder::new()
.with_generated_keys_and_relays(vec!["wss://relay.damus.io".to_string()])
.with_min_level(tracing::Level::INFO)
.init()
.await?;
for job_id in 1..=20 {
if let Err(e) = process_job(job_id).await {
warn!(job_id = job_id, error = %e, "Job failed, will retry");
}
}
Ok(())
}
The layer captures all structured fields from your tracing events:
error!(
user_id = 12345,
error_type = "authentication_failure",
ip_address = "192.168.1.100",
user_agent = "Mozilla/5.0...",
"User authentication failed"
);
All fields are preserved in the SentryStr event and available for filtering and alerting.
use std::env;
let dm_enabled = env::var("SENTRYSTR_DM_ENABLED").unwrap_or_default() == "true";
let min_level = env::var("SENTRYSTR_MIN_LEVEL")
.unwrap_or_else(|_| "info".to_string());
let mut builder = SentryStrTracingBuilder::new()
.with_generated_keys_and_relays(relays);
if dm_enabled {
let recipient = env::var("SENTRYSTR_DM_RECIPIENT")?;
let pubkey = PublicKey::from_bech32(&recipient)?;
builder = builder.with_dm_recipient(pubkey, relays.clone());
}
builder.init().await?;
#[instrument]The layer handles errors gracefully: