<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://thepollyproject.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://thepollyproject.org/" rel="alternate" type="text/html" /><updated>2026-10-12T12:26:01+00:00</updated><id>https://thepollyproject.org/feed.xml</id><title type="html">The Polly Project</title><subtitle>News, releases, and deep dives from the team behind Polly, the .NET resilience and transient-fault-handling library.</subtitle><entry><title type="html">Introducing the Open Source Maintenance Fee for Polly</title><link href="https://thepollyproject.org/2026/07/14/polly-osmf-announcement.html" rel="alternate" type="text/html" title="Introducing the Open Source Maintenance Fee for Polly" /><published>2026-07-14T00:00:00+00:00</published><updated>2026-07-14T00:00:00+00:00</updated><id>https://thepollyproject.org/2026/07/14/polly-osmf-announcement</id><content type="html" xml:base="https://thepollyproject.org/2026/07/14/polly-osmf-announcement.html"><![CDATA[<blockquote class="post-update">
  <p><strong>Update: October 12, 2026</strong></p>

  <p>We’ve heard your questions and want to clarify two points:</p>

  <ul>
    <li><strong>The fee applies only to the next major version of Polly released after November 16, 2026.</strong> Existing versions of Polly are not subject to the fee.</li>
    <li><strong>Only direct references to Polly are subject to the fee.</strong> If Polly is a dependency of a different library, such as <code class="language-plaintext highlighter-rouge">Microsoft.Extensions.Resilience</code> or <code class="language-plaintext highlighter-rouge">Microsoft.Extensions.Http.Resilience</code>, the fee does not apply.</li>
  </ul>
</blockquote>

<p><img src="/assets/images/2026/07/polly+osmf.png" alt="Polly and OSMF" /></p>

<p>For over a decade, Polly has helped .NET developers build resilient applications through strategies like Retry, Circuit Breaker, Hedging, Timeout, Rate Limiter, and Fallback. Today Polly is used by teams around the world, with more than 14,000 stars on GitHub and over 2 billion downloads across its packages on NuGet.org.</p>

<p>That reach is something we’re proud of. It also comes with a cost that isn’t always visible: the ongoing work of keeping the project healthy. Today we’re announcing that Polly is adopting the <a href="https://opensourcemaintenancefee.org">Open Source Maintenance Fee</a> (OSMF), and we want to explain what that means, why we’re doing it, and what it changes (spoiler: for most people, nothing).</p>

<h2 id="the-part-people-dont-see">The part people don’t see</h2>

<p>Writing the library was the fun part. Keeping it alive is the ongoing part. Behind every release is a steady stream of work that never really ends: triaging issues, answering questions, reviewing pull requests, updating dependencies, tracking and responding to security reports, renewing signing certificates, keeping build and CI pipelines green, dealing with spam in our discussion forums, and publishing new releases.</p>

<p>None of that is glamorous, and none of it is free. It takes real time and sustained attention from real people. That work is what lets you depend on Polly in production with confidence.</p>

<h2 id="what-the-open-source-maintenance-fee-is">What the Open Source Maintenance Fee is</h2>

<p>The <a href="https://opensourcemaintenancefee.org">Open Source Maintenance Fee</a> is a simple, sensible idea: the source code stays free and open, but organizations that rely on the project’s maintained releases to generate revenue help fund the people maintaining it.</p>

<p>A few things are worth being clear about, because the OSMF is often misunderstood:</p>

<ul>
  <li><strong>The source code remains free and open.</strong> Polly stays under its existing open source license. Nothing about your right to read, fork, build from, and contribute to the source changes.</li>
  <li><strong>It is not a license fee and not a support contract.</strong> Paying the fee doesn’t buy you an SLA, guaranteed bug fixes, or priority support. It funds the general upkeep that keeps the project running for everyone.</li>
  <li><strong>It’s a small, predictable cost</strong> that creates a direct feedback loop between the organizations that benefit from Polly and the people who keep it maintained.</li>
</ul>

<p>You can read more about the philosophy behind it on the <a href="https://opensourcemaintenancefee.org">OSMF website</a>.</p>

<h2 id="how-this-applies-to-polly">How this applies to Polly</h2>

<p>Here’s the specific arrangement for Polly.</p>

<p>The Maintenance Fee is <strong>US $20 per month</strong> and applies to any company that earns at least <strong>US $20,000</strong> from at least one product or project that uses Polly.</p>

<p>A few details that we’re often asked about:</p>

<ul>
  <li><strong>It’s per organization, not per project.</strong> If you have ten products that use Polly, you pay the fee once. It doesn’t matter how many of your projects depend on the library.</li>
  <li><strong>It’s tied to revenue, not to whether your product is paid.</strong> If a product that uses Polly is offered for free but still generates revenue for your organization (through advertising, paid services, lead generation, and so on), the fee applies.</li>
  <li><strong>It applies only to direct references to Polly.</strong> If Polly is a dependency of a different library, such as <code class="language-plaintext highlighter-rouge">Microsoft.Extensions.Resilience</code> or <code class="language-plaintext highlighter-rouge">Microsoft.Extensions.Http.Resilience</code>, the fee does not apply.</li>
</ul>

<p>If your organization is below the revenue threshold, an individual, a hobbyist, a student, or a nonprofit not generating revenue from Polly, <strong>you owe nothing</strong>. Polly remains free for you exactly as it is today.</p>

<h2 id="what-is-not-changing">What is <em>not</em> changing</h2>

<p>We want to be emphatic about this, because announcements like this one understandably make people nervous:</p>

<ul>
  <li>Polly’s license is <strong>not</strong> changing.</li>
  <li>The source code is <strong>not</strong> moving behind a paywall.</li>
  <li>Free users, contributors, and small projects are <strong>not</strong> being asked to pay.</li>
  <li>Your existing installations will <strong>not</strong> stop working.</li>
</ul>

<p>The library you rely on stays exactly where it is. What we’re adding is a way for the companies that profit from Polly to help sustain it.</p>

<h2 id="when-this-takes-effect">When this takes effect</h2>

<p>We believe in giving our community plenty of time to review this, ask questions, and plan accordingly. So we’re announcing this now, but we will not begin requesting payment from qualifying companies until <strong>November 16, 2026</strong>, roughly four months from today. The fee will apply only to the next major version of Polly released after that date; existing versions of Polly are not subject to it.</p>

<p>Between now and then, nothing is required of anyone. We’ll use this window to answer questions, refine the details, and make the process of paying as painless as possible for the organizations it applies to.</p>

<h2 id="how-to-pay-when-the-time-comes">How to pay when the time comes</h2>

<p>When enforcement begins, qualifying organizations will be able to pay the Maintenance Fee through GitHub Sponsors. We’ll publish the exact sponsorship tier and step-by-step instructions in our README and in a follow-up post well before the November date, so there will be a clear, simple path to becoming a supporter.</p>

<h2 id="why-were-asking">Why we’re asking</h2>

<p>Polly is a member of the <a href="https://www.dotnetfoundation.org/">.NET Foundation</a> and has been generously supported by sponsors including the .NET on AWS Open Source Software Fund, Microsoft’s Free and Open Source Software Fund, and GitHub’s Secure Open Source Fund. We’re grateful for that support, and it has made a real difference.</p>

<p>But grants and donations, by their nature, are unpredictable. They’re wonderful when they arrive, but you can’t build a maintenance roadmap around a bonus that may or may not come next year. The Maintenance Fee gives us something different: a steady, dependable foundation that lets us plan, keep the project secure and current, and continue serving the community that depends on Polly.</p>

<p>If your organization relies on Polly to help run its business, this is a direct and meaningful way to keep the project you depend on healthy for years to come.</p>

<h2 id="questions-and-feedback">Questions and feedback</h2>

<p>We know a change like this raises questions, and we want to hear them. Please share your thoughts and ask anything in our <a href="https://github.com/App-vNext/Polly/discussions">GitHub Discussions</a>, and take a look at the <a href="https://opensourcemaintenancefee.org/consumers/faq/">OSMF FAQ</a>, which answers many common questions in detail.</p>

<p>Thank you for being part of the Polly community. We’re looking forward to keeping the project strong, together.</p>

<p>The Polly Team</p>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/joel-hulen.png&quot;, &quot;website&quot;=&gt;&quot;https://www.linkedin.com/in/joel-hulen-ba76b73&quot;, &quot;bio&quot;=&gt;&quot;Joel Hulen is the lead Polly project owner, a senior member of the App vNext team, and has been developing software for over 33 years. He&apos;s passionate about development and fostering open source communities.&quot;}</name></author><summary type="html"><![CDATA[Update: October 12, 2026 We’ve heard your questions and want to clarify two points: The fee applies only to the next major version of Polly released after November 16, 2026. Existing versions of Polly are not subject to the fee. Only direct references to Polly are subject to the fee. If Polly is a dependency of a different library, such as Microsoft.Extensions.Resilience or Microsoft.Extensions.Http.Resilience, the fee does not apply.]]></summary></entry><entry><title type="html">Polly v8 officially released</title><link href="https://thepollyproject.org/2023/09/28/polly-v8-officially-released.html" rel="alternate" type="text/html" title="Polly v8 officially released" /><published>2023-09-28T00:00:00+00:00</published><updated>2023-09-28T00:00:00+00:00</updated><id>https://thepollyproject.org/2023/09/28/polly-v8-officially-released</id><content type="html" xml:base="https://thepollyproject.org/2023/09/28/polly-v8-officially-released.html"><![CDATA[<p><img src="/assets/images/2023/09/Polly-v8.png" alt="Polly v8 officially released" /></p>

<p>After months of continuous development, Polly v8 is finally here! In our <a href="/2023/03/03/we-want-your-feedback-introducing-polly-v8.html">v8 announcement post</a>, we discussed the background of the Polly project and what motivated us to completely redesign the library with a hyper-focus on performance. We were very fortunate to have top-notch developers from Microsoft do the bulk of the design and implementation of this release. We could not have finished v8 anywhere close to the time it took if we didn’t have their help.</p>

<p>Polly’s latest release brings an array of exciting enhancements that will supercharge your resilience strategies and hopefully boost your application’s performance and reliability. In this post, we’ll discuss key Polly v7 and v8 differences that highlight v8 improvements. So, let’s dive in! 🏊‍♂️</p>

<h2 id="introduction-to-polly-v8">Introduction to Polly v8</h2>

<p>Polly v8 has landed with a bang, bringing major improvements and supporting all the same scenarios as its predecessor but with more speed and flexibility. It has been re-engineered to provide more power and ease of use, ensuring a robust approach to handling your applications’ retries, timeouts, and other resilience strategies.</p>

<blockquote>
  <p><strong>Important note:</strong> To use Polly v8, you need to install the new <a href="https://www.nuget.org/packages/Polly.Core/">Polly.Core</a> NuGet package. If you are not ready to transition existing resilience policies to v8, the v7 API is still available and fully supported even when using the v8 version by referencing the <a href="https://www.nuget.org/packages/Polly">Polly</a> package.</p>
</blockquote>

<p>One of the significant improvements in v8 is <strong>improved speed</strong> and resource efficiency. With its significant performance enhancements and zero-allocation APIs, it’s tailored for advanced and demanding use cases. We now have a <a href="https://github.com/App-vNext/Polly/tree/main/bench">bench</a> folder in the repo that lets you run benchmark tests. We also store the latest benchmark results here so you can view the speed differences within the different strategies.</p>

<p>As we like to say, Polly’s resilience strategies should cost next to nothing when your application is healthy and only add some cost when it steps in to handle failures.</p>

<h3 id="primary-differences-️️">Primary differences 🕵️‍♂️</h3>

<p>There were many outstanding issues that we addressed in this version of Polly. Some items, as well as the performance improvements, required a complete refactoring of the framework, which is a daunting proposition when your library has <a href="https://www.nuget.org/packages/Polly/">almost 500 million downloads</a>. Because of this refactoring, there are several important differences we’d like to highlight.</p>

<h4 id="from-policy-to-strategy">From policy to strategy</h4>

<p><strong>Policy</strong> is now renamed to <a href="https://www.pollydocs.org/strategies/index.html"><strong>strategy</strong></a>. In the world of Polly v8, we talk about resilience strategies rather than policies for retries, timeouts, and the like.</p>

<h4 id="enter-the-resilience-pipelines">Enter the Resilience Pipelines</h4>

<p>Polly v8 introduces the concept of <a href="https://www.pollydocs.org/pipelines/index.html">resilience pipelines</a>, a powerful tool that blends one or more resilience strategies. This new API foundation echoes the Policy Wrap of previous versions but is now integrated seamlessly into the core API. All strategies start with a pipeline.</p>

<h4 id="unified-sync-and-async-flows">Unified sync and async flows</h4>

<p>No more juggling between various interfaces. Polly v8 has unified interfaces like <code class="language-plaintext highlighter-rouge">IAsyncPolicy</code>, <code class="language-plaintext highlighter-rouge">ISyncPolicy</code>, and others under the banner of <code class="language-plaintext highlighter-rouge">ResiliencePipeline</code> and <code class="language-plaintext highlighter-rouge">ResiliencePipeline&lt;T&gt;</code>, effortlessly supporting both synchronous and asynchronous execution flows.</p>

<h4 id="native-async-support">Native async support</h4>

<p>Polly v8 is designed with native asynchronous support from the get-go, enabling smoother and more efficient async operations.</p>

<h4 id="no-more-static-apis">No more static APIs</h4>

<p>Say goodbye to static APIs with Polly v8. This change enhances testability and extensibility while preserving simplicity and ease of use.</p>

<h4 id="flexible-configuration">Flexible configuration</h4>

<p>Polly v8 adopts an options-based configuration for individual resilience strategies, offering more flexibility and improving maintainability and extensibility.</p>

<h4 id="telemetry-at-your-fingertips">Telemetry at your fingertips</h4>

<p><a href="https://www.pollydocs.org/advanced/telemetry.html">Built-in telemetry support</a> is now a part of Polly v8, giving you insights and analytics right out of the box. All built-in resilience strategies can generate telemetry data.</p>

<h2 id="install-v8-today">Install v8 today</h2>

<p>Transitioning to <a href="https://www.nuget.org/packages/Polly.Core/">Polly v8</a> is a breeze. Embrace the change in terminology, adapt to the resilience pipelines, and enjoy the benefits of a more modern Polly library. Be sure to check out <a href="https://www.pollydocs.org/">pollydocs.org</a> for the latest documentation. As always, feel free to <a href="https://github.com/App-vNext/Polly/issues">post GitHub issues</a> if you have questions or feature suggestions. We’ll do our best to address them as we continue to nurture this project.</p>

