From 208e5dc5c924ed73a7c692a07bf07fa3a4e255e5 Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 09:52:53 +0100
Subject: [PATCH 01/12] Rename OnLatency to OnLatencyInjected

---
 docs/chaos/latency.md                            | 16 ++++++++--------
 .../Simmy/Latency/LatencyChaosStrategy.cs        | 12 ++++++------
 src/Polly.Core/Simmy/Latency/LatencyConstants.cs |  2 +-
 .../Simmy/Latency/LatencyStrategyOptions.cs      |  2 +-
 ...rguments.cs => OnLatencyInjectedArguments.cs} |  6 +++---
 src/Snippets/Docs/Chaos.Latency.cs               |  6 +++---
 .../Simmy/Latency/LatencyChaosStrategyTests.cs   |  6 +++---
 .../Simmy/Latency/LatencyConstantsTests.cs       |  2 +-
 .../Simmy/Latency/LatencyStrategyOptionsTests.cs |  2 +-
 ...sts.cs => OnLatencyInjectedArgumentsTests.cs} |  4 ++--
 10 files changed, 29 insertions(+), 29 deletions(-)
 rename src/Polly.Core/Simmy/Latency/{OnLatencyArguments.cs => OnLatencyInjectedArguments.cs} (77%)
 rename test/Polly.Core.Tests/Simmy/Latency/{OnLatencyArgumentsTests.cs => OnLatencyInjectedArgumentsTests.cs} (58%)

diff --git a/docs/chaos/latency.md b/docs/chaos/latency.md
index 8503acd1c4f..b3595e17a48 100644
--- a/docs/chaos/latency.md
+++ b/docs/chaos/latency.md
@@ -45,14 +45,14 @@ var optionsWithLatencyGenerator = new LatencyStrategyOptions
 };
 
 // To get notifications when a delay is injected
-var optionsOnBehaviorInjected = new LatencyStrategyOptions
+var optionsOnLatencyInjected = new LatencyStrategyOptions
 {
     Latency = TimeSpan.FromSeconds(30),
     Enabled = true,
     InjectionRate = 0.1,
-    OnLatency = static args =>
+    OnLatencyInjected = static args =>
     {
-        Console.WriteLine($"OnLatency, Latency: {args.Latency}, Operation: {args.Context.OperationKey}.");
+        Console.WriteLine($"OnLatencyInjected, Latency: {args.Latency}, Operation: {args.Context.OperationKey}.");
         return default;
     }
 };
@@ -92,11 +92,11 @@ var pipeline = new ResiliencePipelineBuilder()
 
 ## Defaults
 
-| Property           | Default Value | Description                                            |
-|--------------------|---------------|--------------------------------------------------------|
-| `Latency`          | `30 seconds`  | A `TimeSpan` indicating the delay to be injected.      |
-| `LatencyGenerator` | `null`        | Generates the latency to inject for a given execution. |
-| `OnLatency`        | `null`        | Action executed when latency is injected.              |
+| Property            | Default Value | Description                                            |
+|---------------------|---------------|--------------------------------------------------------|
+| `Latency`           | `30 seconds`  | A `TimeSpan` indicating the delay to be injected.      |
+| `LatencyGenerator`  | `null`        | Generates the latency to inject for a given execution. |
+| `OnLatencyInjected` | `null`        | Action executed when latency is injected.              |
 
 ## Diagrams
 
diff --git a/src/Polly.Core/Simmy/Latency/LatencyChaosStrategy.cs b/src/Polly.Core/Simmy/Latency/LatencyChaosStrategy.cs
index 409c9a4881f..cdeb5b8efcb 100644
--- a/src/Polly.Core/Simmy/Latency/LatencyChaosStrategy.cs
+++ b/src/Polly.Core/Simmy/Latency/LatencyChaosStrategy.cs
@@ -15,13 +15,13 @@ public LatencyChaosStrategy(
     {
         Latency = options.Latency;
         LatencyGenerator = options.LatencyGenerator is not null ? options.LatencyGenerator : (_) => new(options.Latency);
-        OnLatency = options.OnLatency;
+        OnLatencyInjected = options.OnLatencyInjected;
 
         _telemetry = telemetry;
         _timeProvider = timeProvider;
     }
 
-    public Func<OnLatencyArguments, ValueTask>? OnLatency { get; }
+    public Func<OnLatencyInjectedArguments, ValueTask>? OnLatencyInjected { get; }
 
     public Func<LatencyGeneratorArguments, ValueTask<TimeSpan>> LatencyGenerator { get; }
 
@@ -43,14 +43,14 @@ protected internal override async ValueTask<Outcome<TResult>> ExecuteCore<TResul
                     return await StrategyHelper.ExecuteCallbackSafeAsync(callback, context, state).ConfigureAwait(context.ContinueOnCapturedContext);
                 }
 
-                var args = new OnLatencyArguments(context, latency);
-                _telemetry.Report(new(ResilienceEventSeverity.Information, LatencyConstants.OnLatencyEvent), context, args);
+                var args = new OnLatencyInjectedArguments(context, latency);
+                _telemetry.Report(new(ResilienceEventSeverity.Information, LatencyConstants.OnLatencyInjectedEvent), context, args);
 
                 await _timeProvider.DelayAsync(latency, context).ConfigureAwait(context.ContinueOnCapturedContext);
 
-                if (OnLatency is not null)
+                if (OnLatencyInjected is not null)
                 {
-                    await OnLatency(args).ConfigureAwait(context.ContinueOnCapturedContext);
+                    await OnLatencyInjected(args).ConfigureAwait(context.ContinueOnCapturedContext);
                 }
             }
 
diff --git a/src/Polly.Core/Simmy/Latency/LatencyConstants.cs b/src/Polly.Core/Simmy/Latency/LatencyConstants.cs
index a74b6a58a0e..fdb1a5ab6c3 100644
--- a/src/Polly.Core/Simmy/Latency/LatencyConstants.cs
+++ b/src/Polly.Core/Simmy/Latency/LatencyConstants.cs
@@ -2,7 +2,7 @@
 
 internal static class LatencyConstants
 {
-    public const string OnLatencyEvent = "OnLatency";
+    public const string OnLatencyInjectedEvent = "OnLatencyInjected";
 
     public static readonly TimeSpan DefaultLatency = TimeSpan.FromSeconds(30);
 }
diff --git a/src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs b/src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs
index 534741efa2a..ec7327e878b 100644
--- a/src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs
+++ b/src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs
@@ -13,7 +13,7 @@ public class LatencyStrategyOptions : MonkeyStrategyOptions
     /// <remarks>
     /// Defaults to <see langword="null"/>.
     /// </remarks>
-    public Func<OnLatencyArguments, ValueTask>? OnLatency { get; set; }
+    public Func<OnLatencyInjectedArguments, ValueTask>? OnLatencyInjected { get; set; }
 
     /// <summary>
     /// Gets or sets the latency generator that generates the delay for a given execution.
diff --git a/src/Polly.Core/Simmy/Latency/OnLatencyArguments.cs b/src/Polly.Core/Simmy/Latency/OnLatencyInjectedArguments.cs
similarity index 77%
rename from src/Polly.Core/Simmy/Latency/OnLatencyArguments.cs
rename to src/Polly.Core/Simmy/Latency/OnLatencyInjectedArguments.cs
index 9a3896d2904..b82423ede42 100644
--- a/src/Polly.Core/Simmy/Latency/OnLatencyArguments.cs
+++ b/src/Polly.Core/Simmy/Latency/OnLatencyInjectedArguments.cs
@@ -5,14 +5,14 @@
 /// <summary>
 /// Arguments used by the latency chaos strategy to notify that a delayed occurred.
 /// </summary>
