Lab 14: Chaos Engineering
Overview
Step 1: Fault Injection Middleware
package chaos
import (
"context"
"errors"
"fmt"
"math/rand"
"time"
)
type FaultConfig struct {
ErrorRate float64 // 0.0-1.0: probability of injecting an error
LatencyRate float64 // 0.0-1.0: probability of adding latency
MaxLatency time.Duration // Maximum injected latency
ErrorMsg string
}
var DefaultFaultConfig = FaultConfig{
ErrorRate: 0.1, // 10% errors
LatencyRate: 0.2, // 20% slow responses
MaxLatency: 200 * time.Millisecond,
ErrorMsg: "chaos: injected fault",
}
type ServiceCall func(ctx context.Context, req interface{}) (interface{}, error)
func FaultInjectionMiddleware(cfg FaultConfig) func(ServiceCall) ServiceCall {
return func(next ServiceCall) ServiceCall {
return func(ctx context.Context, req interface{}) (interface{}, error) {
// Inject latency
if rand.Float64() < cfg.LatencyRate {
latency := time.Duration(rand.Float64() * float64(cfg.MaxLatency))
select {
case <-time.After(latency):
case <-ctx.Done():
return nil, ctx.Err()
}
}
// Inject error
if rand.Float64() < cfg.ErrorRate {
return nil, fmt.Errorf("%s (at %v)", cfg.ErrorMsg, time.Now())
}
return next(ctx, req)
}
}
}Step 2: Circuit Breaker
Step 3: Bulkhead — Semaphore Isolation
Step 4: Retry with Jitter
Step 5: Timeout Propagation Chain
Step 6: Chaos Monkey Testing
Step 7: Observability Integration
Step 8: Capstone — Chaos Middleware
Summary
Pattern
Purpose
Trigger
Last updated