<p>Thank you for being a part of our community, and I wish you all the best!</p>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/joel-hulen.png&quot;, &quot;website&quot;=&gt;&quot;https://www.linkedin.com/in/joel-hulen-ba76b73&quot;, &quot;bio&quot;=&gt;&quot;Joel Hulen is the lead Polly project owner, a senior member of the App vNext team, and has been developing software for over 33 years. He&apos;s passionate about development and fostering open source communities.&quot;}</name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">We want your feedback! Introducing Polly v8</title><link href="https://thepollyproject.org/2023/03/03/we-want-your-feedback-introducing-polly-v8.html" rel="alternate" type="text/html" title="We want your feedback! Introducing Polly v8" /><published>2023-03-03T00:00:00+00:00</published><updated>2023-03-03T00:00:00+00:00</updated><id>https://thepollyproject.org/2023/03/03/we-want-your-feedback-introducing-polly-v8</id><content type="html" xml:base="https://thepollyproject.org/2023/03/03/we-want-your-feedback-introducing-polly-v8.html"><![CDATA[<p><img src="/assets/images/2023/03/Polly-v8.png" alt="We want your feedback! Introducing Polly v8" /></p>
<blockquote>
  <p><strong>UPDATE: May 26, 2023</strong></p>

  <p>We have issued a new pull request (<a href="https://github.com/App-vNext/Polly/pull/1233">Polly V8: Public API Review #1233</a>) to introduce the v8 API to the public. <strong>We would love your feedback!</strong> Help shape the API ahead of a tentative June release.</p>
</blockquote>

<p>There is no question that the Polly library has had a big impact on the .NET community in providing useful resilience and transient fault handling policies in an accessible way to <a href="https://www.nuget.org/packages/Polly">millions of projects</a>. Given its widespread use and popularity, we are responsible as maintainers for ensuring the library remains relevant, useful, and highly performant. The last thing we want is for you to invest countless hours designing and crafting an application, with painstaking attention to detail and performance and big plans for scaling at a global level, just to be hampered by a dependency that cannot keep up with those high levels of demand.</p>

<h2 id="what-led-us-here">What led us here?</h2>

<p>Back in 2015, Polly joined the .NET Foundation, which helped us align with Microsoft and the broader .NET community. We wanted to make sure we weren’t progressing in a vacuum.</p>

<p>In 2017, we started working with Glenn Condron and Ryan Nowak from the .NET team via an introduction by Jon Galloway to collaborate on extending the brand new <code class="language-plaintext highlighter-rouge">HttpClientFactory</code> to add Polly as an optional dependency package that lets users easily <a href="https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory">add resilience policies to <code class="language-plaintext highlighter-rouge">HTTPClient</code> requests</a> beginning with ASP.NET Core 2.1. I believe that being a member of the .NET Foundation led to this collaboration with the .NET team.</p>

<p>In early 2019, we recognized that many community members were working on interesting Polly-adjacent projects that added new capabilities to the core library. We wanted to ensure these projects enjoyed the visibility they deserved while providing a space for contributors to collaborate on these projects. To facilitate and encourage this community engagement, we created <a href="https://github.com/orgs/Polly-Contrib/repositories?type=all">Polly.Contrib</a>, out of which many great projects have emerged, from caching, wait-and-retry helper methods, chaos-engineering + fault-injection, and many more. <em>Be sure to watch this space</em>. You may see some new repos for extension packages during the transition to the new SDK version.</p>

<h2 id="the-new-api">The new API</h2>

<p>Fast forward to today, we are once again collaborating with the .NET team to release version 8. Immo Landwerth reached out to our team in December 2022 to discuss significant changes and a proposed solution developed by his team. Candidly, there have been minimal significant updates to the Polly library for the past couple of years, despite excellent contributions by our core team members, Martin Costello and Simon Cropp, and several <a href="https://github.com/App-vNext/Polly/pulls">community members</a>. Meanwhile, the project carries a non-trivial amount of technical debt, including a lack of cancelation tokens in many operations, a lack of full async support for all callbacks (including the circuit breaker), and open performance issues (<a href="https://github.com/App-vNext/Polly/issues/271">#271</a>, <a href="https://github.com/App-vNext/Polly/issues/845">#845</a>, and <a href="https://github.com/App-vNext/Polly/issues/955">#955</a>). As you can imagine, making significant architectural changes to a popular library carries some risk.</p>

<blockquote>
  <p>Polly’s resilience strategies should cost next to nothing when your application is healthy and only add some cost when it steps in to handle failures.</p>
</blockquote>

<p>To address these issues, the .NET team built a prototype version of Polly that simplifies Polly’s API surface area with a single <code class="language-plaintext highlighter-rouge">IResilienceStrategy</code> interface responsible for executing all Polly scenarios and addresses the performance issues with excellent results. In fact, in early tests, the new changes resulted in reduced CPU overhead by 80%. Additionally, the POC significantly reduced allocations by large factors. All of these gains appear before a concerted effort to optimize the POC.</p>

<p>Here is a snapshot of the performance improvements. You can <a href="https://github.com/App-vNext/Polly/tree/v8-poc/src/Polly.Strategies.Bench">view more benchmark results</a> in the <code class="language-plaintext highlighter-rouge">v8-poc</code> branch:</p>

<p><img src="/assets/images/v8-performance.png" alt="v8 vs. v7 performance comparison." /></p>

<p>The new functionality will be exposed through a novel foundational API. New or updated applications will be able to take advantage of this new API to achieve the highest level of performance. The existing v7 Polly API will be reimplemented on top of this new API, ensuring compatibility and full interoperability for existing applications.</p>

<p>Martin Tomka, who authored the v8 POC, wrote a <a href="https://github.com/App-vNext/Polly/blob/v8-poc/docs/Polly-V8.md">document that explains the changes in more detail</a>.</p>

<h2 id="so-whats-the-catch">So, what’s the catch?</h2>

<p>You might be thinking that all of this sounds promising as a compelling way forward to revitalize Polly and address performance issues and technical debt, but how do we approach this in a way that preserves backward compatibility and allows us to reuse Polly policies from the community? We have discussed this at length with our Microsoft colleagues. In short, we will make our best effort to bridge the capabilities of the new API with the legacy (current) Polly policies. This way, your investments in custom Polly policies can be used in the new design. We aim to minimize disruptions as much as possible. We cannot make any guarantees since there may be edge cases, but that is the beauty of open-source projects; all work is performed in the clear so that you can try early releases in your environment. If you find any issues, let us know, or submit a PR! We believe that by adopting the new API in v8 and using the legacy policies, in the worst case, the performance will be the same as with v7 packages. If you adapt your code to take full advantage of the new API, then you will realize those gains and the simplicity of the new API layer.</p>

<h2 id="whats-next">What’s next?</h2>

<p>We have <a href="https://github.com/App-vNext/Polly/issues/1048">created a new GitHub issue</a> for Polly v8. Please use this to raise any issues, concerns, or ideas with the team. As a member of the Polly community, your feedback is very important to us. You can check out the <code class="language-plaintext highlighter-rouge">v8-poc</code> <a href="https://github.com/App-vNext/Polly/tree/v8-poc">branch</a> to review the code in progress and take it for a spin. We have also created a <a href="https://github.com/orgs/App-vNext/projects/1/views/1">GitHub project</a> where we will work in the open by managing tasks associated with our work on the new API. If you want to create new GitHub issues related to v8, please tag it with the <a href="https://github.com/App-vNext/Polly/labels/v8">v8 label</a> for visibility.</p>

<p>Thank you once again for being a valued member of the Polly community. I am excited about our future, and I hope you are too!</p>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/joel-hulen.png&quot;, &quot;website&quot;=&gt;&quot;https://www.linkedin.com/in/joel-hulen-ba76b73&quot;, &quot;bio&quot;=&gt;&quot;Joel Hulen is the lead Polly project owner, a senior member of the App vNext team, and has been developing software for over 33 years. He&apos;s passionate about development and fostering open source communities.&quot;}</name></author><summary type="html"><![CDATA[UPDATE: May 26, 2023 We have issued a new pull request (Polly V8: Public API Review #1233) to introduce the v8 API to the public. We would love your feedback! Help shape the API ahead of a tentative June release.]]></summary></entry><entry><title type="html">Simmy and Azure App Configuration</title><link href="https://thepollyproject.org/2019/08/13/simmy-and-azure-app-configuration.html" rel="alternate" type="text/html" title="Simmy and Azure App Configuration" /><published>2019-08-13T00:00:00+00:00</published><updated>2019-08-13T00:00:00+00:00</updated><id>https://thepollyproject.org/2019/08/13/simmy-and-azure-app-configuration</id><content type="html" xml:base="https://thepollyproject.org/2019/08/13/simmy-and-azure-app-configuration.html"><![CDATA[<blockquote>
  <p>This is a cross-post from <a href="http://elvanydev.com/simmy-with-azure-app-configuration/">elvanydev.com</a>.</p>
</blockquote>

<p>In the <a href="http://elvanydev.com/chaos-injection-with-simmy/">latest post</a>, I introduced you <a href="https://github.com/Polly-Contrib/Simmy">Simmy</a> and we saw all the benefits of <a href="http://principlesofchaos.org/">chaos engineering</a> and how Simmy helps us making chaos in our systems injecting <a href="https://github.com/Polly-Contrib/Simmy#Inject-fault">faults</a>, <a href="https://github.com/Polly-Contrib/Simmy#inject-latency">latency</a> or custom <a href="https://github.com/Polly-Contrib/Simmy#inject-behavior">behavior</a> in order to make sure that our resilience strategies are correctly implemented and guarantee that our system is able to withstand turbulence conditions in a production environment. Also, I walked you through an <a href="http://elvanydev.com/chaos-injection-with-simmy/#hands-on-lab">example</a> using Simmy in a distributed architecture, where one of the pieces that we had was a <a href="http://elvanydev.com/chaos-injection-with-simmy/#chaos-settings-microservice">chaos settings microservice</a> which took care of storing and getting the chaos settings, however we found that the approach has a downside which we should consider: it adds extra latency since it has to retrieve the chaos settings from the <a href="http://elvanydev.com/chaos-injection-with-simmy/#how-does-it-get-the-chaos-settings">API</a> in every request. That’s why in this post we’re going to see how we can manage our chaos settings using <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview">Azure App Configuration</a> avoiding to inject extra latency or additional overhead to our system.</p>

<h2 id="what-is-azure-app-configuration">What is Azure App Configuration?</h2>

<p><a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview">Azure App Configuration</a> is a fully managed service offered by <a href="https://azure.microsoft.com/en-us/">Microsoft Azure</a> to centralize the settings of your applications separately from your code, which is very convenient in distributed architectures where you have deployed your services across Clusters/VM’s/Containers in the cloud. Azure App Configuration also provides <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-feature-flag-aspnet-core">feature management</a> capabilities, but in this example, we’re going to focus only on application settings management.</p>

<p>Azure App Configuration provides several clients, in our case we’re going to use the <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-aspnet-core-app">ASP.NET Core</a> one, which at the end of the day is nothing but an implementation of <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.2">Configuration Provider</a>.</p>

<blockquote>
  <p>Azure App Configuration is currently in public preview and it’s free during the preview period.</p>
</blockquote>

<h2 id="create-an-app-configuration-store">Create an app configuration store</h2>

<p>The first thing we need to do is <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-aspnet-core-app#create-an-app-configuration-store">provisioning</a> our App Configuration store, for which you need an Azure subscription, if you don’t have one, you can create it <a href="https://azure.microsoft.com/en-us/free/">for free</a>.</p>

<p>The second step is to create the settings. I think using the <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/howto-import-export-data">import tool</a> from the portal is the easiest way to do that the first time. It will allow you to import the chaos settings from a <code class="language-plaintext highlighter-rouge">json</code> file (among other options). After that, you should be able to see the chaos settings from the Azure Portal:</p>

<p><img src="https://raw.githubusercontent.com/vany0114/vany0114.github.io/master/images/azure-app-configuration-settings.png" alt="alt" /></p>

<blockquote>
  <p>If you don’t want to import the settings, you can still use the <a href="#the-new-chaos-repository">Chaos UI</a>.</p>
</blockquote>

<h2 id="the-refactor">The Refactor</h2>

<p>I only updated a couple of things in order to introduce Azure App Configuration to our solution (that’s a good sign that our design it’s scalable, maintainable and good enough :smile:), so, let’s start checking how the new component looks like in our architecture and who interacts with.</p>

<p><img src="https://raw.githubusercontent.com/vany0114/vany0114.github.io/master/images/Simmy-with-AppConfiguration.png" alt="alt" /></p>

<h3 id="setting-up-azure-app-configuration">Setting up Azure App Configuration</h3>

<p>As I mentioned before, Azure App Configuration for ASP.NET Core, implements a <em>Configuration Provider</em>, which in this case it will manage the settings using our configuration store created previously in Azure. Let’s see how to do so.</p>

<h4 id="web-projects">Web Projects</h4>

<p>First of all, we need to reference the <code class="language-plaintext highlighter-rouge">Microsoft.Azure.AppConfiguration.AspNetCore</code> package in our web projects, which are: <code class="language-plaintext highlighter-rouge">Duber.WebSite</code>, <code class="language-plaintext highlighter-rouge">Duber.Trip.API</code> and <code class="language-plaintext highlighter-rouge">Duber.Invoice.API</code>, then we need to tell them that we want to get our chaos settings from <em>Azure App Configuration</em> instead of the <code class="language-plaintext highlighter-rouge">appsettings.json</code>, so we need to update our <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/f7e1304722d83a729660ca8785c9ed0e1d31f3b0/src/Web/Duber.WebSite/Program.cs#L49">Program.cs</a> like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public static IWebHost BuildWebHost(string[] args) =&gt;  
    WebHost.CreateDefaultBuilder(args)
        ...
        .ConfigureAppConfiguration((builderContext, config) =&gt;
        {
            var settings = config.Build();
            if (settings.GetValue&lt;bool&gt;("UseAzureAppConfiguration"))
            {
                config.AddAzureAppConfiguration(options =&gt;
                {
                    options.Connect(settings["ConnectionStrings:AppConfig"])
                        .ConfigureRefresh(refresh =&gt;
                        {
                            refresh.Register("GeneralChaosSetting:Sentinel", refreshAll: true);
                            refresh.SetCacheExpiration(TimeSpan.FromSeconds(5));
                        });
                });
            }
        })
        ...
        .Build();
</code></pre></div></div>

<p>We’re using a flag called <code class="language-plaintext highlighter-rouge">UseAzureAppConfiguration</code> which allows the system to identify whether or not to use <em>Azure App Configuration</em> through the method <code class="language-plaintext highlighter-rouge">AddAzureAppConfiguration</code> to get the chaos settings, or use the chaos seettings microservice instead. (That flag is stored in the <code class="language-plaintext highlighter-rouge">appsettings.json</code> file).</p>

<h5 id="the-connection">The connection</h5>

<p>There are two ways to connect to our app configuration store, we can use either <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/howto-integrate-azure-managed-service-identity">Managed Identity</a> or a connection string. In this example we’re using the second one, and as you can see we’re passing the connection string named <code class="language-plaintext highlighter-rouge">AppConfig</code> which is stored into the <code class="language-plaintext highlighter-rouge">appsettings.json</code> file as well.</p>

<h5 id="refreshing-the-settings">Refreshing the settings</h5>

<p>Another great advantage of Azure App Configuration is the ability to refresh the settings when they have changed. In terms of configuration, we can do that through the method <code class="language-plaintext highlighter-rouge">ConfigureRefresh</code>. We can tell it which settings we want to refresh once they change using the <code class="language-plaintext highlighter-rouge">Register</code> method, but what happens when we need to refresh a lot of settings? or even a more complicated scenario, when the settings we need to refresh are dynamic? first, we don’t want to hard-code a lot of settings individually because when we have a new one it means we need to register it, then we’ll need to deploy again, besides in a <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/5e7c1b36181ee04e887962aa40a88f8773caa35c/src/Infrastructure/Duber.Infrastructure.Chaos/GeneralChaosSetting.cs#L42">dynamic scenario</a> you don’t have a fixed number of settings.</p>

<p>So, to achieve that, we need to use a “sentinel” key-value in the app configuration and trigger a reload for all of our configuration when that value changes. That’s why we set the <code class="language-plaintext highlighter-rouge">refreshAll</code> parameter to <code class="language-plaintext highlighter-rouge">true</code>. We need to update the sentinel whenever we want the app to pick up the changes that we made in the app configuration. The sentinel could be anything, just touching that value in app configuration will trigger the refresh for the rest of the settings. The app will see that it got updated and doesn’t need to worry about the actual value. (Although, it will get the new value for the sentinel in case we use one whose value you do care about)</p>

<h5 id="caching-the-settings">Caching the settings</h5>

<p>Azure App Configuration allows us to cache the settings as well, the default value is 30 seconds if you don’t specify it, but you can set the cache expiration as you need it. The minimum value is one second.</p>

<h5 id="azure-app-configuration-middleware">Azure App Configuration Middleware</h5>

<p>The other little change we need to do in our web projects is over the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/f7e1304722d83a729660ca8785c9ed0e1d31f3b0/src/Web/Duber.WebSite/Startup.cs#L96">Startup.cs</a> file. It’s quite easy, we only need to use the azure app configuration middleware:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>if (Configuration.GetValue&lt;bool&gt;("UseAzureAppConfiguration"))  
    app.UseAzureAppConfiguration();
</code></pre></div></div>

<h4 id="chaos-settings-factory">Chaos Settings Factory</h4>

<p>The second change I made (and the most important one), was over the <em>Chaos Settings Factory</em> which takes care of getting the chaos settings, resolving the <em>how</em> at run-time. So, in our <a href="http://elvanydev.com/chaos-injection-with-simmy/#how-does-it-get-the-chaos-settings">original implementation</a>, we returned a <code class="language-plaintext highlighter-rouge">Task&lt;GeneralChaosSetting&gt;</code> which was resolved by the <a href="http://elvanydev.com/chaos-injection-with-simmy/#chaos-settings-microservice">Chaos API</a>.</p>

<p>Now, we are merely getting the chaos settings from <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/index?view=aspnetcore-2.2">App Configuration</a>, in this case using <em>Azure App Configuration</em> as Configuration Provider. Having that said, it’s just a matter of using the right <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.2">Option pattern</a>, in our case, we want to refresh the configuration every time it changes, so, we will use the <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.2#reload-configuration-data-with-ioptionssnapshot">IOptionsSnapshot</a> approach.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public static IServiceCollection AddChaosApiHttpClient(this IServiceCollection services, IConfiguration configuration)  
{
    ...
    if (configuration.GetValue&lt;bool&gt;("UseAzureAppConfiguration"))
        services.Configure&lt;GeneralChaosSetting&gt;(configuration.GetSection("GeneralChaosSetting"));

    services.AddScoped&lt;Lazy&lt;Task&lt;GeneralChaosSetting&gt;&gt;&gt;(sp =&gt;
    {
        if (configuration.GetValue&lt;bool&gt;("UseAzureAppConfiguration"))
        {
            var chaosSettings = sp.GetRequiredService&lt;IOptionsSnapshot&lt;GeneralChaosSetting&gt;&gt;();
            return new Lazy&lt;Task&lt;GeneralChaosSetting&gt;&gt;(() =&gt; Task.FromResult(chaosSettings.Value), LazyThreadSafetyMode.None);
        }
        ...
    });

    return services;
}
</code></pre></div></div>

<p>As you can see, we’re configuring the <code class="language-plaintext highlighter-rouge">GeneralChaosSetting</code> options from the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/f7e1304722d83a729660ca8785c9ed0e1d31f3b0/src/Infrastructure/Duber.Infrastructure.Chaos/IoC/ServiceCollectionExtensions.cs#L21">GeneralChaosSetting</a> configuration section, then we’re just resolving the <code class="language-plaintext highlighter-rouge">Task&lt;GeneralChaosSetting&gt;</code> just returning the <code class="language-plaintext highlighter-rouge">IOptionsSnapshot&lt;GeneralChaosSetting&gt;</code> <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/f7e1304722d83a729660ca8785c9ed0e1d31f3b0/src/Infrastructure/Duber.Infrastructure.Chaos/IoC/ServiceCollectionExtensions.cs#L28">object’s value</a> directly. It means that we’re getting the chaos settings from the app configuration in every request rather than getting them from the <em>Chaos API</em>, which will help us to avoid introducing extra latency.</p>

<p>But, how Azure App Configuration does that magic? I was speaking with <a href="https://github.com/jimmyca15">Jimmy Campbell</a> who is part of the Azure App Configuration team, and he told me that in the web scenario, one thing that they found is that polling on a timer was not exactly the best solution (when the <code class="language-plaintext highlighter-rouge">WatchAndReloadAll</code> method existed in the very beginning of Azure App Configuration), often times this can lead to inactive apps putting load on the app configuration instance as well as extraneous Network and CPU usage on the client. Then, they updated the web app scenario to be smart and reload when the app gets a request (if a refresh is scheduled), but here is the thing, it performs the refresh in a <a href="https://www.enterpriseintegrationpatterns.com/patterns/conversation/FireAndForget.html">fire-and-forget</a> manner, which means we don’t need to wait for a response thus it won’t add extra latency!</p>

<blockquote>
  <p>Azure App Configuration isn’t Open Source yet.</p>
</blockquote>

<p>Up to this point, we’ve integrated <em>Azure App Configuration</em> to our solution. It wasn’t a big deal, right? So, you can just hit F5 and try it out, and see how it gets and refreshes the settings from the cloud!</p>

<h4 id="the-new-chaos-repository">The new Chaos Repository</h4>

<p>Only the changes mentioned above were required to introduce Azure App Configuration in our solution, however, I decided to make a new <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/master/src/Application/Duber.Chaos.API/Infrastructure/Repository/IChaosRepository.cs">IChaosRepository</a> implementation in order to keep our <a href="http://elvanydev.com/chaos-injection-with-simmy/#chaos-settings-microservice">Chaos API</a> working thus our <a href="http://elvanydev.com/chaos-injection-with-simmy/#the-chaos-ui">Chaos UI</a> too. So I created the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/master/src/Application/Duber.Chaos.API/Infrastructure/Repository/AzureAppConfigurationRepository.cs">AzureAppConfigurationRepository</a> which basically wraps the <a href="https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/appconfiguration/Azure.ApplicationModel.Configuration">Azure App Configuration SDK</a>.</p>

<p>Notice that in the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/5e7c1b36181ee04e887962aa40a88f8773caa35c/src/Application/Duber.Chaos.API/Infrastructure/Repository/AzureConfigurationAppRepository.cs#L33">GetChaosSettingsAsync</a> we’re merely returning the <code class="language-plaintext highlighter-rouge">IOptionsSnapshot&lt;GeneralChaosSetting&gt;</code> object’s value which we’re injecting into the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/5e7c1b36181ee04e887962aa40a88f8773caa35c/src/Application/Duber.Chaos.API/Infrastructure/Repository/AzureConfigurationAppRepository.cs#L27">constructor</a>.</p>

<p>Also, notice the last thing we do in the <code class="language-plaintext highlighter-rouge">UpdateChaosSettings</code> method, is updating the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/5e7c1b36181ee04e887962aa40a88f8773caa35c/src/Application/Duber.Chaos.API/Infrastructure/Repository/AzureConfigurationAppRepository.cs#L67">Sentinel</a> in order to trigger the refresh for all the settings.</p>

<blockquote>
  <p>All the dirty code related to <a href="https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/reflection">reflection</a> into that repository is due to <em>Azure App Configuration</em> not allowing you to set/delete in batch or in a <em>Generic</em> way just passing an object, that’s why we need to set/delete every setting one by one.</p>
</blockquote>

<h2 id="wrapping-up">Wrapping up</h2>

<p>So far we’ve seen two different approaches to manage our chaos settings, using <a href="http://elvanydev.com/chaos-injection-with-simmy/#chaos-settings-microservice">our own chaos settings microservice</a> and the one we described in this post using <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview">Azure App Configuration</a>, but you might use other sources to manage the chaos settings: a relational/NoSQL database or even the regular way using a configuration file, etc; whatever makes more sense for you in the context of your project/application. The important thing here is what we’ve seen about how powerful <a href="https://github.com/Polly-Contrib/Simmy">Simmy</a> is when working together with <a href="https://github.com/App-vNext/Polly">Polly</a>, and how you can use a <a href="https://github.com/Polly-Contrib/Simmy#context-driven-behaviour">Context-driven behavior</a> to control the chaos injected in a dynamic and targeted manner.</p>

<p>Personally I would take advantage of both approaches, taking the best of both worlds, for example, I’d still use the <em>Chaos Settings API</em> to automate the chaos injection not only through the <a href="http://elvanydev.com/chaos-injection-with-simmy/#watchmonkey">WatchMonkey</a> but through the deployments using <a href="https://azure.microsoft.com/es-es/services/devops/">Azure DevOps</a>, or another DevOps tool like <a href="https://octopus.com/">Octopus</a>, <a href="https://www.jetbrains.com/teamcity/">TeamCity</a>, etc; to enable the automatic chaos after a release as we mentioned in the previous post. Besides to be used for the <a href="http://elvanydev.com/chaos-injection-with-simmy/#the-chaos-ui">Chaos UI</a> mostly for write operations. On the other hand, I’d use <em>Azure App Configuration</em> from the clients interested to get the chaos settings to inject chaos at some point in time, in our case on the web site and microservices.</p>

<p>I encourage you all to start making experiments using Simmy (if you haven’t started already) and see what is the approach that works better for you, or even to try out your own approaches, we would love to hear about that. We hope Simmy will continue growing with the help and adoption of the community, meanwhile stay tuned because we’re working on enhancements and new features! :monkey_face:</p>

<blockquote>
  <p>Take a look at the whole implementation on my GitHub repo: <a href="https://github.com/vany0114/chaos-injection-using-simmy">https://github.com/vany0114/chaos-injection-using-simmy</a></p>
</blockquote>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/geovanny-alzate-sandoval.jpg&quot;, &quot;website&quot;=&gt;&quot;http://elvanydev.com/&quot;, &quot;bio&quot;=&gt;&quot;Geovanny loves contributing to the community and write on his blog. He&apos;s also Simmy co-author/lead contributor and co-organizer of MDE.NET which is a community for .NET developers in Medellín.&quot;}</name></author><summary type="html"><![CDATA[This is a cross-post from elvanydev.com.]]></summary></entry><entry><title type="html">Simmy, the monkey for making chaos</title><link href="https://thepollyproject.org/2019/06/27/simmy-the-monkey-for-making-chaos.html" rel="alternate" type="text/html" title="Simmy, the monkey for making chaos" /><published>2019-06-27T00:00:00+00:00</published><updated>2019-06-27T00:00:00+00:00</updated><id>https://thepollyproject.org/2019/06/27/simmy-the-monkey-for-making-chaos</id><content type="html" xml:base="https://thepollyproject.org/2019/06/27/simmy-the-monkey-for-making-chaos.html"><![CDATA[<p><img src="/assets/images/2019/06/Simmy_jumbo.png" alt="Simmy, the monkey for making chaos" /></p>
<blockquote>
  <p>This is a cross-post from <a href="http://elvanydev.com/chaos-injection-with-simmy/">elvanydev.com</a>.</p>
</blockquote>

<h2 id="what-is-simmy">What Is Simmy?</h2>

<p><a href="https://github.com/Polly-Contrib/Simmy">Simmy</a> is a chaos-engineering and fault-injection tool based on the idea of the <a href="https://github.com/Netflix/SimianArmy">Netflix Simian Army</a>, integrating with the <a href="https://github.com/App-vNext/Polly">Polly</a> resilience project for .NET, Simmy takes advantage of the power of Polly to help you to answer these questions:</p>

<ul>
  <li>Is my system resilient enough?</li>
  <li>Am I handling the right exceptions/scenarios?</li>
  <li>How will my system behave if X happens?</li>
  <li>How can I test my resilience, without waiting for a handled (or even unhandled) exception to happen in my production environment?</li>
</ul>

<h2 id="why-simmy">Why “Simmy”?</h2>

<p>It’s an analogy with Simian, rhyme with Polly and also give us the idea that the library <strong><em>Sim</em></strong>ulates faults.</p>

<p><img src="https://raw.githubusercontent.com/Polly-Contrib/Simmy/master/Simmy_monkey.png" alt="alt" /></p>

<p>So, Simmy is a pirate monkey, like <a href="https://disney.fandom.com/wiki/Jack_the_Monkey">Jack the monkey</a> from Pirates of the Caribbean, it’s unstoppable!</p>

<h2 id="what-is-chaos-engineering">What is Chaos Engineering?</h2>

<blockquote>
  <p><a href="http://principlesofchaos.org/">Chaos Engineering</a> is the discipline of experimenting on a distributed system in order to build confidence in the system’s capability to withstand turbulent conditions in production.</p>
</blockquote>

<p>Given that distributed architectures nowadays leverage the most critical systems and most popular applications which we use every day, the chaos engineering and <a href="http://principlesofchaos.org/">its principles</a> have become in an important matter, so much so that it’s considered as a discipline and I’d say that for almost every SRE team out there, being aware of those principles is a must when it comes to truly guarantee the resilience and reliability of the systems.</p>

<p>As I mentioned earlier, Netflix is one of the most important contributors in the matter with its <a href="https://netflix.github.io/chaosmonkey/">Simian Army project</a> which in a nutshell, is a framework to inject faults randomly in a production environment, such as stop instances, introduce latency or even simulates an outage of an entire availability zone allowing you to detect abnormal conditions and test the ability to survive them.</p>

<p>Another interesting project is <a href="https://engineering.linkedin.com/blog/2017/11/resilience-engineering-at-linkedin-with-project-waterbear">Waterbear</a> from LinkedIn, which offers tools pretty similar than the Simian Army, but also things like simulate network, disk, CPU and memory failures, DNS pollution, Rack fails, etc. There are also a lot of <a href="https://github.com/dastergon/awesome-chaos-engineering#notable-tools">resources and tools</a> out there that you can find very useful and compatible with the main cloud providers.</p>

<h2 id="how-simmy-works">How Simmy works?</h2>

<p>As I said earlier, Simmy is based on Polly, so at the end of the day the building block of this little simian are the policies as well, which we’ve called <strong><em>Monkey Policies</em></strong> (or chaos policies), which means, as well as a <em>Policy</em> is the minimum unit of resilience for Polly, a <em>MonkeyPolicy</em> is the minimum unit of chaos for Simmy.</p>

<p>In other words, Simmy allows you to introduce a chaos-injection policy (Monkey Policy) or policies at any location where you execute code through Polly. So, for now, Simmy offers three chaos policies:</p>

<ul>
  <li><strong><a href="https://github.com/Polly-Contrib/Simmy#Inject-fault">Fault</a>:</strong> Injects exceptions or substitute results, to fake faults in your system.</li>
  <li><strong><a href="https://github.com/Polly-Contrib/Simmy#inject-latency">Latency</a>:</strong> Injects latency into executions before the calls are made.</li>
  <li><strong><a href="https://github.com/Polly-Contrib/Simmy#inject-behavior">Behavior</a>:</strong> Allows you to inject any extra behaviour, before a call is placed.</li>
</ul>

<p>All chaos policies (Monkey policies) are designed to inject behavior randomly (faults, latency or custom behavior), so a Monkey policy allows you to specify an injection rate between 0 and 1 (0-100%) thus, the higher is the injection rate the higher is the probability to inject them. Also it allows you to specify whether or not the random injection is enabled, that way you can release/hold (turn on/off) the monkeys regardless of injection rate you specify, it means, if you specify an injection rate of 100% but you tell to the policy that the random injection is disabled, it will do nothing.</p>

<h2 id="how-can-simmy-help-me-out">How can Simmy help me out?</h2>

<p>It’s well known that Polly helps us a ton to introduce resilience to our system making it more reliable, but I don’t want to have to wait for expected or even unexpected failures to test it out. My resilience could be wrongly implemented because most of the time we handle transient errors, which is totally fine, but let’s be honest, how many times we’ve seen those errors while we develop/debug? then how are we making sure that the behavior after those kinds of errors is the one that we expect? through the unit test, hopefully? so, are unit tests enough to make sure that the whole workflow is working fine and the underlying chain of calls/dependencies are going to degrade gracefully? Also, testing all the scenarios or mocking failure of some dependencies is not straight forward, for example, a cloud SaaS or PaaS service.</p>

<p>So, how can Simmy help us to make sure that we’re doing our resilience strategies right? the answer is too simple: making chaos! by simulating adverse conditions in our environments (ideally in environments different than development) and watching how our system behaves under those conditions without making assumptions, that way, we’re going to realize if our resilience strategies are well implemented thus, we’ll find out if our system is capable to withstand chaotic conditions.</p>

<p>Using Simmy, we can easily make things that usually aren’t straight forward to do, such as:</p>

<ul>
  <li>Mock failures of dependencies (any service dependency for example).</li>
  <li>Define when to fail based on some external factors - maybe global configuration or some rule.</li>
  <li>A way to revert easily, to control the blast radius.</li>
  <li>Production grade, to run this in a production or near-production system with automation.</li>
</ul>

<p>No more introduction, let’s see Simmy in action!</p>

<h2 id="hands-on-lab">Hands-on Lab</h2>

<p>In order to stay this handy and funny as possible, let’s base on the DUber <a href="http://elvanydev.com//Microservices-part1/#the-problem">problem</a> and <a href="http://elvanydev.com/Microservices-part2/#production-environment-architecture">solution</a> which is, as you know, a distributed architecture based on microservices using <a href="https://dotnet.github.io/">.Net Core</a>, <a href="https://www.docker.com/">Docker</a>, <a href="https://azure.microsoft.com/en-us/services/service-fabric/">Azure Service Fabric</a>, etc that I previously walked you through <a href="http://elvanydev.com/Microservices-part1/">four posts</a>.</p>

<h3 id="the-example">The example</h3>

<p>We’re going to see an example/approach of how to use Simmy in a kind of <em>real</em> but <em>simple</em> scenario over a distributed architecture to inject chaos in our system in a configurable and automatic way.</p>

<p>So, we’re going to demonstrate the following patterns with Simmy:</p>

<ul>
  <li>Configuring StartUp so that Simmy chaos policies are only introduced in builds for certain environments.</li>
  <li>Configuring Simmy chaos policies to be injected into the app without changing any code, using a UI/API to update/get the chaos configuration.</li>
  <li>Injecting faults or chaos automatically by using a <em><a href="#watchmonkey">WatchMonkey</a></em> specifying a frequency and duration of the chaos.</li>
</ul>

<blockquote>
  <p>I based myself on the great <a href="https://github.com/Polly-Contrib/Polly.Contrib.SimmyDemo_WebApi">Dylan’s example</a> in order to configure Simmy chaos policies on StartUp, however, there are significant differences that I’ll explain later.</p>
</blockquote>

<h3 id="the-architecture">The Architecture</h3>

<p><img src="https://raw.githubusercontent.com/vany0114/vany0114.github.io/master/images/Simmy-Example-Architecture.png" alt="alt" /></p>

<p>As you can see, there are a couple of new components in the architecture (respect to the <a href="http://elvanydev.com/Microservices-part2/#production-environment-architecture">old one</a>), let’s see:</p>

<h4 id="chaos-settings-microservice">Chaos Settings Microservice</h4>

<p>It’s a Web API which takes care of to store and get the <a href="#the-chaos-ui">chaos settings</a> using <a href="https://azure.microsoft.com/en-in/services/cache/">Azure Redis Cache</a> as a repository. This is one of the main differences I mentioned earlier; instead of using <code class="language-plaintext highlighter-rouge">IOptionsSnapshot&lt;&gt;</code> to get the chaos settings, we’re getting the settings from the API, which is more convenient in a distributed architecture where you have deployed your services in a cluster over dozens, hundreds or even thousands of instances of your services, so in that case it’s not suitable/easy just changing the <code class="language-plaintext highlighter-rouge">appsettings</code> file in every instance deployed.</p>

<h4 id="watchmonkey">WatchMonkey</h4>

<p>Is an <a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview">Azure Function</a> with a <a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer">timer trigger</a> which is executed every 5 minutes (value set arbitrarily for this example) in order to watch the monkeys (chaos settings/policies) set up trhough the <a href="#the-chaos-ui">chaos UI</a>. So, if the automatic chaos injection is enabled it releases all the monkeys for the given frequency within the time window configured (Max Duration), after that time window all the monkeys are caged (disabled) again. It also watches monkeys with a specific duration, allowing you to disable specific faults in a smaller time window.</p>

<blockquote>
  <p>You can find the whole explanation about DUber architecture <a href="http://elvanydev.com/Microservices-part2/">here</a>.</p>
</blockquote>

<h3 id="the-chaos-ui">The Chaos UI</h3>

<p>Is the monkeys administrator, which allows us to set up the <a href="#general-chaos-settings">general chaos settings</a> and also <a href="#operations-chaos-settings">settings at operation level</a>. The UI uses the <a href="#chaos-settings-microservice">Chaos Settings API</a> to store and get the settings.</p>

<h4 id="general-chaos-settings">General Chaos Settings</h4>

<p><img src="https://raw.githubusercontent.com/vany0114/vany0114.github.io/master/images/Simmy-Example-general-chaos-settings.png" alt="" /></p>

<p><strong><em>Enable Automatic Chaos Injection:</em></strong>
Allows you to inject the chaos automatically based on a frequency and maximum chaos time duration. Which means in the given example, that the chaos will be enabled every day (every 23:59 hours) and it will take 15 minutes.</p>

<p><strong><em>Frequency:</em></strong>
A <code class="language-plaintext highlighter-rouge">Timespan</code> indicating how often the chaos should be injected.</p>

<p><strong><em>Max Duration:</em></strong>
A <code class="language-plaintext highlighter-rouge">Timespan</code> indicating how long the chaos should take once is injected.</p>

<p><strong><em>Enable Cluster Chaos:</em></strong>
Allows you to inject chaos at cluster level. (You will need to create a <a href="https://blog.jongallant.com/2017/11/azure-rest-apis-postman/">service principal</a>, then set up the values for <code class="language-plaintext highlighter-rouge">GeneralChaosSetting</code> section into the <code class="language-plaintext highlighter-rouge">appsettings</code> file of <code class="language-plaintext highlighter-rouge">Duber.Chaos.API</code> project, or their respective environment variables inside <code class="language-plaintext highlighter-rouge">docker-compose.override</code>. You might consider storing these secrets into an <a href="https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis">Azure Key Vault</a>)</p>

<p><strong><em>Percentage Nodes to Restart:</em></strong>
An <code class="language-plaintext highlighter-rouge">int</code> between 0 and 100, indicating the percentage of nodes that should be restarted if cluster chaos is enabled.</p>

<p><strong><em>Percentage Nodes to Stop:</em></strong>
An <code class="language-plaintext highlighter-rouge">int</code> between 0 and 100, indicating the percentage of nodes that should be stopped if cluster chaos is enabled.</p>

<p><strong><em>Resource Group Name:</em></strong>
The name of the resource group where the VM Scale Set of the cluster belongs to.</p>

<p><strong><em>VM Scale Set Name:</em></strong>
The name of the Virtual Machine Scale Set used by the cluster.</p>

<p><strong><em>Injection Rate:</em></strong>
A <code class="language-plaintext highlighter-rouge">double</code> between 0 and 1, indicating what proportion of calls should be subject to failure-injection. For example, if 0.2, twenty percent of calls will be randomly affected; if 0.01, one percent of calls; if 1, all calls.</p>

<h4 id="operations-chaos-settings">Operations Chaos Settings</h4>

<p><img src="https://raw.githubusercontent.com/vany0114/vany0114.github.io/master/images/Simmy-Example-operation-chaos-settings-exception.png" alt="" /></p>

<p><strong><em>Operation:</em></strong>
Which operation within the app these chaos settings apply to. Each call site in your codebase which uses Polly and Simmy can be tagged with an <a href="#using-chaos-settings-factory-from-consumers">OperationKey</a>. This is simply a string tag you choose, to identify different call paths in your app, in our case, we’re using an <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/master/src/Domain/Duber.Domain.SharedKernel/Chaos/OperationKeys.cs">enumeration</a> located in the <em>Shared Kernel</em> project, where we’ve defined (arbitrarily) some operations to inject them some chaos.</p>

<p><strong><em>Duration:</em></strong>
A <code class="language-plaintext highlighter-rouge">Timespan</code> indicating how long the chaos for a specific operation should take once is injected if Automatic Chaos Injection is enabled. (Optional) Should be less than the value configured for <em>MaxDuration</em>.</p>

<p><strong><em>Injection Rate:</em></strong>
A <code class="language-plaintext highlighter-rouge">double</code> between 0 and 1, indicating what proportion of calls should be subject to failure-injection. For example, if 0.2, twenty percent of calls will be randomly affected; if 0.01, one percent of calls; if 1, all calls.</p>

<p><strong><em>Latency:</em></strong>
If set, this much extra latency in ms will be added to affected calls, before the http request is made.</p>

<p><strong><em>Exception:</em></strong>
If set, affected calls will throw the given exception. (The original outbound http/sql/whatever call will not be placed.)</p>

<p><strong><em>Status Code:</em></strong>
If set, a result with the given http status code will be returned for affected calls. (The original outbound http call will not be placed.)</p>

<p><strong><em>Enabled:</em></strong>
A master switch for this call site. When true, faults may be injected at this call site per the other parameters; when false, no faults will be injected.</p>

<h3 id="how-the-chaos-is-injected">How the chaos is injected?</h3>

<p>The best way to build <a href="http://elvanydev.com/resilience-with-polly/">robust resilience strategies</a> using Polly is through the <a href="http://elvanydev.com/resilience-with-polly/#the-power-of-policywrap">PolicyWrap</a>, which at the end of the day makes up a set of policies working together as a single policy. So, the recommended way for introducing <code class="language-plaintext highlighter-rouge">Simmy</code> is to use one or more <em>Monkey Policies</em> as the innermost policies in the <code class="language-plaintext highlighter-rouge">PolicyWrap</code>. That way, they alter the usual outbound call at the last minute, substituting their fault, adding a custom behavior or adding extra latency allowing us to test our resilience strategies and see how we’re handling the chaos/faults injected by <code class="language-plaintext highlighter-rouge">Simmy</code>.</p>

<p>One of the simplest ways to add chaos-injection all across your app without changing existing configuration code is taking advantage of <code class="language-plaintext highlighter-rouge">PolicyRegistry</code> by storing all policies of each strategy in their respective registry (you might have several strategies with different policies to handle different scenarios, thus different <code class="language-plaintext highlighter-rouge">PolicyRegistry's</code>). <br />
So, in order to do that, we’re going to add some code in <code class="language-plaintext highlighter-rouge">StartUp</code> class.</p>

<p>First of all, we need to add our resilience strategies, then we’re going to inject them chaos policies (monkeys). For <code class="language-plaintext highlighter-rouge">Http</code> calls, we’re going to build a strategy on the fly, but for <code class="language-plaintext highlighter-rouge">SQL Azure</code> database calls we’re going to use our <code class="language-plaintext highlighter-rouge">SqlPolicyBuilder</code> which we’ve made <a href="http://elvanydev.com/resilience-with-polly/#putting-all-together-with-builder-pattern">previously</a> because the idea is to reuse our resilience strategies!</p>

<h4 id="setting-up-our-http-resilience-strategy">Setting up our Http resilience strategy</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>var policyRegistry = services.AddPolicyRegistry();  
policyRegistry["ResiliencePolicy"] = GetHttpResiliencePolicy();

services.AddHttpClient&lt;ResilientHttpClient&gt;()  
    .AddPolicyHandlerFromRegistry("ResiliencePolicy");
</code></pre></div></div>

<h4 id="setting-up-our-sql-azure-db-strategy">Setting up our SQL Azure DB strategy</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>services.AddSingleton&lt;IPolicyAsyncExecutor&gt;(sp =&gt;  
{
    var sqlPolicyBuilder = new SqlPolicyBuilder();
    return sqlPolicyBuilder
        .UseAsyncExecutor()
        .WithDefaultPolicies()
        .Build();
});
</code></pre></div></div>

<h4 id="injecting-chaos-policies-monkeys-to-our-resilient-strategies">Injecting chaos policies (monkeys) to our resilient strategies</h4>

<p>We’re injecting the monkeys only in environments different than <code class="language-plaintext highlighter-rouge">Development</code> (which is the usual, but it’s up to you, even you might make it configurable through the Chaos UI as well) through the <code class="language-plaintext highlighter-rouge">AddChaosInjectors/AddHttpChaosInjectors</code> extension methods on <code class="language-plaintext highlighter-rouge">IPolicyRegistry&lt;&gt;</code> which simply takes every policy in our <code class="language-plaintext highlighter-rouge">PolicyRegistry</code> and wraps <code class="language-plaintext highlighter-rouge">Simmy</code> policies (as the innermost policy) inside.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>if (env.IsDevelopment() == false)  
{
    // injects chaos to our Http policies defined previously.
    var httpPolicyRegistry = app.ApplicationServices.GetRequiredService&lt;IPolicyRegistry&lt;string&gt;&gt;();
    httpPolicyRegistry?.AddHttpChaosInjectors();

    // injects chaos to our Sql policies defined previously.
    var sqlPolicyExecutor = app.ApplicationServices.GetRequiredService&lt;IPolicyAsyncExecutor&gt;();
    sqlPolicyExecutor?.PolicyRegistry?.AddChaosInjectors();
}
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public static IPolicyRegistry&lt;string&gt; AddHttpChaosInjectors(this IPolicyRegistry&lt;string&gt; registry)  
{
    foreach (var policyEntry in registry)
    {
        if (policyEntry.Value is IAsyncPolicy&lt;HttpResponseMessage&gt; policy)
        {
            registry[policyEntry.Key] = policy
                    .WrapAsync(MonkeyPolicy.InjectFaultAsync&lt;HttpResponseMessage&gt;(
                        (ctx, ct) =&gt; GetException(ctx, ct),
                        GetInjectionRate,
                        GetEnabled))
                    .WrapAsync(MonkeyPolicy.InjectFaultAsync&lt;HttpResponseMessage&gt;(
                        (ctx, ct) =&gt; GetHttpResponseMessage(ctx, ct),
                        GetInjectionRate,
                        GetHttpResponseEnabled))
                    .WrapAsync(MonkeyPolicy.InjectLatencyAsync&lt;HttpResponseMessage&gt;(
                        GetLatency,
                        GetInjectionRate,
                        GetEnabled))
                    .WrapAsync(MonkeyPolicy.InjectBehaviourAsync&lt;HttpResponseMessage&gt;(
                        (ctx, ct) =&gt; RestartNodes(ctx, ct),
                        GetClusterChaosInjectionRate,
                        GetClusterChaosEnabled))
                    .WrapAsync(MonkeyPolicy.InjectBehaviourAsync&lt;HttpResponseMessage&gt;(
                        (ctx, ct) =&gt; StopNodes(ctx, ct),
                        GetClusterChaosInjectionRate,
                        GetClusterChaosEnabled));
        }
    }

    return registry;
}
</code></pre></div></div>

<p>This allows us to inject <code class="language-plaintext highlighter-rouge">Simmy</code> into our app without changing any of our existing app configuration of <code class="language-plaintext highlighter-rouge">Polly</code> policies. These extension methods configure the policies in the <code class="language-plaintext highlighter-rouge">PolicyRegistry</code> with <code class="language-plaintext highlighter-rouge">Simmy</code> policies which react to chaos configured through the UI getting that configuration from Polly <code class="language-plaintext highlighter-rouge">Context</code> at runtime taking advantage of the power of the <a href="https://github.com/Polly-Contrib/Simmy#context-driven-behaviour">contextual configuration</a>.</p>

<blockquote>
  <p>Notice that we’re using the <em>InjectFaultAsync</em> monkey policy not only to inject an <em>Exception</em> but to inject a <em>HttpResponseMessage</em>. Also, we’re using the <em>InjectBehaviourAsync</em> monkey to inject the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/master/src/Infrastructure/Duber.Infrastructure.Chaos/CustomChaos/ClusterChaosManager.cs">custom behavior</a> which takes care of to restart/stop instances in our cluster.</p>
</blockquote>

<h3 id="how-does-it-get-the-chaos-settings">How does it get the chaos settings?</h3>

<p>We’re injecting a factory which takes care of getting the current chaos settings from the <a href="#chaos-settings-microservice">Chaos API</a>. So we’re injecting the factory as a <code class="language-plaintext highlighter-rouge">Lazy Task Scoped</code> service because we want to avoid to add additional overhead/latency to our system, that way we only retrieve the configuration once per request no matter how many times the factory is executed.</p>

<h4 id="injecting-chaos-settings-factory">Injecting chaos settings factory</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public static IServiceCollection AddChaosApiHttpClient(this IServiceCollection services, IConfiguration configuration)  
{
    services.AddHttpClient&lt;ChaosApiHttpClient&gt;(client =&gt;
    {
        client.Timeout = TimeSpan.FromSeconds(5);
        client.BaseAddress = new Uri(configuration.GetValue&lt;string&gt;("ChaosApiSettings:BaseUrl"));
    });

    services.AddScoped&lt;Lazy&lt;Task&lt;GeneralChaosSetting&gt;&gt;&gt;(sp =&gt;
    {
        // we use LazyThreadSafetyMode.None in order to avoid locking.
        var chaosApiHttpClient = sp.GetRequiredService&lt;ChaosApiHttpClient&gt;();
        return new Lazy&lt;Task&lt;GeneralChaosSetting&gt;&gt;(() =&gt; chaosApiHttpClient.GetGeneralChaosSettings(), LazyThreadSafetyMode.None);
    });

    return services;
}
</code></pre></div></div>

<h4 id="using-chaos-settings-factory-from-consumers">Using chaos settings factory from consumers</h4>

<p>So, wherever we want to make the chaos to be injected inside of the workflow of our application using <code class="language-plaintext highlighter-rouge">Polly</code> and <code class="language-plaintext highlighter-rouge">Simmy</code> (and also using this approach), the only thing we need to do (after setting up the resilience strategies and monkeys, of course) is tagging the executions through the <code class="language-plaintext highlighter-rouge">OperationKey</code> as we explained before and storing the chaos settings inside the <code class="language-plaintext highlighter-rouge">Context</code> using the <code class="language-plaintext highlighter-rouge">WithChaosSettings</code> extension method, that way, the chaos might or might not be injected at runtime contextually.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// constructor
public TripController(Lazy&lt;Task&lt;GeneralChaosSetting&gt;&gt; generalChaosSettingFactory,...)  
{
    ...
}

public async Task&lt;IActionResult&gt; SimulateTrip(TripRequestModel model)  
{
    ...
    generalChaosSetting = await _generalChaosSettingFactory.Value;
    var context = new Context(OperationKeys.TripApiCreate.ToString()).WithChaosSettings(generalChaosSetting);
    var response = await _httpClient.SendAsync(request, context);
    ...
}

private async Task UpdateTripLocation(Guid tripId, LocationModel location)  
{
    ...
    generalChaosSetting = await _generalChaosSettingFactory.Value;
    var context = new Context(OperationKeys.TripApiUpdateCurrentLocation.ToString()).WithChaosSettings(generalChaosSetting);
    var response = await _httpClient.SendAsync(request, context);
    ...
}
</code></pre></div></div>

<h3 id="putting-all-together">Putting all together</h3>

<p>In this example, we’re injecting the monkey policies at different layers such as Application, Data and the Anti Corruption Layer. (which at the end of the day, it is executed in the Application layer) In the case of the Application layer, we’re tagging all the operations related with the simulation of a trip into the website’s <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/1c5b175c9a8cfe8784c09986e36639ce8ee94746/src/Web/Duber.WebSite/Controllers/TripController.cs#L108">Trip controller</a>.</p>

<p>On the other hand, we’re tagging the call to the <em>Payment</em> service which is an external system, that’s why that <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/master/src/Domain/Duber.Domain.ACL/Adapters/PaymentServiceAdapter.cs">guy</a> lives in our ACL (Anti Corruption Layer). So, being able to inject chaos here is pretty interesting, because it’s an external dependency which we don’t have control on, so we might want to simulate how our system behaves when that service returns a <code class="language-plaintext highlighter-rouge">BadRequest</code>, <code class="language-plaintext highlighter-rouge">InternalServelError</code>, etc.</p>

<p>In the case of the Data layer, we’re injecting the chaos at general level by tagging all the operations of the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/master/src/Domain/Invoice/Duber.Domain.Invoice/Persistence/InvoiceContext.cs">InvoiceContext</a> with the same tag. This allows us to test the resilience of our system at different layers but also as granular or as general as we want. So, we can see how the system behaves if there’s an error in the database and how the downstream calls like the repository, controller, etc are degraded.</p>

<p>At the end of the day is up to you where you want to make possible the chaos to be injected, it depends on whatever makes more sense to you given your resilience strategies, for example, in our case, given that we have a strategy for SQL executions, it might be interesting to inject some chaos on the <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/master/src/Web/Duber.WebSite/Infrastructure/Repository/ReportingRepository.cs">ReportingRepository</a> as well, to see how’s the behavior when there’s an error when it’s updating the materialized view, because if we’re not handling the errors properly there, we might lose the messages from the message bus, and that’s not good.</p>

<h3 id="considerations">Considerations</h3>

<ul>
  <li>You might want to consider making the <a href="#the-chaos-ui">Chaos UI</a> in a separated project, in our case it’s housed into <code class="language-plaintext highlighter-rouge">Duber.WebSite</code> just for the example purposes, but that’s usually an internal tool mostly for the SRE team.</li>
  <li>You might want to deploy the <a href="#chaos-settings-microservice">Chaos Settings API</a> outside of the cluster in order to avoid it will be affected when you release the cluster chaos.</li>
  <li>You’ll need to secure the <em>Chaos Settings API</em> properly.</li>
  <li>The cluster chaos does not depend on a specific operation, so when it’s enabled the monkey will be released by the first policy executed, configured previously in our workflow, it means that in our case might be, simulating a trip, creating an invoice or performing the payment. (you could inject it at operation level as well if you want to)</li>
  <li>The chaos cluster may also introduce extra latency since we’re using <a href="https://docs.microsoft.com/en-us/rest/api/azure/">Azure REST API</a> to <a href="https://github.com/vany0114/chaos-injection-using-simmy/blob/master/src/Infrastructure/Duber.Infrastructure.Chaos/CustomChaos/ClusterChaosManager.cs">restart/stop</a> nodes in our cluster. So we need a request to get the token (that’s why we need a <a href="https://blog.jongallant.com/2017/11/azure-rest-apis-postman/">Service Principal</a>) and a couple of requests more to get the VM’s then restart/stop them.</li>
  <li>We choose <a href="https://azure.microsoft.com/en-in/services/cache/">Azure Cache for Redis</a> to store the chaos settings because of the high performance we need here since we need to get the settings in every request and we don’t want to add extra overhead and latency to our system. (We might consider using <a href="https://docs.microsoft.com/en-us/azure/azure-cache-for-redis/cache-how-to-premium-persistence">data persistence</a>)</li>
</ul>

<h2 id="wrapping-up">Wrapping up</h2>

<p>We’ve seen how important is nowadays the chaos engineering and the power of <a href="https://github.com/App-vNext/Polly">Polly</a> and <a href="https://github.com/Polly-Contrib/Simmy">Simmy</a> working together to meet <a href="http://principlesofchaos.org/">its principles</a>, and how they can help us to make sure that our resilience strategies are working fine and we’re truly offering a highly available and reliable service injecting the chaos to our system without changing existing configuration code and in an automatic way to enable making chaos periodically, allowing us to test our system in production environment under chaotic conditions, using chaos policies such as <a href="https://github.com/Polly-Contrib/Simmy#inject-fault">Fault</a>, <a href="https://github.com/Polly-Contrib/Simmy#inject-latency">Latency</a> and <a href="https://github.com/Polly-Contrib/Simmy#inject-behavior">Behavior</a>.</p>

<p>The approach we’ve proposed here has pros and cons (like everything), for instance, one of the biggest advantages of having a <a href="#chaos-settings-microservice">Chaos API</a> is that it allows us to automate the chaos injection not only through the <a href="#watchmonkey">WatchMonkey</a> but after a deployment, we might use an <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/release/approvals/gates?view=azure-devops">Azure DevOps Gate</a> to enable the automatic chaos, then let the <em>WatchMonkey</em> does the dirty work, which is very convenient in order to make sure that our latest releases keep withstanding turbulence conditions in a production environment. Besides the automation, we could take the API to the next level, for example, we can record logs, or whatever metadata to analyze them and make further decisions.</p>

<p>On the other hand, one of the disadvantages could be the latency that the Chaos API may introduce to our system since we’re going to need an additional request where we’re using our <em>Chaos Policies</em>, that’s why we need to ensure that the API is going to be highly available and as fast as possible.</p>

<h2 id="next-steps">Next steps</h2>

<p>We need to have in mind that a good chaos engineering tool/strategy also requires a good monitoring tool/strategy to be able to realize easily about system weaknesses and be aware where they are exactly, then be able to make decisions faster to fix them, otherwise it might be painful and harder trying to improve our system however much we have developed a great chaos engineering strategy. So, I’d recommend <a href="https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview">Application Insights</a>, <a href="https://docs.microsoft.com/en-us/azure/azure-monitor/overview">Azure Monitor</a>, <a href="https://stackify.com/retrace/">Stackify Retrace</a>, etc.</p>

<p>So, stay tuned because in the next post we’ll propose another approach using <a href="https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview">Azure App Configuration</a> and how it can help us to solve the downside we mentioned before of this current approach about the latency. In the meantime, I encourage you all to start making experiments using <a href="https://github.com/Polly-Contrib/Simmy">Simmy</a> so you can realize by yourself about the power of this little monkey!</p>

<h2 id="credits">Credits!</h2>

<p>Simmy was the <a href="https://github.com/App-vNext/Polly/issues/499">brainchild</a> of <a href="https://github.com/mebjas">@mebjas</a> and <a href="https://github.com/reisenberger">@reisenberger</a>. The major part of the implementation was by <a href="https://github.com/mebjas">@mebjas</a> and <a href="https://github.com/vany0114">myself</a>, with contributions also from <a href="https://github.com/reisenberger">@reisenberger</a> of the Polly team. Thanks also to <a href="https://github.com/joelhulen">@joelhulen</a> for the amazing work with the logos and the help on admin/DevOps tasks.</p>

<blockquote>
  <p>Take a look at the whole implementation on my GitHub repo: <a href="https://github.com/vany0114/chaos-injection-using-simmy">https://github.com/vany0114/chaos-injection-using-simmy</a></p>
</blockquote>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/geovanny-alzate-sandoval.jpg&quot;, &quot;website&quot;=&gt;&quot;http://elvanydev.com/&quot;, &quot;bio&quot;=&gt;&quot;Geovanny loves contributing to the community and write on his blog. He&apos;s also Simmy co-author/lead contributor and co-organizer of MDE.NET which is a community for .NET developers in Medellín.&quot;}</name></author><summary type="html"><![CDATA[This is a cross-post from elvanydev.com.]]></summary></entry><entry><title type="html">Authoring a proactive Polly policy (Custom policies Part II)</title><link href="https://thepollyproject.org/2019/02/13/authoring-a-proactive-polly-policy-custom-policies-part-ii.html" rel="alternate" type="text/html" title="Authoring a proactive Polly policy (Custom policies Part II)" /><published>2019-02-13T00:00:00+00:00</published><updated>2019-02-13T00:00:00+00:00</updated><id>https://thepollyproject.org/2019/02/13/authoring-a-proactive-polly-policy-custom-policies-part-ii</id><content type="html" xml:base="https://thepollyproject.org/2019/02/13/authoring-a-proactive-polly-policy-custom-policies-part-ii.html"><![CDATA[<p>In this article we’ll build our first custom Polly policy: a proactive Policy to capture execution timings.</p>

<p>Polly polices fall into two categories: <strong>reactive</strong> (which react to faults) and <strong>non-reactive</strong> or <strong>proactive</strong> (which act on all executions). To author a policy which reacts to faults, see <a href="/2019/02/13/authoring-a-reactive-polly-policy-custom-policies-part-iii-2.html">Part III: Authoring a reactive custom policy</a>.</p>

<p>For background on custom policies and the Polly.Contrib, see <a href="/2019/02/13/introducing-custom-polly-policies-and-polly-contrib-custom-policies-part-i.html">Part I: Introducing custom Polly policies</a>.</p>

<p>A final article in the series, Part IV, covers <a href="/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv.html">Custom policies for all execution types: sync and async, generic and non-generic</a>.</p>

<h2 id="authoring-a-non-reactive-custom-policy-capture-execution-timing">Authoring a non-reactive custom policy: Capture execution timing</h2>

<p>For simplicity, in this article we’ll assume we’re developing a custom policy for use with <a href="https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory">Polly and HttpClientFactory</a>. This means that all executions are async and return <code class="language-plaintext highlighter-rouge">Task&lt;HttpResponseMessage&gt;</code>.</p>

<p>For this, we only need to implement the <code class="language-plaintext highlighter-rouge">IAsyncPolicy&lt;TResult&gt;</code> form of the policy. For other forms, see <a href="/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv.html">Part IV of the series</a>.</p>

<h3 id="step-1-name-your-policy-and-extend-the-base-class">Step 1: Name your policy and extend the base class</h3>

<p>The base class for async generic policies is, as you might expect, <code class="language-plaintext highlighter-rouge">AsyncPolicy&lt;TResult&gt;</code>. So start by declaring:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">AsyncTimingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">AsyncPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span>
<span class="p">{</span>
<span class="p">}</span>
</code></pre></div></div>

<p>By extending the base class, your policy is already plugged in to all the benefits of the existing Polly architecture: the execution-dispatch, the integration into <code class="language-plaintext highlighter-rouge">PolicyWrap</code>.</p>

<p>The compiler or IDE will report:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AsyncTimingPolicy&lt;TResult&gt; does not implement inherited abstract member AsyncPolicy&lt;TResult&gt;
.ImplementationAsync(Func&lt;Context, CancellationToken, Task&lt;TResult&gt;&gt;, Context, CancellationToken, bool)
</code></pre></div></div>

<h3 id="step-2-add-a-no-op-implementation">Step 2: Add a ‘no-op’ implementation</h3>

<p>Let’s fulfil the abstract method with a stub (your IDE may have a tooltip or shortcut to help):</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">ImplementationAsync</span><span class="p">(</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">CancellationToken</span><span class="p">,</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">action</span><span class="p">,</span> 
    <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> 
    <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">continueOnCapturedContext</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">throw</span> <span class="k">new</span> <span class="nf">NotImplementedException</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This method is where your policy defines its implementation!</p>

<p>Let’s look at the parameters - these are the information passed when the user executes a call through the policy:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Func&lt;Context, CancellationToken, Task&lt;TResult&gt;&gt; action</code> represents the delegate executed through the policy</li>
  <li><code class="language-plaintext highlighter-rouge">Context context</code> is the context passed to execution</li>
  <li><code class="language-plaintext highlighter-rouge">CancellationToken cancellationToken</code> is (you guessed it) the cancellation token passed to execution</li>
  <li>and <code class="language-plaintext highlighter-rouge">bool continueOnCapturedContext</code>, whether the user asked to continue after <code class="language-plaintext highlighter-rouge">await</code>s on a captured context.</li>
</ul>

<p>The parameters map directly to the calling code:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">result</span> <span class="p">=</span> <span class="n">policy</span><span class="p">.</span><span class="nf">ExecuteAsync</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">,</span> <span class="n">continueOnCapturedContext</span><span class="p">);</span>
</code></pre></div></div>

<p>So, let’s flesh out our policy to provide a basic ‘no-op’ implementation. This just executes the code passed to the policy ‘as is’, using the parameters the user passed to execute the <code class="language-plaintext highlighter-rouge">action</code>. The parameter <code class="language-plaintext highlighter-rouge">continueOnCapturedContext</code> controls continuation context after the <code class="language-plaintext highlighter-rouge">await</code>:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">ImplementationAsync</span><span class="p">(</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">CancellationToken</span><span class="p">,</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">action</span><span class="p">,</span> 
    <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> 
    <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">continueOnCapturedContext</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="k">await</span> <span class="nf">action</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">).</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="n">continueOnCapturedContext</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>That’s it for a no-op implementation!</p>

<p><em>Aside</em>: To make it easier for you to get started, Polly <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates">provides all this as a template starting point for a custom policy</a>. To author your own custom policy, you can grab the template repo and copy/paste/rename the classes.</p>

<h3 id="step-3-add-your-custom-functionality">Step 3: Add your custom functionality</h3>

<p>To implement custom functionality, you just code … whatever you want … around the <code class="language-plaintext highlighter-rouge">await action(...)</code> statement.</p>

<p>We’re going to calculate execution duration, so we’ll use <code class="language-plaintext highlighter-rouge">System.Diagnostics.Stopwatch</code>:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">ImplementationAsync</span><span class="p">(</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">CancellationToken</span><span class="p">,</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">action</span><span class="p">,</span> 
    <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> 
    <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">continueOnCapturedContext</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">long</span> <span class="n">before</span> <span class="p">=</span> <span class="n">Stopwatch</span><span class="p">.</span><span class="nf">GetTimestamp</span><span class="p">();</span>
    <span class="k">try</span> <span class="p">{</span>
        <span class="k">return</span> <span class="k">await</span> <span class="nf">action</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">).</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="n">continueOnCapturedContext</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">finally</span>
    <span class="p">{</span>
        <span class="kt">long</span> <span class="n">elapsed</span> <span class="p">=</span> <span class="n">Stopwatch</span><span class="p">.</span><span class="nf">GetTimestamp</span><span class="p">()</span> <span class="p">-</span> <span class="n">before</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Hmm, we still need to let the user do something with that <code class="language-plaintext highlighter-rouge">elapsed</code> value. To keep this blog post simple and illustrate some points about async policy implementation, we’ll intentionally allow users to provide an async delegate as <code class="language-plaintext highlighter-rouge">timingPublisher</code>. (<em>For a production implementation, you might want instead to adopt the event pattern or <code class="language-plaintext highlighter-rouge">IObservable&lt;&gt;</code></em>.)</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Func</span><span class="p">&lt;</span><span class="n">TimeSpan</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">Task</span><span class="p">&gt;</span> <span class="n">timingPublisher</span>
</code></pre></div></div>

<p>We also make the <code class="language-plaintext highlighter-rouge">timingPublisher</code> delegate take an input parameter <code class="language-plaintext highlighter-rouge">Polly.Context</code>: this execution-scoped context travels with every Polly execution. Users can (optionally) use it to pass extra information in to the execution, to exchange information between different parts of the execution, or to capture information after execution (<a href="/2017/05/04/putting-the-context-into-polly.html">more info here</a> and <a href="https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory#use-case-exchanging-information-between-policy-execution-and-calling-code">here</a>). It also carries important <a href="https://github.com/App-vNext/Polly/wiki/Keys-And-Context-Data">metadata about the execution</a> which can be useful for filtering. It’s good practice to make <code class="language-plaintext highlighter-rouge">Context</code> an input parameter to any delegate you let users configure on a policy.</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">AsyncTimingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">AsyncPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="k">static</span> <span class="k">readonly</span> <span class="kt">double</span> <span class="n">TimestampToTicks</span> <span class="p">=</span> <span class="n">TimeSpan</span><span class="p">.</span><span class="n">TicksPerSecond</span> <span class="p">/</span> <span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">Stopwatch</span><span class="p">.</span><span class="n">Frequency</span><span class="p">;</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="n">Func</span><span class="p">&lt;</span><span class="n">TimeSpan</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">Task</span><span class="p">&gt;</span> <span class="n">timingPublisher</span><span class="p">;</span>

    <span class="k">public</span> <span class="nf">AsyncTimingPolicy</span><span class="p">(</span><span class="n">System</span><span class="p">.</span><span class="n">Func</span><span class="p">&lt;</span><span class="n">TimeSpan</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">Task</span><span class="p">&gt;</span> <span class="n">timingPublisher</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="n">timingPublisher</span> <span class="p">=</span> <span class="n">timingPublisher</span> <span class="p">??</span> <span class="k">throw</span> <span class="k">new</span> <span class="nf">ArgumentNullException</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">timingPublisher</span><span class="p">));</span>
    <span class="p">}</span>

    <span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">ImplementationAsync</span><span class="p">(</span>
        <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">CancellationToken</span><span class="p">,</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">action</span><span class="p">,</span> 
        <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> 
        <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">,</span>
        <span class="kt">bool</span> <span class="n">continueOnCapturedContext</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">long</span> <span class="n">before</span> <span class="p">=</span> <span class="n">Stopwatch</span><span class="p">.</span><span class="nf">GetTimestamp</span><span class="p">();</span>
        <span class="k">try</span> <span class="p">{</span>
            <span class="k">return</span> <span class="k">await</span> <span class="nf">action</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">).</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="n">continueOnCapturedContext</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">finally</span>
        <span class="p">{</span>
            <span class="kt">long</span> <span class="n">elapsed</span> <span class="p">=</span> <span class="n">Stopwatch</span><span class="p">.</span><span class="nf">GetTimestamp</span><span class="p">()</span> <span class="p">-</span> <span class="n">before</span><span class="p">;</span>
            <span class="n">TimeSpan</span> <span class="n">elapsedAsTimeSpan</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">TimeSpan</span><span class="p">((</span><span class="kt">long</span><span class="p">)(</span><span class="n">TimestampToTicks</span> <span class="p">*</span> <span class="n">elapsed</span><span class="p">));</span>
            <span class="k">await</span> <span class="nf">timingPublisher</span><span class="p">(</span><span class="n">elapsedAsTimeSpan</span><span class="p">,</span> <span class="n">context</span><span class="p">)</span>
                <span class="p">.</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="n">continueOnCapturedContext</span><span class="p">);</span> <span class="c1">// [*]</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Note [*] the use of <code class="language-plaintext highlighter-rouge">.ConfigureAwait(continueOnCapturedContext)</code> on the extra <code class="language-plaintext highlighter-rouge">await</code> we added. Whenever you code a new async policy, you should decorate all <code class="language-plaintext highlighter-rouge">await</code> statements in this way, if you want your policy to play nicely with what Polly users expect. Best practice for libraries is to <code class="language-plaintext highlighter-rouge">.ConfigureAwait(false)</code>. However, some specialist uses of Polly (such as Actors) require continuations to continue on the original context; so Polly provides this control bool to be used on all <code class="language-plaintext highlighter-rouge">await</code> statements.</p>

<h3 id="step-4-add-configuration-syntax">Step 4: Add configuration syntax</h3>

<p>Finally, add some configuration syntax so that users can create instances of your policy!</p>

<p>You’ll see the code above had a public constructor. There’s nothing wrong with this, but by convention, Polly configuration syntax uses static factory methods (eg <code class="language-plaintext highlighter-rouge">Policy.Timeout(30)</code>). So we would suggest amending the construction like this:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">AsyncTimingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">AsyncPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">static</span> <span class="n">AsyncTimingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">Create</span><span class="p">(</span><span class="n">Func</span><span class="p">&lt;</span><span class="n">TimeSpan</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">Task</span><span class="p">&gt;</span> <span class="n">timingPublisher</span><span class="p">)</span> 
        <span class="p">=&gt;</span> <span class="k">new</span> <span class="n">AsyncTimingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;(</span><span class="n">timingPublisher</span><span class="p">);</span>

    <span class="k">private</span> <span class="nf">AsyncTimingPolicy</span><span class="p">(</span><span class="n">Func</span><span class="p">&lt;</span><span class="n">TimeSpan</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">Task</span><span class="p">&gt;</span> <span class="n">timingPublisher</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="n">timingPublisher</span> <span class="p">=</span> <span class="n">timingPublisher</span> <span class="p">??</span> <span class="k">throw</span> <span class="k">new</span> <span class="nf">ArgumentNullException</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">timingPublisher</span><span class="p">));</span>
    <span class="p">}</span>

    <span class="cm">/* rest of policy unchanged */</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="lets-take-it-for-a-spin">Let’s take it for a spin!</h2>

<p>Let’s take the new <code class="language-plaintext highlighter-rouge">AsyncTimingPolicy&lt;TResult&gt;</code> for a spin!</p>

<p>This is also an example of a quick way to test HttpClientFactory with Polly policies in a Console App.</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Microsoft.Extensions.DependencyInjection</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Polly</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Polly.Contrib.TimingPolicy</span><span class="p">;</span>

<span class="k">namespace</span> <span class="nn">ConsoleAppExampleForBlogPost</span>
<span class="p">{</span>
    <span class="k">class</span> <span class="nc">Program</span>
    <span class="p">{</span>
        <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">const</span> <span class="kt">string</span> <span class="n">TestClient</span> <span class="p">=</span> <span class="s">"TestClient"</span><span class="p">;</span>

            <span class="n">IServiceCollection</span> <span class="n">services</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ServiceCollection</span><span class="p">();</span>

            <span class="n">services</span><span class="p">.</span><span class="nf">AddHttpClient</span><span class="p">(</span><span class="n">TestClient</span><span class="p">)</span>
                <span class="p">.</span><span class="nf">AddPolicyHandler</span><span class="p">(</span><span class="n">AsyncTimingPolicy</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;.</span><span class="nf">Create</span><span class="p">(</span><span class="n">PublishTiming</span><span class="p">));</span>

            <span class="n">HttpClient</span> <span class="n">configuredClient</span> <span class="p">=</span>
                <span class="n">services</span>
                    <span class="p">.</span><span class="nf">BuildServiceProvider</span><span class="p">()</span>
                    <span class="p">.</span><span class="n">GetRequiredService</span><span class="p">&lt;</span><span class="n">IHttpClientFactory</span><span class="p">&gt;()</span>
                    <span class="p">.</span><span class="nf">CreateClient</span><span class="p">(</span><span class="n">TestClient</span><span class="p">);</span>

            <span class="kt">string</span><span class="p">[]</span> <span class="n">urls</span> <span class="p">=</span> 
            <span class="p">{</span>
                <span class="s">"https://www.google.com/"</span><span class="p">,</span>
                <span class="s">"https://www.google.co.uk/"</span><span class="p">,</span>
                <span class="s">"https://www.bbc.co.uk/"</span>
            <span class="p">};</span>

            <span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">url</span> <span class="k">in</span> <span class="n">urls</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="kt">var</span> <span class="n">context</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Context</span> <span class="p">{[</span><span class="s">"url"</span><span class="p">]</span> <span class="p">=</span> <span class="n">url</span><span class="p">};</span>
                <span class="n">HttpRequestMessage</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span>
                <span class="n">request</span><span class="p">.</span><span class="nf">SetPolicyExecutionContext</span><span class="p">(</span><span class="n">context</span><span class="p">);</span>

                <span class="kt">var</span> <span class="n">result</span> <span class="p">=</span> <span class="k">await</span> <span class="n">configuredClient</span><span class="p">.</span><span class="nf">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="k">default</span><span class="p">(</span><span class="n">CancellationToken</span><span class="p">));</span>
            <span class="p">}</span>

            <span class="n">Console</span><span class="p">.</span><span class="nf">ReadKey</span><span class="p">();</span>

        <span class="p">}</span>

        <span class="k">static</span> <span class="n">Task</span> <span class="nf">PublishTiming</span><span class="p">(</span><span class="n">TimeSpan</span> <span class="n">executionDuration</span><span class="p">,</span> <span class="n">Context</span> <span class="n">context</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="kt">object</span> <span class="n">url</span> <span class="p">=</span> <span class="s">"[unknown]"</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">context</span><span class="p">?.</span><span class="nf">TryGetValue</span><span class="p">(</span><span class="s">"url"</span><span class="p">,</span> <span class="k">out</span> <span class="n">url</span><span class="p">)</span> <span class="p">??</span> <span class="k">false</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Took </span><span class="p">{</span><span class="n">executionDuration</span><span class="p">.</span><span class="n">TotalSeconds</span><span class="p">:</span><span class="m">0.</span><span class="err">###</span><span class="p">}</span><span class="s"> seconds retrieving </span><span class="p">{</span><span class="n">url</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="k">return</span> <span class="n">Task</span><span class="p">.</span><span class="n">CompletedTask</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Here’s some example output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Took 0.331 seconds retrieving https://www.google.com/
Took 0.146 seconds retrieving https://www.google.co.uk/
Took 0.121 seconds retrieving https://www.bbc.co.uk/
</code></pre></div></div>

<p>Of course, writing to the Console is the least imaginative use. The intention of this policy is to enable you to capture execution timing metrics to your favourite time-series db (Prometheus, InfluxDB, Azure Time Series, App-Metrics).</p>

<h3 id="where-can-i-get-the-code">Where can I get the code?</h3>

<p>The full source code for <code class="language-plaintext highlighter-rouge">AsyncTimingPolicy&lt;TResult&gt;</code> and the test console app is available in <a href="https://github.com/Polly-Contrib/Polly.Contrib.TimingPolicy">this Github repo</a>.</p>

<h2 id="where-next">Where next?</h2>

<h3 id="grab-the-template">Grab the template</h3>

<p>If you want to dive straight in to experimenting with a custom policy, just grab the <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates">template repo</a> and start copy/paste/rename/extend-ing the classes.</p>

<h3 id="authoring-a-reactive-custom-policy">Authoring a reactive custom policy</h3>

<p>In the next part of this series, <a href="/2019/02/13/authoring-a-reactive-polly-policy-custom-policies-part-iii-2.html">Part III</a>, we’ll look at authoring a <em>reactive</em> custom policy, to log any exception or fault and then rethrow or bubble it outwards. The new policy will allow you to inject custom logging into any position in a <code class="language-plaintext highlighter-rouge">PolicyWrap</code>.</p>

<p>Finally, in <a href="/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv.html">Part IV</a>, we’ll look at how to author other forms of policy - synchronous policies and non-generic policies - in the most efficient manner.</p>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/dylan-reisenberger.png&quot;, &quot;website&quot;=&gt;&quot;http://software.reisenberger.net/&quot;, &quot;bio&quot;=&gt;&quot;Dylan is the lead contributor and architect on Polly, and the brains behind the roadmap, which is seeing Polly growing into the most robust, flexible and fully-featured resilience library for .NET!&quot;}</name></author><summary type="html"><![CDATA[In this article we’ll build our first custom Polly policy: a proactive Policy to capture execution timings.]]></summary></entry><entry><title type="html">Authoring a reactive Polly policy (Custom policies Part III)</title><link href="https://thepollyproject.org/2019/02/13/authoring-a-reactive-polly-policy-custom-policies-part-iii-2.html" rel="alternate" type="text/html" title="Authoring a reactive Polly policy (Custom policies Part III)" /><published>2019-02-13T00:00:00+00:00</published><updated>2019-02-13T00:00:00+00:00</updated><id>https://thepollyproject.org/2019/02/13/authoring-a-reactive-polly-policy-custom-policies-part-iii-2</id><content type="html" xml:base="https://thepollyproject.org/2019/02/13/authoring-a-reactive-polly-policy-custom-policies-part-iii-2.html"><![CDATA[<p>In this article we’ll build our first reactive custom Polly policy: a policy to log exceptions or fault-results.</p>

<p>Polly polices fall into two categories: <strong>reactive</strong> (which react to configured faults) and <strong>non-reactive</strong> / <strong>proactive</strong> (which act on all executions). To author a proactive policy, see <a href="/2019/02/13/authoring-a-proactive-polly-policy-custom-policies-part-ii.html">Part II: Authoring a proactive custom policy</a>.</p>

<p>For background on custom policies and the Polly.Contrib, see <a href="/2019/02/13/introducing-custom-polly-policies-and-polly-contrib-custom-policies-part-i.html">Part I: Introducing custom Polly policies</a>.</p>

<p>If you’ve already read Part II of this article series, the initial steps to create the reactive policy here are similar to those for the proactive policy covered in Part II. For what’s different, skip straight to Steps 3 onwards, where we make the implementation react to the faults the policy handles, and tie the policy to Polly’s existing <code class="language-plaintext highlighter-rouge">Policy.Handle&lt;&gt;(...)</code> configuration syntax.</p>

<h2 id="the-goal-a-policy-to-log-faults">The goal: a policy to log faults</h2>

<p>Polly already has configurable delegates hooks such as <code class="language-plaintext highlighter-rouge">onRetry</code>, <code class="language-plaintext highlighter-rouge">onBreak</code> and <code class="language-plaintext highlighter-rouge">onFallback</code>, which many users use for logging with the relevant policies. So why a new policy to log faults? And what exactly will the policy do?</p>

<p>The aim is that the policy will log any exception or fault and then just rethrow or bubble it outwards.</p>

<p>This makes it a flexible logging construct that can be injected into any position in a <a href="https://github.com/App-vNext/Polly/wiki/PolicyWrap"><code class="language-plaintext highlighter-rouge">PolicyWrap</code></a> (users have been <a href="https://stackoverflow.com/questions/42952057/polly-policy-to-log-exception-and-rethrow">asking for this</a>).</p>

<p>It also makes for a good blog post example :~)</p>