-public readonly struct OnLatencyArguments
+public readonly struct OnLatencyInjectedArguments
 {
     /// <summary>
-    /// Initializes a new instance of the <see cref="OnLatencyArguments"/> struct.
+    /// Initializes a new instance of the <see cref="OnLatencyInjectedArguments"/> struct.
     /// </summary>
     /// <param name="context">The context associated with the execution of a user-provided callback.</param>
     /// <param name="latency">The latency that was injected.</param>
-    public OnLatencyArguments(ResilienceContext context, TimeSpan latency)
+    public OnLatencyInjectedArguments(ResilienceContext context, TimeSpan latency)
     {
         Context = context;
         Latency = latency;
diff --git a/src/Snippets/Docs/Chaos.Latency.cs b/src/Snippets/Docs/Chaos.Latency.cs
index 75fdf174d9e..e1cd6d49f30 100644
--- a/src/Snippets/Docs/Chaos.Latency.cs
+++ b/src/Snippets/Docs/Chaos.Latency.cs
@@ -42,14 +42,14 @@ public static void LatencyUsage()
         };
 
         // To get notifications when a delay is injected
-        var optionsOnBehaviorInjected = new LatencyStrategyOptions
+        var optionsOnLatencyInjected = new LatencyStrategyOptions
         {
             Latency = TimeSpan.FromSeconds(30),
             Enabled = true,
             InjectionRate = 0.1,
-            OnLatency = static args =>
+            OnLatencyInjected = static args =>
             {
-                Console.WriteLine($"OnLatency, Latency: {args.Latency}, Operation: {args.Context.OperationKey}.");
+                Console.WriteLine($"OnLatencyInjected, Latency: {args.Latency}, Operation: {args.Context.OperationKey}.");
                 return default;
             }
         };
diff --git a/test/Polly.Core.Tests/Simmy/Latency/LatencyChaosStrategyTests.cs b/test/Polly.Core.Tests/Simmy/Latency/LatencyChaosStrategyTests.cs
index 361ab2d75ba..b44aa136e2e 100644
--- a/test/Polly.Core.Tests/Simmy/Latency/LatencyChaosStrategyTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Latency/LatencyChaosStrategyTests.cs
@@ -32,7 +32,7 @@ public async Task Given_enabled_and_randomly_within_threshold_should_inject_late
         _options.Enabled = true;
         _options.Latency = _delay;
         _options.Randomizer = () => 0.5;
-        _options.OnLatency = args =>
+        _options.OnLatencyInjected = args =>
         {
             args.Context.Should().NotBeNull();
             args.Context.CancellationToken.IsCancellationRequested.Should().BeFalse();
@@ -51,7 +51,7 @@ public async Task Given_enabled_and_randomly_within_threshold_should_inject_late
         (after - before).Should().Be(_delay);
 
         _args.Should().HaveCount(1);
-        _args[0].Arguments.Should().BeOfType<OnLatencyArguments>();
+        _args[0].Arguments.Should().BeOfType<OnLatencyInjectedArguments>();
         onLatencyExecuted.Should().BeTrue();
     }
 
@@ -110,7 +110,7 @@ public async Task Given_latency_is_negative_should_not_inject_latency(double lat
         _options.Latency = TimeSpan.FromSeconds(latency);
         _options.Randomizer = () => 0.5;
 
-        _options.OnLatency = args =>
+        _options.OnLatencyInjected = args =>
         {
             args.Context.Should().NotBeNull();
             args.Context.CancellationToken.IsCancellationRequested.Should().BeFalse();
diff --git a/test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs b/test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs
index 1d27e28bf8f..ea5e02f513e 100644
--- a/test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs
@@ -7,7 +7,7 @@ public class LatencyConstantsTests
     [Fact]
     public void EnsureDefaults()
     {
-        LatencyConstants.OnLatencyEvent.Should().Be("OnLatency");
+        LatencyConstants.OnLatencyInjectedEvent.Should().Be("OnLatencyInjected");
         LatencyConstants.DefaultLatency.Should().Be(TimeSpan.FromSeconds(30));
     }
 }
diff --git a/test/Polly.Core.Tests/Simmy/Latency/LatencyStrategyOptionsTests.cs b/test/Polly.Core.Tests/Simmy/Latency/LatencyStrategyOptionsTests.cs
index 571b5c2df7d..2999b798082 100644
--- a/test/Polly.Core.Tests/Simmy/Latency/LatencyStrategyOptionsTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Latency/LatencyStrategyOptionsTests.cs
@@ -16,6 +16,6 @@ public void Ctor_Ok()
         sut.InjectionRateGenerator.Should().BeNull();
         sut.Latency.Should().Be(LatencyConstants.DefaultLatency);
         sut.LatencyGenerator.Should().BeNull();
-        sut.OnLatency.Should().BeNull();
+        sut.OnLatencyInjected.Should().BeNull();
     }
 }
diff --git a/test/Polly.Core.Tests/Simmy/Latency/OnLatencyArgumentsTests.cs b/test/Polly.Core.Tests/Simmy/Latency/OnLatencyInjectedArgumentsTests.cs
similarity index 58%
rename from test/Polly.Core.Tests/Simmy/Latency/OnLatencyArgumentsTests.cs
rename to test/Polly.Core.Tests/Simmy/Latency/OnLatencyInjectedArgumentsTests.cs
index 5c834634e5f..838ea641690 100644
--- a/test/Polly.Core.Tests/Simmy/Latency/OnLatencyArgumentsTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Latency/OnLatencyInjectedArgumentsTests.cs
@@ -2,12 +2,12 @@
 
 namespace Polly.Core.Tests.Simmy.Latency;
 
-public class OnLatencyArgumentsTests
+public class OnLatencyInjectedArgumentsTests
 {
     [Fact]
     public void Ctor_Ok()
     {
-        var args = new OnLatencyArguments(ResilienceContextPool.Shared.Get(), TimeSpan.FromSeconds(10));
+        var args = new OnLatencyInjectedArguments(ResilienceContextPool.Shared.Get(), TimeSpan.FromSeconds(10));
         args.Context.Should().NotBeNull();
         args.Latency.Should().Be(TimeSpan.FromSeconds(10));
     }

From 61cbae6e3cb8c347f41b3bbec91becfab3808f0a Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 09:53:51 +0100
Subject: [PATCH 02/12] Remove Event suffix from the OnFaultInjectedEvent
 constant

---
 src/Polly.Core/Simmy/Fault/FaultConstants.cs             | 2 +-
 test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/Polly.Core/Simmy/Fault/FaultConstants.cs b/src/Polly.Core/Simmy/Fault/FaultConstants.cs
index 1e8f325af5b..0f7dc2c93c8 100644
--- a/src/Polly.Core/Simmy/Fault/FaultConstants.cs
+++ b/src/Polly.Core/Simmy/Fault/FaultConstants.cs
@@ -2,5 +2,5 @@
 
 internal static class FaultConstants
 {
-    public const string OnFaultInjectedEvent = "OnFaultInjectedEvent";
+    public const string OnFaultInjectedEvent = "OnFaultInjected";
 }
diff --git a/test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs b/test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs
index ffc1cfd1ff4..647bccc67ff 100644
--- a/test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs
@@ -7,6 +7,6 @@ public class FaultConstantsTests
     [Fact]
     public void EnsureDefaults()
     {
-        FaultConstants.OnFaultInjectedEvent.Should().Be("OnFaultInjectedEvent");
+        FaultConstants.OnFaultInjectedEvent.Should().Be("OnFaultInjected");
     }
 }

From d4f39adb08590f43c67252910490690efbfd279f Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 09:54:15 +0100
Subject: [PATCH 03/12] Remove obsolete documentation comment

---
 src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs b/src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs
index deb8d61a602..0cf8f9b9199 100644
--- a/src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs
+++ b/src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs
@@ -19,8 +19,7 @@ public class FaultStrategyOptions : MonkeyStrategyOptions
     /// Gets or sets the fault generator to be injected for a given execution.
     /// </summary>
     /// <remarks>
-    /// Defaults to <see langword="null"/>. Either <see cref="Fault"/> or this property is required.
-    /// When this property is <see langword="null"/> the <see cref="Fault"/> is used.
+    /// Defaults to <see langword="null"/>.
     /// </remarks>
     [Required]
     public Func<FaultGeneratorArguments, ValueTask<Exception?>>? FaultGenerator { get; set; } = default!;

From 0e1a3a853e6f730137b7ddbc22739269eca36c7e Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 09:54:32 +0100
Subject: [PATCH 04/12] Fix markdown table

---
 docs/chaos/index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/chaos/index.md b/docs/chaos/index.md
