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.

InjectLatencyOptions and InjectLatencyAsyncOptions are the configuration objects you supply to MonkeyPolicy.InjectLatency and MonkeyPolicy.InjectLatencyAsync. Both types use a fluent builder pattern: a configuration callback receives a fresh options instance, you chain .Latency(...), .InjectionRate(...), and .Enabled(...) calls, and the factory validates the result before constructing the policy. Latency is always injected before the wrapped delegate executes — the policy sleeps first, then runs your code. This makes it easy to simulate downstream slowness without modifying the application under test.

Namespaces

using Polly.Contrib.Simmy.Latency; // options types
using Polly.Contrib.Simmy;         // base extension methods

InjectLatencyOptions (sync)

public class InjectLatencyOptions : InjectOptionsBase
Synchronous latency options. Inherits InjectionRate and Enabled delegates from InjectOptionsBase. The internal LatencyInternal property holds the TimeSpan delegate and is set by the .Latency(...) extension methods below.

InjectLatencyAsyncOptions (async)

public class InjectLatencyAsyncOptions : InjectOptionsAsyncBase
Asynchronous latency options. Inherits async InjectionRate and Enabled delegates from InjectOptionsAsyncBase. The internal LatencyInternal property is Func<Context, CancellationToken, Task<TimeSpan>>.

Latency extension methods

.Latency(TimeSpan) — sync, fixed duration

Configures a constant delay to inject before the wrapped delegate.
public static InjectLatencyOptions Latency(
    this InjectLatencyOptions options,
    TimeSpan latency)
options
InjectLatencyOptions
required
The sync options object being configured (supplied automatically by the fluent chain).
latency
TimeSpan
required
The fixed duration to sleep before executing the wrapped call. For example, TimeSpan.FromSeconds(5) simulates a five-second downstream stall.
MonkeyPolicy.InjectLatency(with =>
    with.Latency(TimeSpan.FromSeconds(5))
        .InjectionRate(0.1)
        .Enabled());

.Latency(Func<Context, CancellationToken, TimeSpan>) — sync delegate

Configures a delegate that is evaluated at injection-time to produce the delay. Use this when the latency amount must vary per call — for example, based on the operation key stored in the Polly Context.
public static InjectLatencyOptions Latency(
    this InjectLatencyOptions options,
    Func<Context, CancellationToken, TimeSpan> latency)
options
InjectLatencyOptions
required
The sync options object being configured.
latency
Func<Context, CancellationToken, TimeSpan>
required
A synchronous delegate invoked at injection-time. Receives the current Polly Context and a CancellationToken; returns the TimeSpan delay to apply for this execution.
MonkeyPolicy.InjectLatency(with =>
    with.Latency((ctx, ct) =>
        {
            // Add extra latency for the slower read operation
            return ctx.OperationKey == "heavy-read"
                ? TimeSpan.FromSeconds(10)
                : TimeSpan.FromSeconds(2);
        })
        .InjectionRate(0.2)
        .Enabled());

.Latency(TimeSpan) — async, fixed duration

Configures a fixed delay for an async latency policy. The value is wrapped in Task.FromResult internally.
public static InjectLatencyAsyncOptions Latency(
    this InjectLatencyAsyncOptions options,
    TimeSpan latency)
options
InjectLatencyAsyncOptions
required
The async options object being configured.
latency
TimeSpan
required
The fixed duration to inject. Uses Task.Delay internally so it does not block the thread.
MonkeyPolicy.InjectLatencyAsync(with =>
    with.Latency(TimeSpan.FromMilliseconds(800))
        .InjectionRate(0.15)
        .Enabled());

.Latency(Func<Context, CancellationToken, Task<TimeSpan>>) — async delegate

Configures an async delegate that resolves the delay at injection-time, enabling dynamic latency values fetched from remote configuration.
public static InjectLatencyAsyncOptions Latency(
    this InjectLatencyAsyncOptions options,
    Func<Context, CancellationToken, Task<TimeSpan>> latency)
options
InjectLatencyAsyncOptions
required
The async options object being configured.
latency
Func<Context, CancellationToken, Task<TimeSpan>>
required
An async delegate returning Task<TimeSpan>. Receives the Polly Context and CancellationToken; useful when the delay should be looked up from a live configuration or feature-flag service at the moment of injection.
MonkeyPolicy.InjectLatencyAsync(with =>
    with.Latency(async (ctx, ct) =>
        {
            var ms = await configStore.GetLatencyMillisecondsAsync(ct);
            return TimeSpan.FromMilliseconds(ms);
        })
        .InjectionRate(0.1)
        .Enabled());

Inherited base options

InjectLatencyOptions inherits from InjectOptionsBase and InjectLatencyAsyncOptions from InjectOptionsAsyncBase. The following methods control when and how often chaos is triggered. All three must be configured — the factory throws ArgumentNullException for InjectionRate or Enabled if either is missing.