<h2 id="authoring-a-reactive-custom-policy-log-exceptions-and-fault-results">Authoring a reactive custom policy: Log exceptions and fault-results</h2>

<p>For simplicity, we’ll assume we’re developing a custom policy for use with <a href="https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory">Polly and HttpClientFactory</a>. This means that all executions are async and return <code class="language-plaintext highlighter-rouge">Task&lt;HttpResponseMessage&gt;</code>.</p>

<p>For this, we only need to implement the <code class="language-plaintext highlighter-rouge">IAsyncPolicy&lt;TResult&gt;</code> form of the policy. For other forms, see Part IV of the series.</p>

<h3 id="step-1-name-your-policy-and-extend-the-base-class">Step 1: Name your policy and extend the base class</h3>

<p>The base class for async generic policies is, as you might expect, <code class="language-plaintext highlighter-rouge">AsyncPolicy&lt;TResult&gt;</code>. So start by declaring:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">AsyncLoggingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">AsyncPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span>
<span class="p">{</span>
<span class="p">}</span>
</code></pre></div></div>

<p>By extending the base class, your policy is already plugged in to all the benefits of the existing Polly architecture: the execution-dispatch, the integration into <code class="language-plaintext highlighter-rouge">PolicyWrap</code>.</p>

<p>The compiler or IDE will report:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AsyncLoggingPolicy&lt;TResult&gt; does not implement inherited abstract member AsyncPolicy&lt;TResult&gt;
.ImplementationAsync(Func&lt;Context, CancellationToken, Task&lt;TResult&gt;&gt;, Context, CancellationToken, bool)
</code></pre></div></div>

