Mutineer (mutineer v0.2.0)

Copy Markdown

Mutineer macro system for introducing controlled failures into functions.

This module provides macros to wrap functions and make them fail randomly, inspired by Netflix's Chaos Monkey. Useful for testing resilience and error handling in development and staging environments.

Configuration

Configure in config/config.exs or environment-specific config files:

# Enable Mutineer globally
config :mutineer,
  Mutineer,
  enabled: true,
  default_failure_rate: 0.1,  # 10% failure rate
  default_failure_types: :error

Usage

Use the @chaos attribute before function definitions:

defmodule MyModule do
  use Mutineer

  # Will fail 10% of the time with default settings
  @chaos true
  def my_function(arg) do
    # normal implementation
  end

  # Custom failure rate (30%)
  @chaos failure_rate: 0.3
  def risky_function(arg) do
    # normal implementation
  end

  # Custom failure type and message
  @chaos failure_rate: 0.2, failure_type: :raise, message: "Chaos!"
  def another_function(arg) do
    # normal implementation
  end
end

Or use the defchaos macro directly:

defmodule MyModule do
  use Mutineer

  defchaos my_function(arg), failure_rate: 0.2 do
    # normal implementation
  end
end

Global configuration options

  • enabled - Enables or disables chaos globally (default: false)
  • default_failure_types - Sets the default failure types for all functions, can be a list of failure types or a single failure type (default: :error)
  • default_failure_rate - Sets the default failure rate for all functions (default: 0.1)

Failure types

  • :error - Returns {:error, :mutineer_chaos} (default)
  • :raise - Raises either a Mutineer.ChaosError exception (default) or a custom error specified in the raised_errors option
  • :delay - Introduces a random delay (1-5 seconds) before executing function
  • :timeout - Same as :raise, but with a random delay before raising the exception
  • :nil - Returns nil
  • :exit - Calls exit(:mutineer_chaos); the atom can be specified in the exit_errors option

Failure options

Options can be passed to @chaos, defchaos, or defchaosp:

  • failure_rate is the probability of failure for a given function (0.0 - 1.0), where 1.0 or above will always fail
  • failure_types (or failure_type) is either a list of failure types to trigger (e.g. [:error, :delay]) or a single failure type (e.g. :error)
  • errors (or error) is either a list of objects to be randomly selected from or a single object to return when the :error type is triggered
  • raised_errors (or raised_error) is a list of errors to be randomly selected from or a single error to be raised when the :raise type is triggered
  • exit_errors (or exit_error) is a list of errors to be randomly selected from or a single error to be raised when the :exit type is triggered
  • delay is the upperbound of the delay in milliseconds or a range of milliseconds for :timeout and :delay types

Important Notes

  • Mutineer is disabled by default
  • When disabled at runtime, functions execute normally with minimal overhead
  • Recommended to only enable in development/staging environments
  • Never enable in production unless you know what you're doing

Summary

Functions

Returns the default failure rate (0.0 to 1.0).

Returns the default failure type.

Defines a public function that may randomly fail when Mutineer is enabled.

Defines a private function that may randomly fail when Mutineer is enabled.

Returns whether Mutineer is globally enabled at runtime.

Wraps a function call with Mutineer logic.

Determines if a failure should be triggered based on the given rate.

Functions

default_failure_rate()

Returns the default failure rate (0.0 to 1.0).

default_failure_types()

Returns the default failure type.

defchaos(call, expr_or_opts)

(macro)

Defines a public function that may randomly fail when Mutineer is enabled.

Options

  • failure_rate is the probability of failure for a given function (0.0 - 1.0), where 1.0 or above will always fail and 0.0 or below will never fail.
  • failure_types (or failure_type) is either a list of failure types to trigger (e.g. [:error, :delay]) or a single failure type (e.g. :error)
  • errors (or error) is either a list of objects to be randomly selected from or a single object to return when the :error type is triggered
  • raised_errors (or raised_error) is a list of errors to be randomly selected from or a single error to be raised when the :raise type is triggered
  • exit_errors (or exit_error) is a list of errors to be randomly selected from or a single error to be raised when the :exit type is triggered
  • delay is the upperbound of the delay in milliseconds or a range of milliseconds for :timeout and :delay types

Examples

defchaos my_function(arg1, arg2), failure_rate: 0.2 do
  # function body
end

defchaos api_call(url), failure_type: :timeout, delay: 3000 do
  # function body
end

defchaos(call, opts, expr)

(macro)

defchaosp(call, expr_or_opts)

(macro)

Defines a private function that may randomly fail when Mutineer is enabled.

Same options as defchaos/2.

defchaosp(call, opts, expr)

(macro)

enabled?()

Returns whether Mutineer is globally enabled at runtime.

maybe_chaos(func, opts)

Wraps a function call with Mutineer logic.

This is the runtime function that checks if chaos should trigger. When chaos is disabled, immediately executes the function with minimal overhead.

should_fail?(rate)

Determines if a failure should be triggered based on the given rate.