Sync base (InjectOptionsBaseExtensions)

.Enabled() — always on

public static InjectOptionsBase Enabled(this InjectOptionsBase options)
Unconditionally enables the policy. Equivalent to .Enabled(true).

.Enabled(bool)

public static InjectOptionsBase Enabled(this InjectOptionsBase options, bool enabled)
enabled
bool
required
true to enable chaos injection; false to disable it entirely for all calls regardless of injection rate.

.EnabledWhen(Func<Context, CancellationToken, bool>)

public static InjectOptionsBase EnabledWhen(
    this InjectOptionsBase options,
    Func<Context, CancellationToken, bool> enabledWhen)
enabledWhen
Func<Context, CancellationToken, bool>
required
A synchronous delegate evaluated on every execution. Return true to permit injection for that call; false to skip it. Common use: gate chaos on an environment variable or per-operation-key flag.

.InjectionRate(double)

public static InjectOptionsBase InjectionRate(this InjectOptionsBase options, double injectionRate)
injectionRate
double
required
A constant value in [0, 1]. 0.0 means the delay is never injected; 1.0 means every call is delayed. Values outside this range throw ArgumentOutOfRangeException.

.InjectionRate(Func<Context, CancellationToken, double>)

public static InjectOptionsBase InjectionRate(
    this InjectOptionsBase options,
    Func<Context, CancellationToken, double> injectionRateProvider)
injectionRateProvider
Func<Context, CancellationToken, double>
required
A delegate evaluated on each execution to provide a dynamic injection rate. Use this to ramp chaos up or down in production without redeploying.

Async base (InjectOptionsAsyncBaseExtensions)

The async base exposes the same .Enabled(), .Enabled(bool), and .InjectionRate(double) overloads and adds async-delegate variants:

.EnabledWhen(Func<Context, CancellationToken, Task<bool>>)

public static InjectOptionsAsyncBase EnabledWhen(
    this InjectOptionsAsyncBase options,
    Func<Context, CancellationToken, Task<bool>> enabledWhen)
enabledWhen
Func<Context, CancellationToken, Task<bool>>
required
An async delegate returning Task<bool>. Use this when the enabled check must call an async service, such as a remote feature-flag API.

.InjectionRate(Func<Context, CancellationToken, Task<double>>)

public static InjectOptionsAsyncBase InjectionRate(
    this InjectOptionsAsyncBase options,
    Func<Context, CancellationToken, Task<double>> injectionRateProvider)
injectionRateProvider
Func<Context, CancellationToken, Task<double>>
required
An async delegate returning Task<double> in [0, 1]. Enables the chaos rate to be fetched from an async configuration service on every execution.

Complete examples

Sync latency injection

using Polly;
using Polly.Contrib.Simmy;
using Polly.Contrib.Simmy.Latency;

// Delay all calls by 3 seconds on 20% of executions, only in the staging environment
var latencyPolicy = MonkeyPolicy.InjectLatency(with =>
    with.Latency(TimeSpan.FromSeconds(3))
        .InjectionRate(0.2)
        .EnabledWhen((ctx, ct) =>
            Environment.GetEnvironmentVariable("APP_ENV") == "staging"));

// Combine with a timeout so chaos-induced latency is bounded
var timeoutPolicy = Policy.Timeout(TimeSpan.FromSeconds(10));
var resilient = Policy.Wrap(timeoutPolicy, latencyPolicy);

resilient.Execute(() => CallDependency());

Async latency injection with dynamic rate and context-aware delay

using Polly;
using Polly.Contrib.Simmy;
using Polly.Contrib.Simmy.Latency;

var latencyPolicy = MonkeyPolicy.InjectLatencyAsync(with =>
    with.Latency(async (ctx, ct) =>
        {
            // Different latency profiles per operation
            var baseMs = ctx.OperationKey == "search" ? 2000 : 500;
            return TimeSpan.FromMilliseconds(baseMs);
        })
        .InjectionRate(async (ctx, ct) =>
        {
            return await chaosSettings.GetLatencyRateAsync(ct);
        })
        .EnabledWhen(async (ctx, ct) =>
        {
            return await featureFlags.IsChaosEnabledAsync(ct);
        }));

await latencyPolicy.ExecuteAsync(
    async ct => await PerformOperationAsync(ct),
    new Context("search"),
    CancellationToken.None);

Typed async latency policy (TResult)

using Polly.Contrib.Simmy;
using Polly.Contrib.Simmy.Latency;

var latencyPolicy = MonkeyPolicy.InjectLatencyAsync<HttpResponseMessage>(with =>
    with.Latency(TimeSpan.FromSeconds(2))
        .InjectionRate(0.1)
        .Enabled());

HttpResponseMessage response = await latencyPolicy.ExecuteAsync(
    async ct => await httpClient.GetAsync("/api/data", ct),
    CancellationToken.None);

Build docs developers (and LLMs) love