<h3 id="step-2-add-a-no-op-implementation">Step 2: Add a ‘no-op’ implementation</h3>

<p>Let’s fulfil the abstract method with a stub (your IDE may have a tooltip or shortcut to help):</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">ImplementationAsync</span><span class="p">(</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">CancellationToken</span><span class="p">,</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">action</span><span class="p">,</span> 
    <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> 
    <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">continueOnCapturedContext</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">throw</span> <span class="k">new</span> <span class="nf">NotImplementedException</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This method is where your policy defines its implementation!</p>

<p>Let’s look at the parameters - these are the information passed when the user executes a call through the policy:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Func&lt;Context, CancellationToken, Task&lt;TResult&gt;&gt; action</code> represents the delegate executed through the policy</li>
  <li><code class="language-plaintext highlighter-rouge">Context context</code> is the context passed to execution</li>
  <li><code class="language-plaintext highlighter-rouge">CancellationToken cancellationToken</code> is (you guessed it) the cancellation token passed to execution</li>
  <li>and <code class="language-plaintext highlighter-rouge">bool continueOnCapturedContext</code>, whether the user asked to continue after <code class="language-plaintext highlighter-rouge">await</code>s on a captured context.</li>
</ul>

<p>The parameters map directly to the calling code:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">result</span> <span class="p">=</span> <span class="n">policy</span><span class="p">.</span><span class="nf">ExecuteAsync</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">,</span> <span class="n">continueOnCapturedContext</span><span class="p">);</span>
</code></pre></div></div>

