Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/visible/cruel/llms.txt

Use this file to discover all available pages before exploring further.

Cruel provides an event system to monitor chaos injection in real-time, allowing you to track failures, retries, and circuit breaker state changes.

Event types

Cruel emits these event types:
type CruelEventType =
  | "call"           // Function was called
  | "success"        // Function succeeded
  | "failure"        // Function failed
  | "timeout"        // Function timed out
  | "retry"          // Retry attempt
  | "circuitOpen"    // Circuit breaker opened
  | "circuitClose"   // Circuit breaker closed

Listen to events

import { cruel } from "cruel"

// Add event listener
const unsubscribe = cruel.on((event) => {
  console.log(`Event: ${event.type}`, event)
})

// Remove listener when done
unsubscribe()

Event data

cruel.on((event) => {
  // Common fields
  console.log(event.type)     // Event type
  console.log(event.target)   // Function name
  console.log(event.duration) // Duration in ms
  console.log(event.error)    // Error object (if failed)
})

Monitor failures

import { cruel } from "cruel"

let failureCount = 0

cruel.on((event) => {
  if (event.type === "failure") {
    failureCount++
    console.log(`Failure #${failureCount}: ${event.target}`)
    console.log(`Error: ${event.error?.message}`)
    console.log(`Duration: ${event.duration}ms`)
  }
})

Monitor circuit breaker

import { cruel } from "cruel"

cruel.on((event) => {
  if (event.type === "circuitOpen") {
    console.log("🔴 Circuit opened - requests blocked")
    // Alert operations team
  }
  
  if (event.type === "circuitClose") {
    console.log("🟢 Circuit closed - normal operation")
  }
})

const api = cruel.circuitBreaker(fetch, {
  threshold: 5,
  timeout: 30000,
})

Monitor retries

import { cruel } from "cruel"

cruel.on((event) => {
  if (event.type === "retry") {
    console.log("Retrying after error:", event.error)
  }
})

const api = cruel.retry(fetch, {
  attempts: 3,
  delay: 1000,
})

Track latency

import { cruel } from "cruel"

const latencies: number[] = []

cruel.on((event) => {
  if (event.type === "success" && event.duration) {
    latencies.push(event.duration)
    
    // Calculate average
    const avg = latencies.reduce((a, b) => a + b, 0) / latencies.length
    console.log(`Average latency: ${avg.toFixed(2)}ms`)
  }
})

Multiple listeners

import { cruel } from "cruel"

// Logger
cruel.on((event) => {
  console.log(`[${event.type}] ${event.target}`, event.duration)
})

// Metrics
cruel.on((event) => {
  metrics.increment(`chaos.${event.type}`)
  if (event.duration) {
    metrics.histogram("chaos.duration", event.duration)
  }
})

// Alerting
cruel.on((event) => {
  if (event.type === "failure") {
    alerting.notify(`Chaos failure: ${event.target}`)
  }
})

Remove all listeners

import { cruel } from "cruel"

// Remove all event listeners
cruel.removeAllListeners()

Testing with events

import { test, beforeEach } from "bun:test"
import { cruel } from "cruel"

test("emits failure events", async () => {
  const events: CruelEventType[] = []
  
  cruel.on((event) => {
    events.push(event.type)
  })
  
  const api = cruel(fetch, { fail: 1 })
  
  try {
    await api("https://api.example.com")
  } catch (e) {
    // Expected
  }
  
  expect(events).toContain("call")
  expect(events).toContain("failure")
})

beforeEach(() => {
  cruel.removeAllListeners()
})

Real-world monitoring

import { cruel } from "cruel"

// Production monitoring
cruel.on((event) => {
  // Send to monitoring service
  monitoring.track({
    event: event.type,
    target: event.target,
    duration: event.duration,
    failed: event.type === "failure",
    timestamp: Date.now(),
  })
  
  // Alert on high failure rate
  const stats = cruel.stats()
  const failureRate = stats.failures / stats.calls
  
  if (failureRate > 0.5) {
    alerting.critical(`High chaos failure rate: ${(failureRate * 100).toFixed(1)}%`)
  }
})
Events are emitted synchronously. Heavy processing in event handlers may impact performance.
Use cruel.removeAllListeners() in test cleanup to avoid memory leaks.