index d9be339cd1f..2882f58f296 100644
--- a/docs/chaos/index.md
+++ b/docs/chaos/index.md
@@ -48,6 +48,6 @@ All the strategies' options implement the [`MonkeyStrategyOptions`](xref:Polly.S
 | `InjectionRate`          | 0.001 ms      | A decimal between 0 and 1 inclusive. The strategy will inject the chaos, randomly, that proportion of the time, e.g.: if 0.2, twenty percent of calls will be randomly affected; if 0.01, one percent of calls; if 1, all calls. |
 | `InjectionRateGenerator` | `null`        | Generates the injection rate for a given execution, which the value should be between [0, 1] (inclusive).                                                                                                                        |
 | `Enabled`                | `false`       | Determines whether the strategy is enabled or not.                                                                                                                                                                               |
-| `EnabledGenerator`       | `null`        | The generator that indicates whether the chaos strategy is enabled for a given execution.                                                                                                                          |
+| `EnabledGenerator`       | `null`        | The generator that indicates whether the chaos strategy is enabled for a given execution.                                                                                                                                        |
 
 [simmy]: https://github.com/Polly-Contrib/Simmy

From 1c6b603b2374a0a9bddfcc198014c5ef85af8870 Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 10:11:23 +0100
Subject: [PATCH 05/12] Update unshipped

---
 src/Polly.Core/PublicAPI.Unshipped.txt | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/Polly.Core/PublicAPI.Unshipped.txt b/src/Polly.Core/PublicAPI.Unshipped.txt
index 97bb9afd8e9..68d606407b8 100644
--- a/src/Polly.Core/PublicAPI.Unshipped.txt
+++ b/src/Polly.Core/PublicAPI.Unshipped.txt
@@ -50,13 +50,13 @@ Polly.Simmy.Latency.LatencyStrategyOptions.Latency.set -> void
 Polly.Simmy.Latency.LatencyStrategyOptions.LatencyGenerator.get -> System.Func<Polly.Simmy.Latency.LatencyGeneratorArguments, System.Threading.Tasks.ValueTask<System.TimeSpan>>?
 Polly.Simmy.Latency.LatencyStrategyOptions.LatencyGenerator.set -> void
 Polly.Simmy.Latency.LatencyStrategyOptions.LatencyStrategyOptions() -> void
-Polly.Simmy.Latency.LatencyStrategyOptions.OnLatency.get -> System.Func<Polly.Simmy.Latency.OnLatencyArguments, System.Threading.Tasks.ValueTask>?
-Polly.Simmy.Latency.LatencyStrategyOptions.OnLatency.set -> void
-Polly.Simmy.Latency.OnLatencyArguments
-Polly.Simmy.Latency.OnLatencyArguments.Context.get -> Polly.ResilienceContext!
-Polly.Simmy.Latency.OnLatencyArguments.Latency.get -> System.TimeSpan
-Polly.Simmy.Latency.OnLatencyArguments.OnLatencyArguments() -> void
-Polly.Simmy.Latency.OnLatencyArguments.OnLatencyArguments(Polly.ResilienceContext! context, System.TimeSpan latency) -> void
+Polly.Simmy.Latency.LatencyStrategyOptions.OnLatencyInjected.get -> System.Func<Polly.Simmy.Latency.OnLatencyInjectedArguments, System.Threading.Tasks.ValueTask>?
+Polly.Simmy.Latency.LatencyStrategyOptions.OnLatencyInjected.set -> void
+Polly.Simmy.Latency.OnLatencyInjectedArguments
+Polly.Simmy.Latency.OnLatencyInjectedArguments.Context.get -> Polly.ResilienceContext!
+Polly.Simmy.Latency.OnLatencyInjectedArguments.Latency.get -> System.TimeSpan
+Polly.Simmy.Latency.OnLatencyInjectedArguments.OnLatencyInjectedArguments() -> void
+Polly.Simmy.Latency.OnLatencyInjectedArguments.OnLatencyInjectedArguments(Polly.ResilienceContext! context, System.TimeSpan latency) -> void
 Polly.Simmy.LatencyPipelineBuilderExtensions
 Polly.Simmy.MonkeyStrategy
 Polly.Simmy.MonkeyStrategy.MonkeyStrategy(Polly.Simmy.MonkeyStrategyOptions! options) -> void

From c5064714475918f19977243b022dc226eea97c62 Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 11:25:24 +0100
Subject: [PATCH 06/12] Apply suggestions for Fault chaos strategy

---
 src/Polly.Core/Simmy/Fault/FaultConstants.cs             | 4 +++-
 src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs       | 5 +++++
 test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs | 3 ++-
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/Polly.Core/Simmy/Fault/FaultConstants.cs b/src/Polly.Core/Simmy/Fault/FaultConstants.cs
index 0f7dc2c93c8..a38c84a9fcc 100644
--- a/src/Polly.Core/Simmy/Fault/FaultConstants.cs
+++ b/src/Polly.Core/Simmy/Fault/FaultConstants.cs
@@ -2,5 +2,7 @@
 
 internal static class FaultConstants
 {
-    public const string OnFaultInjectedEvent = "OnFaultInjected";
+    public const string DefaultName = "Chaos.Fault";
+
+    public const string OnFaultInjectedEvent = "Chaos.OnFault";
 }
diff --git a/src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs b/src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs
index 0cf8f9b9199..abb10ebd639 100644
--- a/src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs
+++ b/src/Polly.Core/Simmy/Fault/FaultStrategyOptions.cs
@@ -7,6 +7,11 @@ namespace Polly.Simmy.Fault;
 /// </summary>
 public class FaultStrategyOptions : MonkeyStrategyOptions
 {
+    /// <summary>
+    /// Initializes a new instance of the <see cref="FaultStrategyOptions"/> class.
+    /// </summary>
+    public FaultStrategyOptions() => Name = FaultConstants.DefaultName;
+
     /// <summary>
     /// Gets or sets the delegate that's raised when the outcome is injected.
     /// </summary>
diff --git a/test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs b/test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs
index 647bccc67ff..2a52b8cd2d1 100644
--- a/test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Fault/FaultConstantsTests.cs
@@ -7,6 +7,7 @@ public class FaultConstantsTests
     [Fact]
     public void EnsureDefaults()
     {
-        FaultConstants.OnFaultInjectedEvent.Should().Be("OnFaultInjected");
+        FaultConstants.DefaultName.Should().Be("Chaos.Fault");
+        FaultConstants.OnFaultInjectedEvent.Should().Be("Chaos.OnFault");
     }
 }

From 324f4c145dc52b4d149440075ac6ed8d688d669d Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 11:28:56 +0100
Subject: [PATCH 07/12] Apply suggestions for Latency chaos strategy

---
 src/Polly.Core/Simmy/Latency/LatencyConstants.cs             | 4 +++-
 src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs       | 5 +++++
 test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs | 3 ++-
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/Polly.Core/Simmy/Latency/LatencyConstants.cs b/src/Polly.Core/Simmy/Latency/LatencyConstants.cs
index fdb1a5ab6c3..e226d8d4062 100644
--- a/src/Polly.Core/Simmy/Latency/LatencyConstants.cs
+++ b/src/Polly.Core/Simmy/Latency/LatencyConstants.cs
@@ -2,7 +2,9 @@
 
 internal static class LatencyConstants
 {
-    public const string OnLatencyInjectedEvent = "OnLatencyInjected";
+    public const string DefaultName = "Chaos.Latency";
+
+    public const string OnLatencyInjectedEvent = "Chaos.OnLatency";
 
     public static readonly TimeSpan DefaultLatency = TimeSpan.FromSeconds(30);
 }
