Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Polly-Contrib/Simmy/llms.txt

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

Every Simmy monkey policy is configured through a fluent builder that is passed as a callback to the relevant MonkeyPolicy factory method. The callback receives a typed options object — for example InjectOutcomeOptions<Exception> or InjectLatencyOptions — and you chain extension methods on it to define what chaos to inject, how often, and when. All options that accept a delegate receive both a Polly Context and a CancellationToken, letting you vary behaviour dynamically at call time.
Every policy must have Enabled (or EnabledWhen), InjectionRate, and the chaos payload (e.g. Fault, Result, Latency, or Behaviour) configured before it is built. Missing any of these three parts will cause an ArgumentNullException to be thrown from the factory method.

Enabled / EnabledWhen

These options live on InjectOptionsBase (sync) and InjectOptionsAsyncBase (async) and are available on every Simmy policy.
Enabled()
void
Marks the policy as unconditionally enabled. Equivalent to calling Enabled(true).
var chaosPolicy = MonkeyPolicy.InjectException(with =>
    with.Fault(new TimeoutException())
        .InjectionRate(0.05)
        .Enabled()           // always enabled
);
Enabled(bool enabled)
void
Enables or disables the policy based on a boolean value known at configuration time. Useful when the flag is read from app config at startup.
bool chaosEnabled = bool.Parse(Configuration["Chaos:Enabled"]);

var chaosPolicy = MonkeyPolicy.InjectLatency(with =>
    with.Latency(TimeSpan.FromSeconds(5))
        .InjectionRate(0.1)
        .Enabled(chaosEnabled)   // true or false from config
);
EnabledWhen(Func<Context, CancellationToken, bool> enabledWhen)
void
Accepts a delegate that is evaluated on every policy execution. Returning true means the policy is active for that call; returning false means the call passes through untouched.
var chaosPolicy = MonkeyPolicy.InjectBehaviour(with =>
    with.Behaviour(() => RestartVirtualMachine())
        .InjectionRate(0.01)
        .EnabledWhen((ctx, ct) => IsEnabled(ctx, ct))
);
Because the delegate receives the full Polly Context, you can key on ctx.OperationKey to enable chaos for only specific operations. See the Context-Driven Configuration guide for this pattern in detail.

InjectionRate

Controls how often the chaos is triggered. A value of 0.05 means chaos is injected in approximately 5 % of executions; 1.0 means every execution is affected.
InjectionRate(double injectionRate)
void
Sets a constant injection rate from a double in the range [0, 1]. The value is validated at configuration time (since v0.3.0); an out-of-range value throws immediately rather than waiting until the first execution.
var chaosPolicy = MonkeyPolicy.InjectException(with =>
    with.Fault(new SocketException(errorCode: 10013))
        .InjectionRate(0.05)   // 5% of calls throw SocketException
        .Enabled()
);
Passing a value outside [0, 1] will throw an exception at configuration time. Always use a literal or a validated variable here.
InjectionRate(Func<Context, CancellationToken, double> injectionRateProvider)
void
Evaluates the delegate on every execution to obtain the current injection rate. This allows rates to be driven from external configuration without redeploying the app.
var chaosPolicy = MonkeyPolicy.InjectException(with =>
    with.Fault(new TimeoutException())
        .InjectionRate((ctx, ct) =>
        {
            // Read the live rate from your config service
            return configService.GetInjectionRate(ctx.OperationKey);
        })
        .EnabledWhen((ctx, ct) => configService.IsChaosEnabled(ctx.OperationKey))
);

Fault

Applies to InjectOutcomeOptions<Exception> (sync) and InjectOutcomeAsyncOptions<Exception> (async). Used when building a policy with MonkeyPolicy.InjectException or MonkeyPolicy.InjectExceptionAsync.
Fault(Exception fault)
void
Configures a specific exception instance to throw. The same instance is re-thrown on every affected execution.
var fault = new SocketException(errorCode: 10013);

var chaosPolicy = MonkeyPolicy.InjectException(with =>
    with.Fault(fault)
        .InjectionRate(0.05)
        .Enabled()
);
Fault(Func<Context, CancellationToken, Exception> fault)
void
Delegates exception creation to a factory function so you can vary the exception type or message per call.
var chaosPolicy = MonkeyPolicy.InjectException(with =>
    with.Fault((ctx, ct) =>
        {
            // Choose exception type based on operation
            return ctx.OperationKey == "DatabaseQuery"
                ? new TimeoutException("DB timeout")
                : new HttpRequestException("HTTP error");
        })
        .InjectionRate(0.1)
        .Enabled()
);
var chaosPolicy = MonkeyPolicy.InjectException(with =>
    with.Fault(new InvalidOperationException("chaos fault"))
        .InjectionRate(0.1)
        .Enabled()
);

Result

