Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update README.md for Polly.Extensions with telemetry info #1401

Merged
merged 5 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Polly.Core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,10 @@ new ResilienceStrategyBuilder()
## Registering Custom Callbacks

When setting the delegates, ensure to respect the `ResilienceContext.IsSynchronous` property's value and execute your delegates synchronously for synchronous executions. In addition, use the `ResilienceContext.ContinueOnCapturedContext` property when your user code uses execution with synchronization context (for example, asynchronous calls in UI applications, such as in Windows Forms or WPF applications).

## Telemetry

Each individual resilience strategy can emit telemetry by using the [`ResilienceStrategyTelemetry`](Telemetry/ResilienceStrategyTelemetry.cs) API. Polly wraps the arguments as [`TelemetryEventArguments`](Telemetry/TelemetryEventArguments.cs) and emits them using `DiagnosticSource`.
To consume the telemetry, Polly adopters needs to assign an instance of `DiagnosticSource` to `ResilienceStrategyBuilder.DiagnosticSource` and consume `TelemetryEventArguments`.

For common use-cases, it is anticipated that Polly users would leverage `Polly.Extensions`. This allows all of the aforementioned functionalities by invoking the `ResilienceStrategyBuilder.ConfigureTelemetry(...)` extension method. `ConfigureTelemetry` processes `TelemetryEventArguments` and generates logs and metrics from it.
145 changes: 134 additions & 11 deletions src/Polly.Extensions/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
# About Polly.Hosting
# Polly.Extensions Overview