diff --git a/src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs b/src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs
index ec7327e878b..364c6625aca 100644
--- a/src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs
+++ b/src/Polly.Core/Simmy/Latency/LatencyStrategyOptions.cs
@@ -7,6 +7,11 @@
 /// </summary>
 public class LatencyStrategyOptions : MonkeyStrategyOptions
 {
+    /// <summary>
+    /// Initializes a new instance of the <see cref="LatencyStrategyOptions"/> class.
+    /// </summary>
+    public LatencyStrategyOptions() => Name = LatencyConstants.DefaultName;
+
     /// <summary>
     /// Gets or sets the delegate that's raised when a delay occurs.
     /// </summary>
diff --git a/test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs b/test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs
index ea5e02f513e..b1c3b4462b3 100644
--- a/test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Latency/LatencyConstantsTests.cs
@@ -7,7 +7,8 @@ public class LatencyConstantsTests
     [Fact]
     public void EnsureDefaults()
     {
-        LatencyConstants.OnLatencyInjectedEvent.Should().Be("OnLatencyInjected");
+        LatencyConstants.DefaultName.Should().Be("Chaos.Latency");
+        LatencyConstants.OnLatencyInjectedEvent.Should().Be("Chaos.OnLatency");
         LatencyConstants.DefaultLatency.Should().Be(TimeSpan.FromSeconds(30));
     }
 }

From 3f12fbff2c07be4918b33cbb66b0177ee7407914 Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 11:32:51 +0100
Subject: [PATCH 08/12] Apply suggestions for Behavior chaos strategy

---
 src/Polly.Core/Simmy/Behavior/BehaviorConstants.cs           | 4 +++-
 src/Polly.Core/Simmy/Behavior/BehaviorStrategyOptions.cs     | 5 +++++
 .../Simmy/Behavior/BehaviorConstantsTests.cs                 | 3 ++-
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/Polly.Core/Simmy/Behavior/BehaviorConstants.cs b/src/Polly.Core/Simmy/Behavior/BehaviorConstants.cs
index 91341bdb948..188e392f32b 100644
--- a/src/Polly.Core/Simmy/Behavior/BehaviorConstants.cs
+++ b/src/Polly.Core/Simmy/Behavior/BehaviorConstants.cs
@@ -2,5 +2,7 @@
 
 internal static class BehaviorConstants
 {
-    public const string OnBehaviorInjectedEvent = "OnBehaviorInjected";
+    public const string DefaultName = "Chaos.Behavior";
+
+    public const string OnBehaviorInjectedEvent = "Chaos.OnBehavior";
 }
diff --git a/src/Polly.Core/Simmy/Behavior/BehaviorStrategyOptions.cs b/src/Polly.Core/Simmy/Behavior/BehaviorStrategyOptions.cs
index 1541fbc9b3f..84fcb3703ab 100644
--- a/src/Polly.Core/Simmy/Behavior/BehaviorStrategyOptions.cs
+++ b/src/Polly.Core/Simmy/Behavior/BehaviorStrategyOptions.cs
@@ -7,6 +7,11 @@ namespace Polly.Simmy.Behavior;
 /// </summary>
 public class BehaviorStrategyOptions : MonkeyStrategyOptions
 {
+    /// <summary>
+    /// Initializes a new instance of the <see cref="BehaviorStrategyOptions"/> class.
+    /// </summary>
+    public BehaviorStrategyOptions() => Name = BehaviorConstants.DefaultName;
+
     /// <summary>
     /// Gets or sets the delegate that's raised when the custom behavior is injected.
     /// </summary>
diff --git a/test/Polly.Core.Tests/Simmy/Behavior/BehaviorConstantsTests.cs b/test/Polly.Core.Tests/Simmy/Behavior/BehaviorConstantsTests.cs
index e25fffb3fe0..13f0d4a6578 100644
--- a/test/Polly.Core.Tests/Simmy/Behavior/BehaviorConstantsTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Behavior/BehaviorConstantsTests.cs
@@ -7,6 +7,7 @@ public class BehaviorConstantsTests
     [Fact]
     public void EnsureDefaults()
     {
-        BehaviorConstants.OnBehaviorInjectedEvent.Should().Be("OnBehaviorInjected");
+        BehaviorConstants.DefaultName.Should().Be("Chaos.Behavior");
+        BehaviorConstants.OnBehaviorInjectedEvent.Should().Be("Chaos.OnBehavior");
     }
 }

From 1b6f696572e0b843e69501ffde6024ff6bcb89c3 Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 11:34:23 +0100
Subject: [PATCH 09/12] Apply suggestions for Outcome chaos strategy

---
 src/Polly.Core/Simmy/Outcomes/OutcomeConstants.cs            | 4 +++-
 .../Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs         | 5 +++++
 .../Polly.Core.Tests/Simmy/Outcomes/OutcomeConstantsTests.cs | 3 ++-
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/Polly.Core/Simmy/Outcomes/OutcomeConstants.cs b/src/Polly.Core/Simmy/Outcomes/OutcomeConstants.cs
index d061a0579f1..1ac0882db04 100644
--- a/src/Polly.Core/Simmy/Outcomes/OutcomeConstants.cs
+++ b/src/Polly.Core/Simmy/Outcomes/OutcomeConstants.cs
@@ -2,5 +2,7 @@
 
 internal static class OutcomeConstants
 {
-    public const string OnOutcomeInjectedEvent = "OnOutcomeInjected";
+    public const string DefaultName = "Chaos.Outcome";
+
+    public const string OnOutcomeInjectedEvent = "Chaos.OnOutcome";
 }
diff --git a/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs b/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs
index 4236d870254..44a2ba1e9bb 100644
--- a/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs
+++ b/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs
@@ -8,6 +8,11 @@ namespace Polly.Simmy.Outcomes;
 /// <typeparam name="TResult">The type of the outcome that was injected.</typeparam>
 public class OutcomeStrategyOptions<TResult> : MonkeyStrategyOptions
 {
+    /// <summary>
+    /// Initializes a new instance of the <see cref="OutcomeStrategyOptions{TResult}"/> class.
+    /// </summary>
+    public OutcomeStrategyOptions() => Name = OutcomeConstants.DefaultName;
+
     /// <summary>
     /// Gets or sets the delegate that's raised when the outcome is injected.
     /// </summary>
diff --git a/test/Polly.Core.Tests/Simmy/Outcomes/OutcomeConstantsTests.cs b/test/Polly.Core.Tests/Simmy/Outcomes/OutcomeConstantsTests.cs
index dcd92910518..f2c085bdd01 100644
--- a/test/Polly.Core.Tests/Simmy/Outcomes/OutcomeConstantsTests.cs
+++ b/test/Polly.Core.Tests/Simmy/Outcomes/OutcomeConstantsTests.cs
@@ -7,6 +7,7 @@ public class OutcomeConstantsTests
     [Fact]
     public void EnsureDefaults()
     {
-        OutcomeConstants.OnOutcomeInjectedEvent.Should().Be("OnOutcomeInjected");
+        OutcomeConstants.DefaultName.Should().Be("Chaos.Outcome");
+        OutcomeConstants.OnOutcomeInjectedEvent.Should().Be("Chaos.OnOutcome");
     }
 }