<p>So, let’s flesh out our policy to provide a basic ‘no-op’ implementation. This just executes the code passed to the policy ‘as is’, using the parameters the user passed to execute the <code class="language-plaintext highlighter-rouge">action</code>. The parameter <code class="language-plaintext highlighter-rouge">continueOnCapturedContext</code> controls continuation context after the <code class="language-plaintext highlighter-rouge">await</code>:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">ImplementationAsync</span><span class="p">(</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">CancellationToken</span><span class="p">,</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">action</span><span class="p">,</span> 
    <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> 
    <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">continueOnCapturedContext</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="k">await</span> <span class="nf">action</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">).</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="n">continueOnCapturedContext</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>That’s it for a no-op implementation!</p>

<p><em>Aside</em>: To make it easier for you to get started, Polly <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates">provides all this as a template starting point for a custom policy</a>. To author your own custom policy, you can grab the template repo and copy/paste/rename the classes.</p>

<h3 id="step-3-matching-the-faults-the-user-configured">Step 3: Matching the faults the user configured</h3>

<h4 id="aka-do-what-the-user-told-you">aka: Do what the user told you!</h4>

<p>The first thing any reactive policy needs to do is honor the exceptions and results which the user configured the policy to handle. Remember, the user specifies this with syntax such as:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Policy</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;</span>
    <span class="p">.</span><span class="n">Handle</span><span class="p">&lt;</span><span class="n">HttpRequestException</span><span class="p">&gt;()</span>
    <span class="p">.</span><span class="nf">OrResult</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">response</span><span class="p">.</span><span class="n">StatusCode</span> <span class="p">&gt;=</span> <span class="m">500</span> 
       <span class="p">||</span> <span class="n">response</span><span class="p">.</span><span class="n">StatusCode</span> <span class="p">==</span> <span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">RequestTimeout</span><span class="p">);</span>
</code></pre></div></div>

<p>Polly wraps that configuration up for you in two properties which are available on the configured policy instance:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">ExceptionPredicates</code> - any exceptions the user configured the policy to handle</li>
  <li><code class="language-plaintext highlighter-rouge">ResultPredicates</code> - any results the user configured the policy to handle</li>
</ul>

<p>These are predicates, so essentially the implementation wants to do something like <code class="language-plaintext highlighter-rouge">ExceptionPredicates.Any(predicate =&gt; predicate(exception))</code>. The below skeleton for our reactive policy implementation shows the actual syntax:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">ImplementationAsync</span><span class="p">(</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">CancellationToken</span><span class="p">,</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">action</span><span class="p">,</span> 
    <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> 
    <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">continueOnCapturedContext</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">try</span>
    <span class="p">{</span>
        <span class="n">TResult</span> <span class="n">result</span> <span class="p">=</span> <span class="k">await</span> <span class="nf">action</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">).</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="n">continueOnCapturedContext</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(!</span><span class="n">ResultPredicates</span><span class="p">.</span><span class="nf">AnyMatch</span><span class="p">(</span><span class="n">result</span><span class="p">))</span> <span class="c1">// [1]</span>
        <span class="p">{</span>
            <span class="k">return</span> <span class="n">result</span><span class="p">;</span> <span class="c1">// Not an outcome the policy handles - just return it.</span>
        <span class="p">}</span>

        <span class="cm">/* Here you add your custom logic for the results you handle */</span> <span class="c1">// [3]</span>
    
        <span class="cm">/* The policy then has to return or exit somehow - return the result, substitute another result, or throw an exception */</span> <span class="c1">// [5]</span>
    <span class="p">}</span>
    <span class="k">catch</span> <span class="p">(</span><span class="n">Exception</span> <span class="n">exception</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">Exception</span> <span class="n">handledException</span> <span class="p">=</span> <span class="n">ExceptionPredicates</span><span class="p">.</span><span class="nf">FirstMatchOrDefault</span><span class="p">(</span><span class="n">exception</span><span class="p">);</span> <span class="c1">// [2]</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">handledException</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">throw</span><span class="p">;</span> <span class="c1">// Not an exception the policy handles - propagate the exception.</span>
        <span class="p">}</span>
        
        <span class="cm">/* Here you add your custom logic for the exceptions you handle */</span> <span class="c1">// [4]</span>
    
        <span class="cm">/* The policy then has to return or exit somehow - substitute a result, rethrow the exception, or throw another exception */</span> <span class="c1">// [6]</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Let’s dive in:</p>

<p>At [1] we check whether a returned result matches any of our <code class="language-plaintext highlighter-rouge">ResultPredicates</code>.</p>

<p>If an exception is thrown, we check for matches at [2]. What’s with the syntax there? Why is <code class="language-plaintext highlighter-rouge">handledException</code> different from <code class="language-plaintext highlighter-rouge">exception</code>?</p>

<p>Well, certain call chains can result in messy <code class="language-plaintext highlighter-rouge">AggregateException</code>s with <code class="language-plaintext highlighter-rouge">InnerException</code>s, and writing predicates to match those <code class="language-plaintext highlighter-rouge">InnerException</code>s (including if nested) can be messy. So Polly provides <a href="https://github.com/App-vNext/Polly/wiki/Handling-InnerExceptions-and-AggregateExceptions">in-built <code class="language-plaintext highlighter-rouge">.HandleInner&lt;TException&gt;()</code> syntax</a> to help. This line of code matches those exceptions, whether the user has configured <code class="language-plaintext highlighter-rouge">.HandleInner&lt;&gt;()</code> or straight <code class="language-plaintext highlighter-rouge">.Handle&lt;&gt;()</code> or a mixture:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Exception</span> <span class="n">handledException</span> <span class="p">=</span> <span class="n">ExceptionPredicates</span><span class="p">.</span><span class="nf">FirstMatchOrDefault</span><span class="p">(</span><span class="n">exception</span><span class="p">);</span> <span class="c1">// [2]</span>
</code></pre></div></div>

<p>If Polly plucks a matching <code class="language-plaintext highlighter-rouge">InnerException</code> out of a messy <code class="language-plaintext highlighter-rouge">AggregateException</code> chain, <br />
<code class="language-plaintext highlighter-rouge">handledException</code> will be it. If Polly matches a plain non-inner exception, again, <code class="language-plaintext highlighter-rouge">handledException</code> will be it.</p>

<h3 id="step-4-add-your-custom-functionality">Step 4: Add your custom functionality</h3>

<h4 id="aka-you-hit-the-jackpot-do-your-stuff--then-lets-get-outta-here">aka: You hit the jackpot! Do your stuff … then let’s get outta here!</h4>

<p>If your code hits [3] or [4], the policy has matched a result or exception it was configured to handle - code your custom logic for your policy here!</p>

<p>Finally, your custom policy has to decide how to exit, at [5] and [6].</p>

<p>To be clear, the policy could do anything you choose, as its exit - substitute a different result (as <a href="https://github.com/App-vNext/Polly/wiki/Fallback">Fallback policy</a> does); rethrow a different exception; or just bubble the result or exception it was handling.</p>

<p>And also, you can build any structure you like within <code class="language-plaintext highlighter-rouge">ImplementationAsync(...)</code> - it doesn’t have exactly to follow the form above. Polly’s <a href="https://github.com/App-vNext/Polly/wiki/Retry">Retry policy</a>, for example, as you can guess, builds a loop.</p>

<p>In the logging policy, after we’ve logged, we’ll exit by just returning the matched result or rethrowing the matched exception.</p>