Applies to InjectOutcomeOptions<TResult> (sync) and InjectOutcomeAsyncOptions<TResult> (async). Used when building a policy with MonkeyPolicy.InjectResult<TResult> or MonkeyPolicy.InjectResultAsync<TResult>.
Result<TResult>(TResult result)
void
Returns a constant substitute result value instead of executing the wrapped call.
var badResponse = new HttpResponseMessage(HttpStatusCode.BadRequest);

var chaosPolicy = MonkeyPolicy.InjectResult<HttpResponseMessage>(with =>
    with.Result(badResponse)
        .InjectionRate(0.05)
        .Enabled()
);
Result<TResult>(Func<Context, CancellationToken, TResult> result)
void
Computes the substitute result through a delegate, allowing you to vary the injected value per execution.
var chaosPolicy = MonkeyPolicy.InjectResult<HttpResponseMessage>(with =>
    with.Result((ctx, ct) =>
        {
            var statusCode = ctx.OperationKey == "PaymentGateway"
                ? HttpStatusCode.ServiceUnavailable
                : HttpStatusCode.BadRequest;
            return new HttpResponseMessage(statusCode);
        })
        .InjectionRate(0.1)
        .Enabled()
);

Latency

Applies to InjectLatencyOptions (sync) and InjectLatencyAsyncOptions (async). Used when building a policy with MonkeyPolicy.InjectLatency or MonkeyPolicy.InjectLatencyAsync.
Latency(TimeSpan latency)
void
Injects a fixed delay before the wrapped call executes.
var chaosPolicy = MonkeyPolicy.InjectLatency(with =>
    with.Latency(TimeSpan.FromSeconds(5))
        .InjectionRate(0.1)
        .Enabled()
);
Latency(Func<Context, CancellationToken, TimeSpan> latency)
void
Computes the delay from a delegate. This lets you serve latency values from external configuration and adjust them without redeploying.
var chaosPolicy = MonkeyPolicy.InjectLatency(with =>
    with.Latency((ctx, ct) =>
        {
            int ms = configService.GetLatencyMs(ctx.OperationKey);
            return TimeSpan.FromMilliseconds(ms);
        })
        .InjectionRate(0.1)
        .Enabled()
);
Async latency policies introduced in v0.2.0 are fully cancellable: if the CancellationToken is triggered during the injected delay, the delay is cancelled and the token’s cancellation propagates normally.

Behaviour

Applies to InjectBehaviourOptions (sync) and InjectBehaviourAsyncOptions (async). Used when building a policy with MonkeyPolicy.InjectBehaviour or MonkeyPolicy.InjectBehaviourAsync.
Behaviour(Action behaviour)
void
Runs a simple, parameterless action before the wrapped call. Handy for side effects such as clearing a cache or writing a log entry.
var chaosPolicy = MonkeyPolicy.InjectBehaviour(with =>
    with.Behaviour(() => ClearLocalCache())
        .InjectionRate(0.02)
        .Enabled()
);
Behaviour(Action<Context, CancellationToken> behaviour)
void
Runs an action that receives the current Polly Context and CancellationToken. Use this when the behaviour needs to vary based on the calling context or must respect cancellation.
var chaosPolicy = MonkeyPolicy.InjectBehaviour(with =>
    with.Behaviour((ctx, ct) =>
        {
            logger.LogWarning(
                "Chaos behaviour triggered for operation: {Op}",
                ctx.OperationKey);
            RestartVirtualMachine(ctx.OperationKey);
        })
        .InjectionRate(0.01)
        .EnabledWhen((ctx, ct) => IsEnabled(ctx, ct))
);
var chaosPolicy = MonkeyPolicy.InjectBehaviour(with =>
    with.Behaviour(() => restartRedisVM())
        .InjectionRate(0.01)
        .EnabledWhen((ctx, ct) => isEnabled(ctx, ct))
);

Quick Reference

OptionSync overloadsAsync overloadsApplies to
Enabled()All policies
Enabled(bool)All policies
EnabledWhen(Func<Context, CancellationToken, bool>)All policies (sync)
EnabledWhen(Func<Context, CancellationToken, Task<bool>>)All policies (async)
InjectionRate(double)All policies
InjectionRate(Func<…, double>)All policies (sync)
InjectionRate(Func<…, Task<double>>)All policies (async)
Fault(Exception)InjectException
Fault(Func<…, Exception>)InjectException (sync)
Fault(Func<…, Task<Exception>>)InjectException (async)
Result<TResult>(TResult)InjectResult
Result<TResult>(Func<…, TResult>)InjectResult (sync)
Result<TResult>(Func<…, Task<TResult>>)InjectResult (async)
Latency(TimeSpan)InjectLatency
Latency(Func<…, TimeSpan>)InjectLatency (sync)
Latency(Func<…, Task<TimeSpan>>)InjectLatency (async)
Behaviour(Action)InjectBehaviour (sync)
Behaviour(Action<Context, CancellationToken>)InjectBehaviour (sync)
Behaviour(Func<Task>)InjectBehaviour (async)
Behaviour(Func<Context, CancellationToken, Task>)InjectBehaviour (async)

Build docs developers (and LLMs) love