From 7732a076a3c092bb6aeabd8cda98defa16c055de Mon Sep 17 00:00:00 2001
From: peter-csala <57183693+peter-csala@users.noreply.github.com>
Date: Fri, 19 Jan 2024 12:49:28 +0100
Subject: [PATCH 10/12] [Docs] Add banner to chaos docs (#1910)

---
 docs/chaos/behavior.md | 3 +++
 docs/chaos/fault.md    | 3 +++
 docs/chaos/index.md    | 3 +++
 docs/chaos/latency.md  | 3 +++
 docs/chaos/result.md   | 3 +++
 5 files changed, 15 insertions(+)

diff --git a/docs/chaos/behavior.md b/docs/chaos/behavior.md
index 777de831800..31a39d38328 100644
--- a/docs/chaos/behavior.md
+++ b/docs/chaos/behavior.md
@@ -1,5 +1,8 @@
 # Behavior chaos strategy
 
+> [!IMPORTANT]
+> This documentation page describes an upcoming feature of Polly.
+
 ## About
 
 - **Options**: [`BehaviorStrategyOptions`](xref:Polly.Simmy.Behavior.BehaviorStrategyOptions)
diff --git a/docs/chaos/fault.md b/docs/chaos/fault.md
index 8f4c2deb3cf..1f7f4182083 100644
--- a/docs/chaos/fault.md
+++ b/docs/chaos/fault.md
@@ -1,5 +1,8 @@
 # Fault chaos strategy
 
+> [!IMPORTANT]
+> This documentation page describes an upcoming feature of Polly.
+
 ## About
 
 - **Options**: [`FaultStrategyOptions`](xref:Polly.Simmy.Fault.FaultStrategyOptions)
diff --git a/docs/chaos/index.md b/docs/chaos/index.md
index 2882f58f296..484abccfcff 100644
--- a/docs/chaos/index.md
+++ b/docs/chaos/index.md
@@ -1,5 +1,8 @@
 # Chaos engineering with Simmy
 
+> [!IMPORTANT]
+> This documentation page describes an upcoming feature of Polly.
+
 [Simmy][simmy] is a major new addition to Polly library, adding a chaos engineering and fault-injection dimension to Polly, through the provision of strategies to selectively inject faults, latency, custom behavior or fake results.
 
 ![Simmy](../media/simmy-logo.png)
diff --git a/docs/chaos/latency.md b/docs/chaos/latency.md
index b3595e17a48..9fcf430852d 100644
--- a/docs/chaos/latency.md
+++ b/docs/chaos/latency.md
@@ -1,5 +1,8 @@
 # Latency chaos strategy
 
+> [!IMPORTANT]
+> This documentation page describes an upcoming feature of Polly.
+
 ## About
 
 - **Options**: [`LatencyStrategyOptions`](xref:Polly.Simmy.Latency.LatencyStrategyOptions)
diff --git a/docs/chaos/result.md b/docs/chaos/result.md
index 0ec40f41cbe..c2ccffdf12c 100644
--- a/docs/chaos/result.md
+++ b/docs/chaos/result.md
@@ -1,5 +1,8 @@
 # Outcome chaos strategy
 
+> [!IMPORTANT]
+> This documentation page describes an upcoming feature of Polly.
+
 ## About
 
 - **Options**:

From 8f6813e366b1504b590adfa86592fe8edd370d78 Mon Sep 17 00:00:00 2001
From: martintmk <103487740+martintmk@users.noreply.github.com>
Date: Sun, 21 Jan 2024 21:09:18 +0100
Subject: [PATCH 11/12] Introduce `FaultGenerator` and `OutcomeGenerator<T>`
 (#1911)

---
 src/Polly.Core/PublicAPI.Unshipped.txt        |  16 ++-
 src/Polly.Core/Simmy/Fault/FaultGenerator.cs  |  84 ++++++++++++
 .../Simmy/Outcomes/OutcomeGenerator.cs        | 120 ++++++++++++++++++
 .../OutcomeStrategyOptions.TResult.cs         |  29 -----
 .../Simmy/Outcomes/OutcomeStrategyOptions.cs  |  24 +++-
 src/Polly.Core/Simmy/Utils/GeneratorHelper.cs |  52 ++++++++
 src/Polly.Core/Utils/RandomUtil.cs            |   2 +
 .../Simmy/Fault/FaultGeneratorTests.cs        |  49 +++++++
 .../Simmy/Outcomes/OutcomeGeneratorTests.cs   |  77 +++++++++++
 .../Simmy/Utils/GeneratorHelperTests.cs       |  56 ++++++++
 10 files changed, 475 insertions(+), 34 deletions(-)
 create mode 100644 src/Polly.Core/Simmy/Fault/FaultGenerator.cs
 create mode 100644 src/Polly.Core/Simmy/Outcomes/OutcomeGenerator.cs
 delete mode 100644 src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs
 create mode 100644 src/Polly.Core/Simmy/Utils/GeneratorHelper.cs
 create mode 100644 test/Polly.Core.Tests/Simmy/Fault/FaultGeneratorTests.cs
 create mode 100644 test/Polly.Core.Tests/Simmy/Outcomes/OutcomeGeneratorTests.cs
 create mode 100644 test/Polly.Core.Tests/Simmy/Utils/GeneratorHelperTests.cs

diff --git a/src/Polly.Core/PublicAPI.Unshipped.txt b/src/Polly.Core/PublicAPI.Unshipped.txt
index 68d606407b8..af7eab4a0e0 100644
--- a/src/Polly.Core/PublicAPI.Unshipped.txt
+++ b/src/Polly.Core/PublicAPI.Unshipped.txt
@@ -20,6 +20,11 @@ Polly.Simmy.EnabledGeneratorArguments
 Polly.Simmy.EnabledGeneratorArguments.Context.get -> Polly.ResilienceContext!
 Polly.Simmy.EnabledGeneratorArguments.EnabledGeneratorArguments() -> void
 Polly.Simmy.EnabledGeneratorArguments.EnabledGeneratorArguments(Polly.ResilienceContext! context) -> void
+Polly.Simmy.Fault.FaultGenerator
+Polly.Simmy.Fault.FaultGenerator.AddException(System.Func<Polly.ResilienceContext!, System.Exception!>! generator, int weight = 100) -> Polly.Simmy.Fault.FaultGenerator!
+Polly.Simmy.Fault.FaultGenerator.AddException(System.Func<System.Exception!>! generator, int weight = 100) -> Polly.Simmy.Fault.FaultGenerator!
+Polly.Simmy.Fault.FaultGenerator.AddException<TException>(int weight = 100) -> Polly.Simmy.Fault.FaultGenerator!
+Polly.Simmy.Fault.FaultGenerator.FaultGenerator() -> void
 Polly.Simmy.Fault.FaultGeneratorArguments
 Polly.Simmy.Fault.FaultGeneratorArguments.Context.get -> Polly.ResilienceContext!
 Polly.Simmy.Fault.FaultGeneratorArguments.FaultGeneratorArguments() -> void
@@ -84,12 +89,17 @@ Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>.Context.get -> Polly.Re
 Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>.OnOutcomeInjectedArguments() -> void
 Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>.OnOutcomeInjectedArguments(Polly.ResilienceContext! context, Polly.Outcome<TResult> outcome) -> void
 Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>.Outcome.get -> Polly.Outcome<TResult>
+Polly.Simmy.Outcomes.OutcomeGenerator<TResult>
+Polly.Simmy.Outcomes.OutcomeGenerator<TResult>.AddException(System.Func<Polly.ResilienceContext!, System.Exception!>! generator, int weight = 100) -> Polly.Simmy.Outcomes.OutcomeGenerator<TResult>!
+Polly.Simmy.Outcomes.OutcomeGenerator<TResult>.AddException(System.Func<System.Exception!>! generator, int weight = 100) -> Polly.Simmy.Outcomes.OutcomeGenerator<TResult>!
+Polly.Simmy.Outcomes.OutcomeGenerator<TResult>.AddException<TException>(int weight = 100) -> Polly.Simmy.Outcomes.OutcomeGenerator<TResult>!
+Polly.Simmy.Outcomes.OutcomeGenerator<TResult>.AddResult(System.Func<Polly.ResilienceContext!, TResult>! generator, int weight = 100) -> Polly.Simmy.Outcomes.OutcomeGenerator<TResult>!
+Polly.Simmy.Outcomes.OutcomeGenerator<TResult>.AddResult(System.Func<TResult>! generator, int weight = 100) -> Polly.Simmy.Outcomes.OutcomeGenerator<TResult>!
+Polly.Simmy.Outcomes.OutcomeGenerator<TResult>.OutcomeGenerator() -> void
 Polly.Simmy.Outcomes.OutcomeGeneratorArguments
 Polly.Simmy.Outcomes.OutcomeGeneratorArguments.Context.get -> Polly.ResilienceContext!
 Polly.Simmy.Outcomes.OutcomeGeneratorArguments.OutcomeGeneratorArguments() -> void
 Polly.Simmy.Outcomes.OutcomeGeneratorArguments.OutcomeGeneratorArguments(Polly.ResilienceContext! context) -> void
-Polly.Simmy.Outcomes.OutcomeStrategyOptions
-Polly.Simmy.Outcomes.OutcomeStrategyOptions.OutcomeStrategyOptions() -> void
 Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>
 Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OnOutcomeInjected.get -> System.Func<Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>, System.Threading.Tasks.ValueTask>?
 Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OnOutcomeInjected.set -> void
@@ -98,9 +108,11 @@ Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OutcomeGenerator.set -> voi
 Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OutcomeStrategyOptions() -> void
 static Polly.Simmy.BehaviorPipelineBuilderExtensions.AddChaosBehavior<TBuilder>(this TBuilder! builder, double injectionRate, System.Func<System.Threading.Tasks.ValueTask>! behavior) -> TBuilder!
 static Polly.Simmy.BehaviorPipelineBuilderExtensions.AddChaosBehavior<TBuilder>(this TBuilder! builder, Polly.Simmy.Behavior.BehaviorStrategyOptions! options) -> TBuilder!
+static Polly.Simmy.Fault.FaultGenerator.implicit operator System.Func<Polly.Simmy.Fault.FaultGeneratorArguments, System.Threading.Tasks.ValueTask<System.Exception?>>!(Polly.Simmy.Fault.FaultGenerator! generator) -> System.Func<Polly.Simmy.Fault.FaultGeneratorArguments, System.Threading.Tasks.ValueTask<System.Exception?>>!
 static Polly.Simmy.FaultPipelineBuilderExtensions.AddChaosFault<TBuilder>(this TBuilder! builder, double injectionRate, System.Func<System.Exception?>! faultGenerator) -> TBuilder!
 static Polly.Simmy.FaultPipelineBuilderExtensions.AddChaosFault<TBuilder>(this TBuilder! builder, Polly.Simmy.Fault.FaultStrategyOptions! options) -> TBuilder!
 static Polly.Simmy.LatencyPipelineBuilderExtensions.AddChaosLatency<TBuilder>(this TBuilder! builder, double injectionRate, System.TimeSpan latency) -> TBuilder!
 static Polly.Simmy.LatencyPipelineBuilderExtensions.AddChaosLatency<TBuilder>(this TBuilder! builder, Polly.Simmy.Latency.LatencyStrategyOptions! options) -> TBuilder!
 static Polly.Simmy.OutcomePipelineBuilderExtensions.AddChaosResult<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, double injectionRate, System.Func<TResult?>! resultGenerator) -> Polly.ResiliencePipelineBuilder<TResult>!
 static Polly.Simmy.OutcomePipelineBuilderExtensions.AddChaosResult<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>! options) -> Polly.ResiliencePipelineBuilder<TResult>!
