pub struct CracklePattern { /* private fields */ }Expand description
A pattern detected during the cooling phase.
Like a craze line in pottery glaze, each pattern is a record of something that wasn’t designed — it emerged from the interaction of many tasks as the system cooled.
Implementations§
Source§impl CracklePattern
impl CracklePattern
Sourcepub fn new(
kind: PatternKind,
description: impl Into<String>,
involved_tasks: Vec<String>,
confidence: f64,
) -> Self
pub fn new( kind: PatternKind, description: impl Into<String>, involved_tasks: Vec<String>, confidence: f64, ) -> Self
Create a new detected pattern.
Sourcepub fn kind(&self) -> &PatternKind
pub fn kind(&self) -> &PatternKind
The kind of pattern detected.
Examples found in repository?
examples/basic.rs (line 44)
29fn main() {
30 let mut kiln = Kiln::new(ThermalProfile::fast_cooling());
31
32 kiln.fire_and_record(NumberTask { value: 2.0, name: "a".into() }).unwrap();
33 kiln.fire_and_record(NumberTask { value: 2.1, name: "b".into() }).unwrap();
34 kiln.fire_and_record(NumberTask { value: 9.8, name: "c".into() }).unwrap();
35 kiln.fire_and_record(NumberTask { value: 10.0, name: "d".into() }).unwrap();
36 kiln.fire_and_record(NumberTask { value: 2.2, name: "e".into() }).unwrap();
37
38 println!("Tasks in kiln: {}", kiln.task_count());
39
40 let patterns = kiln.cool();
41 println!("\nDetected {} pattern(s):\n", patterns.len());
42
43 for p in &patterns {
44 println!("[{}] {}", p.kind(), p.description());
45 println!(" confidence: {:.2}", p.confidence());
46 println!(" tasks: {:?}\n", p.involved_tasks());
47 }
48}More examples
examples/ci_patterns.rs (line 47)
30fn main() {
31 let mut kiln = Kiln::new(ThermalProfile::default());
32
33 // Normal builds
34 kiln.fire_and_record(CiBuild { duration_secs: 45.0, test_count: 200.0, branch: "feature/auth".into() }).unwrap();
35 kiln.fire_and_record(CiBuild { duration_secs: 42.0, test_count: 195.0, branch: "fix/typo".into() }).unwrap();
36 kiln.fire_and_record(CiBuild { duration_secs: 48.0, test_count: 210.0, branch: "feature/ui".into() }).unwrap();
37
38 // Something changed — builds got slower
39 kiln.fire_and_record(CiBuild { duration_secs: 95.0, test_count: 200.0, branch: "feature/cache".into() }).unwrap();
40 kiln.fire_and_record(CiBuild { duration_secs: 102.0, test_count: 198.0, branch: "chore/deps".into() }).unwrap();
41
42 let patterns = kiln.cool();
43 println!("CI Build Pattern Analysis");
44 println!("=========================\n");
45
46 for p in &patterns {
47 println!("[{}] {}", p.kind().to_string().to_uppercase(), p.description());
48 println!(" confidence: {:.2}", p.confidence());
49 println!(" branches: {:?}\n", p.involved_tasks());
50 }
51
52 // Check for phase transition in build duration
53 let phase_shifts: Vec<_> = patterns.iter()
54 .filter(|p| format!("{}", p.kind()) == "phase transition")
55 .collect();
56
57 if !phase_shifts.is_empty() {
58 println!("⚠️ Build duration shifted significantly — investigate recent changes!");
59 }
60}examples/api_monitoring.rs (line 54)
32fn main() {
33 let mut kiln = Kiln::new(ThermalProfile::default());
34
35 // /api/users — fast, small responses
36 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 45.0, status: 200, response_bytes: 1200.0 }).unwrap();
37 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 48.0, status: 200, response_bytes: 1150.0 }).unwrap();
38 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 52.0, status: 200, response_bytes: 1300.0 }).unwrap();
39
40 // /api/reports — slow, large responses (correlated with bytes)
41 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 350.0, status: 200, response_bytes: 55000.0 }).unwrap();
42 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 380.0, status: 200, response_bytes: 62000.0 }).unwrap();
43
44 // /api/health — tiny, always fast (conservation candidate)
45 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 3.0, status: 200, response_bytes: 15.0 }).unwrap();
46 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 4.0, status: 200, response_bytes: 15.0 }).unwrap();
47
48 let patterns = kiln.cool();
49 println!("API Monitoring — Pattern Report");
50 println!("================================\n");
51 println!("{} patterns detected:\n", patterns.len());
52
53 for p in &patterns {
54 println!("[{}] {}", p.kind(), p.description());
55 println!(" confidence: {:.2}", p.confidence());
56 if !p.involved_tasks().is_empty() {
57 println!(" endpoints: {:?}", p.involved_tasks());
58 }
59 println!();
60 }
61
62 // Highlight correlations between latency and response size
63 let correlations: Vec<_> = patterns.iter()
64 .filter(|p| format!("{}", p.kind()) == "correlation")
65 .collect();
66
67 if !correlations.is_empty() {
68 println!("📊 Latency and response size are correlated — consider pagination or caching.");
69 }
70}examples/event_stream_processor.rs (line 133)
98fn main() {
99 let total_events = 1000;
100 let batch_size = 100;
101 let num_batches = total_events / batch_size;
102
103 println!("═══════════════════════════════════════════════════════════════");
104 println!(" CRACKLE-RUNTIME: EVENT STREAM PROCESSOR TEST");
105 println!("═══════════════════════════════════════════════════════════════\n");
106 println!("Processing {} events across {} batches of {}...\n",
107 total_events, num_batches, batch_size);
108
109 let start = Instant::now();
110
111 // Phase 1: Healthy system (batches 1-4)
112 println!("─── Phase 1: Healthy System ───");
113 let mut healthy_kiln = Kiln::new(
114 ThermalProfile::fast_cooling()
115 );
116
117 // Batch 1-4: all healthy, 10ms baseline latency
118 for batch_id in 1..=4 {
119 let events = simulate_batch(batch_id, batch_size as u32, 10.0, 0.05);
120 for event in events {
121 healthy_kiln.fire_and_record(event).unwrap();
122 }
123
124 let elapsed = start.elapsed();
125 println!(" Batch {}/{} fired ({} events, {:.0}ms)",
126 batch_id, num_batches, batch_size, elapsed.as_millis());
127 }
128
129 // Cool healthy phase
130 let healthy_patterns = healthy_kiln.cool();
131 println!("\n Healthy system patterns ({} detected):", healthy_patterns.len());
132 for p in &healthy_patterns {
133 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
134 }
135 // Also check conservation on records_in/records_out
136 let conservation = healthy_kiln.distribution_shift(10);
137 println!(" Distribution shifts:");
138 for (name, shift) in &conservation[..conservation.len().min(3)] {
139 println!(" {} → KL = {:.4}", name, shift);
140 }
141
142 println!();
143
144 // Phase 2: Degrading system (batches 5-8)
145 println!("─── Phase 2: Degrading System ───");
146
147 let mut degrading_kiln = Kiln::new(
148 ThermalProfile::fast_cooling()
149 );
150
151 // Batches where degradation ramps up
152 let degradation_levels = [0.2, 0.5, 0.9, 1.5];
153 for (i, °radation) in degradation_levels.iter().enumerate() {
154 let batch_id = (5 + i) as u32;
155 // latency increases with degradation
156 let base_latency = 10.0 + degradation * 50.0;
157
158 let events = simulate_batch(batch_id, batch_size as u32, base_latency, degradation);
159 for event in events {
160 degrading_kiln.fire_and_record(event).unwrap();
161 }
162
163 let elapsed = start.elapsed();
164 println!(" Batch {}/{} [degradation={:.1}x] fired (latency baseline: {:.0}ms, {:.0}ms total)",
165 batch_id, num_batches, degradation, base_latency, elapsed.as_millis());
166 }
167
168 let degrading_patterns = degrading_kiln.cool();
169 println!("\n Degrading system patterns ({} detected):", degrading_patterns.len());
170 for p in °rading_patterns {
171 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
172 }
173
174 // JSD shift (distribution shape changes)
175 let jsd_shifts = degrading_kiln.jsd_shift(10);
176 println!(" JSD shifts (distribution shape changes):");
177 for (name, shift) in &jsd_shifts[..jsd_shifts.len().min(5)] {
178 println!(" {} → JSD = {:.4}", name, shift);
179 }
180
181 // Permutation entropy (temporal structure)
182 let pes = degrading_kiln.permutation_entropies(4);
183 println!(" Permutation entropies (temporal structure):");
184 for (name, pe) in &pes {
185 println!(" {} → PE = {:.4}", name, pe);
186 }
187
188 println!();
189
190 // Phase 3: Conservation law test — records in = records out should be violated
191 // as errors increase
192 println!("─── Phase 3: Conservation Law Verification ───");
193 let mut conservation_kiln = Kiln::new(
194 ThermalProfile::fast_cooling()
195 );
196
197 // Force records_in = records_out for first 3 batches (healthy conservation)
198 for batch_id in 1..=3 {
199 let event = ProcessedEvent {
200 event_id: batch_id as u64,
201 batch_id: batch_id as u32,
202 processing_time_ms: 10.0,
203 throughput: 100.0,
204 memory_mb: 128.0,
205 error_rate: 0.01,
206 records_in: 1000.0,
207 records_out: 995.0, // nearly conserved
208 cpu_temp_c: 65.0,
209 latency_p99_ms: 25.0,
210 consumer_lag: 10.0,
211 gc_pause_ms: 5.0,
212 };
213 conservation_kiln.fire_and_record(event).unwrap();
214 }
215
216 // Force violation of records conservation (errors spike)
217 for batch_id in 4..=6 {
218 let event = ProcessedEvent {
219 event_id: batch_id as u64,
220 batch_id: batch_id as u32,
221 processing_time_ms: 10.0 + batch_id as f64 * 10.0,
222 throughput: 50.0,
223 memory_mb: 256.0,
224 error_rate: 0.3,
225 records_in: 1000.0,
226 records_out: 700.0, // 30% loss — conservation violated
227 cpu_temp_c: 80.0,
228 latency_p99_ms: 100.0,
229 consumer_lag: 500.0,
230 gc_pause_ms: 20.0,
231 };
232 conservation_kiln.fire_and_record(event).unwrap();
233 }
234
235 let conservation_patterns = conservation_kiln.cool();
236 println!(" Conservation-specific patterns ({} detected):", conservation_patterns.len());
237 for p in &conservation_patterns {
238 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
239 }
240
241 // MI matrix to show nonlinear dependencies
242 let mi = conservation_kiln.mi_matrix(8);
243 println!(" Mutual Information matrix (8 bins):");
244 let metric_names = ["processing_time_ms", "error_rate", "records_in", "records_out", "memory_mb"];
245 for (i, name_i) in metric_names.iter().enumerate() {
246 for (j, name_j) in metric_names.iter().enumerate() {
247 if i == j {
248 println!(" I({:25}; {:25}) = H({})", name_i, name_j, name_i);
249 } else {
250 println!(" I({:25}; {:25}) = {:.4} bits", name_i, name_j, mi[i][j]);
251 }
252 }
253 }
254
255 println!();
256 println!("───────────────────────────────────────────────────────────────");
257 println!(" SUMMARY");
258 println!("───────────────────────────────────────────────────────────────\n");
259
260 // Degradation detection analysis
261 println!(" Degradation Metrics:");
262 let pt = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::PhaseTransition));
263 let pt_count = pt.count();
264 println!(" Phase transitions detected in degraded system: {} alerts",
265 pt_count);
266
267 let corr = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Correlation));
268 let corr_count = corr.count();
269 println!(" Correlations in degraded system: {} pairs", corr_count);
270
271 let cons = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Conservation));
272 let cons_count = cons.count();
273 println!(" Conservation laws in degraded system: {} found", cons_count);
274
275 let clust = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Clustering));
276 let clust_count = clust.count();
277 println!(" Clusters in degraded system: {} groups", clust_count);
278
279 println!();
280 let total_duration = start.elapsed();
281 println!(" Total test duration: {:.2}s", total_duration.as_secs_f64());
282 println!(" Events processed: {}", total_events);
283 println!(" Avg throughput: {:.0} events/s",
284 total_events as f64 / total_duration.as_secs_f64());
285}Sourcepub fn description(&self) -> &str
pub fn description(&self) -> &str
Human-readable description of the pattern.
Examples found in repository?
examples/basic.rs (line 44)
29fn main() {
30 let mut kiln = Kiln::new(ThermalProfile::fast_cooling());
31
32 kiln.fire_and_record(NumberTask { value: 2.0, name: "a".into() }).unwrap();
33 kiln.fire_and_record(NumberTask { value: 2.1, name: "b".into() }).unwrap();
34 kiln.fire_and_record(NumberTask { value: 9.8, name: "c".into() }).unwrap();
35 kiln.fire_and_record(NumberTask { value: 10.0, name: "d".into() }).unwrap();
36 kiln.fire_and_record(NumberTask { value: 2.2, name: "e".into() }).unwrap();
37
38 println!("Tasks in kiln: {}", kiln.task_count());
39
40 let patterns = kiln.cool();
41 println!("\nDetected {} pattern(s):\n", patterns.len());
42
43 for p in &patterns {
44 println!("[{}] {}", p.kind(), p.description());
45 println!(" confidence: {:.2}", p.confidence());
46 println!(" tasks: {:?}\n", p.involved_tasks());
47 }
48}More examples
examples/ci_patterns.rs (line 47)
30fn main() {
31 let mut kiln = Kiln::new(ThermalProfile::default());
32
33 // Normal builds
34 kiln.fire_and_record(CiBuild { duration_secs: 45.0, test_count: 200.0, branch: "feature/auth".into() }).unwrap();
35 kiln.fire_and_record(CiBuild { duration_secs: 42.0, test_count: 195.0, branch: "fix/typo".into() }).unwrap();
36 kiln.fire_and_record(CiBuild { duration_secs: 48.0, test_count: 210.0, branch: "feature/ui".into() }).unwrap();
37
38 // Something changed — builds got slower
39 kiln.fire_and_record(CiBuild { duration_secs: 95.0, test_count: 200.0, branch: "feature/cache".into() }).unwrap();
40 kiln.fire_and_record(CiBuild { duration_secs: 102.0, test_count: 198.0, branch: "chore/deps".into() }).unwrap();
41
42 let patterns = kiln.cool();
43 println!("CI Build Pattern Analysis");
44 println!("=========================\n");
45
46 for p in &patterns {
47 println!("[{}] {}", p.kind().to_string().to_uppercase(), p.description());
48 println!(" confidence: {:.2}", p.confidence());
49 println!(" branches: {:?}\n", p.involved_tasks());
50 }
51
52 // Check for phase transition in build duration
53 let phase_shifts: Vec<_> = patterns.iter()
54 .filter(|p| format!("{}", p.kind()) == "phase transition")
55 .collect();
56
57 if !phase_shifts.is_empty() {
58 println!("⚠️ Build duration shifted significantly — investigate recent changes!");
59 }
60}examples/api_monitoring.rs (line 54)
32fn main() {
33 let mut kiln = Kiln::new(ThermalProfile::default());
34
35 // /api/users — fast, small responses
36 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 45.0, status: 200, response_bytes: 1200.0 }).unwrap();
37 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 48.0, status: 200, response_bytes: 1150.0 }).unwrap();
38 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 52.0, status: 200, response_bytes: 1300.0 }).unwrap();
39
40 // /api/reports — slow, large responses (correlated with bytes)
41 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 350.0, status: 200, response_bytes: 55000.0 }).unwrap();
42 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 380.0, status: 200, response_bytes: 62000.0 }).unwrap();
43
44 // /api/health — tiny, always fast (conservation candidate)
45 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 3.0, status: 200, response_bytes: 15.0 }).unwrap();
46 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 4.0, status: 200, response_bytes: 15.0 }).unwrap();
47
48 let patterns = kiln.cool();
49 println!("API Monitoring — Pattern Report");
50 println!("================================\n");
51 println!("{} patterns detected:\n", patterns.len());
52
53 for p in &patterns {
54 println!("[{}] {}", p.kind(), p.description());
55 println!(" confidence: {:.2}", p.confidence());
56 if !p.involved_tasks().is_empty() {
57 println!(" endpoints: {:?}", p.involved_tasks());
58 }
59 println!();
60 }
61
62 // Highlight correlations between latency and response size
63 let correlations: Vec<_> = patterns.iter()
64 .filter(|p| format!("{}", p.kind()) == "correlation")
65 .collect();
66
67 if !correlations.is_empty() {
68 println!("📊 Latency and response size are correlated — consider pagination or caching.");
69 }
70}examples/event_stream_processor.rs (line 133)
98fn main() {
99 let total_events = 1000;
100 let batch_size = 100;
101 let num_batches = total_events / batch_size;
102
103 println!("═══════════════════════════════════════════════════════════════");
104 println!(" CRACKLE-RUNTIME: EVENT STREAM PROCESSOR TEST");
105 println!("═══════════════════════════════════════════════════════════════\n");
106 println!("Processing {} events across {} batches of {}...\n",
107 total_events, num_batches, batch_size);
108
109 let start = Instant::now();
110
111 // Phase 1: Healthy system (batches 1-4)
112 println!("─── Phase 1: Healthy System ───");
113 let mut healthy_kiln = Kiln::new(
114 ThermalProfile::fast_cooling()
115 );
116
117 // Batch 1-4: all healthy, 10ms baseline latency
118 for batch_id in 1..=4 {
119 let events = simulate_batch(batch_id, batch_size as u32, 10.0, 0.05);
120 for event in events {
121 healthy_kiln.fire_and_record(event).unwrap();
122 }
123
124 let elapsed = start.elapsed();
125 println!(" Batch {}/{} fired ({} events, {:.0}ms)",
126 batch_id, num_batches, batch_size, elapsed.as_millis());
127 }
128
129 // Cool healthy phase
130 let healthy_patterns = healthy_kiln.cool();
131 println!("\n Healthy system patterns ({} detected):", healthy_patterns.len());
132 for p in &healthy_patterns {
133 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
134 }
135 // Also check conservation on records_in/records_out
136 let conservation = healthy_kiln.distribution_shift(10);
137 println!(" Distribution shifts:");
138 for (name, shift) in &conservation[..conservation.len().min(3)] {
139 println!(" {} → KL = {:.4}", name, shift);
140 }
141
142 println!();
143
144 // Phase 2: Degrading system (batches 5-8)
145 println!("─── Phase 2: Degrading System ───");
146
147 let mut degrading_kiln = Kiln::new(
148 ThermalProfile::fast_cooling()
149 );
150
151 // Batches where degradation ramps up
152 let degradation_levels = [0.2, 0.5, 0.9, 1.5];
153 for (i, °radation) in degradation_levels.iter().enumerate() {
154 let batch_id = (5 + i) as u32;
155 // latency increases with degradation
156 let base_latency = 10.0 + degradation * 50.0;
157
158 let events = simulate_batch(batch_id, batch_size as u32, base_latency, degradation);
159 for event in events {
160 degrading_kiln.fire_and_record(event).unwrap();
161 }
162
163 let elapsed = start.elapsed();
164 println!(" Batch {}/{} [degradation={:.1}x] fired (latency baseline: {:.0}ms, {:.0}ms total)",
165 batch_id, num_batches, degradation, base_latency, elapsed.as_millis());
166 }
167
168 let degrading_patterns = degrading_kiln.cool();
169 println!("\n Degrading system patterns ({} detected):", degrading_patterns.len());
170 for p in °rading_patterns {
171 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
172 }
173
174 // JSD shift (distribution shape changes)
175 let jsd_shifts = degrading_kiln.jsd_shift(10);
176 println!(" JSD shifts (distribution shape changes):");
177 for (name, shift) in &jsd_shifts[..jsd_shifts.len().min(5)] {
178 println!(" {} → JSD = {:.4}", name, shift);
179 }
180
181 // Permutation entropy (temporal structure)
182 let pes = degrading_kiln.permutation_entropies(4);
183 println!(" Permutation entropies (temporal structure):");
184 for (name, pe) in &pes {
185 println!(" {} → PE = {:.4}", name, pe);
186 }
187
188 println!();
189
190 // Phase 3: Conservation law test — records in = records out should be violated
191 // as errors increase
192 println!("─── Phase 3: Conservation Law Verification ───");
193 let mut conservation_kiln = Kiln::new(
194 ThermalProfile::fast_cooling()
195 );
196
197 // Force records_in = records_out for first 3 batches (healthy conservation)
198 for batch_id in 1..=3 {
199 let event = ProcessedEvent {
200 event_id: batch_id as u64,
201 batch_id: batch_id as u32,
202 processing_time_ms: 10.0,
203 throughput: 100.0,
204 memory_mb: 128.0,
205 error_rate: 0.01,
206 records_in: 1000.0,
207 records_out: 995.0, // nearly conserved
208 cpu_temp_c: 65.0,
209 latency_p99_ms: 25.0,
210 consumer_lag: 10.0,
211 gc_pause_ms: 5.0,
212 };
213 conservation_kiln.fire_and_record(event).unwrap();
214 }
215
216 // Force violation of records conservation (errors spike)
217 for batch_id in 4..=6 {
218 let event = ProcessedEvent {
219 event_id: batch_id as u64,
220 batch_id: batch_id as u32,
221 processing_time_ms: 10.0 + batch_id as f64 * 10.0,
222 throughput: 50.0,
223 memory_mb: 256.0,
224 error_rate: 0.3,
225 records_in: 1000.0,
226 records_out: 700.0, // 30% loss — conservation violated
227 cpu_temp_c: 80.0,
228 latency_p99_ms: 100.0,
229 consumer_lag: 500.0,
230 gc_pause_ms: 20.0,
231 };
232 conservation_kiln.fire_and_record(event).unwrap();
233 }
234
235 let conservation_patterns = conservation_kiln.cool();
236 println!(" Conservation-specific patterns ({} detected):", conservation_patterns.len());
237 for p in &conservation_patterns {
238 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
239 }
240
241 // MI matrix to show nonlinear dependencies
242 let mi = conservation_kiln.mi_matrix(8);
243 println!(" Mutual Information matrix (8 bins):");
244 let metric_names = ["processing_time_ms", "error_rate", "records_in", "records_out", "memory_mb"];
245 for (i, name_i) in metric_names.iter().enumerate() {
246 for (j, name_j) in metric_names.iter().enumerate() {
247 if i == j {
248 println!(" I({:25}; {:25}) = H({})", name_i, name_j, name_i);
249 } else {
250 println!(" I({:25}; {:25}) = {:.4} bits", name_i, name_j, mi[i][j]);
251 }
252 }
253 }
254
255 println!();
256 println!("───────────────────────────────────────────────────────────────");
257 println!(" SUMMARY");
258 println!("───────────────────────────────────────────────────────────────\n");
259
260 // Degradation detection analysis
261 println!(" Degradation Metrics:");
262 let pt = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::PhaseTransition));
263 let pt_count = pt.count();
264 println!(" Phase transitions detected in degraded system: {} alerts",
265 pt_count);
266
267 let corr = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Correlation));
268 let corr_count = corr.count();
269 println!(" Correlations in degraded system: {} pairs", corr_count);
270
271 let cons = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Conservation));
272 let cons_count = cons.count();
273 println!(" Conservation laws in degraded system: {} found", cons_count);
274
275 let clust = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Clustering));
276 let clust_count = clust.count();
277 println!(" Clusters in degraded system: {} groups", clust_count);
278
279 println!();
280 let total_duration = start.elapsed();
281 println!(" Total test duration: {:.2}s", total_duration.as_secs_f64());
282 println!(" Events processed: {}", total_events);
283 println!(" Avg throughput: {:.0} events/s",
284 total_events as f64 / total_duration.as_secs_f64());
285}Sourcepub fn involved_tasks(&self) -> &[String]
pub fn involved_tasks(&self) -> &[String]
Labels of tasks involved in this pattern.
Examples found in repository?
examples/basic.rs (line 46)
29fn main() {
30 let mut kiln = Kiln::new(ThermalProfile::fast_cooling());
31
32 kiln.fire_and_record(NumberTask { value: 2.0, name: "a".into() }).unwrap();
33 kiln.fire_and_record(NumberTask { value: 2.1, name: "b".into() }).unwrap();
34 kiln.fire_and_record(NumberTask { value: 9.8, name: "c".into() }).unwrap();
35 kiln.fire_and_record(NumberTask { value: 10.0, name: "d".into() }).unwrap();
36 kiln.fire_and_record(NumberTask { value: 2.2, name: "e".into() }).unwrap();
37
38 println!("Tasks in kiln: {}", kiln.task_count());
39
40 let patterns = kiln.cool();
41 println!("\nDetected {} pattern(s):\n", patterns.len());
42
43 for p in &patterns {
44 println!("[{}] {}", p.kind(), p.description());
45 println!(" confidence: {:.2}", p.confidence());
46 println!(" tasks: {:?}\n", p.involved_tasks());
47 }
48}More examples
examples/ci_patterns.rs (line 49)
30fn main() {
31 let mut kiln = Kiln::new(ThermalProfile::default());
32
33 // Normal builds
34 kiln.fire_and_record(CiBuild { duration_secs: 45.0, test_count: 200.0, branch: "feature/auth".into() }).unwrap();
35 kiln.fire_and_record(CiBuild { duration_secs: 42.0, test_count: 195.0, branch: "fix/typo".into() }).unwrap();
36 kiln.fire_and_record(CiBuild { duration_secs: 48.0, test_count: 210.0, branch: "feature/ui".into() }).unwrap();
37
38 // Something changed — builds got slower
39 kiln.fire_and_record(CiBuild { duration_secs: 95.0, test_count: 200.0, branch: "feature/cache".into() }).unwrap();
40 kiln.fire_and_record(CiBuild { duration_secs: 102.0, test_count: 198.0, branch: "chore/deps".into() }).unwrap();
41
42 let patterns = kiln.cool();
43 println!("CI Build Pattern Analysis");
44 println!("=========================\n");
45
46 for p in &patterns {
47 println!("[{}] {}", p.kind().to_string().to_uppercase(), p.description());
48 println!(" confidence: {:.2}", p.confidence());
49 println!(" branches: {:?}\n", p.involved_tasks());
50 }
51
52 // Check for phase transition in build duration
53 let phase_shifts: Vec<_> = patterns.iter()
54 .filter(|p| format!("{}", p.kind()) == "phase transition")
55 .collect();
56
57 if !phase_shifts.is_empty() {
58 println!("⚠️ Build duration shifted significantly — investigate recent changes!");
59 }
60}examples/api_monitoring.rs (line 56)
32fn main() {
33 let mut kiln = Kiln::new(ThermalProfile::default());
34
35 // /api/users — fast, small responses
36 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 45.0, status: 200, response_bytes: 1200.0 }).unwrap();
37 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 48.0, status: 200, response_bytes: 1150.0 }).unwrap();
38 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 52.0, status: 200, response_bytes: 1300.0 }).unwrap();
39
40 // /api/reports — slow, large responses (correlated with bytes)
41 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 350.0, status: 200, response_bytes: 55000.0 }).unwrap();
42 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 380.0, status: 200, response_bytes: 62000.0 }).unwrap();
43
44 // /api/health — tiny, always fast (conservation candidate)
45 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 3.0, status: 200, response_bytes: 15.0 }).unwrap();
46 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 4.0, status: 200, response_bytes: 15.0 }).unwrap();
47
48 let patterns = kiln.cool();
49 println!("API Monitoring — Pattern Report");
50 println!("================================\n");
51 println!("{} patterns detected:\n", patterns.len());
52
53 for p in &patterns {
54 println!("[{}] {}", p.kind(), p.description());
55 println!(" confidence: {:.2}", p.confidence());
56 if !p.involved_tasks().is_empty() {
57 println!(" endpoints: {:?}", p.involved_tasks());
58 }
59 println!();
60 }
61
62 // Highlight correlations between latency and response size
63 let correlations: Vec<_> = patterns.iter()
64 .filter(|p| format!("{}", p.kind()) == "correlation")
65 .collect();
66
67 if !correlations.is_empty() {
68 println!("📊 Latency and response size are correlated — consider pagination or caching.");
69 }
70}Sourcepub fn confidence(&self) -> f64
pub fn confidence(&self) -> f64
Confidence score (0.0 to 1.0).
Examples found in repository?
examples/basic.rs (line 45)
29fn main() {
30 let mut kiln = Kiln::new(ThermalProfile::fast_cooling());
31
32 kiln.fire_and_record(NumberTask { value: 2.0, name: "a".into() }).unwrap();
33 kiln.fire_and_record(NumberTask { value: 2.1, name: "b".into() }).unwrap();
34 kiln.fire_and_record(NumberTask { value: 9.8, name: "c".into() }).unwrap();
35 kiln.fire_and_record(NumberTask { value: 10.0, name: "d".into() }).unwrap();
36 kiln.fire_and_record(NumberTask { value: 2.2, name: "e".into() }).unwrap();
37
38 println!("Tasks in kiln: {}", kiln.task_count());
39
40 let patterns = kiln.cool();
41 println!("\nDetected {} pattern(s):\n", patterns.len());
42
43 for p in &patterns {
44 println!("[{}] {}", p.kind(), p.description());
45 println!(" confidence: {:.2}", p.confidence());
46 println!(" tasks: {:?}\n", p.involved_tasks());
47 }
48}More examples
examples/ci_patterns.rs (line 48)
30fn main() {
31 let mut kiln = Kiln::new(ThermalProfile::default());
32
33 // Normal builds
34 kiln.fire_and_record(CiBuild { duration_secs: 45.0, test_count: 200.0, branch: "feature/auth".into() }).unwrap();
35 kiln.fire_and_record(CiBuild { duration_secs: 42.0, test_count: 195.0, branch: "fix/typo".into() }).unwrap();
36 kiln.fire_and_record(CiBuild { duration_secs: 48.0, test_count: 210.0, branch: "feature/ui".into() }).unwrap();
37
38 // Something changed — builds got slower
39 kiln.fire_and_record(CiBuild { duration_secs: 95.0, test_count: 200.0, branch: "feature/cache".into() }).unwrap();
40 kiln.fire_and_record(CiBuild { duration_secs: 102.0, test_count: 198.0, branch: "chore/deps".into() }).unwrap();
41
42 let patterns = kiln.cool();
43 println!("CI Build Pattern Analysis");
44 println!("=========================\n");
45
46 for p in &patterns {
47 println!("[{}] {}", p.kind().to_string().to_uppercase(), p.description());
48 println!(" confidence: {:.2}", p.confidence());
49 println!(" branches: {:?}\n", p.involved_tasks());
50 }
51
52 // Check for phase transition in build duration
53 let phase_shifts: Vec<_> = patterns.iter()
54 .filter(|p| format!("{}", p.kind()) == "phase transition")
55 .collect();
56
57 if !phase_shifts.is_empty() {
58 println!("⚠️ Build duration shifted significantly — investigate recent changes!");
59 }
60}examples/api_monitoring.rs (line 55)
32fn main() {
33 let mut kiln = Kiln::new(ThermalProfile::default());
34
35 // /api/users — fast, small responses
36 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 45.0, status: 200, response_bytes: 1200.0 }).unwrap();
37 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 48.0, status: 200, response_bytes: 1150.0 }).unwrap();
38 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 52.0, status: 200, response_bytes: 1300.0 }).unwrap();
39
40 // /api/reports — slow, large responses (correlated with bytes)
41 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 350.0, status: 200, response_bytes: 55000.0 }).unwrap();
42 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 380.0, status: 200, response_bytes: 62000.0 }).unwrap();
43
44 // /api/health — tiny, always fast (conservation candidate)
45 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 3.0, status: 200, response_bytes: 15.0 }).unwrap();
46 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 4.0, status: 200, response_bytes: 15.0 }).unwrap();
47
48 let patterns = kiln.cool();
49 println!("API Monitoring — Pattern Report");
50 println!("================================\n");
51 println!("{} patterns detected:\n", patterns.len());
52
53 for p in &patterns {
54 println!("[{}] {}", p.kind(), p.description());
55 println!(" confidence: {:.2}", p.confidence());
56 if !p.involved_tasks().is_empty() {
57 println!(" endpoints: {:?}", p.involved_tasks());
58 }
59 println!();
60 }
61
62 // Highlight correlations between latency and response size
63 let correlations: Vec<_> = patterns.iter()
64 .filter(|p| format!("{}", p.kind()) == "correlation")
65 .collect();
66
67 if !correlations.is_empty() {
68 println!("📊 Latency and response size are correlated — consider pagination or caching.");
69 }
70}examples/event_stream_processor.rs (line 133)
98fn main() {
99 let total_events = 1000;
100 let batch_size = 100;
101 let num_batches = total_events / batch_size;
102
103 println!("═══════════════════════════════════════════════════════════════");
104 println!(" CRACKLE-RUNTIME: EVENT STREAM PROCESSOR TEST");
105 println!("═══════════════════════════════════════════════════════════════\n");
106 println!("Processing {} events across {} batches of {}...\n",
107 total_events, num_batches, batch_size);
108
109 let start = Instant::now();
110
111 // Phase 1: Healthy system (batches 1-4)
112 println!("─── Phase 1: Healthy System ───");
113 let mut healthy_kiln = Kiln::new(
114 ThermalProfile::fast_cooling()
115 );
116
117 // Batch 1-4: all healthy, 10ms baseline latency
118 for batch_id in 1..=4 {
119 let events = simulate_batch(batch_id, batch_size as u32, 10.0, 0.05);
120 for event in events {
121 healthy_kiln.fire_and_record(event).unwrap();
122 }
123
124 let elapsed = start.elapsed();
125 println!(" Batch {}/{} fired ({} events, {:.0}ms)",
126 batch_id, num_batches, batch_size, elapsed.as_millis());
127 }
128
129 // Cool healthy phase
130 let healthy_patterns = healthy_kiln.cool();
131 println!("\n Healthy system patterns ({} detected):", healthy_patterns.len());
132 for p in &healthy_patterns {
133 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
134 }
135 // Also check conservation on records_in/records_out
136 let conservation = healthy_kiln.distribution_shift(10);
137 println!(" Distribution shifts:");
138 for (name, shift) in &conservation[..conservation.len().min(3)] {
139 println!(" {} → KL = {:.4}", name, shift);
140 }
141
142 println!();
143
144 // Phase 2: Degrading system (batches 5-8)
145 println!("─── Phase 2: Degrading System ───");
146
147 let mut degrading_kiln = Kiln::new(
148 ThermalProfile::fast_cooling()
149 );
150
151 // Batches where degradation ramps up
152 let degradation_levels = [0.2, 0.5, 0.9, 1.5];
153 for (i, °radation) in degradation_levels.iter().enumerate() {
154 let batch_id = (5 + i) as u32;
155 // latency increases with degradation
156 let base_latency = 10.0 + degradation * 50.0;
157
158 let events = simulate_batch(batch_id, batch_size as u32, base_latency, degradation);
159 for event in events {
160 degrading_kiln.fire_and_record(event).unwrap();
161 }
162
163 let elapsed = start.elapsed();
164 println!(" Batch {}/{} [degradation={:.1}x] fired (latency baseline: {:.0}ms, {:.0}ms total)",
165 batch_id, num_batches, degradation, base_latency, elapsed.as_millis());
166 }
167
168 let degrading_patterns = degrading_kiln.cool();
169 println!("\n Degrading system patterns ({} detected):", degrading_patterns.len());
170 for p in °rading_patterns {
171 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
172 }
173
174 // JSD shift (distribution shape changes)
175 let jsd_shifts = degrading_kiln.jsd_shift(10);
176 println!(" JSD shifts (distribution shape changes):");
177 for (name, shift) in &jsd_shifts[..jsd_shifts.len().min(5)] {
178 println!(" {} → JSD = {:.4}", name, shift);
179 }
180
181 // Permutation entropy (temporal structure)
182 let pes = degrading_kiln.permutation_entropies(4);
183 println!(" Permutation entropies (temporal structure):");
184 for (name, pe) in &pes {
185 println!(" {} → PE = {:.4}", name, pe);
186 }
187
188 println!();
189
190 // Phase 3: Conservation law test — records in = records out should be violated
191 // as errors increase
192 println!("─── Phase 3: Conservation Law Verification ───");
193 let mut conservation_kiln = Kiln::new(
194 ThermalProfile::fast_cooling()
195 );
196
197 // Force records_in = records_out for first 3 batches (healthy conservation)
198 for batch_id in 1..=3 {
199 let event = ProcessedEvent {
200 event_id: batch_id as u64,
201 batch_id: batch_id as u32,
202 processing_time_ms: 10.0,
203 throughput: 100.0,
204 memory_mb: 128.0,
205 error_rate: 0.01,
206 records_in: 1000.0,
207 records_out: 995.0, // nearly conserved
208 cpu_temp_c: 65.0,
209 latency_p99_ms: 25.0,
210 consumer_lag: 10.0,
211 gc_pause_ms: 5.0,
212 };
213 conservation_kiln.fire_and_record(event).unwrap();
214 }
215
216 // Force violation of records conservation (errors spike)
217 for batch_id in 4..=6 {
218 let event = ProcessedEvent {
219 event_id: batch_id as u64,
220 batch_id: batch_id as u32,
221 processing_time_ms: 10.0 + batch_id as f64 * 10.0,
222 throughput: 50.0,
223 memory_mb: 256.0,
224 error_rate: 0.3,
225 records_in: 1000.0,
226 records_out: 700.0, // 30% loss — conservation violated
227 cpu_temp_c: 80.0,
228 latency_p99_ms: 100.0,
229 consumer_lag: 500.0,
230 gc_pause_ms: 20.0,
231 };
232 conservation_kiln.fire_and_record(event).unwrap();
233 }
234
235 let conservation_patterns = conservation_kiln.cool();
236 println!(" Conservation-specific patterns ({} detected):", conservation_patterns.len());
237 for p in &conservation_patterns {
238 println!(" [{:?}] {} (conf: {:.2})", p.kind(), p.description(), p.confidence());
239 }
240
241 // MI matrix to show nonlinear dependencies
242 let mi = conservation_kiln.mi_matrix(8);
243 println!(" Mutual Information matrix (8 bins):");
244 let metric_names = ["processing_time_ms", "error_rate", "records_in", "records_out", "memory_mb"];
245 for (i, name_i) in metric_names.iter().enumerate() {
246 for (j, name_j) in metric_names.iter().enumerate() {
247 if i == j {
248 println!(" I({:25}; {:25}) = H({})", name_i, name_j, name_i);
249 } else {
250 println!(" I({:25}; {:25}) = {:.4} bits", name_i, name_j, mi[i][j]);
251 }
252 }
253 }
254
255 println!();
256 println!("───────────────────────────────────────────────────────────────");
257 println!(" SUMMARY");
258 println!("───────────────────────────────────────────────────────────────\n");
259
260 // Degradation detection analysis
261 println!(" Degradation Metrics:");
262 let pt = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::PhaseTransition));
263 let pt_count = pt.count();
264 println!(" Phase transitions detected in degraded system: {} alerts",
265 pt_count);
266
267 let corr = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Correlation));
268 let corr_count = corr.count();
269 println!(" Correlations in degraded system: {} pairs", corr_count);
270
271 let cons = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Conservation));
272 let cons_count = cons.count();
273 println!(" Conservation laws in degraded system: {} found", cons_count);
274
275 let clust = degrading_patterns.iter().filter(|p| matches!(p.kind(), crackle_runtime::PatternKind::Clustering));
276 let clust_count = clust.count();
277 println!(" Clusters in degraded system: {} groups", clust_count);
278
279 println!();
280 let total_duration = start.elapsed();
281 println!(" Total test duration: {:.2}s", total_duration.as_secs_f64());
282 println!(" Events processed: {}", total_events);
283 println!(" Avg throughput: {:.0} events/s",
284 total_events as f64 / total_duration.as_secs_f64());
285}Sourcepub fn with_metric(self, name: impl Into<String>, value: f64) -> Self
pub fn with_metric(self, name: impl Into<String>, value: f64) -> Self
Add a metric to this pattern.
Sourcepub fn with_metrics(self, metrics: Vec<(String, f64)>) -> Self
pub fn with_metrics(self, metrics: Vec<(String, f64)>) -> Self
Create a pattern with additional metrics.
Trait Implementations§
Source§impl Clone for CracklePattern
impl Clone for CracklePattern
Source§fn clone(&self) -> CracklePattern
fn clone(&self) -> CracklePattern
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for CracklePattern
impl RefUnwindSafe for CracklePattern
impl Send for CracklePattern
impl Sync for CracklePattern
impl Unpin for CracklePattern
impl UnsafeUnpin for CracklePattern
impl UnwindSafe for CracklePattern
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more