// rust/01-structured-logging.rs/*Structured logging patterns and best practices*/usestd::collections::HashMap;useserde::{Deserialize,Serialize};usestd::time::{SystemTime,UNIX_EPOCH};/// Structured log entry.#[derive(Debug, Clone, Serialize, Deserialize)]pubstructLogEntry{pubtimestamp:u64,publevel:LogLevel,pubmessage:String,pubfields:HashMap<String,serde_json::Value>,pubtarget:String,pubspan_id:Option<String>,pubtrace_id:Option<String>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubenumLogLevel{Trace,Debug,Info,Warn,Error,}implLogEntry{pubfnnew(level:LogLevel,message:String,target:String)->Self{Self{timestamp:SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()asu64,level,message,fields:HashMap::new(),target,span_id:None,trace_id:None,}}/// Add a field to the log entry.pubfnfield(mutself,key:String,value:serde_json::Value)->Self{self.fields.insert(key,value);self}/// Set span ID for distributed tracing.pubfnspan_id(mutself,span_id:String)->Self{self.span_id=Some(span_id);self}/// Set trace ID for distributed tracing.pubfntrace_id(mutself,trace_id:String)->Self{self.trace_id=Some(trace_id);self}}/// Structured logger.pubstructStructuredLogger{app_name:String,version:String,environment:String,log_level:LogLevel,fields:HashMap<String,serde_json::Value>,}implStructuredLogger{pubfnnew(app_name:String,version:String,environment:String)->Self{Self{app_name,version,environment,log_level:LogLevel::Info,fields:HashMap::new(),}}/// Set the minimum log level.pubfnset_log_level(&mutself,level:LogLevel){self.log_level=level;}/// Add a global field to all log entries.pubfnadd_global_field(&mutself,key:String,value:serde_json::Value){self.fields.insert(key,value);}/// Create a log entry.pubfnlog(&self,level:LogLevel,message:String,target:String)->LogEntry{letmutentry=LogEntry::new(level,message,target);// Add global fieldsfor(key,value)in&self.fields{entry.fields.insert(key.clone(),value.clone());}// Add application metadataentry.fields.insert("app_name".to_string(),serde_json::Value::String(self.app_name.clone()));entry.fields.insert("version".to_string(),serde_json::Value::String(self.version.clone()));entry.fields.insert("environment".to_string(),serde_json::Value::String(self.environment.clone()));entry}/// Log an info message.pubfninfo(&self,message:String,target:String)->LogEntry{self.log(LogLevel::Info,message,target)}/// Log a warning message.pubfnwarn(&self,message:String,target:String)->LogEntry{self.log(LogLevel::Warn,message,target)}/// Log an error message.pubfnerror(&self,message:String,target:String)->LogEntry{self.log(LogLevel::Error,message,target)}/// Log a debug message.pubfndebug(&self,message:String,target:String)->LogEntry{self.log(LogLevel::Debug,message,target)}/// Log a trace message.pubfntrace(&self,message:String,target:String)->LogEntry{self.log(LogLevel::Trace,message,target)}}/// Log formatter for different output formats.pubtraitLogFormatter{fnformat(&self,entry:&LogEntry)->String;}/// JSON log formatter.pubstructJsonFormatter;implLogFormatterforJsonFormatter{fnformat(&self,entry:&LogEntry)->String{serde_json::to_string(entry).unwrap_or_else(|_|"{}".to_string())}}/// Text log formatter.pubstructTextFormatter;implLogFormatterforTextFormatter{fnformat(&self,entry:&LogEntry)->String{format!("[{}] {} {}: {}",entry.timestamp,entry.level,entry.target,entry.message)}}/// Log handler for processing log entries.pubtraitLogHandler{fnhandle(&self,entry:&LogEntry)->Result<(),String>;}/// Console log handler.pubstructConsoleLogHandler{formatter:Box<dynLogFormatter>,}implConsoleLogHandler{pubfnnew(formatter:Box<dynLogFormatter>)->Self{Self{formatter}}}implLogHandlerforConsoleLogHandler{fnhandle(&self,entry:&LogEntry)->Result<(),String>{letformatted=self.formatter.format(entry);println!("{}",formatted);Ok(())}}/// File log handler.pubstructFileLogHandler{file_path:String,formatter:Box<dynLogFormatter>,}implFileLogHandler{pubfnnew(file_path:String,formatter:Box<dynLogFormatter>)->Self{Self{file_path,formatter}}}implLogHandlerforFileLogHandler{fnhandle(&self,entry:&LogEntry)->Result<(),String>{letformatted=self.formatter.format(entry);std::fs::OpenOptions::new().create(true).append(true).open(&self.file_path).map_err(|e|format!("Failed to open log file: {}",e))?.write_all(formatted.as_bytes()).map_err(|e|format!("Failed to write to log file: {}",e))?;Ok(())}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_structured_logger(){letlogger=StructuredLogger::new("test-app".to_string(),"1.0.0".to_string(),"test".to_string(),);letentry=logger.info("Test message".to_string(),"test::module".to_string());assert_eq!(entry.message,"Test message");assert_eq!(entry.target,"test::module");}#[test]fntest_log_entry_fields(){letmutentry=LogEntry::new(LogLevel::Info,"Test message".to_string(),"test::module".to_string(),);entry=entry.field("user_id".to_string(),serde_json::Value::String("123".to_string()));entry=entry.field("request_id".to_string(),serde_json::Value::String("req-123".to_string()));assert!(entry.fields.contains_key("user_id"));assert!(entry.fields.contains_key("request_id"));}}
// rust/02-metrics-collection.rs/*Metrics collection patterns and best practices*/usestd::collections::HashMap;usestd::sync::Arc;usestd::sync::atomic::{AtomicU64,AtomicF64,Ordering};useserde::{Deserialize,Serialize};/// Metric types.#[derive(Debug, Clone, Serialize, Deserialize)]pubenumMetricType{Counter,Gauge,Histogram,Summary,}/// Metric value.#[derive(Debug, Clone, Serialize, Deserialize)]pubstructMetricValue{pubname:String,pubvalue:f64,publabels:HashMap<String,String>,pubtimestamp:u64,}/// Counter metric.pubstructCounter{name:String,value:AtomicU64,labels:HashMap<String,String>,}implCounter{pubfnnew(name:String,labels:HashMap<String,String>)->Self{Self{name,value:AtomicU64::new(0),labels,}}/// Increment the counter.pubfninc(&self){self.value.fetch_add(1,Ordering::Relaxed);}/// Add a value to the counter.pubfnadd(&self,value:u64){self.value.fetch_add(value,Ordering::Relaxed);}/// Get the current value.pubfnget(&self)->u64{self.value.load(Ordering::Relaxed)}/// Get the metric value.pubfnget_metric_value(&self)->MetricValue{MetricValue{name:self.name.clone(),value:self.get()asf64,labels:self.labels.clone(),timestamp:std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis()asu64,}}}/// Gauge metric.pubstructGauge{name:String,value:AtomicF64::new(0.0),labels:HashMap<String,String>,}implGauge{pubfnnew(name:String,labels:HashMap<String,String>)->Self{Self{name,value:AtomicF64::new(0.0),labels,}}/// Set the gauge value.pubfnset(&self,value:f64){self.value.store(value,Ordering::Relaxed);}/// Add a value to the gauge.pubfnadd(&self,value:f64){self.value.fetch_add(value,Ordering::Relaxed);}/// Subtract a value from the gauge.pubfnsub(&self,value:f64){self.value.fetch_sub(value,Ordering::Relaxed);}/// Get the current value.pubfnget(&self)->f64{self.value.load(Ordering::Relaxed)}/// Get the metric value.pubfnget_metric_value(&self)->MetricValue{MetricValue{name:self.name.clone(),value:self.get(),labels:self.labels.clone(),timestamp:std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis()asu64,}}}/// Histogram metric.pubstructHistogram{name:String,buckets:Vec<f64>,counts:Vec<AtomicU64>,sum:AtomicF64,labels:HashMap<String,String>,}implHistogram{pubfnnew(name:String,buckets:Vec<f64>,labels:HashMap<String,String>)->Self{letcounts=vec![AtomicU64::new(0);buckets.len()+1];// +1 for +Inf bucketSelf{name,buckets,counts,sum:AtomicF64::new(0.0),labels,}}/// Observe a value.pubfnobserve(&self,value:f64){self.sum.fetch_add(value,Ordering::Relaxed);// Find the appropriate bucketletmutbucket_index=self.buckets.len();for(i,bucket)inself.buckets.iter().enumerate(){ifvalue<=*bucket{bucket_index=i;break;}}self.counts[bucket_index].fetch_add(1,Ordering::Relaxed);}/// Get the metric value.pubfnget_metric_value(&self)->MetricValue{MetricValue{name:self.name.clone(),value:self.sum.load(Ordering::Relaxed),labels:self.labels.clone(),timestamp:std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis()asu64,}}}/// Metrics registry.pubstructMetricsRegistry{counters:HashMap<String,Arc<Counter>>,gauges:HashMap<String,Arc<Gauge>>,histograms:HashMap<String,Arc<Histogram>>,}implMetricsRegistry{pubfnnew()->Self{Self{counters:HashMap::new(),gauges:HashMap::new(),histograms:HashMap::new(),}}/// Register a counter.pubfnregister_counter(&mutself,name:String,labels:HashMap<String,String>)->Arc<Counter>{letcounter=Arc::new(Counter::new(name.clone(),labels));self.counters.insert(name,counter.clone());counter}/// Register a gauge.pubfnregister_gauge(&mutself,name:String,labels:HashMap<String,String>)->Arc<Gauge>{letgauge=Arc::new(Gauge::new(name.clone(),labels));self.gauges.insert(name,gauge.clone());gauge}/// Register a histogram.pubfnregister_histogram(&mutself,name:String,buckets:Vec<f64>,labels:HashMap<String,String>)->Arc<Histogram>{lethistogram=Arc::new(Histogram::new(name.clone(),buckets,labels));self.histograms.insert(name,histogram.clone());histogram}/// Get all metric values.pubfnget_all_metrics(&self)->Vec<MetricValue>{letmutmetrics=Vec::new();forcounterinself.counters.values(){metrics.push(counter.get_metric_value());}forgaugeinself.gauges.values(){metrics.push(gauge.get_metric_value());}forhistograminself.histograms.values(){metrics.push(histogram.get_metric_value());}metrics}/// Get metrics in Prometheus format.pubfnget_prometheus_metrics(&self)->String{letmutoutput=String::new();forcounterinself.counters.values(){letmetric=counter.get_metric_value();output.push_str(&format!("# HELP {} Counter metric\n",metric.name));output.push_str(&format!("# TYPE {} counter\n",metric.name));output.push_str(&format!("{} {} {}\n",metric.name,metric.value,metric.timestamp));}forgaugeinself.gauges.values(){letmetric=gauge.get_metric_value();output.push_str(&format!("# HELP {} Gauge metric\n",metric.name));output.push_str(&format!("# TYPE {} gauge\n",metric.name));output.push_str(&format!("{} {} {}\n",metric.name,metric.value,metric.timestamp));}output}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_counter(){letcounter=Counter::new("test_counter".to_string(),HashMap::new());counter.inc();counter.add(5);assert_eq!(counter.get(),6);}#[test]fntest_gauge(){letgauge=Gauge::new("test_gauge".to_string(),HashMap::new());gauge.set(10.0);gauge.add(5.0);assert_eq!(gauge.get(),15.0);}#[test]fntest_histogram(){lethistogram=Histogram::new("test_histogram".to_string(),vec![0.1,0.5,1.0,2.5,5.0,10.0],HashMap::new(),);histogram.observe(0.3);histogram.observe(0.7);histogram.observe(1.5);assert!(histogram.sum.load(Ordering::Relaxed)>0.0);}#[test]fntest_metrics_registry(){letmutregistry=MetricsRegistry::new();letcounter=registry.register_counter("test_counter".to_string(),HashMap::new());counter.inc();letgauge=registry.register_gauge("test_gauge".to_string(),HashMap::new());gauge.set(10.0);letmetrics=registry.get_all_metrics();assert_eq!(metrics.len(),2);}}
// rust/03-distributed-tracing.rs/*Distributed tracing patterns and best practices*/usestd::collections::HashMap;useserde::{Deserialize,Serialize};useuuid::Uuid;/// Trace context for distributed tracing.#[derive(Debug, Clone, Serialize, Deserialize)]pubstructTraceContext{pubtrace_id:String,pubspan_id:String,pubparent_span_id:Option<String>,pubbaggage:HashMap<String,String>,}implTraceContext{pubfnnew(trace_id:String,span_id:String)->Self{Self{trace_id,span_id,parent_span_id:None,baggage:HashMap::new(),}}/// Create a new trace context.pubfncreate()->Self{Self::new(Uuid::new_v4().to_string(),Uuid::new_v4().to_string(),)}/// Create a child span context.pubfncreate_child(&self)->Self{Self{trace_id:self.trace_id.clone(),span_id:Uuid::new_v4().to_string(),parent_span_id:Some(self.span_id.clone()),baggage:self.baggage.clone(),}}/// Add baggage to the trace context.pubfnadd_baggage(&mutself,key:String,value:String){self.baggage.insert(key,value);}/// Get baggage from the trace context.pubfnget_baggage(&self,key:&str)->Option<&String>{self.baggage.get(key)}}/// Span for distributed tracing.pubstructSpan{pubcontext:TraceContext,puboperation_name:String,pubstart_time:u64,pubend_time:Option<u64>,pubtags:HashMap<String,String>,publogs:Vec<SpanLog>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructSpanLog{pubtimestamp:u64,pubfields:HashMap<String,String>,}implSpan{pubfnnew(context:TraceContext,operation_name:String)->Self{Self{context,operation_name,start_time:std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis()asu64,end_time:None,tags:HashMap::new(),logs:Vec::new(),}}/// Add a tag to the span.pubfntag(&mutself,key:String,value:String){self.tags.insert(key,value);}/// Add a log entry to the span.pubfnlog(&mutself,fields:HashMap<String,String>){letlog=SpanLog{timestamp:std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis()asu64,fields,};self.logs.push(log);}/// Finish the span.pubfnfinish(&mutself){self.end_time=Some(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis()asu64,);}/// Get the duration of the span.pubfnduration(&self)->Option<u64>{self.end_time.map(|end|end-self.start_time)}}/// Tracer for distributed tracing.pubstructTracer{service_name:String,service_version:String,spans:Vec<Span>,}implTracer{pubfnnew(service_name:String,service_version:String)->Self{Self{service_name,service_version,spans:Vec::new(),}}/// Start a new span.pubfnstart_span(&mutself,operation_name:String,parent_context:Option<&TraceContext>)->TraceContext{letcontext=ifletSome(parent)=parent_context{parent.create_child()}else{TraceContext::create()};letmutspan=Span::new(context.clone(),operation_name);span.tag("service.name".to_string(),self.service_name.clone());span.tag("service.version".to_string(),self.service_version.clone());self.spans.push(span);context}/// Finish a span.pubfnfinish_span(&mutself,context:&TraceContext)->Option<Span>{ifletSome(span)=self.spans.iter_mut().find(|s|s.context.span_id==context.span_id){span.finish();Some(span.clone())}else{None}}/// Get all spans.pubfnget_spans(&self)->&[Span]{&self.spans}/// Get spans for a specific trace.pubfnget_spans_for_trace(&self,trace_id:&str)->Vec<&Span>{self.spans.iter().filter(|span|span.context.trace_id==trace_id).collect()}}/// Trace exporter for sending traces to external systems.pubtraitTraceExporter{fnexport(&self,spans:&[Span])->Result<(),String>;}/// Console trace exporter.pubstructConsoleTraceExporter;implTraceExporterforConsoleTraceExporter{fnexport(&self,spans:&[Span])->Result<(),String>{forspaninspans{println!("Span: {} ({}ms)",span.operation_name,span.duration().unwrap_or(0));println!(" Trace ID: {}",span.context.trace_id);println!(" Span ID: {}",span.context.span_id);ifletSome(parent_id)=&span.context.parent_span_id{println!(" Parent Span ID: {}",parent_id);}println!(" Tags: {:?}",span.tags);println!(" Logs: {}",span.logs.len());}Ok(())}}/// Jaeger trace exporter.pubstructJaegerTraceExporter{endpoint:String,service_name:String,}implJaegerTraceExporter{pubfnnew(endpoint:String,service_name:String)->Self{Self{endpoint,service_name}}}implTraceExporterforJaegerTraceExporter{fnexport(&self,spans:&[Span])->Result<(),String>{// In a real implementation, you would send the spans to Jaegerprintln!("Exporting {} spans to Jaeger at {}",spans.len(),self.endpoint);Ok(())}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_trace_context(){letcontext=TraceContext::create();assert!(!context.trace_id.is_empty());assert!(!context.span_id.is_empty());letchild_context=context.create_child();assert_eq!(child_context.trace_id,context.trace_id);assert_eq!(child_context.parent_span_id,Some(context.span_id));}#[test]fntest_span(){letcontext=TraceContext::create();letmutspan=Span::new(context,"test_operation".to_string());span.tag("test_key".to_string(),"test_value".to_string());span.log(HashMap::from([("message".to_string(),"test log".to_string())]));span.finish();assert!(span.duration().is_some());assert_eq!(span.tags.get("test_key"),Some(&"test_value".to_string()));assert_eq!(span.logs.len(),1);}#[test]fntest_tracer(){letmuttracer=Tracer::new("test_service".to_string(),"1.0.0".to_string());letcontext=tracer.start_span("test_operation".to_string(),None);assert!(!context.trace_id.is_empty());assert!(!context.span_id.is_empty());letspan=tracer.finish_span(&context);assert!(span.is_some());assert_eq!(tracer.get_spans().len(),1);}}
// rust/04-health-checks.rs/*Health check patterns and best practices*/usestd::collections::HashMap;useserde::{Deserialize,Serialize};usestd::time::{Duration,Instant};/// Health check status.#[derive(Debug, Clone, Serialize, Deserialize)]pubenumHealthStatus{Healthy,Unhealthy,Degraded,}/// Health check result.#[derive(Debug, Clone, Serialize, Deserialize)]pubstructHealthCheckResult{pubname:String,pubstatus:HealthStatus,pubmessage:Option<String>,pubduration:Duration,pubtimestamp:u64,pubmetadata:HashMap<String,serde_json::Value>,}/// Health check trait.pubtraitHealthCheck{fnname(&self)->&str;fncheck(&self)->HealthCheckResult;}/// Database health check.pubstructDatabaseHealthCheck{name:String,connection_string:String,}implDatabaseHealthCheck{pubfnnew(name:String,connection_string:String)->Self{Self{name,connection_string}}}implHealthCheckforDatabaseHealthCheck{fnname(&self)->&str{&self.name}fncheck(&self)->HealthCheckResult{letstart_time=Instant::now();// In a real implementation, you would test the database connectionletstatus=ifself.connection_string.contains("test"){HealthStatus::Healthy}else{HealthStatus::Unhealthy};letduration=start_time.elapsed();HealthCheckResult{name:self.name.clone(),status,message:Some("Database connection test".to_string()),duration,timestamp:std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis()asu64,metadata:HashMap::new(),}}}/// Redis health check.pubstructRedisHealthCheck{name:String,redis_url:String,}implRedisHealthCheck{pubfnnew(name:String,redis_url:String)->Self{Self{name,redis_url}}}implHealthCheckforRedisHealthCheck{fnname(&self)->&str{&self.name}fncheck(&self)->HealthCheckResult{letstart_time=Instant::now();// In a real implementation, you would test the Redis connectionletstatus=ifself.redis_url.contains("test"){HealthStatus::Healthy}else{HealthStatus::Unhealthy};letduration=start_time.elapsed();HealthCheckResult{name:self.name.clone(),status,message:Some("Redis connection test".to_string()),duration,timestamp:std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis()asu64,metadata:HashMap::new(),}}}/// Health check manager.pubstructHealthCheckManager{checks:Vec<Box<dynHealthCheck>>,results:HashMap<String,HealthCheckResult>,}implHealthCheckManager{pubfnnew()->Self{Self{checks:Vec::new(),results:HashMap::new(),}}/// Add a health check.pubfnadd_check(&mutself,check:Box<dynHealthCheck>){self.checks.push(check);}/// Run all health checks.pubfnrun_checks(&mutself)->HashMap<String,HealthCheckResult>{letmutresults=HashMap::new();forcheckin&self.checks{letresult=check.check();results.insert(check.name().to_string(),result.clone());}self.results=results.clone();results}/// Get the overall health status.pubfnget_overall_status(&self)->HealthStatus{ifself.results.is_empty(){returnHealthStatus::Unhealthy;}lethas_unhealthy=self.results.values().any(|r|r.status==HealthStatus::Unhealthy);lethas_degraded=self.results.values().any(|r|r.status==HealthStatus::Degraded);ifhas_unhealthy{HealthStatus::Unhealthy}elseifhas_degraded{HealthStatus::Degraded}else{HealthStatus::Healthy}}/// Get health check results.pubfnget_results(&self)->&HashMap<String,HealthCheckResult>{&self.results}/// Get health check summary.pubfnget_summary(&self)->String{lettotal_checks=self.results.len();lethealthy_checks=self.results.values().filter(|r|r.status==HealthStatus::Healthy).count();letunhealthy_checks=self.results.values().filter(|r|r.status==HealthStatus::Unhealthy).count();letdegraded_checks=self.results.values().filter(|r|r.status==HealthStatus::Degraded).count();format!("Health Checks: {} total, {} healthy, {} degraded, {} unhealthy",total_checks,healthy_checks,degraded_checks,unhealthy_checks)}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_database_health_check(){letcheck=DatabaseHealthCheck::new("database".to_string(),"postgresql://test:test@localhost/test".to_string(),);letresult=check.check();assert_eq!(result.name,"database");assert_eq!(result.status,HealthStatus::Healthy);}#[test]fntest_redis_health_check(){letcheck=RedisHealthCheck::new("redis".to_string(),"redis://test:6379".to_string(),);letresult=check.check();assert_eq!(result.name,"redis");assert_eq!(result.status,HealthStatus::Healthy);}#[test]fntest_health_check_manager(){letmutmanager=HealthCheckManager::new();manager.add_check(Box::new(DatabaseHealthCheck::new("database".to_string(),"postgresql://test:test@localhost/test".to_string(),)));manager.add_check(Box::new(RedisHealthCheck::new("redis".to_string(),"redis://test:6379".to_string(),)));letresults=manager.run_checks();assert_eq!(results.len(),2);assert_eq!(manager.get_overall_status(),HealthStatus::Healthy);}}