+static Polly.Simmy.Outcomes.OutcomeGenerator<TResult>.implicit operator System.Func<Polly.Simmy.Outcomes.OutcomeGeneratorArguments, System.Threading.Tasks.ValueTask<Polly.Outcome<TResult>?>>!(Polly.Simmy.Outcomes.OutcomeGenerator<TResult>! generator) -> System.Func<Polly.Simmy.Outcomes.OutcomeGeneratorArguments, System.Threading.Tasks.ValueTask<Polly.Outcome<TResult>?>>!
diff --git a/src/Polly.Core/Simmy/Fault/FaultGenerator.cs b/src/Polly.Core/Simmy/Fault/FaultGenerator.cs
new file mode 100644
index 00000000000..374faee6a70
--- /dev/null
+++ b/src/Polly.Core/Simmy/Fault/FaultGenerator.cs
@@ -0,0 +1,84 @@
+using System.ComponentModel;
+using Polly.Simmy.Utils;
+
+namespace Polly.Simmy.Fault;
+
+#pragma warning disable CA2225 // Operator overloads have named alternates
+#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
+
+/// <summary>
+/// A generator for creating faults (exceptions) using registered delegate functions.
+/// </summary>
+/// <remarks>
+/// An instance of this class can be assigned to the <see cref="FaultStrategyOptions.FaultGenerator"/> property.
+/// </remarks>
+public sealed class FaultGenerator
+{
+    private const int DefaultWeight = 100;
+
+    private readonly GeneratorHelper<VoidResult> _helper;
+
+    /// <summary>
+    /// Initializes a new instance of the <see cref="FaultGenerator"/> class.
+    /// </summary>
+    public FaultGenerator()
+        => _helper = new GeneratorHelper<VoidResult>(RandomUtil.Instance.Next);
+
+    /// <summary>
+    /// Registers an exception generator delegate.
+    /// </summary>
+    /// <param name="generator">The delegate that generates the exception.</param>
+    /// <param name="weight">The weight assigned to this generator. Defaults to <c>100</c>.</param>
+    /// <returns>The current instance of <see cref="FaultGenerator"/>.</returns>
+    public FaultGenerator AddException(Func<Exception> generator, int weight = DefaultWeight)
+    {
+        Guard.NotNull(generator);
+
+        _helper.AddOutcome(_ => Outcome.FromException<VoidResult>(generator()), weight);
+
+        return this;
+    }
+
+    /// <summary>
+    /// Registers an exception generator delegate that accepts a <see cref="ResilienceContext"/>.
+    /// </summary>
+    /// <param name="generator">The delegate that generates the exception, accepting a <see cref="ResilienceContext"/>.</param>
+    /// <param name="weight">The weight assigned to this generator. Defaults to <c>100</c>.</param>
+    /// <returns>The current instance of <see cref="FaultGenerator"/>.</returns>
+    public FaultGenerator AddException(Func<ResilienceContext, Exception> generator, int weight = DefaultWeight)
+    {
+        Guard.NotNull(generator);
+
+        _helper.AddOutcome(context => Outcome.FromException<VoidResult>(generator(context)), weight);
+
+        return this;
+    }
+
+    /// <summary>
+    /// Registers an exception generator for a specific exception type, using the default constructor of that exception.
+    /// </summary>
+    /// <typeparam name="TException">The type of the exception to generate.</typeparam>
+    /// <param name="weight">The weight assigned to this generator. Defaults to <c>100</c>.</param>
+    /// <returns>The current instance of <see cref="FaultGenerator"/>.</returns>
+    public FaultGenerator AddException<TException>(int weight = DefaultWeight)
+        where TException : Exception, new()
+    {
+        _helper.AddOutcome(_ => Outcome.FromException<VoidResult>(new TException()), weight);
+
+        return this;
+    }
+
+    /// <summary>
+    /// Provides an implicit conversion from <see cref="FaultGenerator"/> to a delegate compatible with <see cref="FaultStrategyOptions.FaultGenerator"/>.
+    /// </summary>
+    /// <param name="generator">The instance of <see cref="FaultGenerator"/>.</param>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public static implicit operator Func<FaultGeneratorArguments, ValueTask<Exception?>>(FaultGenerator generator)
+    {
+        Guard.NotNull(generator);
+
+        var generatorDelegate = generator._helper.CreateGenerator();
+
+        return args => new ValueTask<Exception?>(generatorDelegate(args.Context)!.Value.Exception);
+    }
+}
diff --git a/src/Polly.Core/Simmy/Outcomes/OutcomeGenerator.cs b/src/Polly.Core/Simmy/Outcomes/OutcomeGenerator.cs
new file mode 100644
index 00000000000..3d1439ab80f
--- /dev/null
+++ b/src/Polly.Core/Simmy/Outcomes/OutcomeGenerator.cs
@@ -0,0 +1,120 @@
+using System.ComponentModel;
+using Polly.Simmy.Utils;
+
+namespace Polly.Simmy.Outcomes;
+
+#pragma warning disable CA2225 // Operator overloads have named alternates
+#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
+
+/// <summary>
+/// Generator that produces faults such as exceptions or results.
+/// </summary>
+/// <typeparam name="TResult">The type of the result.</typeparam>
+/// <remarks>
+/// An instance of this class is assignable to <see cref="OutcomeStrategyOptions{TResult}.OutcomeGenerator"/>.
+/// </remarks>
+public sealed class OutcomeGenerator<TResult>
+{
+    private const int DefaultWeight = 100;
+    private readonly GeneratorHelper<TResult> _helper;
+
+    /// <summary>
+    /// Initializes a new instance of the <see cref="OutcomeGenerator{TResult}"/> class.
+    /// </summary>
+    public OutcomeGenerator()
+        : this(RandomUtil.Instance.Next)
+    {
+    }
+
+    internal OutcomeGenerator(Func<int, int> weightGenerator)
+        => _helper = new GeneratorHelper<TResult>(weightGenerator);
+
+    /// <summary>
+    /// Registers an exception generator delegate.
+    /// </summary>
+    /// <param name="generator">The delegate that generates the exception.</param>
+    /// <param name="weight">The weight assigned to this generator. Defaults to <c>100</c>.</param>
+    /// <returns>The current instance of <see cref="OutcomeGenerator{TResult}"/>.</returns>
+    public OutcomeGenerator<TResult> AddException(Func<Exception> generator, int weight = DefaultWeight)
+    {
+        Guard.NotNull(generator);
+
+        _helper.AddOutcome(_ => Outcome.FromException<TResult>(generator()), weight);
+
+        return this;
+    }
+
+    /// <summary>
+    /// Registers an exception generator delegate that accepts a <see cref="ResilienceContext"/>.
+    /// </summary>
+    /// <param name="generator">The delegate that generates the exception, accepting a <see cref="ResilienceContext"/>.</param>
+    /// <param name="weight">The weight assigned to this generator. Defaults to <c>100</c>.</param>
+    /// <returns>The current instance of <see cref="OutcomeGenerator{TResult}"/>.</returns>
+    public OutcomeGenerator<TResult> AddException(Func<ResilienceContext, Exception> generator, int weight = DefaultWeight)
+    {
+        Guard.NotNull(generator);
+
+        _helper.AddOutcome(context => Outcome.FromException<TResult>(generator(context)), weight);
+
+        return this;
+    }
+
+    /// <summary>
+    /// Registers an exception generator for a specific exception type, using the default constructor of that exception.
+    /// </summary>
+    /// <typeparam name="TException">The type of the exception to generate.</typeparam>
+    /// <param name="weight">The weight assigned to this generator. Defaults to <c>100</c>.</param>
+    /// <returns>The current instance of <see cref="OutcomeGenerator{TResult}"/>.</returns>
+    public OutcomeGenerator<TResult> AddException<TException>(int weight = DefaultWeight)
+        where TException : Exception, new()
+    {
+        _helper.AddOutcome(_ => Outcome.FromException<TResult>(new TException()), weight);
+
+        return this;
+    }
+
+    /// <summary>
+    /// Registers a result generator.
+    /// </summary>
+    /// <param name="generator">The delegate that generates the result.</param>
+    /// <param name="weight">The weight assigned to this generator. Defaults to <c>100</c>.</param>
+    /// <returns>The current instance of <see cref="OutcomeGenerator{TResult}"/>.</returns>
+    public OutcomeGenerator<TResult> AddResult(Func<TResult> generator, int weight = DefaultWeight)
+    {
+        Guard.NotNull(generator);
+
+        _helper.AddOutcome(_ => Outcome.FromResult(generator()), weight);
+
+        return this;
+    }
+
+    /// <summary>
+    /// Registers a result generator.
+    /// </summary>
+    /// <param name="generator">The delegate that generates the result, accepting a <see cref="ResilienceContext"/>.</param>
+    /// <param name="weight">The weight assigned to this generator. Defaults to <c>100</c>.</param>
+    /// <returns>The current instance of <see cref="OutcomeGenerator{TResult}"/>.</returns>
+    public OutcomeGenerator<TResult> AddResult(Func<ResilienceContext, TResult> generator, int weight = DefaultWeight)
+    {
+        Guard.NotNull(generator);
+
+        _helper.AddOutcome(context => Outcome.FromResult(generator(context)), weight);
+
+        return this;
+    }
+
+    /// <summary>
+    /// Implicit conversion to <see cref="OutcomeStrategyOptions{TResult}.OutcomeGenerator"/>.
+    /// </summary>
+    /// <param name="generator">The generator instance.</param>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public static implicit operator Func<OutcomeGeneratorArguments, ValueTask<Outcome<TResult>?>>(OutcomeGenerator<TResult> generator)
+    {
+        Guard.NotNull(generator);
+
+        var generatorDelegate = generator._helper.CreateGenerator();
+
+        return args => new ValueTask<Outcome<TResult>?>(generatorDelegate(args.Context));
+    }
+}
+
diff --git a/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs b/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs
deleted file mode 100644
index 44a2ba1e9bb..00000000000
--- a/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.TResult.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-
-namespace Polly.Simmy.Outcomes;
-
-/// <summary>
-/// Represents the options for the Outcome chaos strategy.
-/// </summary>
-/// <typeparam name="TResult">The type of the outcome that was injected.</typeparam>
-public class OutcomeStrategyOptions<TResult> : MonkeyStrategyOptions
-{
-    /// <summary>
-    /// Initializes a new instance of the <see cref="OutcomeStrategyOptions{TResult}"/> class.
-    /// </summary>
-    public OutcomeStrategyOptions() => Name = OutcomeConstants.DefaultName;
-
-    /// <summary>
-    /// Gets or sets the delegate that's raised when the outcome is injected.
-    /// </summary>
-    /// <remarks>
-    /// Defaults to <see langword="null"/>.
-    /// </remarks>
-    public Func<OnOutcomeInjectedArguments<TResult>, ValueTask>? OnOutcomeInjected { get; set; }
-
-    /// <summary>
-    /// Gets or sets the outcome generator to be injected for a given execution.
-    /// </summary>
-    [Required]
-    public Func<OutcomeGeneratorArguments, ValueTask<Outcome<TResult>?>> OutcomeGenerator { get; set; } = default!;
-}
diff --git a/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs b/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs
index 7a29aa8ef5d..fa8f21fddad 100644
--- a/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs
+++ b/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs
@@ -1,6 +1,24 @@
-namespace Polly.Simmy.Outcomes;
+using System.ComponentModel.DataAnnotations;
 