<p>Here’s a (near-final) implementation:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">ILogger</span><span class="p">&gt;</span> <span class="n">LoggerProvider</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>  <span class="c1">// [a]</span>
<span class="n">Action</span><span class="p">&lt;</span><span class="n">ILogger</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">LogAction</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// [b]</span>

<span class="k">protected</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="nf">ImplementationAsync</span><span class="p">(</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">CancellationToken</span><span class="p">,</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">action</span><span class="p">,</span> 
    <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> 
    <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">continueOnCapturedContext</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">try</span>
    <span class="p">{</span>
        <span class="n">TResult</span> <span class="n">result</span> <span class="p">=</span> <span class="k">await</span> <span class="nf">action</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">cancellationToken</span><span class="p">).</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="n">continueOnCapturedContext</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(!</span><span class="n">ResultPredicates</span><span class="p">.</span><span class="nf">AnyMatch</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
        <span class="p">{</span>
            <span class="k">return</span> <span class="n">result</span><span class="p">;</span> <span class="c1">// Not an outcome the policy handles - just return it.</span>
        <span class="p">}</span>

        <span class="n">ILogger</span> <span class="n">logger</span> <span class="p">=</span> <span class="nf">LoggerProvider</span><span class="p">(</span><span class="n">context</span><span class="p">);</span> <span class="c1">// [a]</span>
        <span class="nf">LogAction</span><span class="p">(</span><span class="n">logger</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="k">new</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;(</span><span class="n">result</span><span class="p">));</span> <span class="c1">// [b]</span>

        <span class="c1">// The policy intentionally bubbles the result outwards after logging.</span>
        <span class="k">return</span> <span class="n">result</span><span class="p">;</span> <span class="c1">// [c]</span>
    <span class="p">}</span>
    <span class="k">catch</span> <span class="p">(</span><span class="n">Exception</span> <span class="n">exception</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">Exception</span> <span class="n">handledException</span> <span class="p">=</span> <span class="n">ExceptionPredicates</span><span class="p">.</span><span class="nf">FirstMatchOrDefault</span><span class="p">(</span><span class="n">exception</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">handledException</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">throw</span><span class="p">;</span> <span class="c1">// Not an exception the policy handles - propagate the exception.</span>
        <span class="p">}</span>
        
        <span class="n">ILogger</span> <span class="n">logger</span> <span class="p">=</span> <span class="nf">LoggerProvider</span><span class="p">(</span><span class="n">context</span><span class="p">);</span> <span class="c1">// [a]</span>
        <span class="nf">LogAction</span><span class="p">(</span><span class="n">logger</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="k">new</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;(</span><span class="n">exception</span><span class="p">));</span> <span class="c1">// [b]</span>
        
        <span class="c1">// The policy intentionally bubbles the exception outwards after logging.</span>
        <span class="n">handledException</span><span class="p">.</span><span class="nf">RethrowWithOriginalStackTraceIfDiffersFrom</span><span class="p">(</span><span class="n">exception</span><span class="p">);</span> <span class="c1">// [d]</span>
        <span class="k">throw</span><span class="p">;</span> <span class="c1">// [d]</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>At [c], the policy returns the result it just handled.</p>

<p>The lines marked [d] show some special syntax for rethrowing an exception preserving the original call stack, when Polly’s predicates have worked their magic to match an <code class="language-plaintext highlighter-rouge">InnerException</code> (as described earlier).</p>

<p>What about the lines marked [a] and [b], where we do the actual logging?</p>

<p>We opted to let the user provide [a] a <code class="language-plaintext highlighter-rouge">Func&lt;Context, ILogger&gt;</code> to specify the logger. Why? Well, policies are typically (particularly with HttpClientFactory) configured in the <code class="language-plaintext highlighter-rouge">StartUp</code> file. On the other hand, loggers in .NET Core <em>local to the particular component</em> are usually only resolved at the call site by DI - for instance, a Controller class might take an <code class="language-plaintext highlighter-rouge">ILogger&lt;FooController&gt;</code> by constructor injection.</p>

<p>The <code class="language-plaintext highlighter-rouge">Func&lt;Context, ILogger&gt; loggerProvider</code> allows the user to bridge this, by providing a <code class="language-plaintext highlighter-rouge">Func</code> to select the logger at execution time. <code class="language-plaintext highlighter-rouge">Polly.Context</code> is an execution-scoped context which travels with every Polly execution, and has dictionary-like semantics - users can attach any information they like to it, to pass into the execution. The <a href="TO LINK">worked example at the end of this blog post</a> shows how we’ll pass the local <code class="language-plaintext highlighter-rouge">ILogger</code> instance in to the call in practice; and the Polly wiki covers the general technique <a href="https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory#use-case-exchanging-information-between-policy-execution-and-calling-code">here</a>.</p>

<p><em>Note that the complexity here around obtaining an instance of <code class="language-plaintext highlighter-rouge">ILogger</code> is a factor of the split between early-binding to create the policy on HttpClientFactory and .NET Core’s preference for category-specific <code class="language-plaintext highlighter-rouge">ILogger&lt;TCategory&gt;</code> resolved in a late-binding manner by DI</em>, usually by constructor injection into the relevant component. This complexity is a feature of these dimensions of logging in .NET Core rather than Polly <em>per se</em>. An alternative, simpler approach would replace [a] with a simple <code class="language-plaintext highlighter-rouge">ILogger</code>, and use the overloads described <a href="https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory#configuring-policies-to-use-services-registered-with-di-such-as-iloggert">here</a> to configure the policy with a fixed <code class="language-plaintext highlighter-rouge">ILogger&lt;TFixed&gt;</code> at startup.</p>

<p>To log to the logger, we chose [b] an <code class="language-plaintext highlighter-rouge">Action&lt;ILogger, Context, DelegateResult&lt;TResult&gt;&gt;</code>. You’ll be getting the picture here: It’s good practice to make <code class="language-plaintext highlighter-rouge">Context</code> an input parameter to any delegate you let users configure on a policy. We can let the user attach some custom data to <code class="language-plaintext highlighter-rouge">Context</code> which they want to log (or in your own custom policy, use <code class="language-plaintext highlighter-rouge">Context</code> information to influence policy operation some other way). And, in-built, <code class="language-plaintext highlighter-rouge">Context</code> carries <a href="https://github.com/App-vNext/Polly/wiki/Keys-And-Context-Data">metadata about the Polly execution</a> which can be useful for logging - which Policy is in use, which PolicyWrap, and a CorrelationId for the execution.</p>

<p>Finally, <code class="language-plaintext highlighter-rouge">DelegateResult&lt;TResult&gt;</code> is a <a href="https://github.com/reisenberger/Polly/blob/72c55eabd10c11f5820c4d9742a82313a846cd13/src/Polly.Shared/DelegateResult.cs">discriminated union</a> representing either:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">DelegateResult&lt;TResult&gt;.Exception</code> - the exception the underlying execution threw (or null, if not)</li>
  <li><code class="language-plaintext highlighter-rouge">DelegateResult&lt;TResult&gt;.Result</code> - the result the underlying execution returned.</li>
</ul>

<h3 id="step-5-add-configuration-syntax">Step 5: Add configuration syntax</h3>

<p>Finally, add some configuration syntax so that users can create instances of your policy!</p>

<p>The policy constructor will need to take the parameters:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">ILogger</span><span class="p">&gt;</span> <span class="n">LoggerProvider</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>  <span class="c1">// [a]</span>
<span class="n">Action</span><span class="p">&lt;</span><span class="n">ILogger</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">LogAction</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// [b]</span>
</code></pre></div></div>

<p>However, for a <strong>reactive</strong> policy, users will configure the policy with syntax something like:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Action</span><span class="p">&lt;</span><span class="n">ILogger</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;&gt;</span> <span class="n">logAction</span> <span class="p">=</span> <span class="p">(</span><span class="n">logger</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">outcome</span><span class="p">)</span> <span class="p">=&gt;</span> 
<span class="p">{</span>
    <span class="n">logger</span><span class="p">.</span><span class="nf">LogError</span><span class="p">(</span><span class="s">"The call resulted in outcome: {happened}"</span><span class="p">,</span> <span class="n">outcome</span><span class="p">.</span><span class="n">Exception</span><span class="p">?.</span><span class="n">Message</span> <span class="p">??</span> <span class="n">outcome</span><span class="p">.</span><span class="n">Result</span><span class="p">.</span><span class="n">StatusCode</span><span class="p">.</span><span class="nf">ToString</span><span class="p">());</span>
<span class="p">}</span>

<span class="n">Policy</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;</span>
    <span class="p">.</span><span class="n">Handle</span><span class="p">&lt;</span><span class="n">HttpRequestException</span><span class="p">&gt;()</span>
    <span class="p">.</span><span class="nf">OrResult</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">response</span><span class="p">.</span><span class="n">StatusCode</span> <span class="p">&gt;=</span> <span class="m">500</span> <span class="p">||</span> <span class="n">response</span><span class="p">.</span><span class="n">StatusCode</span> <span class="p">==</span> <span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">RequestTimeout</span><span class="p">)</span>
    <span class="p">.</span><span class="nf">AsyncLog</span><span class="p">(</span><span class="n">ctx</span> <span class="p">=&gt;</span> <span class="n">ctx</span><span class="p">.</span><span class="nf">GetLogger</span><span class="p">(),</span> <span class="n">logAction</span><span class="p">);</span>
</code></pre></div></div>

<p>Or with HttpClientFactory:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Action</span><span class="p">&lt;</span><span class="n">ILogger</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;&gt;</span> <span class="n">logAction</span> <span class="p">=</span> <span class="p">(</span><span class="n">logger</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">outcome</span><span class="p">)</span> <span class="p">=&gt;</span> 
<span class="p">{</span>
    <span class="n">logger</span><span class="p">.</span><span class="nf">LogError</span><span class="p">(</span><span class="s">"The call resulted in outcome: {happened}"</span><span class="p">,</span> <span class="n">outcome</span><span class="p">.</span><span class="n">Exception</span><span class="p">?.</span><span class="n">Message</span> <span class="p">??</span> <span class="n">outcome</span><span class="p">.</span><span class="n">Result</span><span class="p">.</span><span class="n">StatusCode</span><span class="p">.</span><span class="nf">ToString</span><span class="p">());</span>
<span class="p">}</span>

<span class="n">services</span><span class="p">.</span><span class="n">AddHttpClient</span><span class="p">&lt;</span><span class="n">FooClient</span><span class="p">&gt;()</span>
    <span class="p">.</span><span class="nf">AddTransientHttpErrorPolicy</span><span class="p">(</span><span class="n">policy</span> <span class="p">=&gt;</span> <span class="n">policy</span><span class="p">.</span><span class="nf">AsyncLog</span><span class="p">(</span><span class="n">ctx</span> <span class="p">=&gt;</span> <span class="n">ctx</span><span class="p">.</span><span class="nf">GetLogger</span><span class="p">(),</span> <span class="n">logAction</span><span class="p">));</span>
</code></pre></div></div>

<p>How do we make <code class="language-plaintext highlighter-rouge">.AsyncLog(...)</code> follow on from the various <code class="language-plaintext highlighter-rouge">.Handle&lt;&gt;()</code> and <code class="language-plaintext highlighter-rouge">.Or...()</code> clauses? The answer is that handle clauses such as:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Policy</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;</span>
    <span class="p">.</span><span class="n">Handle</span><span class="p">&lt;</span><span class="n">HttpRequestException</span><span class="p">&gt;()</span>
    <span class="p">.</span><span class="nf">OrResult</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">response</span><span class="p">.</span><span class="n">StatusCode</span> <span class="p">&gt;=</span> <span class="m">500</span> 
       <span class="p">||</span> <span class="n">response</span><span class="p">.</span><span class="n">StatusCode</span> <span class="p">==</span> <span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">RequestTimeout</span><span class="p">);</span>
</code></pre></div></div>

<p>return an instance of a special builder type, <code class="language-plaintext highlighter-rouge">PolicyBuilder&lt;TResult&gt;</code>, which encapsulates the choices the user has made about exceptions and results to handle. So the <code class="language-plaintext highlighter-rouge">.AsyncLog(...)</code> overload must be coded as an extension method on this class. Shown combined with the constructor, the pattern looks like this:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">LoggingPolicySyntax</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">static</span> <span class="n">AsyncLoggingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="n">AsyncLog</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;(</span>
      <span class="k">this</span> <span class="n">PolicyBuilder</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="n">policyBuilder</span><span class="p">,</span> <span class="c1">// [i]</span>
      <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">ILogger</span><span class="p">&gt;</span> <span class="n">loggerProvider</span><span class="p">,</span> <span class="c1">// [a]</span>
      <span class="n">Action</span><span class="p">&lt;</span><span class="n">ILogger</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">logAction</span> <span class="c1">// [b]</span>
      <span class="p">)</span>
        <span class="p">{</span>
            <span class="k">return</span> <span class="k">new</span> <span class="n">AsyncLoggingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;(</span>
                <span class="n">policyBuilder</span><span class="p">,</span> <span class="c1">// [i]</span>
                <span class="n">loggerProvider</span><span class="p">,</span>
                <span class="n">logAction</span>
            <span class="p">);</span>
        <span class="p">}</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">class</span> <span class="nc">AsyncLoggingPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">AsyncPolicy</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">ILogger</span><span class="p">&gt;</span> <span class="n">_loggerProvider</span><span class="p">;</span> <span class="c1">// [a]</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="n">Action</span><span class="p">&lt;</span><span class="n">ILogger</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">_logAction</span><span class="p">;</span> <span class="c1">// [b]</span>

    <span class="k">internal</span> <span class="nf">AsyncLoggingPolicy</span><span class="p">(</span>
        <span class="n">PolicyBuilder</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;</span> <span class="n">policyBuilder</span><span class="p">,</span> <span class="c1">// [i]</span>
        <span class="n">Func</span><span class="p">&lt;</span><span class="n">Context</span><span class="p">,</span> <span class="n">ILogger</span><span class="p">&gt;</span> <span class="n">loggerProvider</span><span class="p">,</span>
        <span class="n">Action</span><span class="p">&lt;</span><span class="n">ILogger</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">TResult</span><span class="p">&gt;&gt;</span> <span class="n">logAction</span><span class="p">)</span>
            <span class="p">:</span> <span class="k">base</span><span class="p">(</span><span class="n">policyBuilder</span><span class="p">)</span>  <span class="c1">// [ii]</span>
        <span class="p">{</span>
            <span class="n">_loggerProvider</span> <span class="p">=</span> <span class="n">loggerProvider</span> <span class="p">??</span> <span class="k">throw</span> <span class="k">new</span> <span class="nf">NullReferenceException</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">loggerProvider</span><span class="p">));</span>
            <span class="n">_logAction</span> <span class="p">=</span> <span class="n">logAction</span> <span class="p">??</span> <span class="k">throw</span> <span class="k">new</span> <span class="nf">NullReferenceException</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">logAction</span><span class="p">));</span>
        <span class="p">}</span>
 
    <span class="cm">/* rest of policy implementation as before */</span>

<span class="p">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">policyBuilder</code> instance [i] should be passed down to Polly’s <code class="language-plaintext highlighter-rouge">AsyncPolicy&lt;TResult&gt;</code> base class constructor (as shown at [ii]), so that the <code class="language-plaintext highlighter-rouge">ExceptionPredicates</code> and <code class="language-plaintext highlighter-rouge">ResultPredicates</code> properties can be configured on the policy. These also support Polly’s <a href="https://github.com/App-vNext/Polly/blob/master/README.md#post-execution-capturing-the-result-or-any-final-exception"><code class="language-plaintext highlighter-rouge">.ExecuteAndCaptureAsync(...)</code> syntax</a>.</p>

<h2 id="lets-take-it-for-a-spin">Let’s take it for a spin!</h2>

<p>Let’s take the new <code class="language-plaintext highlighter-rouge">AsyncLoggingPolicy&lt;TResult&gt;</code> for a spin!</p>

<p>The below example includes a number of classes which feature in the <a href="https://github.com/Polly-Contrib/Polly.Contrib.LoggingPolicy">Github repo</a> for this policy:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Program.cs</code>: example program configuring an <code class="language-plaintext highlighter-rouge">AsyncLoggingPolicy&lt;HttpResponseMessage&gt;</code> using <code class="language-plaintext highlighter-rouge">HttpClientFactory</code></li>
  <li><code class="language-plaintext highlighter-rouge">ContextExtensions.cs</code>: helper methods on the <code class="language-plaintext highlighter-rouge">Polly.Context</code> class, to make selection of <code class="language-plaintext highlighter-rouge">ILogger</code> at runtime easier</li>
  <li><code class="language-plaintext highlighter-rouge">FooClient.cs</code>: a typed client configured by <code class="language-plaintext highlighter-rouge">HttpClientFactory</code></li>
  <li><code class="language-plaintext highlighter-rouge">StubErroringDelegatingHandler.cs</code>: a delegating handler also configured by <code class="language-plaintext highlighter-rouge">Program.cs</code> within <code class="language-plaintext highlighter-rouge">FooClient</code>, to randomly generate errors - just to give the <code class="language-plaintext highlighter-rouge">LoggingPolicy&lt;T&gt;</code> some errors for us to log in this demonstration!</li>
</ul>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span>

<span class="k">namespace</span> <span class="nn">Polly.Contrib.LoggingPolicy</span>
<span class="p">{</span>
    <span class="c1">/// &lt;summary&gt;</span>
    <span class="c1">/// Defines extension methods on &lt;see cref="Polly.Context"/&gt; for registering and retrieving instances of &lt;see cref="ILogger"/&gt;.</span>
    <span class="c1">/// &lt;/summary&gt;</span>
    <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">ContextExtensions</span>
    <span class="p">{</span>
        <span class="k">private</span> <span class="k">static</span> <span class="k">readonly</span> <span class="kt">string</span> <span class="n">LoggerKey</span> <span class="p">=</span> <span class="s">$"</span><span class="p">{</span><span class="k">nameof</span><span class="p">(</span><span class="n">LoggingPolicy</span><span class="p">)}</span><span class="s">.Logger"</span><span class="p">;</span>

        <span class="c1">/// &lt;summary&gt;</span>
        <span class="c1">/// Registers a &lt;see cref="ILogger"/&gt; on the Polly execution &lt;see cref="Context"/&gt;, so that a policy from &lt;see cref="Polly.Contrib.LoggingPolicy"/&gt;</span>
        <span class="c1">/// can retrieve it using the &lt;see cref="GetLogger"/&gt; method.</span>
        <span class="c1">/// &lt;/summary&gt;</span>
        <span class="c1">/// &lt;param name="context"&gt;The Polly execution context.&lt;/param&gt;</span>
        <span class="c1">/// &lt;param name="logger"&gt;The logger to register on the execution context.&lt;/param&gt;</span>
        <span class="c1">/// &lt;returns&gt;The Polly execution &lt;see cref="Context"/&gt;, for fluent chaining.&lt;/returns&gt;</span>
        <span class="k">public</span> <span class="k">static</span> <span class="n">Context</span> <span class="nf">WithLogger</span><span class="p">(</span><span class="k">this</span> <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">logger</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">context</span><span class="p">[</span><span class="n">LoggerKey</span><span class="p">]</span> <span class="p">=</span> <span class="n">logger</span><span class="p">;</span>
            <span class="k">return</span> <span class="n">context</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="c1">/// &lt;summary&gt;</span>
        <span class="c1">/// Retrieves a &lt;see cref="ILogger"/&gt; previously registered on the Polly execution &lt;see cref="Context"/&gt;</span>
        <span class="c1">/// using the &lt;see cref="WithLogger"/&gt; method.</span>
        <span class="c1">/// &lt;/summary&gt;</span>
        <span class="c1">/// &lt;param name="context"&gt;The Polly execution context.&lt;/param&gt;</span>
        <span class="c1">/// &lt;returns&gt;The &lt;see cref="ILogger"/&gt;; or null, if none was registered.&lt;/returns&gt;</span>
        <span class="k">public</span> <span class="k">static</span> <span class="n">ILogger</span> <span class="nf">GetLogger</span><span class="p">(</span><span class="k">this</span> <span class="n">Context</span> <span class="n">context</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="nf">TryGetValue</span><span class="p">(</span><span class="n">LoggerKey</span><span class="p">,</span> <span class="k">out</span> <span class="kt">object</span> <span class="n">logger</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="k">return</span> <span class="n">logger</span> <span class="k">as</span> <span class="n">ILogger</span><span class="p">;</span>
            <span class="p">}</span>

            <span class="k">return</span> <span class="k">null</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Polly</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Polly.Contrib.LoggingPolicy</span><span class="p">;</span>

<span class="k">namespace</span> <span class="nn">ConsoleAppExampleForBlogPost</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">class</span> <span class="nc">FooClient</span>
    <span class="p">{</span>
        <span class="k">private</span> <span class="k">readonly</span> <span class="n">ILogger</span> <span class="n">logger</span><span class="p">;</span>
        <span class="k">private</span> <span class="k">readonly</span> <span class="n">HttpClient</span> <span class="n">client</span><span class="p">;</span>

        <span class="k">public</span> <span class="nf">FooClient</span><span class="p">(</span><span class="n">ILogger</span><span class="p">&lt;</span><span class="n">FooClient</span><span class="p">&gt;</span> <span class="n">logger</span><span class="p">,</span> <span class="n">HttpClient</span> <span class="n">client</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">this</span><span class="p">.</span><span class="n">logger</span> <span class="p">=</span> <span class="n">logger</span><span class="p">;</span>
            <span class="k">this</span><span class="p">.</span><span class="n">client</span> <span class="p">=</span> <span class="n">client</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="k">public</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="nf">GetStringAsync</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">CancellationToken</span> <span class="n">token</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="kt">var</span> <span class="n">context</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Context</span> <span class="p">{</span> <span class="p">[</span><span class="s">"url"</span><span class="p">]</span> <span class="p">=</span> <span class="n">url</span> <span class="p">}.</span><span class="nf">WithLogger</span><span class="p">(</span><span class="n">logger</span><span class="p">);</span>
            <span class="n">HttpRequestMessage</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span>
            <span class="n">request</span><span class="p">.</span><span class="nf">SetPolicyExecutionContext</span><span class="p">(</span><span class="n">context</span><span class="p">);</span>

            <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="nf">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">token</span><span class="p">);</span>

            <span class="k">return</span> <span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="nf">ReadAsStringAsync</span><span class="p">();</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Collections.Generic</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Microsoft.Extensions.DependencyInjection</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Polly</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Polly.Contrib.LoggingPolicy</span><span class="p">;</span>

<span class="k">namespace</span> <span class="nn">ConsoleAppExampleForBlogPost</span>
<span class="p">{</span>
    <span class="k">class</span> <span class="nc">Program</span>
    <span class="p">{</span>
        <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">IServiceCollection</span> <span class="n">services</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ServiceCollection</span><span class="p">();</span>

            <span class="n">services</span><span class="p">.</span><span class="nf">AddLogging</span><span class="p">(</span><span class="n">configure</span> <span class="p">=&gt;</span> <span class="n">configure</span><span class="p">.</span><span class="nf">AddConsole</span><span class="p">());</span>

            <span class="k">void</span> <span class="nf">LogAction</span><span class="p">(</span><span class="n">ILogger</span> <span class="n">logger</span><span class="p">,</span> <span class="n">Context</span> <span class="n">context</span><span class="p">,</span> <span class="n">DelegateResult</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;</span> <span class="n">outcome</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="c1">// This logging can be as sophisticated as you like; this is a simple example to illustrate principles.</span>
                <span class="kt">string</span> <span class="n">url</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="nf">GetValueOrDefault</span><span class="p">(</span><span class="s">"url"</span><span class="p">).</span><span class="nf">ToString</span><span class="p">()</span> <span class="p">??</span> <span class="s">"[unknown]"</span><span class="p">;</span>
                <span class="kt">string</span> <span class="n">happened</span> <span class="p">=</span> <span class="n">outcome</span><span class="p">.</span><span class="n">Exception</span><span class="p">?.</span><span class="n">Message</span> <span class="p">??</span> <span class="n">outcome</span><span class="p">.</span><span class="n">Result</span><span class="p">.</span><span class="n">StatusCode</span><span class="p">.</span><span class="nf">ToString</span><span class="p">();</span>
                <span class="n">logger</span><span class="p">?.</span><span class="nf">LogInformation</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">url</span><span class="p">}</span><span class="s">: </span><span class="p">{</span><span class="n">happened</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
            <span class="p">}</span>

            <span class="n">services</span><span class="p">.</span><span class="n">AddHttpClient</span><span class="p">&lt;</span><span class="n">FooClient</span><span class="p">&gt;()</span>
                
                <span class="c1">// Whatever standard resilience logic you want.</span>
                <span class="p">.</span><span class="nf">AddTransientHttpErrorPolicy</span><span class="p">(</span><span class="n">policy</span> <span class="p">=&gt;</span> <span class="n">policy</span><span class="p">.</span><span class="nf">RetryAsync</span><span class="p">(</span><span class="m">5</span><span class="p">))</span>
                
                <span class="c1">// Logging policy to log transient faults as they occur.</span>
                <span class="c1">// The logging policy is inside the retry policy, so will log faults from each try, before they are retried.</span>
                <span class="p">.</span><span class="nf">AddTransientHttpErrorPolicy</span><span class="p">(</span><span class="n">policy</span> <span class="p">=&gt;</span> <span class="n">policy</span><span class="p">.</span><span class="nf">AsyncLog</span><span class="p">(</span><span class="n">ctx</span> <span class="p">=&gt;</span> <span class="n">ctx</span><span class="p">.</span><span class="nf">GetLogger</span><span class="p">(),</span> <span class="n">LogAction</span><span class="p">))</span>
                
                <span class="c1">// For this test example we add a stub DelegatingHandler which will manufacture faults for us.</span>
                <span class="p">.</span><span class="nf">AddHttpMessageHandler</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="nf">StubErroringDelegatingHandler</span><span class="p">());</span>


            <span class="c1">// Quickly test our FooClient.</span>
            <span class="kt">var</span> <span class="n">fooClient</span> <span class="p">=</span> <span class="n">services</span>
                <span class="p">.</span><span class="nf">BuildServiceProvider</span><span class="p">()</span>
                <span class="p">.</span><span class="n">GetRequiredService</span><span class="p">&lt;</span><span class="n">FooClient</span><span class="p">&gt;();</span>

            <span class="kt">string</span> <span class="n">result</span> <span class="p">=</span> <span class="k">await</span> <span class="n">fooClient</span><span class="p">.</span><span class="nf">GetStringAsync</span><span class="p">(</span><span class="s">"https://www.google.com"</span><span class="p">,</span> <span class="k">default</span><span class="p">(</span><span class="n">CancellationToken</span><span class="p">));</span>

            <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Got result: </span><span class="p">{</span><span class="n">result</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>

            <span class="n">Console</span><span class="p">.</span><span class="nf">ReadKey</span><span class="p">();</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Net</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span>

<span class="k">namespace</span> <span class="nn">ConsoleAppExampleForBlogPost</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">class</span> <span class="nc">StubErroringDelegatingHandler</span> <span class="p">:</span> <span class="n">DelegatingHandler</span>
    <span class="p">{</span>
        <span class="k">private</span> <span class="k">readonly</span> <span class="n">Random</span> <span class="n">random</span><span class="p">;</span>

        <span class="k">public</span> <span class="nf">StubErroringDelegatingHandler</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="n">random</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Random</span><span class="p">();</span>
        <span class="p">}</span>

        <span class="k">protected</span> <span class="k">override</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">HttpResponseMessage</span><span class="p">&gt;</span> <span class="nf">SendAsync</span><span class="p">(</span><span class="n">HttpRequestMessage</span> <span class="n">request</span><span class="p">,</span> <span class="n">CancellationToken</span> <span class="n">cancellationToken</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">switch</span> <span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="nf">Next</span><span class="p">(</span><span class="m">3</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="k">case</span> <span class="m">1</span><span class="p">:</span>
                    <span class="k">return</span> <span class="n">Task</span><span class="p">.</span><span class="nf">FromResult</span><span class="p">(</span><span class="k">new</span> <span class="nf">HttpResponseMessage</span><span class="p">(</span><span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">InternalServerError</span><span class="p">));</span>
                <span class="k">case</span> <span class="m">2</span><span class="p">:</span>
                    <span class="k">throw</span> <span class="k">new</span> <span class="nf">HttpRequestException</span><span class="p">();</span>

                <span class="k">default</span><span class="p">:</span>
                    <span class="k">return</span> <span class="n">Task</span><span class="p">.</span><span class="nf">FromResult</span><span class="p">(</span><span class="k">new</span> <span class="nf">HttpResponseMessage</span><span class="p">(</span><span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">OK</span><span class="p">){</span><span class="n">Content</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">StringContent</span><span class="p">(</span><span class="s">"Dummy content from the stub helper class."</span><span class="p">)});</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Here’s some example output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>info: System.Net.Http.HttpClient.FooClient.LogicalHandler[100]
      Start processing HTTP request GET https://www.google.com/
info: ConsoleAppExampleForBlogPost.FooClient[0]
      https://www.google.com: InternalServerError
info: ConsoleAppExampleForBlogPost.FooClient[0]
      https://www.google.com: Exception of type 'System.Net.Http.HttpRequestException' was thrown.
info: ConsoleAppExampleForBlogPost.FooClient[0]
      https://www.google.com: InternalServerError
info: ConsoleAppExampleForBlogPost.FooClient[0]
      https://www.google.com: Exception of type 'System.Net.Http.HttpRequestException' was thrown.
info: ConsoleAppExampleForBlogPost.FooClient[0]
      https://www.google.com: Exception of type 'System.Net.Http.HttpRequestException' was thrown.
info: System.Net.Http.HttpClient.FooClient.LogicalHandler[101]
      End processing HTTP request after 47.3552ms - OK
Got result: Dummy content from the stub helper class.
</code></pre></div></div>

<p>Note that this output includes some default logging from <code class="language-plaintext highlighter-rouge">HttpClient</code> as well as that provided by <code class="language-plaintext highlighter-rouge">AsyncLoggingPolicy&lt;TResult&gt;</code>.</p>

<h3 id="where-can-i-get-the-code">Where can I get the code?</h3>

<p>The full source code for <code class="language-plaintext highlighter-rouge">AsyncLoggingPolicy&lt;TResult&gt;</code> and the test console app is available in <a href="https://github.com/Polly-Contrib/Polly.Contrib.LoggingPolicy">this Github repo</a>.</p>

<h2 id="where-next">Where next?</h2>

<h3 id="grab-the-template">Grab the template</h3>

<p>If you want to dive straight in to experimenting with a custom policy, just grab the <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates">template repo</a> and start copy/paste/rename/extend-ing the classes.</p>

<h3 id="authoring-a-proactive-custom-policy">Authoring a proactive custom policy</h3>

<p>If you haven’t already looked at it, <a href="/2019/02/13/authoring-a-proactive-polly-policy-custom-policies-part-ii.html">Part II</a> covers authoring a <em>proactive</em> custom policy. The example chosen captures execution timing for any execution through the policy.</p>

<h3 id="understanding-other-forms-of-polly-policy">Understanding other forms of Polly policy</h3>

<p><a href="/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv.html">Part IV</a> looks at how to author other forms of policy - synchronous policies and non-generic policies - in the most efficient manner.</p>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/dylan-reisenberger.png&quot;, &quot;website&quot;=&gt;&quot;http://software.reisenberger.net/&quot;, &quot;bio&quot;=&gt;&quot;Dylan is the lead contributor and architect on Polly, and the brains behind the roadmap, which is seeing Polly growing into the most robust, flexible and fully-featured resilience library for .NET!&quot;}</name></author><summary type="html"><![CDATA[In this article we’ll build our first reactive custom Polly policy: a policy to log exceptions or fault-results.]]></summary></entry><entry><title type="html">Custom policies for all execution types (Custom policies Part IV)</title><link href="https://thepollyproject.org/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv.html" rel="alternate" type="text/html" title="Custom policies for all execution types (Custom policies Part IV)" /><published>2019-02-13T00:00:00+00:00</published><updated>2019-02-13T00:00:00+00:00</updated><id>https://thepollyproject.org/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv</id><content type="html" xml:base="https://thepollyproject.org/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv.html"><![CDATA[<p>In the previous articles in this series, we have seen how to author custom reactive and proactive Polly policies:</p>

<ul>
  <li><a href="/2019/02/13/introducing-custom-polly-policies-and-polly-contrib-custom-policies-part-i.html">Part I: Introducing custom Polly policies and the Polly.Contrib</a></li>
  <li><a href="/2019/02/13/authoring-a-proactive-polly-policy-custom-policies-part-ii.html">Part II: Authoring a proactive custom policy</a> (a policy which acts on all executions)</li>
  <li><a href="/2019/02/13/authoring-a-reactive-polly-policy-custom-policies-part-iii-2.html">Part III: Authoring a reactive custom policy</a> (a policy which react to faults).</li>
</ul>

<p>This article in the series - Part IV - explains (with links to examples) the easiest way to author all forms of a Polly policy, for both sync and async, and both generic and non-generic cases.</p>

<h3 id="the-four-forms-of-each-polly-policy">The four forms of each Polly policy</h3>

<p>For simplicity, Parts II and III of this series assumed we were developing a custom policy for use with <a href="https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory">Polly and HttpClientFactory</a>. This means that all executions were async and returned <code class="language-plaintext highlighter-rouge">Task&lt;HttpResponseMessage&gt;</code>. This meant we only needed to demonstrate the <code class="language-plaintext highlighter-rouge">AsyncPolicy&lt;TResult&gt;</code> form of each policy.</p>

<p>Those familiar with Polly will know that policies offered by Polly in fact exist in four forms:</p>

<ul>
  <li>synchronous non-generic : <code class="language-plaintext highlighter-rouge">Policy</code></li>
  <li>synchronous generic : <code class="language-plaintext highlighter-rouge">Policy&lt;TResult&gt;</code></li>
  <li>asynchronous non-generic : <code class="language-plaintext highlighter-rouge">AsyncPolicy</code></li>
  <li>asynchronous generic : <code class="language-plaintext highlighter-rouge">AsyncPolicy&lt;TResult&gt;</code></li>
</ul>

<p>A Polly policy intended to be generally useful (for example, to be offered as a nuget package) should generally support all four of these forms. However, in fact only implementing two forms is necessary:</p>

<ul>
  <li>synchronous generic (ie the expected implementation for <code class="language-plaintext highlighter-rouge">Policy&lt;TResult&gt;</code>)</li>
  <li>asynchronous generic (the expected implementation for <code class="language-plaintext highlighter-rouge">AsyncPolicy&lt;TResult&gt;</code>)</li>
</ul>

<p>This blog post explains a pattern for achieving that simplification.</p>

<h3 id="separate-sync-and-async-implementations">Separate sync and async implementations</h3>

<p>It should be relatively obvious that separate sync and async implementations are needed. Async is viral. Async implementations need to be able to execute the <code class="language-plaintext highlighter-rouge">Func&lt;Context, CancellationToken, Task&lt;TResult&gt;&gt;</code> passed by the user to <code class="language-plaintext highlighter-rouge">policy.ExecuteAsync(...)</code>. To do this they have to use <code class="language-plaintext highlighter-rouge">await</code> internally.</p>

<p>Synchronous implementations, on the other hand, cannot use <code class="language-plaintext highlighter-rouge">await</code> internally.</p>

<h3 id="common-implementations-for-non-generic-and-generic-policy-forms">Common implementations for non-generic and generic policy forms</h3>

<p>Consider for a moment the synchronous non-generic <code class="language-plaintext highlighter-rouge">Policy</code> (eg <code class="language-plaintext highlighter-rouge">RetryPolicy</code>). Users can either (among various related overloads):</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">.Execute(Action)</code>; or</li>
  <li><code class="language-plaintext highlighter-rouge">.Execute&lt;TResult&gt;(Func&lt;TResult&gt;)</code>.</li>
</ul>

<p>Polly avoids you having to write a separate implementation for the <code class="language-plaintext highlighter-rouge">Action</code> case by simply executing an <code class="language-plaintext highlighter-rouge">Action action</code> through the <code class="language-plaintext highlighter-rouge">Func&lt;TResult&gt;</code> implementation, as the equivalent of:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Func&lt;object&gt; wrapper = () =&gt; { action(); return ThrowAwaySingleton; }
</code></pre></div></div>

<p>(In current implementations, in fact an empty struct rather than object is used.)</p>

<p>Similar simplifications exist for the async case.</p>

<p>The net effect of this is that the only implementations needed are:</p>

<ul>
  <li>a single <code class="language-plaintext highlighter-rouge">TResult</code>-returning implementation for both non-generic and generic synchronous policy forms</li>
  <li>a single <code class="language-plaintext highlighter-rouge">Task&lt;TResult&gt;</code>-returning implementation for both non-generic and generic asynchronous policy forms</li>
</ul>

<h3 id="seeing-the-simplification-in-practice">Seeing the simplification in practice</h3>

<p>A suggested implementation to achieve the simplification is shown in our custom policy templates (and also ready for you to lift off the shelf as a template):</p>

<ul>
  <li>a <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates/blob/04de137ddb518fd8adadb43408bad5f58df93640/ProactivePolicyTemplate/src/Polly.Contrib.ProactiveCustomPolicyTemplate/ProactiveFooEngine.cs">common implementation as a static method in a third class</a> (often called <code class="language-plaintext highlighter-rouge">FooEngine</code>)</li>
  <li>the non-generic form of the policy just <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates/blob/04de137ddb518fd8adadb43408bad5f58df93640/ProactivePolicyTemplate/src/Polly.Contrib.ProactiveCustomPolicyTemplate/ProactiveFooPolicy.cs#L36-L49">delegating to this implementation</a></li>
  <li>the generic form of the policy <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates/blob/04de137ddb518fd8adadb43408bad5f58df93640/ProactivePolicyTemplate/src/Polly.Contrib.ProactiveCustomPolicyTemplate/ProactiveFooPolicyTResult.cs#L35-L48">delegating to the same implementation</a></li>
</ul>

<p>The async files in <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates/tree/04de137ddb518fd8adadb43408bad5f58df93640/ProactivePolicyTemplate/src/Polly.Contrib.ProactiveCustomPolicyTemplate">the same folder as above</a> also demonstrate the same pattern for async policies.</p>

<p>Any policy implementation in the main Polly repo also demonstrates the pattern.</p>

<h2 id="where-next">Where next?</h2>

<p>This concludes our series on authoring custom policies in Polly.</p>

<h3 id="grab-the-template">Grab the template</h3>

<p>If you want to dive straight in to experimenting with a custom policy, just grab the <a href="https://github.com/Polly-Contrib/Polly.Contrib.CustomPolicyTemplates">template repo</a> and start copy/paste/rename/extend-ing the classes.</p>

<p>For any questions, reach out to the Polly team at <a href="https://github.com/App-vNext/Polly/">Polly github</a> or <a href="http://www.pollytalk.org/">Polly slack</a>.</p>

<p>If you’d like your custom policy to be part of <a href="https://github.com/Polly-Contrib">Polly.Contrib</a>, <a href="http://www.pollytalk.org/">contact us on Polly slack</a>, we’ll have some brief discussion to understand how the policy fits, then we can set up a Polly.Contrib repo - to which you have full rights - to help you manage and deliver your awesomeness to the Polly community!</p>

<p>Happy customising!</p>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/dylan-reisenberger.png&quot;, &quot;website&quot;=&gt;&quot;http://software.reisenberger.net/&quot;, &quot;bio&quot;=&gt;&quot;Dylan is the lead contributor and architect on Polly, and the brains behind the roadmap, which is seeing Polly growing into the most robust, flexible and fully-featured resilience library for .NET!&quot;}</name></author><summary type="html"><![CDATA[In the previous articles in this series, we have seen how to author custom reactive and proactive Polly policies:]]></summary></entry><entry><title type="html">Introducing custom Polly policies and Polly.Contrib (Custom policies Part I)</title><link href="https://thepollyproject.org/2019/02/13/introducing-custom-polly-policies-and-polly-contrib-custom-policies-part-i.html" rel="alternate" type="text/html" title="Introducing custom Polly policies and Polly.Contrib (Custom policies Part I)" /><published>2019-02-13T00:00:00+00:00</published><updated>2019-02-13T00:00:00+00:00</updated><id>https://thepollyproject.org/2019/02/13/introducing-custom-polly-policies-and-polly-contrib-custom-policies-part-i</id><content type="html" xml:base="https://thepollyproject.org/2019/02/13/introducing-custom-polly-policies-and-polly-contrib-custom-policies-part-i.html"><![CDATA[<h1 id="introducing-custom-policies">Introducing custom policies</h1>

<p>The Polly team have long wanted to allow users to extend Polly’s capability with custom policies.</p>

<p><a href="https://www.nuget.org/packages/Polly/7.0.0">Polly v7.0</a> introduces a simple mechanism for authoring custom policies which integrate fully with the existing Polly architecture: the fault-handling syntax, the execution overloads, and the ability to combine policies in a <code class="language-plaintext highlighter-rouge">PolicyWrap</code>.</p>

<p>This article introduces custom policies and the Polly.Contrib. If you’re just interested in the how, skip straight to:</p>

<ul>
  <li><a href="/2019/02/13/authoring-a-proactive-polly-policy-custom-policies-part-ii.html">Part II: Authoring a non-reactive custom policy</a> (a policy which acts on all executions)</li>
  <li><a href="/2019/02/13/authoring-a-reactive-polly-policy-custom-policies-part-iii-2.html">Part III: Authoring a reactive custom policy</a> (a policy which react to faults).</li>
  <li><a href="/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv.html">Part IV: Custom policies for all execution types</a>: sync and async, generic and non-generic.</li>
</ul>

<h2 id="why-custom-policies">Why custom policies?</h2>

<p>There were three drivers for introducing custom policies to Polly:</p>

<h4 id="1-to-allow-users-to-write-any-custom-policy">1. To allow users to write <em>any</em> custom Policy</h4>

<p>Custom policies allow you to use <code class="language-plaintext highlighter-rouge">PolicyWrap</code> as a generalised execution-dispatch wrapper - your custom Policy can act as middleware for <em>any</em> execution.</p>

<p>There is no limit to what custom policies can do (we don’t impose a structure) - a new policy could add extra information, capture extra information, intervene in how the passed code actually executes (as many Polly policies do), schedule execution in a new way …</p>

<h4 id="2-to-start-a-pollycontrib">2. To start a Polly.Contrib</h4>

<p>Sometimes the community has more ideas for features than the core Polly maintainers have time to build! As well as accepting PRs into Polly, we want to give the community easier ways to explore and author add-ons to Polly - be that cache providers, syntax additions, or custom policies which can integrate with all the goodness of the existing Polly execution dispatch.</p>

<p>The Polly team is kick-starting the Polly.Contrib with:</p>

<ul>
  <li>blank templates for authoring your own custom policy - these ready-made repos integrate to the latest Polly and have built-in build-script packaging to nuget</li>
  <li>an example custom policy to capture execution timings</li>
  <li>an example custom policy simply to log exceptions/faults and rethrow.</li>
</ul>

<p>To get going, simply fork/duplicate one of the blank templates and code away!</p>

<p>If you’d like your custom policy to be part of <a href="https://github.com/Polly-Contrib">Polly.Contrib</a>, that’d be awesome (in fact we actively encourage it!). Bringing your custom policy (or other contribution) into the Polly-Contrib gives you:</p>

<ul>
  <li>exposure and recognition under the Polly brand</li>
  <li>in-built CI (AppVeyor) which builds to nuget packages</li>
  <li>ability to publish the nugets under the Polly-Contrib organisation</li>
  <li>involvement in a wider team who can support and advise.</li>
</ul>

<p><a href="http://www.pollytalk.org/">Contact us on Polly slack</a> to move your contrib into Polly-Contrib and we can help organise delivering your awesomeness to the Polly community!</p>

<h4 id="3-to-deliver-new-functionality-outside-the-main-polly-package-welcome-simmy">3. To deliver new functionality outside the main Polly package (…“Welcome Simmy!”)</h4>

<p><a href="https://github.com/Polly-Contrib/Simmy">Simmy</a> is a major new package from the Polly team and some awesome contributors <a href="https://github.com/vany0114">@vany0114</a> and <a href="https://github.com/mebjas">@mebjas</a>. Simmy opens a path for <strong>chaos-engineering</strong> and <strong>fault injection</strong> using Polly. It’s aimed at both live-testing the resilience of your production systems; and simulating faults in the unit testing or CI phase.</p>

<p>As a fault-<em>injection</em> tool, Simmy has a different focus to Polly, and we wanted to host the new concept in a package with its own name and identity.</p>

<h2 id="where-next">Where next?</h2>

<p>To learn how to author your first custom policy, skip straight to:</p>

<ul>
  <li><a href="/2019/02/13/authoring-a-proactive-polly-policy-custom-policies-part-ii.html">Part II: Authoring a non-reactive custom policy</a> (a policy which acts on all executions)</li>
  <li><a href="/2019/02/13/authoring-a-reactive-polly-policy-custom-policies-part-iii-2.html">Part III: Authoring a reactive custom policy</a> (a policy which react to faults).</li>
  <li><a href="/2019/02/13/custom-policies-for-all-execution-types-custom-policies-part-iv.html">Part IV: Custom policies for all execution types</a>: sync and async, generic and non-generic.</li>
</ul>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/dylan-reisenberger.png&quot;, &quot;website&quot;=&gt;&quot;http://software.reisenberger.net/&quot;, &quot;bio&quot;=&gt;&quot;Dylan is the lead contributor and architect on Polly, and the brains behind the roadmap, which is seeing Polly growing into the most robust, flexible and fully-featured resilience library for .NET!&quot;}</name></author><summary type="html"><![CDATA[Introducing custom policies]]></summary></entry><entry><title type="html">Policy recommendations for Azure Cognitive Services</title><link href="https://thepollyproject.org/2018/03/06/policy-recommendations-for-azure-cognitive-services.html" rel="alternate" type="text/html" title="Policy recommendations for Azure Cognitive Services" /><published>2018-03-06T00:00:00+00:00</published><updated>2018-03-06T00:00:00+00:00</updated><id>https://thepollyproject.org/2018/03/06/policy-recommendations-for-azure-cognitive-services</id><content type="html" xml:base="https://thepollyproject.org/2018/03/06/policy-recommendations-for-azure-cognitive-services.html"><![CDATA[<p><img src="/assets/images/2018/03/Polly-Heart-Cognitive-1.png" alt="Policy recommendations for Azure Cognitive Services" /></p>

<p><a href="https://azure.microsoft.com/services/cognitive-services/">Azure Cognitive Services</a> is an excellent series of cloud-based APIs that open up a world of artificial intelligence (AI) opportunities that you can easily add to your applications and data process flow. Each service contains a set of trained and field-tested machine learning models that are continuously retrained for greater accuracy over time. Using these Cognitive Services models is as simple as making a REST call, which can be invoked from any application or process that is able to do so. <a href="https://docs.microsoft.com/azure/architecture/data-guide/technology-choices/cognitive-services">Read more</a> about the available services.</p>

<h3 id="the-challenge">The challenge</h3>

<p>Like most public APIs, Cognitive Services invokes rate limiting for your requests, depending on the pricing plan you choose.</p>

<p><img src="/assets/images/2018/03/Cognitive-Services-pricing-plans.png" alt="Azure Cognitive Services pricing plans showing rate limits" /></p>

<p>The above screen capture shows the available pricing tiers for the Computer Vision API. <strong>F0 - Free</strong> is limited to 20 calls per minute, while <strong>S1 - Standard</strong> is limited to 10 calls per second.</p>

<p>The challenge here is obvious: you can easily hit these rate limits during busy periods of traffic, or when batch processing many items that result in multiple calls to the API within a short time frame. There are two ways to approach this challenge. The first is by being <strong>proactive</strong>, and throttle requests to the API from your application. The second approach is <strong>reactive</strong>. This means that you alter your application or process to slow down or pause requests to allow the service to recover.</p>

<p>Polly currently has a <a href="https://github.com/App-vNext/Polly/wiki/Polly-Roadmap#rate-limit-policy">Rate-limit Policy</a> on the road map. There is currently no plan to create this policy (we could use your help!), but the road map link above does refer to a couple of different options for doing this yourself. Because of this, we’ll focus on the reactionary approach, and one way you can create and use a resiliency strategy through the combination of a couple of different policies.</p>

<h3 id="the-environment">The environment</h3>

<p>In this example, I have created an <a href="https://docs.microsoft.com/azure/azure-functions/functions-overview">Azure Function</a> that is triggered whenever a photo is uploaded to an Azure <a href="https://docs.microsoft.com/azure/storage/blobs/storage-blobs-introduction">Blob Storage</a> container. If you’ve not heard of or used Azure Functions, I highly recommend looking into it further. I’ve been diving head-first into serverless lately, and I believe there are a lot of great capabilities around this space. The most interesting aspect about serverless (though there are still servers in play) is how you only pay for what you use. Azure Functions, as opposed to standard App Services, uses sub-second billing on the <a href="https://docs.microsoft.com/azure/azure-functions/functions-overview#pricing">consumption plan</a>. This means you only pay for when the function is used, rather than paying a monthly fee for the privilege of being able to use it. Another benefit is its ability to automatically scale out to n-number of servers to meet demand, all without any configuration on my part. After the deluge of requests subside, the function will scale back to zero servers, or however are needed for incoming requests.</p>

<p>The purpose of my function is to perform an object character recognition (OCR) process on each uploaded image as it is added to the storage container. To do this, I am using the <a href="https://docs.microsoft.com/en-us/azure/cognitive-services/computer-vision/home">Computer Vision API</a> Cognitive Service.</p>

<p>Below is a diagram of my overall solution. We will just be focusing on the left-hand side for this post:</p>

<p><img src="/assets/images/2018/03/Polly-resiliency-Functions-Cognitive-Services.png" alt="Architecture diagram for Blob Storage, Azure Functions, and Computer Vision API" /></p>

<h3 id="creating-a-resiliency-policy-with-polly">Creating a resiliency policy with Polly</h3>

<p>Let’s start with the overall resiliency policy, then work backwards from there. There are two policies we’ll use a Retry policy (<a href="https://github.com/App-vNext/Polly#wait-and-retry">wait and retry</a>), and a <a href="https://github.com/App-vNext/Polly#circuit-breaker">Circuit Breaker</a> policy. Because we want these two policies to work together, we’ll use a <a href="https://github.com/App-vNext/Polly#policywrap">PolicyWrap</a> to combine them.</p>

<p>The method below creates a Polly-based resiliency strategy that does the following when communicating with the external (downstream) Computer Vision API service:</p>

<p>If requests to the service are being throttled, as indicated by 429 or 503 responses, and try again in a bit by exponentially backing off each time. This should give the service time to recover or allow enough time to pass that removes the throttling restriction. is implemented through the <code class="language-plaintext highlighter-rouge">WaitAndRetry</code> policy named <strong>waitAndRetryPolicy</strong>.</p>

<p>Alternately, if requests to the service result in an <code class="language-plaintext highlighter-rouge">HttpResponseException</code>, or a number of codes worth retrying (such as 500, 502, or 504), break the circuit to block any more for the specified period of time, send a test request to see if the error is still occurring, then reset the circuit once successful.</p>

<p>These policies are executed through the <code class="language-plaintext highlighter-rouge">PolicyWrap</code> policy that is returned by the method.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/// &lt;summary&gt;
/// Creates a Polly-based resiliency strategy that helps deal with transient faults when communicating
/// with the external (downstream) Computer Vision API service.
/// &lt;/summary&gt;
/// &lt;returns&gt;&lt;/returns&gt;
private PolicyWrap&lt;HttpResponseMessage&gt; DefineAndRetrieveResiliencyStrategy()  
{
    // Retry when these status codes are encountered.
    HttpStatusCode[] httpStatusCodesWorthRetrying = {
       HttpStatusCode.InternalServerError, // 500
       HttpStatusCode.BadGateway, // 502
       HttpStatusCode.GatewayTimeout // 504
    };

    // Define our waitAndRetry policy: retry n times with an exponential backoff in case the Computer Vision API throttles us for too many requests.
    var waitAndRetryPolicy = Policy
        .HandleResult&lt;HttpResponseMessage&gt;(e =&gt; e.StatusCode == HttpStatusCode.ServiceUnavailable ||
            e.StatusCode == (System.Net.HttpStatusCode)429)
        .WaitAndRetryAsync(10, // Retry 10 times with a delay between retries before ultimately giving up
            attempt =&gt; TimeSpan.FromSeconds(0.25 * Math.Pow(2, attempt)), // Back off!  2, 4, 8, 16 etc times 1/4-second
                                                                          //attempt =&gt; TimeSpan.FromSeconds(6), // Wait 6 seconds between retries
            (exception, calculatedWaitDuration) =&gt;
            {
                _log.Info($"Computer Vision API server is throttling our requests. Automatically delaying for {calculatedWaitDuration.TotalMilliseconds}ms");
            }
        );

    // Define our first CircuitBreaker policy: Break if the action fails 4 times in a row.
    // This is designed to handle Exceptions from the Computer Vision API, as well as
    // a number of recoverable status messages, such as 500, 502, and 504.
    var circuitBreakerPolicyForRecoverable = Policy
        .Handle&lt;HttpResponseException&gt;()
        .OrResult&lt;HttpResponseMessage&gt;(r =&gt; httpStatusCodesWorthRetrying.Contains(r.StatusCode))
        .CircuitBreakerAsync(
            handledEventsAllowedBeforeBreaking: 3,
            durationOfBreak: TimeSpan.FromSeconds(3),
            onBreak: (outcome, breakDelay) =&gt;
            {
                _log.Info($"Polly Circuit Breaker logging: Breaking the circuit for {breakDelay.TotalMilliseconds}ms due to: {outcome.Exception?.Message ?? outcome.Result.StatusCode.ToString()}");
            },
            onReset: () =&gt; _log.Info("Polly Circuit Breaker logging: Call ok... closed the circuit again"),
            onHalfOpen: () =&gt; _log.Info("Polly Circuit Breaker logging: Half-open: Next call is a trial")
        );

    // Combine the waitAndRetryPolicy and circuit breaker policy into a PolicyWrap. This defines our resiliency strategy.
    return Policy.WrapAsync(waitAndRetryPolicy, circuitBreakerPolicyForRecoverable);
}
</code></pre></div></div>

<p><strong>NOTE:</strong> A longer-term resiliency strategy would have us share the circuit breaker state across instances, ensuring subsequent calls to the struggling downstream service from new instances adhere to the circuit state, allowing that service to recover. This could possibly be handled by a <em>Distributed Circuit Breaker</em> (<a href="https://github.com/App-vNext/Polly/issues/287">https://github.com/App-vNext/Polly/issues/287</a>) in the future, or perhaps by using <a href="https://docs.microsoft.com/azure/azure-functions/durable-functions-overview">Durable Functions</a> that can hold the state.</p>

<h3 id="using-the-new-resiliency-policy">Using the new resiliency policy</h3>

<p>To use the policy, all we need to do is to <code class="language-plaintext highlighter-rouge">Execute</code> it, passing our <code class="language-plaintext highlighter-rouge">Action</code> to it:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Execute the REST API call, implementing our resiliency strategy.
                HttpResponseMessage response = await resiliencyStrategy.ExecuteAsync(() =&gt; _client.PostAsync(uri, GetImageHttpContent(imageBytes)));
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">resiliencyStrategy</code> variable is the <code class="language-plaintext highlighter-rouge">PolicyWrap</code> policy returned by the <code class="language-plaintext highlighter-rouge">DefineAndRetrieveResiliencyStrategy</code> method shown in the previous section.</p>

<p>The <code class="language-plaintext highlighter-rouge">GetImageHttpContent</code> method is a static method used to request the <code class="language-plaintext highlighter-rouge">ByteArrayContent</code> object from the uploaded photo’s image bytes. This helps prevent us from attempting to access a disposed object when the policy is throttled. Here’s the method for context:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/// &lt;summary&gt;
/// Request the ByteArrayContent object through a static method so
/// it is not disposed when the Polly resiliency policy asynchronously
/// executes our method that posts the image content to the Computer
/// Vision API. Otherwise, we'll receive the following error when the
/// API service is throttled:
/// System.ObjectDisposedException: Cannot access a disposed object. Object name: 'System.Net.Http.ByteArrayContent'
/// 
/// More information can be found on the HttpClient class in the
/// .NET Core library source code:
/// https://github.com/dotnet/corefx/blob/6d7fca5aecc135b97aeb3f78938a6afee55b1b5d/src/System.Net.Http/src/System/Net/Http/HttpClient.cs#L500
/// &lt;/summary&gt;
/// &lt;param name="imageBytes"&gt;&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
private static ByteArrayContent GetImageHttpContent(byte[] imageBytes)  
{
    var content = new ByteArrayContent(imageBytes);

    // Add application/octet-stream header for the content.
    content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

    return content;
}
</code></pre></div></div>

<p>To put it all together, here’s the method that references and uses the resiliency policy, calling out to the Computer Vision API:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private async Task&lt;string&gt; MakeOCRRequest(byte[] imageBytes)  
{
    _log.Info("Making OCR request");
    var licensePlate = string.Empty;
    // Request parameters.
    const string requestParameters = "language=unk&amp;detectOrientation=true";
    // Get the API URL and the API key from settings.
    // TODO 2: Populate the below two variables with the correct AppSettings properties.
    var uriBase = ConfigurationManager.AppSettings["computerVisionApiUrl"];
    var apiKey = ConfigurationManager.AppSettings["computerVisionApiKey"];

    var resiliencyStrategy = DefineAndRetrieveResiliencyStrategy();

    // Configure the HttpClient request headers.
    _client.DefaultRequestHeaders.Clear();
    _client.DefaultRequestHeaders.Accept.Clear();
    _client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
    _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    // Assemble the URI for the REST API Call.
    var uri = uriBase + "?" + requestParameters;

    try
    {
        // Execute the REST API call, implementing our resiliency strategy.
        HttpResponseMessage response = await resiliencyStrategy.ExecuteAsync(() =&gt; _client.PostAsync(uri, GetImageHttpContent(imageBytes)));

        // Get the JSON response.
        var result = await response.Content.ReadAsAsync&lt;OCRResult&gt;();
        licensePlate = GetLicensePlateTextFromResult(result);
    }
    catch (BrokenCircuitException bce)
    {
        _log.Error($"Could not contact the Computer Vision API service due to the following error: {bce.Message}");
    }
    catch (Exception e)
    {
        _log.Error($"Critical error: {e.Message}", e);
    }

    _log.Info($"Finished OCR request. Result: {licensePlate}");

    return licensePlate;
}
</code></pre></div></div>

<p>Here is the Azure Function code. Note that it is triggered with a <code class="language-plaintext highlighter-rouge">BlobTrigger</code>, every time a new photo is uploaded to the Blob Storage container.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public static class ProcessImage  
{
    public static HttpClient _client;

    [FunctionName("ProcessImage")]
    public static async Task Run([BlobTrigger("images/{name}", Connection = "blobStorageConnection")]Stream incomingPlate, string name, TraceWriter log)
    {
        string licensePlateText = string.Empty;
        // Reuse the HttpClient across calls as much as possible so as not to exhaust all available sockets on the server on which it runs.
        _client = _client ??  new HttpClient();
        log.Info($"Processing {name}");

        try
        {
            byte[] licensePlateImage;
            // Convert the incoming image stream to a byte array.
            using (var br = new BinaryReader(incomingPlate))
            {
                licensePlateImage = br.ReadBytes((int)incomingPlate.Length);
            }
            // Set the licensePlateText value by awaiting a new FindLicensePlateText.GetLicensePlate method.
            licensePlateText = await new FindLicensePlateText(log, _client).GetLicensePlate(licensePlateImage);

            // Send the details to Event Grid.
            await new SendToEventGrid(log, _client).SendLicensePlateData(new LicensePlateData()
            {
                FileName = name,
                LicensePlateText = licensePlateText,
                TimeStamp = DateTime.UtcNow
            });
        }
        catch (Exception e)
        {
            log.Error(e.Message);
        }

        log.Info($"Finished processing. Detected the following license plate: {licensePlateText}");
    }
}
</code></pre></div></div>

<p>The following line within the function is where the <code class="language-plaintext highlighter-rouge">MakeOCRRequest</code> is invoked. I’ve omitted the <code class="language-plaintext highlighter-rouge">FindLicensePlateText</code> class for brevity.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>licensePlateText = await new FindLicensePlateText(log, _client).GetLicensePlate(licensePlateImage);
</code></pre></div></div>

<h3 id="watching-the-policy-work-its-magic">Watching the policy work its magic</h3>

<p>I’ve instrumented my Azure Function App that holds my functions with <a href="https://azure.microsoft.com/services/application-insights/">Application Insights</a> so I can capture and view telemetry in real-time. Because it is asynchronous, it does not impact my solution’s performance in any way.</p>

<p>Here is a screen capture of the Live Metrics Stream provided by my Application Insights instance, showing the results of my function making calls to the Computer Vision API (S1 - Standard pricing tier) while rapidly uploading 1,000 photos:</p>

<p><img src="/assets/images/2018/03/Application-Insights-non-constrained.png" alt="Application Insights Live Metrics Stream" /></p>

<p>I’ve highlighted key areas to observe. You will notice that the CPU usage is in line with the Request Rate, the average Request Duration stays between zero seconds and 500 milliseconds, and there are two servers that have been allocated to handle the function’s demand.</p>

<p>Now, I’ve switched the Computer Vision API to the F0 - Free tier, which is constrained to <strong>20 calls per minute</strong>. Now observe the output of the Live Metrics Stream while rapidly uploading 1,000 photos, prompting our resiliency policy to kick into action:</p>

<p><img src="/assets/images/2018/03/Application-Insights-constrained.png" alt="Application Insights Live Metrics Stream - resource-constrained" /></p>

<p>After running for a couple of minutes, we start to notice a few things. The Request Duration will start to increase over time. As this happens, we notice more servers being brought online (11 in this case). Each time a server is brought online, you should see a message in the Sample Telemetry stating that it is “Generating 2 job function(s)”, followed by a Starting Host message. We also see messages logged by the resiliency policy that the Computer Vision API server is throttling the requests. This is known by the response codes sent back from the service (429). A sample message is “Computer Vision API server is throttling our requests. Automatically delaying for 32000ms”.</p>

<p>What has happened is, our resiliency policy detects the rate-limiting response codes being sent back from the Computer Vision API, then begins exponentially backing off requests to the Computer Vision API, allowing it to recover and lift the rate limit for the next available period of time. This intentional delay greatly increases the function’s response time, thus causing the Consumption plan’s dynamic scaling to kick in, allocating several more servers.</p>

<p>I hope this information is helpful as a more prescriptive way to handle a specific scenario, but can be more broadly applied to any service that imposes rate limits.</p>]]></content><author><name>{&quot;photo&quot;=&gt;&quot;/assets/images/authors/joel-hulen.png&quot;, &quot;website&quot;=&gt;&quot;https://www.linkedin.com/in/joel-hulen-ba76b73&quot;, &quot;bio&quot;=&gt;&quot;Joel Hulen is the lead Polly project owner, a senior member of the App vNext team, and has been developing software for over 33 years. He&apos;s passionate about development and fostering open source communities.&quot;}</name></author><summary type="html"><![CDATA[]]></summary></entry></feed>