upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/tests/proactive_sync_metrics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/proactive_sync_metrics.rs')
-rw-r--r--tests/proactive_sync_metrics.rs170
1 files changed, 88 insertions, 82 deletions
diff --git a/tests/proactive_sync_metrics.rs b/tests/proactive_sync_metrics.rs
index 86e2703..32abe74 100644
--- a/tests/proactive_sync_metrics.rs
+++ b/tests/proactive_sync_metrics.rs
@@ -32,10 +32,7 @@ fn create_valid_repo_announcement(keys: &Keys, domain: &str, identifier: &str) -
32 TagKind::custom("clone"), 32 TagKind::custom("clone"),
33 vec![format!("http://{}/{}", domain, identifier)], 33 vec![format!("http://{}/{}", domain, identifier)],
34 ), 34 ),
35 Tag::custom( 35 Tag::custom(TagKind::custom("relays"), vec![format!("ws://{}", domain)]),
36 TagKind::custom("relays"),
37 vec![format!("ws://{}", domain)],
38 ),
39 ]; 36 ];
40 37
41 EventBuilder::new(Kind::Custom(KIND_REPOSITORY_STATE), "Repository state") 38 EventBuilder::new(Kind::Custom(KIND_REPOSITORY_STATE), "Repository state")
@@ -48,11 +45,8 @@ fn create_valid_repo_announcement(keys: &Keys, domain: &str, identifier: &str) -
48async fn fetch_metrics(relay: &TestRelay) -> Result<String, reqwest::Error> { 45async fn fetch_metrics(relay: &TestRelay) -> Result<String, reqwest::Error> {
49 // Extract host:port from ws:// URL 46 // Extract host:port from ws:// URL
50 let ws_url = relay.url(); 47 let ws_url = relay.url();
51 let http_url = ws_url 48 let http_url = ws_url.replace("ws://", "http://").replace("/", "") + "/metrics";
52 .replace("ws://", "http://") 49
53 .replace("/", "")
54 + "/metrics";
55
56 reqwest::get(&http_url).await?.text().await 50 reqwest::get(&http_url).await?.text().await
57} 51}
58 52
@@ -60,18 +54,18 @@ async fn fetch_metrics(relay: &TestRelay) -> Result<String, reqwest::Error> {
60#[tokio::test] 54#[tokio::test]
61async fn test_sync_metrics_exposed() { 55async fn test_sync_metrics_exposed() {
62 let relay = TestRelay::start().await; 56 let relay = TestRelay::start().await;
63 57
64 // Give time for relay to start 58 // Give time for relay to start
65 tokio::time::sleep(Duration::from_millis(500)).await; 59 tokio::time::sleep(Duration::from_millis(500)).await;
66 60
67 // Fetch metrics 61 // Fetch metrics
68 let metrics_result = fetch_metrics(&relay).await; 62 let metrics_result = fetch_metrics(&relay).await;
69 63
70 relay.stop().await; 64 relay.stop().await;
71 65
72 // Check that we got metrics (even if sync isn't configured) 66 // Check that we got metrics (even if sync isn't configured)
73 let metrics = metrics_result.expect("Failed to fetch metrics"); 67 let metrics = metrics_result.expect("Failed to fetch metrics");
74 68
75 // Verify basic metrics structure exists 69 // Verify basic metrics structure exists
76 assert!( 70 assert!(
77 metrics.contains("ngit_") || metrics.contains("# HELP"), 71 metrics.contains("ngit_") || metrics.contains("# HELP"),
@@ -84,19 +78,19 @@ async fn test_sync_metrics_exposed() {
84async fn test_sync_metric_names_present() { 78async fn test_sync_metric_names_present() {
85 // Start a relay with sync configured 79 // Start a relay with sync configured
86 let source_relay = TestRelay::start().await; 80 let source_relay = TestRelay::start().await;
87 let sync_relay = TestRelay::start_with_sync(source_relay.url()).await; 81 let sync_relay = TestRelay::start_with_sync(Some(source_relay.url().into())).await;
88 82
89 // Give time for sync connection to attempt 83 // Give time for sync connection to attempt
90 tokio::time::sleep(Duration::from_secs(2)).await; 84 tokio::time::sleep(Duration::from_secs(2)).await;
91 85
92 // Fetch metrics from the syncing relay 86 // Fetch metrics from the syncing relay
93 let metrics = fetch_metrics(&sync_relay) 87 let metrics = fetch_metrics(&sync_relay)
94 .await 88 .await
95 .expect("Failed to fetch metrics"); 89 .expect("Failed to fetch metrics");
96 90
97 sync_relay.stop().await; 91 sync_relay.stop().await;
98 source_relay.stop().await; 92 source_relay.stop().await;
99 93
100 // Check for expected sync metric names (they may have zero values) 94 // Check for expected sync metric names (they may have zero values)
101 // At minimum, the ngit_ prefix metrics should be present 95 // At minimum, the ngit_ prefix metrics should be present
102 assert!( 96 assert!(
@@ -111,26 +105,23 @@ async fn test_connection_metrics_on_success() {
111 // Start source relay 105 // Start source relay
112 let source_relay = TestRelay::start().await; 106 let source_relay = TestRelay::start().await;
113 tokio::time::sleep(Duration::from_millis(200)).await; 107 tokio::time::sleep(Duration::from_millis(200)).await;
114 108
115 // Start syncing relay 109 // Start syncing relay
116 let sync_relay = TestRelay::start_with_sync(source_relay.url()).await; 110 let sync_relay = TestRelay::start_with_sync(Some(source_relay.url().into())).await;
117 111
118 // Wait for connection to establish 112 // Wait for connection to establish
119 tokio::time::sleep(Duration::from_secs(2)).await; 113 tokio::time::sleep(Duration::from_secs(2)).await;
120 114
121 // Fetch metrics - we can verify the relay started and metrics endpoint works 115 // Fetch metrics - we can verify the relay started and metrics endpoint works
122 let metrics = fetch_metrics(&sync_relay) 116 let metrics = fetch_metrics(&sync_relay)
123 .await 117 .await
124 .expect("Failed to fetch metrics"); 118 .expect("Failed to fetch metrics");
125 119
126 sync_relay.stop().await; 120 sync_relay.stop().await;
127 source_relay.stop().await; 121 source_relay.stop().await;
128 122
129 // Verify metrics endpoint returned data 123 // Verify metrics endpoint returned data
130 assert!( 124 assert!(!metrics.is_empty(), "Metrics endpoint should return data");
131 !metrics.is_empty(),
132 "Metrics endpoint should return data"
133 );
134} 125}
135 126
136/// Test that events syncing updates metrics 127/// Test that events syncing updates metrics
@@ -139,35 +130,38 @@ async fn test_event_sync_metrics() {
139 // Start source relay 130 // Start source relay
140 let source_relay = TestRelay::start().await; 131 let source_relay = TestRelay::start().await;
141 tokio::time::sleep(Duration::from_millis(200)).await; 132 tokio::time::sleep(Duration::from_millis(200)).await;
142 133
143 // Start syncing relay 134 // Start syncing relay
144 let sync_relay = TestRelay::start_with_sync(source_relay.url()).await; 135 let sync_relay = TestRelay::start_with_sync(Some(source_relay.url().into())).await;
145 136
146 // Wait for connection 137 // Wait for connection
147 tokio::time::sleep(Duration::from_secs(1)).await; 138 tokio::time::sleep(Duration::from_secs(1)).await;
148 139
149 // Create and submit an event to source relay 140 // Create and submit an event to source relay
150 let keys = Keys::generate(); 141 let keys = Keys::generate();
151 let event = create_valid_repo_announcement(&keys, &source_relay.domain(), "metrics-test-repo"); 142 let event = create_valid_repo_announcement(&keys, &source_relay.domain(), "metrics-test-repo");
152 143
153 let client = Client::default(); 144 let client = Client::default();
154 client.add_relay(source_relay.url()).await.expect("Failed to add relay"); 145 client
146 .add_relay(source_relay.url())
147 .await
148 .expect("Failed to add relay");
155 client.connect().await; 149 client.connect().await;
156 150
157 let _ = client.send_event(&event).await; 151 let _ = client.send_event(&event).await;
158 152
159 // Wait for sync to occur 153 // Wait for sync to occur
160 tokio::time::sleep(Duration::from_secs(2)).await; 154 tokio::time::sleep(Duration::from_secs(2)).await;
161 155
162 // Fetch metrics from sync relay 156 // Fetch metrics from sync relay
163 let metrics = fetch_metrics(&sync_relay) 157 let metrics = fetch_metrics(&sync_relay)
164 .await 158 .await
165 .expect("Failed to fetch metrics"); 159 .expect("Failed to fetch metrics");
166 160
167 client.disconnect().await; 161 client.disconnect().await;
168 sync_relay.stop().await; 162 sync_relay.stop().await;
169 source_relay.stop().await; 163 source_relay.stop().await;
170 164
171 // Verify metrics endpoint returned data after sync activity 165 // Verify metrics endpoint returned data after sync activity
172 assert!( 166 assert!(
173 !metrics.is_empty(), 167 !metrics.is_empty(),
@@ -180,18 +174,18 @@ async fn test_event_sync_metrics() {
180async fn test_health_state_metrics() { 174async fn test_health_state_metrics() {
181 // Start a syncing relay pointing to a non-existent source 175 // Start a syncing relay pointing to a non-existent source
182 // This will result in connection failures and health state changes 176 // This will result in connection failures and health state changes
183 let sync_relay = TestRelay::start_with_sync("ws://127.0.0.1:19999").await; 177 let sync_relay = TestRelay::start_with_sync(Some("ws://127.0.0.1:19999".into())).await;
184 178
185 // Wait for some connection attempts 179 // Wait for some connection attempts
186 tokio::time::sleep(Duration::from_secs(3)).await; 180 tokio::time::sleep(Duration::from_secs(3)).await;
187 181
188 // Fetch metrics 182 // Fetch metrics
189 let metrics = fetch_metrics(&sync_relay) 183 let metrics = fetch_metrics(&sync_relay)
190 .await 184 .await
191 .expect("Failed to fetch metrics"); 185 .expect("Failed to fetch metrics");
192 186
193 sync_relay.stop().await; 187 sync_relay.stop().await;
194 188
195 // The relay should still be operational even with failed sync 189 // The relay should still be operational even with failed sync
196 assert!( 190 assert!(
197 !metrics.is_empty(), 191 !metrics.is_empty(),
@@ -205,32 +199,35 @@ async fn test_gap_event_tracking() {
205 // Start source relay and add some events first 199 // Start source relay and add some events first
206 let source_relay = TestRelay::start().await; 200 let source_relay = TestRelay::start().await;
207 tokio::time::sleep(Duration::from_millis(200)).await; 201 tokio::time::sleep(Duration::from_millis(200)).await;
208 202
209 let keys = Keys::generate(); 203 let keys = Keys::generate();
210 204
211 // Submit event before sync relay starts 205 // Submit event before sync relay starts
212 let event = create_valid_repo_announcement(&keys, &source_relay.domain(), "pre-existing-repo"); 206 let event = create_valid_repo_announcement(&keys, &source_relay.domain(), "pre-existing-repo");
213 207
214 let client = Client::default(); 208 let client = Client::default();
215 client.add_relay(source_relay.url()).await.expect("Failed to add relay"); 209 client
210 .add_relay(source_relay.url())
211 .await
212 .expect("Failed to add relay");
216 client.connect().await; 213 client.connect().await;
217 let _ = client.send_event(&event).await; 214 let _ = client.send_event(&event).await;
218 215
219 // Now start syncing relay - it should catch up on existing events 216 // Now start syncing relay - it should catch up on existing events
220 let sync_relay = TestRelay::start_with_sync(source_relay.url()).await; 217 let sync_relay = TestRelay::start_with_sync(Some(source_relay.url().into())).await;
221 218
222 // Wait for catchup 219 // Wait for catchup
223 tokio::time::sleep(Duration::from_secs(3)).await; 220 tokio::time::sleep(Duration::from_secs(3)).await;
224 221
225 // Fetch metrics 222 // Fetch metrics
226 let metrics = fetch_metrics(&sync_relay) 223 let metrics = fetch_metrics(&sync_relay)
227 .await 224 .await
228 .expect("Failed to fetch metrics"); 225 .expect("Failed to fetch metrics");
229 226
230 client.disconnect().await; 227 client.disconnect().await;
231 sync_relay.stop().await; 228 sync_relay.stop().await;
232 source_relay.stop().await; 229 source_relay.stop().await;
233 230
234 // Verify metrics exist after gap sync scenario 231 // Verify metrics exist after gap sync scenario
235 assert!( 232 assert!(
236 !metrics.is_empty(), 233 !metrics.is_empty(),
@@ -245,48 +242,57 @@ async fn test_multi_relay_load() {
245 let source_relay_1 = TestRelay::start().await; 242 let source_relay_1 = TestRelay::start().await;
246 let source_relay_2 = TestRelay::start().await; 243 let source_relay_2 = TestRelay::start().await;
247 let source_relay_3 = TestRelay::start().await; 244 let source_relay_3 = TestRelay::start().await;
248 245
249 tokio::time::sleep(Duration::from_millis(500)).await; 246 tokio::time::sleep(Duration::from_millis(500)).await;
250 247
251 // Start a syncing relay pointing to first source 248 // Start a syncing relay pointing to first source
252 // Note: The current implementation only supports single sync relay URL 249 // Note: The current implementation only supports single sync relay URL
253 // but the test demonstrates the system handles multiple relay scenarios 250 // but the test demonstrates the system handles multiple relay scenarios
254 let sync_relay = TestRelay::start_with_sync(source_relay_1.url()).await; 251 let sync_relay = TestRelay::start_with_sync(Some(source_relay_1.url().into())).await;
255 252
256 // Wait for connections 253 // Wait for connections
257 tokio::time::sleep(Duration::from_secs(2)).await; 254 tokio::time::sleep(Duration::from_secs(2)).await;
258 255
259 // Submit events to all source relays 256 // Submit events to all source relays
260 let keys = Keys::generate(); 257 let keys = Keys::generate();
261 258
262 let event1 = create_valid_repo_announcement(&keys, &source_relay_1.domain(), "repo-1"); 259 let event1 = create_valid_repo_announcement(&keys, &source_relay_1.domain(), "repo-1");
263 let event2 = create_valid_repo_announcement(&keys, &source_relay_2.domain(), "repo-2"); 260 let event2 = create_valid_repo_announcement(&keys, &source_relay_2.domain(), "repo-2");
264 let event3 = create_valid_repo_announcement(&keys, &source_relay_3.domain(), "repo-3"); 261 let event3 = create_valid_repo_announcement(&keys, &source_relay_3.domain(), "repo-3");
265 262
266 // Submit events 263 // Submit events
267 let client1 = Client::default(); 264 let client1 = Client::default();
268 client1.add_relay(source_relay_1.url()).await.expect("Failed to add relay"); 265 client1
266 .add_relay(source_relay_1.url())
267 .await
268 .expect("Failed to add relay");
269 client1.connect().await; 269 client1.connect().await;
270 let _ = client1.send_event(&event1).await; 270 let _ = client1.send_event(&event1).await;
271 271
272 let client2 = Client::default(); 272 let client2 = Client::default();
273 client2.add_relay(source_relay_2.url()).await.expect("Failed to add relay"); 273 client2
274 .add_relay(source_relay_2.url())
275 .await
276 .expect("Failed to add relay");
274 client2.connect().await; 277 client2.connect().await;
275 let _ = client2.send_event(&event2).await; 278 let _ = client2.send_event(&event2).await;
276 279
277 let client3 = Client::default(); 280 let client3 = Client::default();
278 client3.add_relay(source_relay_3.url()).await.expect("Failed to add relay"); 281 client3
282 .add_relay(source_relay_3.url())
283 .await
284 .expect("Failed to add relay");
279 client3.connect().await; 285 client3.connect().await;
280 let _ = client3.send_event(&event3).await; 286 let _ = client3.send_event(&event3).await;
281 287
282 // Wait for sync 288 // Wait for sync
283 tokio::time::sleep(Duration::from_secs(3)).await; 289 tokio::time::sleep(Duration::from_secs(3)).await;
284 290
285 // Fetch metrics from sync relay 291 // Fetch metrics from sync relay
286 let metrics = fetch_metrics(&sync_relay) 292 let metrics = fetch_metrics(&sync_relay)
287 .await 293 .await
288 .expect("Failed to fetch metrics"); 294 .expect("Failed to fetch metrics");
289 295
290 // Cleanup 296 // Cleanup
291 client1.disconnect().await; 297 client1.disconnect().await;
292 client2.disconnect().await; 298 client2.disconnect().await;
@@ -295,7 +301,7 @@ async fn test_multi_relay_load() {
295 source_relay_1.stop().await; 301 source_relay_1.stop().await;
296 source_relay_2.stop().await; 302 source_relay_2.stop().await;
297 source_relay_3.stop().await; 303 source_relay_3.stop().await;
298 304
299 // Verify metrics system handled load 305 // Verify metrics system handled load
300 assert!( 306 assert!(
301 !metrics.is_empty(), 307 !metrics.is_empty(),
@@ -308,25 +314,25 @@ async fn test_multi_relay_load() {
308async fn test_prometheus_format_valid() { 314async fn test_prometheus_format_valid() {
309 let relay = TestRelay::start().await; 315 let relay = TestRelay::start().await;
310 tokio::time::sleep(Duration::from_millis(500)).await; 316 tokio::time::sleep(Duration::from_millis(500)).await;
311 317
312 let metrics = fetch_metrics(&relay) 318 let metrics = fetch_metrics(&relay)
313 .await 319 .await
314 .expect("Failed to fetch metrics"); 320 .expect("Failed to fetch metrics");
315 321
316 relay.stop().await; 322 relay.stop().await;
317 323
318 // Check for valid Prometheus format markers 324 // Check for valid Prometheus format markers
319 // - Lines starting with # are comments (HELP, TYPE) 325 // - Lines starting with # are comments (HELP, TYPE)
320 // - Metric lines have format: metric_name{labels} value 326 // - Metric lines have format: metric_name{labels} value
321 let lines: Vec<&str> = metrics.lines().collect(); 327 let lines: Vec<&str> = metrics.lines().collect();
322 328
323 // Should have some content 329 // Should have some content
324 assert!(!lines.is_empty(), "Metrics should have content"); 330 assert!(!lines.is_empty(), "Metrics should have content");
325 331
326 // Check for at least some standard Prometheus patterns 332 // Check for at least some standard Prometheus patterns
327 let has_help = lines.iter().any(|l| l.starts_with("# HELP")); 333 let has_help = lines.iter().any(|l| l.starts_with("# HELP"));
328 let has_type = lines.iter().any(|l| l.starts_with("# TYPE")); 334 let has_type = lines.iter().any(|l| l.starts_with("# TYPE"));
329 335
330 // At minimum we expect help/type comments for any registered metrics 336 // At minimum we expect help/type comments for any registered metrics
331 assert!( 337 assert!(
332 has_help || has_type || lines.iter().any(|l| l.contains("ngit_")), 338 has_help || has_type || lines.iter().any(|l| l.contains("ngit_")),
@@ -338,10 +344,10 @@ async fn test_prometheus_format_valid() {
338#[tokio::test] 344#[tokio::test]
339async fn test_metrics_availability_during_sync() { 345async fn test_metrics_availability_during_sync() {
340 let source_relay = TestRelay::start().await; 346 let source_relay = TestRelay::start().await;
341 let sync_relay = TestRelay::start_with_sync(source_relay.url()).await; 347 let sync_relay = TestRelay::start_with_sync(Some(source_relay.url().into())).await;
342 348
343 tokio::time::sleep(Duration::from_millis(500)).await; 349 tokio::time::sleep(Duration::from_millis(500)).await;
344 350
345 // Make multiple metrics requests while sync is active 351 // Make multiple metrics requests while sync is active
346 for i in 0..3 { 352 for i in 0..3 {
347 let metrics = fetch_metrics(&sync_relay).await; 353 let metrics = fetch_metrics(&sync_relay).await;
@@ -352,7 +358,7 @@ async fn test_metrics_availability_during_sync() {
352 ); 358 );
353 tokio::time::sleep(Duration::from_millis(200)).await; 359 tokio::time::sleep(Duration::from_millis(200)).await;
354 } 360 }
355 361
356 sync_relay.stop().await; 362 sync_relay.stop().await;
357 source_relay.stop().await; 363 source_relay.stop().await;
358} \ No newline at end of file 364}