-/// <inheritdoc/>
-public class OutcomeStrategyOptions : OutcomeStrategyOptions<object>
+namespace Polly.Simmy.Outcomes;
+
+/// <summary>
+/// Represents the options for the Outcome chaos strategy.
+/// </summary>
+/// <typeparam name="TResult">The type of the outcome that was injected.</typeparam>
+public class OutcomeStrategyOptions<TResult> : MonkeyStrategyOptions
 {
+    /// <summary>
+    /// Gets or sets the delegate that's invoked when the outcome is injected.
+    /// </summary>
+    /// <remarks>
+    /// Defaults to <see langword="null"/>.
+    /// </remarks>
+    public Func<OnOutcomeInjectedArguments<TResult>, ValueTask>? OnOutcomeInjected { get; set; }
+
+    /// <summary>
+    /// Gets or sets the outcome generator to be injected for a given execution.
+    /// </summary>
+    [Required]
+    public Func<OutcomeGeneratorArguments, ValueTask<Outcome<TResult>?>> OutcomeGenerator { get; set; } = default!;
 }
diff --git a/src/Polly.Core/Simmy/Utils/GeneratorHelper.cs b/src/Polly.Core/Simmy/Utils/GeneratorHelper.cs
new file mode 100644
index 00000000000..6ec4090a0f2
--- /dev/null
+++ b/src/Polly.Core/Simmy/Utils/GeneratorHelper.cs
@@ -0,0 +1,52 @@
+namespace Polly.Simmy.Utils;
+
+internal sealed class GeneratorHelper<TResult>
+{
+    private readonly Func<int, int> _weightGenerator;
+
+    private readonly List<int> _weights = [];
+    private readonly List<Func<ResilienceContext, Outcome<TResult>>> _factories = [];
+    private int _totalWeight;
+
+    public GeneratorHelper(Func<int, int> weightGenerator) => _weightGenerator = weightGenerator;
+
+    public void AddOutcome(Func<ResilienceContext, Outcome<TResult>> generator, int weight)
+    {
+        Guard.NotNull(generator);
+
+        _totalWeight += weight;
+        _factories.Add(generator);
+        _weights.Add(weight);
+    }
+
+    internal Func<ResilienceContext, Outcome<TResult>?> CreateGenerator()
+    {
+        if (_factories.Count == 0)
+        {
+            return _ => null;
+        }
+
+        var totalWeight = _totalWeight;
+        var factories = _factories.ToArray();
+        var weights = _weights.ToArray();
+        var generator = _weightGenerator;
+
+        return context =>
+        {
+            var generatedWeight = generator(totalWeight);
+            var weight = 0;
+
+            for (var i = 0; i < factories.Length; i++)
+            {
+                weight += weights[i];
+                if (generatedWeight < weight)
+                {
+                    return factories[i](context);
+                }
+            }
+
+            return null;
+        };
+    }
+}
+
diff --git a/src/Polly.Core/Utils/RandomUtil.cs b/src/Polly.Core/Utils/RandomUtil.cs
index aac063fcc7a..de7bc6ff6ce 100644
--- a/src/Polly.Core/Utils/RandomUtil.cs
+++ b/src/Polly.Core/Utils/RandomUtil.cs
@@ -13,4 +13,6 @@ internal sealed class RandomUtil
     public RandomUtil(int? seed) => _random = new ThreadLocal<Random>(() => seed == null ? new Random() : new Random(seed.Value));
 
     public double NextDouble() => _random.Value!.NextDouble();