The `Polly.Hosting` enables the following features:
`Polly.Extensions` provides a set of features that streamline the integration of Polly with the standard `IServiceCollection` Dependency Injection (DI) container. It further enhances telemetry by exposing a `ConfigureTelemetry` extension method that enables [logging](https://learn.microsoft.com/dotnet/core/extensions/logging?tabs=command-line) and [metering](https://learn.microsoft.com/dotnet/core/diagnostics/metrics) for all strategies created via DI extension points. Note that telemetry is enabled by default when utilizing the `AddResilienceStrategy` extension method.


- Integrates Polly with the standard `IServiceCollection` Dependency Injection (DI) container.
- Implements `ResilienceTelemetryFactory` that adds [logging](https://learn.microsoft.com/dotnet/core/extensions/logging?tabs=command-line) and [metering](https://learn.microsoft.com/dotnet/core/diagnostics/metrics) for all strategies created using the DI extension points.

Example:
Below is an example illustrating these capabilities:

``` csharp
var services = new ServiceCollection();

// Define your strategy
// Define a strategy
services.AddResilienceStrategy(
"my-key",
context => context.Builder.AddTimeout(TimeSpan.FromSeconds(10)));
context => context.Builder.AddTimeout(TimeSpan.FromSeconds(10)));

// Define your strategy using custom options
// Define a strategy with custom options
services.AddResilienceStrategy(
"my-timeout",
context =>
Expand All @@ -25,9 +21,136 @@ services.AddResilienceStrategy(
context.Builder.AddTimeout(myOptions.Timeout);
});

// Use your strategy
// Utilize the strategy
var serviceProvider = services.BuildServiceProvider();
var strategyProvider = serviceProvider.GetRequiredService<ResilienceStrategyProvider<string>>();
var resilienceStrategy = strategyProvider.Get("my-key");
```

## Telemetry Features

Upon invoking the `ConfigureTelemetry` extension method, Polly begins to emit logs and metrics. Here's an example:

``` csharp
var telemetryOptions = new TelemetryOptions();

// Configure logging
telemetryOptions.LoggerFactory = LoggerFactory.Create(builder => builder.AddConsole());

// Configure enrichers
telemetryOptions.Enrichers.Add(context =>
{
context.Tags.Add(new("my-custom-tag", "custom-value"));
});

// Manually handle the event
telemetryOptions.OnTelemetryEvent = args =>
{
Console.WriteLine($"Telemetry event occurred: {args.Event.EventName}");
});

var builder = new ResilienceStrategyBuilder()
.AddTimeout(TimeSpan.FromSeconds(1))
.ConfigureTelemetry(telemetryOptions) // This method enables telemetry in the builder
.Build();
```

Alternatively, you can use the `AddResilienceStrategy` extension which automatically adds telemetry:

``` csharp
var serviceCollection = new ServiceCollection()
.AddLogging(builder => builder.AddConsole())
.AddResilienceStrategy("my-strategy", builder => builder.AddTimeout(TimeSpan.FromSeconds(1)))
// Configure the default settings for TelemetryOptions
.Configure<TelemetryOptions>(options =>
{
// Configure enrichers
options.Enrichers.Add(context => context.Tags.Add(new("my-custom-tag", "custom-value")));

// Manually handle the event
options.OnTelemetryEvent = args =>
{
Console.WriteLine($"Telemetry event occurred: {args.Event.EventName}");
};
});
```

### Emitted Metrics

The emitted metrics are emitted under the `Polly` meter name. The subsequent sections provide insights into the metrics produced by Polly. Please note that any custom enriched dimensions are not depicted in the following tables.

#### resilience-events

- Type: *Counter*
- Description: Emitted upon the occurrence of a resilience event.

Dimensions:

|Name|Description|
|---| ---|
|`event-name`| The name of the emitted event.|
|`event-severity`| The severity of the event (`Debug`, `Information`, `Warning`, `Error`, `Critical`).|
|`builder-name`| The name of the builder corresponding to the resilience strategy.|
|`builder-instance`| The instance name of the builder corresponding to the resilience strategy.|
|`strategy-name`| The name of the strategy generating this event.|
|`strategy-type`| The type of the strategy generating this event.|
|`operation-key`| The operation key associated with the call site. |
|`result-type`| The result type (`string`, `HttpResponseMessage`). |
|`exception-name`| The full name of the exception assigned to the execution result (`System.InvalidOperationException`). |

#### execution-attempt-duration

- Type: *Histogram*
- Unit: *milliseconds*
- Description: Tracks the duration of execution attempts, produced by `Retry` and `Hedging` resilience strategies.

Dimensions:

|Name|Description|
|---| ---|
|`event-name`| The name of the emitted event.|
|`event-severity`| The severity of the event (`Debug`, `Information`, `Warning`, `Error`, `Critical`).|
|`builder-name`| The name of the builder corresponding to the resilience strategy.|
|`builder-instance`| The instance name of the builder corresponding to the resilience strategy.|
|`strategy-name`| The name of the strategy generating this event.|
|`strategy-type`| The type of the strategy generating this event.|
|`operation-key`| The operation key associated with the call site. |
|`result-type`| The result type (`string`, `HttpResponseMessage`). |
|`exception-name`| The full name of the exception assigned to the execution result (`System.InvalidOperationException`). |
|`attempt-number`| The execution attempt number, starting at 0 (0, 1, 2). |
|`attempt-handled`| Indicates if the execution outcome was handled. A handled outcome indicates execution failure and the need for retry (`true`, `false`). |

#### strategy-execution-duration

- Type: *Histogram*
- Unit: *milliseconds*
- Description: Measures the duration and results of resilience strategy executions.

Dimensions:

|Name|Description|
|---| ---|
|`builder-name`| The name of the builder corresponding to the resilience strategy.|
|`builder-instance`| The instance name of the builder corresponding to the resilience strategy.|
|`operation-key`| The operation key associated with the call site. |
|`result-type`| The result type (`string`, `HttpResponseMessage`). |
|`exception-name`| The full name of the exception assigned to the execution result (`System.InvalidOperationException`). |
|`execution-health`| Indicates whether the execution was healthy or not (`Healthy`, `Unhealthy`). |

### Logs

Logs are registered under the `Polly` logger name. Here are some examples of the logs:

``` text
// This log is recorded whenever a resilience event occurs. EventId = 0
Resilience event occurred. EventName: '{EventName}', Source: '{BuilderName}[{BuilderInstance}]/{StrategyType}[{StrategyName}]', Operation Key: '{OperationKey}', Result: '{Result}'
// This log is recorded when a resilience strategy begins executing. EventId = 1
Resilience strategy executing. Source: '{BuilderName}[{BuilderInstance}]', Operation Key: '{OperationKey}', Result Type: '{ResultType}'
// This log is recorded when a resilience strategy finishes execution. EventId = 2
Resilience strategy executed. Source: '{BuilderName}[{BuilderInstance}]', Operation Key: '{OperationKey}', Result Type: '{ResultType}', Result: '{Result}', Execution Health: '{ExecutionHealth}', Execution Time: {ExecutionTime}ms
// This log is recorded upon the completion of every execution attempt. EventId = 3
Execution attempt. Source: '{BuilderName}[{BuilderInstance}]/{StrategyType}[{StrategyName}]', Operation Key: '{OperationKey}', Result: '{Result}', Handled: '{Handled}', Attempt: '{Attempt}', Execution Time: '{ExecutionTimeMs}'
```
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal sealed class TelemetryResilienceStrategy : ResilienceStrategy
ExecutionDuration = ResilienceTelemetryDiagnosticSource.Meter.CreateHistogram<double>(
"strategy-execution-duration",
unit: "ms",
description: "The execution duration and execution result of resilience strategies.");
description: "The execution duration and execution results of resilience strategies.");
}

public Histogram<double> ExecutionDuration { get; }
Expand Down
Loading