sentrystr_tracing/
builder.rs1use crate::{Result, SentryStrLayer, TracingError};
2use nostr::prelude::*;
3use nostr_sdk::prelude::*;
4use sentrystr::{Config, DirectMessageBuilder, NostrSentryClient};
5use tracing_subscriber::prelude::*;
6
7pub struct SentryStrTracingBuilder {
25 config: Option<Config>,
26 dm_config: Option<DirectMessageConfig>,
27 min_level: Option<tracing::Level>,
28 include_fields: bool,
29 include_metadata: bool,
30}
31
32#[derive(Clone)]
52pub struct DirectMessageConfig {
53 pub recipient_pubkey: PublicKey,
54 pub min_level: Option<sentrystr::Level>,
55 pub use_nip17: bool,
56 pub relays: Vec<String>,
57}
58
59impl SentryStrTracingBuilder {
60 pub fn new() -> Self {
62 Self {
63 config: None,
64 dm_config: None,
65 min_level: None,
66 include_fields: true,
67 include_metadata: true,
68 }
69 }
70
71 pub fn with_config(mut self, config: Config) -> Self {
72 self.config = Some(config);
73 self
74 }
75
76 pub fn with_secret_key_and_relays(mut self, secret_key: String, relays: Vec<String>) -> Self {
77 self.config = Some(Config::new(secret_key, relays));
78 self
79 }
80
81 pub fn with_generated_keys_and_relays(mut self, relays: Vec<String>) -> Self {
82 let keys = Keys::generate();
83 self.config = Some(Config::new(
84 keys.secret_key().display_secret().to_string(),
85 relays,
86 ));
87 self
88 }
89
90 pub fn with_direct_messaging(mut self, dm_config: DirectMessageConfig) -> Self {
91 self.dm_config = Some(dm_config);
92 self
93 }
94
95 pub fn with_dm_recipient(mut self, recipient_pubkey: PublicKey, relays: Vec<String>) -> Self {
96 self.dm_config = Some(DirectMessageConfig {
97 recipient_pubkey,
98 min_level: None,
99 use_nip17: true,
100 relays,
101 });
102 self
103 }
104
105 pub fn with_min_level(mut self, level: tracing::Level) -> Self {
106 self.min_level = Some(level);
107 self
108 }
109
110 pub fn with_fields(mut self, include: bool) -> Self {
111 self.include_fields = include;
112 self
113 }
114
115 pub fn with_metadata(mut self, include: bool) -> Self {
116 self.include_metadata = include;
117 self
118 }
119
120 pub async fn build(self) -> Result<SentryStrLayer> {
121 let config = self
122 .config
123 .ok_or_else(|| TracingError::Config("SentryStr config is required".to_string()))?;
124
125 let client = NostrSentryClient::new(config).await?;
126
127 let mut layer = SentryStrLayer::new(client)
128 .with_fields(self.include_fields)
129 .with_metadata(self.include_metadata);
130
131 if let Some(min_level) = self.min_level {
132 layer = layer.with_min_level(min_level);
133 }
134
135 if let Some(dm_config) = self.dm_config {
136 let dm_keys = Keys::generate();
137 let dm_client = Client::new(dm_keys.clone());
138
139 for relay in &dm_config.relays {
140 dm_client.add_relay(relay).await?;
141 }
142 dm_client.connect().await;
143
144 let dm_sender = DirectMessageBuilder::new()
145 .with_client(dm_client)
146 .with_keys(dm_keys)
147 .with_recipient(dm_config.recipient_pubkey)
148 .with_min_level(
149 dm_config
150 .min_level
151 .unwrap_or(sentrystr::Level::Warning),
152 )
153 .with_nip17(dm_config.use_nip17)
154 .build()?;
155
156 layer = layer.with_direct_messaging(dm_sender);
157 }
158
159 Ok(layer)
160 }
161
162 pub async fn init(self) -> Result<()> {
163 let layer = self.build().await?;
164
165 tracing_subscriber::registry()
166 .with(layer)
167 .with(tracing_subscriber::fmt::layer())
168 .init();
169
170 Ok(())
171 }
172
173 pub async fn init_with_env_filter(self, env_filter: &str) -> Result<()> {
174 let layer = self.build().await?;
175
176 tracing_subscriber::registry()
177 .with(tracing_subscriber::EnvFilter::new(env_filter))
178 .with(layer)
179 .with(tracing_subscriber::fmt::layer())
180 .init();
181
182 Ok(())
183 }
184}
185
186impl Default for SentryStrTracingBuilder {
187 fn default() -> Self {
188 Self::new()
189 }
190}
191
192impl DirectMessageConfig {
193 pub fn new(recipient_pubkey: PublicKey, relays: Vec<String>) -> Self {
194 Self {
195 recipient_pubkey,
196 min_level: None,
197 use_nip17: true,
198 relays,
199 }
200 }
201
202 pub fn with_min_level(mut self, level: sentrystr::Level) -> Self {
203 self.min_level = Some(level);
204 self
205 }
206
207 pub fn with_nip17(mut self, use_nip17: bool) -> Self {
208 self.use_nip17 = use_nip17;
209 self
210 }
211}