+
+    public int Next(int maxValue) => _random.Value!.Next(maxValue);
 }
diff --git a/test/Polly.Core.Tests/Simmy/Fault/FaultGeneratorTests.cs b/test/Polly.Core.Tests/Simmy/Fault/FaultGeneratorTests.cs
new file mode 100644
index 00000000000..0ffe3c121cf
--- /dev/null
+++ b/test/Polly.Core.Tests/Simmy/Fault/FaultGeneratorTests.cs
@@ -0,0 +1,49 @@
+using System;
+using Polly.Simmy.Fault;
+
+namespace Polly.Core.Tests.Simmy.Fault;
+
+public class FaultGeneratorTests
+{
+    [Fact]
+    public void AddException_Generic_Ok()
+    {
+        var generator = new FaultGenerator();
+
+        generator.AddException<InvalidOperationException>();
+
+        Generate(generator).Should().BeOfType<InvalidOperationException>();
+    }
+
+    [Fact]
+    public void AddException_Factory_Ok()
+    {
+        var generator = new FaultGenerator();
+
+        generator.AddException(() => new InvalidOperationException());
+
+        Generate(generator).Should().BeOfType<InvalidOperationException>();
+    }
+
+    [Fact]
+    public void AddException_FactoryWithResilienceContext_Ok()
+    {
+        var generator = new FaultGenerator();
+
+        generator.AddException(context =>
+        {
+            context.Should().NotBeNull();
+
+            return new InvalidOperationException();
+        });
+
+        Generate(generator).Should().BeOfType<InvalidOperationException>();
+    }
+
+    private static Exception? Generate(FaultGenerator generator)
+    {
+        Func<FaultGeneratorArguments, ValueTask<Exception?>> func = generator;
+
+        return func(new FaultGeneratorArguments(ResilienceContextPool.Shared.Get())).AsTask().Result;
+    }
+}
diff --git a/test/Polly.Core.Tests/Simmy/Outcomes/OutcomeGeneratorTests.cs b/test/Polly.Core.Tests/Simmy/Outcomes/OutcomeGeneratorTests.cs
new file mode 100644
index 00000000000..924de797690
--- /dev/null
+++ b/test/Polly.Core.Tests/Simmy/Outcomes/OutcomeGeneratorTests.cs
@@ -0,0 +1,77 @@
+using System;
+using Polly.Simmy.Outcomes;
+
+namespace Polly.Core.Tests.Simmy.Outcomes;
+
+public class OutcomeGeneratorTests
+{
+    [Fact]
+    public void AddException_Generic_Ok()
+    {
+        var generator = new OutcomeGenerator<string>();
+
+        generator.AddException<InvalidOperationException>();
+
+        Generate(generator)!.Value.Exception.Should().BeOfType<InvalidOperationException>();
+    }
+
+    [Fact]
+    public void AddException_Factory_Ok()
+    {
+        var generator = new OutcomeGenerator<string>();
+
+        generator.AddException(() => new InvalidOperationException());
+
+        Generate(generator)!.Value.Exception.Should().BeOfType<InvalidOperationException>();
+    }
+
+    [Fact]
+    public void AddException_FactoryWithResilienceContext_Ok()
+    {
+        var generator = new OutcomeGenerator<string>();
+
+        generator.AddException(context =>
+        {
+            context.Should().NotBeNull();
+
+            return new InvalidOperationException();
+        });
+
+        Generate(generator)!.Value.Exception.Should().BeOfType<InvalidOperationException>();
+    }
+
+    [Fact]
+    public void AddResult_Factory_Ok()
+    {
+        var generator = new OutcomeGenerator<string>();
+
+        generator.AddResult(() =>
+        {
+            return "dummy";
+        });
+
+        Generate(generator)!.Value.Result.Should().Be("dummy");
+    }
+
+    [Fact]
+    public void AddResult_FactoryWithResilienceContext_Ok()
+    {
+        var generator = new OutcomeGenerator<string>();
+
+        generator.AddResult(context =>
+        {
+            context.Should().NotBeNull();
+
+            return "dummy";
+        });
+
+        Generate(generator)!.Value.Result.Should().Be("dummy");
+    }
+
+    private static Outcome<string>? Generate(OutcomeGenerator<string> generator)
+    {
+        Func<OutcomeGeneratorArguments, ValueTask<Outcome<string>?>> func = generator;
+
+        return func(new OutcomeGeneratorArguments(ResilienceContextPool.Shared.Get())).AsTask().Result;
+    }
+}
diff --git a/test/Polly.Core.Tests/Simmy/Utils/GeneratorHelperTests.cs b/test/Polly.Core.Tests/Simmy/Utils/GeneratorHelperTests.cs
new file mode 100644
index 00000000000..258124cec77
--- /dev/null
+++ b/test/Polly.Core.Tests/Simmy/Utils/GeneratorHelperTests.cs
@@ -0,0 +1,56 @@
+using System;
+using Polly.Simmy.Utils;
+
+namespace Polly.Core.Tests.Simmy.Utils;
+
+public class GeneratorHelperTests
+{
+    [Fact]
+    public void CreateGenerator_NoGenerators_Ok()
+    {
+        var helper = new GeneratorHelper<int>(_ => 10);
+
+        helper.CreateGenerator()(ResilienceContextPool.Shared.Get()).Should().BeNull();
+    }
+
+    [Fact]
+    public void AddOutcome_EnsureWeightRespected()
+    {
+        int weight = 0;
+        int maxWeight = 0;
+        var context = ResilienceContextPool.Shared.Get();
+
+        var helper = new GeneratorHelper<int>(max =>
+        {
+            maxWeight = max;
+            return weight;
+        });
+
+        helper.AddOutcome(_ => Outcome.FromResult(1), 40);
+        helper.AddOutcome(_ => Outcome.FromResult(2), 80);
+
+        var generator = helper.CreateGenerator();
+
+        weight = 0;
+        generator(context)!.Value.Result.Should().Be(1);
+        weight = 39;
+        generator(context)!.Value.Result.Should().Be(1);
+
+        weight = 40;
+        generator(context)!.Value.Result.Should().Be(2);
+
+        maxWeight.Should().Be(120);
+    }
+
+    [Fact]
+    public void Generator_OutsideRange_ReturnsNull()
+    {
+        var context = ResilienceContextPool.Shared.Get();
+        var helper = new GeneratorHelper<int>(_ => 1000);
+
+        helper.AddOutcome(_ => Outcome.FromResult(1), 40);
+
+        var generator = helper.CreateGenerator();
+        generator(context).Should().BeNull();
+    }
+}

From ad256009957ebfb3ab5a03c66a2dc3157868e8fd Mon Sep 17 00:00:00 2001
From: peter-csala <csalasoft@hotmail.com>
Date: Fri, 19 Jan 2024 11:34:23 +0100
Subject: [PATCH 12/12] Apply suggestions for Outcome chaos strategy

---
 src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs b/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs
index fa8f21fddad..31867aafbf2 100644
--- a/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs
+++ b/src/Polly.Core/Simmy/Outcomes/OutcomeStrategyOptions.cs
@@ -8,6 +8,11 @@ namespace Polly.Simmy.Outcomes;
 /// <typeparam name="TResult">The type of the outcome that was injected.</typeparam>
 public class OutcomeStrategyOptions<TResult> : MonkeyStrategyOptions
 {
+    /// <summary>
+    /// Initializes a new instance of the <see cref="OutcomeStrategyOptions{TResult}"/> class.
+    /// </summary>
+    public OutcomeStrategyOptions() => Name = OutcomeConstants.DefaultName;
+
     /// <summary>
     /// Gets or sets the delegate that's invoked when the outcome is injected.
     /// </summary>