<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="4.2.2">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2023-12-10T08:23:50+00:00</updated><id>/feed.xml</id><title type="html">Daniel Correia</title><subtitle>This is a software development and all  things technology blog by Daniel Correia.</subtitle><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><entry><title type="html">Making OpenTelemetry play well with Kotlin Coroutines</title><link href="/opentelemetry-kotlin-coroutines/" rel="alternate" type="text/html" title="Making OpenTelemetry play well with Kotlin Coroutines" /><published>2023-08-12T00:00:00+00:00</published><updated>2023-08-12T00:00:00+00:00</updated><id>/opentelemetry-kotlin-coroutines</id><content type="html" xml:base="/opentelemetry-kotlin-coroutines/"><![CDATA[<p>When using OpenTelemetry with different execution models you might notice that Context is not properly propagated by default between execution flows. This is not an OpenTelemetry-specific problem, there isn’t much documentation on the particular integration with Kotlin to begin with, which makes it particularly challenging.</p>

<h2 id="what-happens-when-we-use-the-opentelemetry-java-sdk-in-kotlin-coroutines-and-other-execution-models">What happens when we use the OpenTelemetry Java SDK in Kotlin Coroutines? (and other execution models)</h2>

<p>Even though the Java SDK is properly suited for usage in Kotlin applications, you will notice that when trying to create nested/child spans, these won’t be connected - in fact, they will be exported as their own Trace!</p>

<p>This is obviously a no-go and defeats the purpose of Tracing in general. Thankfully, OpenTelemetry provides some abstractions and extensions to deal with these kinds of problems.</p>

<h2 id="a-deeper-look-into-the-opentelemetry-sdk">A deeper look into the OpenTelemetry SDK</h2>

<p>One of the abstractions that is usually implemented by different frameworks to bridge their internal Context-passing mechanisms for OpenTelemetry is <code class="language-plaintext highlighter-rouge">io.opentelemetry.context.ContextStorageProvider</code> and <code class="language-plaintext highlighter-rouge">io.opentelemetry.context.ContextStorage</code>. These are not really needed for Kotlin Coroutines in particular, but you may see them in other types of integrations. We’ll explore this in a future post on the Eclipse Vert.x integration with OpenTelemetry.</p>

<p>What you need to know for now is that this abstraction allows OpenTelemetry to save and restore the state of its internal context (which we change when we perform actions such as setting the active span for the current OpenTelemetry Context). By default, OpenTelemetry uses ThreadLocal as the backing storage.</p>

<p>However, we use a different approach for Kotlin Coroutines. Looking into the GitHub repository for the OpenTelemetry Java SDK you’ll find this module:
https://github.com/open-telemetry/opentelemetry-java/tree/main/extensions/kotlin</p>

<p>It mainly consists of an implementation of <code class="language-plaintext highlighter-rouge">CoroutineContext.Element</code>, which you may have seen if you’ve looked into Coroutines and especially Coroutine Contexts in the past. Namely, OpenTelemetry defines a <code class="language-plaintext highlighter-rouge">KotlinContextElement</code> which extends <code class="language-plaintext highlighter-rouge">ThreadContextElement</code>. The latter type allows implementers to define state that should be installed into <code class="language-plaintext highlighter-rouge">ThreadLocal</code> each time a coroutine resumes execution.</p>

<p>Two methods are relevant to this implementation:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">updateThreadContext</code>: invoked before a coroutine is resumed on current thread; OpenTelemetry sets its context as current and stores the resulting scope</li>
  <li><code class="language-plaintext highlighter-rouge">restoreThreadContext</code>: invoked after a coroutine has suspended on current thread; OpenTelemetry takes the previous scope and closes it.</li>
</ul>

<h1 id="but-how-do-you-use-these-extensions">But how do you use these extensions?</h1>

<p>Ah! OpenTelemetry also provides a single Kotlin file with useful extension methods: 
https://github.com/open-telemetry/opentelemetry-java/blob/main/extensions/kotlin/src/main/kotlin/io/opentelemetry/extension/kotlin/ContextExtensions.kt</p>

<p>What we really need is to have a way to transform our current Span or Context into a CoroutineContext.Element, so that we can use it when building our CoroutineContext and then run our coroutines with the correct state. That’s what the <code class="language-plaintext highlighter-rouge">asContextElement</code> methods provide here. By the way, Spans implement <code class="language-plaintext highlighter-rouge">ImplicitContextKeyed</code>, so that’s what you see as the receiver for one of the extension methods.</p>

<p>To use them, you would use a syntax like this:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">withContext</span><span class="p">(</span><span class="n">pan</span><span class="p">.</span><span class="nf">asContextElement</span><span class="p">())</span> <span class="p">{</span>
    <span class="nf">someCode</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="higher-level-extension-methods-for-cleaner-code">Higher-level extension methods for cleaner code</h2>

<p>Now that we got the fundamentals out of the way, it’s time to present to you some of the ways I like to use these features in my own code. Having to pass around Tracers and build spans manually within code blocks is boring and noisy. Most of the time you just want to mark a code block as “relevant” for tracing and add attributes to spans as needed.</p>

<p>For this purpose, let’s start with a simple suspend function:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">suspend</span> <span class="k">fun</span> <span class="nf">getUser</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="nc">UserRequest</span><span class="p">):</span> <span class="nc">UserReply</span> <span class="p">{</span>
    <span class="c1">// some code</span>
<span class="p">}</span>
</code></pre></div></div>

<p>When instrumenting for the first time you might do something like this (note that this doesn’t deal with context propagation yet):</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="py">tracer</span> <span class="p">=</span> <span class="nc">GlobalOpenTelemetry</span><span class="p">.</span><span class="k">get</span><span class="p">().</span><span class="nf">getTracer</span><span class="p">(</span><span class="s">"my-tracer"</span><span class="p">)</span>

<span class="k">suspend</span> <span class="k">fun</span> <span class="nf">getUser</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="nc">UserRequest</span><span class="p">):</span> <span class="nc">UserReply</span> <span class="p">{</span>
    <span class="nc">Span</span> <span class="n">span</span> <span class="p">=</span> <span class="n">tracer</span><span class="p">.</span><span class="nf">spanBuilder</span><span class="p">(</span><span class="s">"my-span"</span><span class="p">).</span><span class="nf">startSpan</span><span class="p">()</span>

    <span class="c1">// using the closeable pattern or we could just close the scope in the finally block</span>
    <span class="n">span</span><span class="p">.</span><span class="nf">makeCurrent</span><span class="p">().</span><span class="nf">use</span> <span class="p">{</span>
        <span class="k">try</span> <span class="p">{</span>
            <span class="c1">// run some code, maybe add a few attributes</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="n">throwable</span><span class="p">:</span> <span class="nc">Throwable</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">span</span><span class="p">.</span><span class="nf">setStatus</span><span class="p">(</span><span class="nc">StatusCode</span><span class="p">.</span><span class="nc">ERROR</span><span class="p">)</span>
            <span class="n">span</span><span class="p">.</span><span class="nf">recordException</span><span class="p">(</span><span class="n">throwable</span><span class="p">)</span>
            <span class="k">throw</span> <span class="n">throwable</span>
        <span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
            <span class="n">span</span><span class="p">.</span><span class="nf">end</span><span class="p">()</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>However, I argue that there is a better way:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">suspend</span> <span class="k">fun</span> <span class="nf">getUser</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="nc">UserRequest</span><span class="p">):</span> <span class="nc">UserReply</span> <span class="p">=</span> <span class="nf">withSpan</span><span class="p">(</span><span class="s">"my-span"</span><span class="p">)</span> <span class="p">{</span> <span class="n">span</span> <span class="p">-&gt;</span>
    <span class="c1">// run some code, maybe add a few attributes</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Much cleaner right? This seems like some kind of black magic, but there’s really not much to it. 
Let’s take a look at this new utility.</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">suspend</span> <span class="k">fun</span> <span class="p">&lt;</span><span class="nc">T</span><span class="p">&gt;</span> <span class="nf">withSpan</span><span class="p">(</span>
    <span class="n">spanName</span><span class="p">:</span> <span class="nc">String</span><span class="p">,</span>
    <span class="n">parameters</span><span class="p">:</span> <span class="p">(</span><span class="nc">SpanBuilder</span><span class="p">.()</span> <span class="p">-&gt;</span> <span class="nc">Unit</span><span class="p">)?</span> <span class="p">=</span> <span class="k">null</span><span class="p">,</span>
    <span class="n">coroutineContext</span><span class="p">:</span> <span class="nc">CoroutineContext</span> <span class="p">=</span> <span class="nc">EmptyCoroutineContext</span><span class="p">,</span>
    <span class="n">block</span><span class="p">:</span> <span class="k">suspend</span> <span class="p">(</span><span class="n">span</span><span class="p">:</span> <span class="nc">Span</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="nc">T</span>
<span class="p">):</span> <span class="nc">T</span> <span class="p">=</span> <span class="n">tracer</span><span class="p">.</span><span class="nf">startSpan</span><span class="p">(</span><span class="n">spanName</span><span class="p">,</span> <span class="n">parameters</span><span class="p">,</span> <span class="n">coroutineContext</span><span class="p">,</span> <span class="n">block</span><span class="p">)</span>
</code></pre></div></div>

<p>At this point, you don’t see any implementation details, but there are a couple of things I’d like to point out:</p>
<ul>
  <li>for this syntax to work properly we need to allow the return type to be preserved;</li>
  <li>a few optional parameters will make your code utility more flexible, in case you need to manually set the parent span or run a coroutine in a different execution context;</li>
  <li>as with everything else, composition is the key to flexibility - these utilities allow for usage with or without a provided tracer.</li>
</ul>

<p>And finally:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">suspend</span> <span class="k">fun</span> <span class="p">&lt;</span><span class="nc">T</span><span class="p">&gt;</span> <span class="nc">Tracer</span><span class="p">.</span><span class="nf">startSpan</span><span class="p">(</span>
    <span class="n">spanName</span><span class="p">:</span> <span class="nc">String</span><span class="p">,</span>
    <span class="n">parameters</span><span class="p">:</span> <span class="p">(</span><span class="nc">SpanBuilder</span><span class="p">.()</span> <span class="p">-&gt;</span> <span class="nc">Unit</span><span class="p">)?</span> <span class="p">=</span> <span class="k">null</span><span class="p">,</span>
    <span class="n">coroutineContext</span><span class="p">:</span> <span class="nc">CoroutineContext</span> <span class="p">=</span> <span class="nc">EmptyCoroutineContext</span><span class="p">,</span>
    <span class="n">block</span><span class="p">:</span> <span class="k">suspend</span> <span class="p">(</span><span class="n">span</span><span class="p">:</span> <span class="nc">Span</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="nc">T</span>
<span class="p">):</span> <span class="nc">T</span> <span class="p">{</span>
    <span class="kd">val</span> <span class="py">span</span><span class="p">:</span> <span class="nc">Span</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="nf">spanBuilder</span><span class="p">(</span><span class="n">spanName</span><span class="p">).</span><span class="nf">run</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">parameters</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="nf">parameters</span><span class="p">()</span>
        <span class="nf">startSpan</span><span class="p">()</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="nf">withContext</span><span class="p">(</span><span class="n">coroutineContext</span> <span class="p">+</span> <span class="n">span</span><span class="p">.</span><span class="nf">asContextElement</span><span class="p">())</span> <span class="p">{</span>
        <span class="k">try</span> <span class="p">{</span>
            <span class="nf">block</span><span class="p">(</span><span class="n">span</span><span class="p">)</span>
        <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="n">throwable</span><span class="p">:</span> <span class="nc">Throwable</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">span</span><span class="p">.</span><span class="nf">setStatus</span><span class="p">(</span><span class="nc">StatusCode</span><span class="p">.</span><span class="nc">ERROR</span><span class="p">)</span>
            <span class="n">span</span><span class="p">.</span><span class="nf">recordException</span><span class="p">(</span><span class="n">throwable</span><span class="p">)</span>
            <span class="k">throw</span> <span class="n">throwable</span>
        <span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
            <span class="n">span</span><span class="p">.</span><span class="nf">end</span><span class="p">()</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>One thing you might find weird is the syntax for building the CoroutineContext passed into withContext. However, this is a pretty common pattern when dealing with them, as CoroutineContexts are composable we can add them together to build our final context.</p>

<p>One scenario where you might find this useful is when your framework already provides a <code class="language-plaintext highlighter-rouge">CoroutineContext</code>, so you’d want to reuse that for sure and add the OpenTelemetry context on top.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Dealing with framework internals can be daunting at first, but you’ll end up understanding how things work and how to make them work for you. I hope this post has helped you understand how OpenTelemetry works with Kotlin Coroutines, and how higher-level abstractions can help you instrument your code while keeping it clean and expressive.</p>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="opentelemetry" /><category term="observability" /><category term="monitoring" /><category term="distributed-tracing" /><category term="kotlin" /><category term="coroutines" /><summary type="html"><![CDATA[When using OpenTelemetry with different execution models you might notice that Context is not properly propagated by default between execution flows. This is not an OpenTelemetry-specific problem, there isn’t much documentation on the particular integration with Kotlin to begin with, which makes it particularly challenging.]]></summary></entry><entry><title type="html">Cost-effective tracing with sampling</title><link href="/cost-effective-tracing-with-sampling/" rel="alternate" type="text/html" title="Cost-effective tracing with sampling" /><published>2023-05-17T00:00:00+00:00</published><updated>2023-05-17T00:00:00+00:00</updated><id>/cost-effective-tracing-with-sampling</id><content type="html" xml:base="/cost-effective-tracing-with-sampling/"><![CDATA[<p><img src="/assets/img/trace-sampling.png" alt="Trace Sampling" /></p>

<p>While traces are extremely useful, in a standard application most of the traces are not very interesting, especially when they represent a successful execution - usually, we’re more interested in the traces that are out of the ordinary, or represent errors or slow operations.</p>

<p>It doesn’t mean that we don’t store traces that represent success, but we might want to store fewer of them, just enough where we can still look at patterns and extract metrics and other useful information.</p>

<h2 id="why-do-we-need-sampling">Why do we need sampling?</h2>

<p>When using traces at scale, the amount of data generated can be overwhelming and, at the same time, costly to store and process. Sampling is a technique that allows us to reduce the amount of data collected, while still providing a representative view of the system.</p>

<p>It’s not always trivial to choose the right sampling strategy, as it depends on the use case and the type of data we want to collect. In general, we can distinguish between two main categories of sampling: head-based and tail-based.</p>

<h2 id="head-based-sampling">Head-based sampling</h2>

<p>The first type of sampling is called head-based sampling and the goal is to make a decision as early as possible, so it doesn’t take into account the whole trace. The most common implementation of this strategy is to sample a fixed percentage of traces.</p>

<p>On the one hand, this type of sampling is very efficient and can be implemented with very little overhead, but on the other hand, it’s not very flexible and it’s not very useful when we want to sample based on the characteristics of the trace. If we want to sample based on the attributes of the whole Trace, like the duration or errors, we need tail-based sampling.</p>

<h2 id="tail-based-sampling">Tail-based sampling</h2>

<p>The other type of sampling is tail-based sampling, and it happens after the full set of spans have been completed. This means that we can use the attributes of the Trace to decide if we want to sample it or not.</p>

<p>We can use this type of sampling to do things to collect Traces that:</p>
<ul>
  <li>are longer than a certain threshold</li>
  <li>contain errors</li>
  <li>contain specific attributes</li>
</ul>

<p>And also change the sampling rate based on these rules (e.g. sample 100% of traces that contain errors, but only 10% of traces that are longer than 5 seconds).</p>

<p>However, we must be aware of some of the drawbacks of tail-based sampling:</p>
<ul>
  <li>more expensive, as we need to collect the full Trace before we can make a decision</li>
  <li>more difficult to implement, and may require changes when the applications evolve</li>
  <li>depending on the implementation/infrastructure it may require special care when scaling intermediaries like OpenTelemetry Collector</li>
</ul>

<h2 id="the-problem-of-sampling-in-a-distributed-tracing-system">The problem of sampling in a Distributed Tracing system</h2>

<p>While we can use head-based and tail-based sampling in a single application, it’s not as straightforward when we’re dealing with a distributed system. In this case, we need to make sure that we’re sampling consistently across all the services involved in a single trace, otherwise, we’ll end up with incomplete Traces that are not very useful.</p>

<p>What we need is a way to decide if a Trace should be sampled or not, and make sure every service involved in the Trace makes the same decision. We can use context propagation to signal downstream services that a Trace should be sampled, and then configure each service to look at the context first to decide if a Trace should be sampled or not.</p>

<p>This is called Parent-based sampling - in Distributed Tracing, to ensure consistency, before applying any sampling strategy, we first check if the parent Trace was sampled or not, and then apply the same decision to the current Trace.</p>

<p>It doesn’t mean that some service in the middle of a call chain can’t create more Traces than the parent, but it means that the parent’s decision is always respected. There are still situations where we might want to sample a Trace when we detect odd behavior - we won’t have a complete call chain, but we’ll still have a Trace that can help us understand what’s going on.</p>

<h2 id="real-world-examples">Real-world examples</h2>

<p>In most scenarios, we want to use a combination of head-based and tail-based sampling. 
It can be implemented in layers, and we can use different sampling strategies at each layer. For example, we can use Parent-based sampling at the first layer, then allow for 100% sampling of traces that are longer than 5 seconds or contain errors.</p>

<p>We can restrict or control the amount of data flowing through the telemetry infrastructure by using head-based sampling (e.g. probability sampling) on the first nodes of a call chain (the others would use parent-based sampling).</p>

<p>Then, we can use tail-based sampling to further reduce the amount of data we collect, and make more informed decisions based on the characteristics of the Trace.</p>

<h2 id="implementing-a-custom-sampler-with-the-opentelemetry-sdk">Implementing a custom Sampler with the OpenTelemetry SDK</h2>

<p>The OpenTelemetry SDK provides a Sampler interface that we can implement to create our own custom Samplers. The interface is very simple, and it only requires us to implement a single method called <code class="language-plaintext highlighter-rouge">shouldSample</code> that takes a bunch of parameters and returns a <code class="language-plaintext highlighter-rouge">SamplingResult</code> object. There is technically one more method called <code class="language-plaintext highlighter-rouge">getDescription</code> but usually, you’ll only need to return the name of your sampler here.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">AllErrorsSampler</span> <span class="kd">implements</span> <span class="nc">Sampler</span> <span class="o">{</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">SamplingResult</span> <span class="nf">shouldSample</span><span class="o">(</span>
        <span class="nc">Context</span> <span class="n">parentContext</span><span class="o">,</span>
        <span class="nc">String</span> <span class="n">traceId</span><span class="o">,</span>
        <span class="nc">String</span> <span class="n">name</span><span class="o">,</span>
        <span class="nc">SpanKind</span> <span class="n">spanKind</span><span class="o">,</span>
        <span class="nc">Attributes</span> <span class="n">attributes</span><span class="o">,</span>
        <span class="nc">List</span><span class="o">&lt;</span><span class="nc">LinkData</span><span class="o">&gt;</span> <span class="n">parentLinks</span>
    <span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nc">SamplingResult</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">SamplingDecision</span><span class="o">.</span><span class="na">RECORD_AND_SAMPLE</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">String</span> <span class="nf">getDescription</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s">"AllErrorsSampler"</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>You may notice that this interface could be used to implement either head-based or tail-based sampling but unless you are tracing a single service, most of the time this won’t work for tail-based sampling.</p>

<p>While you can look at the service spans and their attributes to decide if you want to sample a Trace or not, you can’t look at the spans of the other services involved in the Trace. Also, if you detect an error in a downstream service call, you can’t change the sampling decision retroactively for that, since the context was already propagated without that information.</p>

<p>This essentially means that you can only implement tail-based sampling correctly for a distributed system if you have access to the full Trace, which in turn means that you need to implement it in the OpenTelemetry Collector - making sure every single Span is received by the same Collector instance. We’ll get into more detail about the OpenTelemetry Collector deployment strategies in a future post.</p>

<h2 id="using-opentelemetry-collector-for-sampling">Using OpenTelemetry Collector for sampling</h2>

<p>The OpenTelemetry Collector provides a lot of flexibility when it comes to sampling. It supports head-based sampling out of the box, and it also provides a way to implement tail-based sampling using the <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/tailsamplingprocessor">Tail Sampling Processor</a>.</p>

<p>This article is not about the OpenTelemetry Collector, so we won’t go into too much detail here, but we’ll see how we can configure it to implement a simple tail-based sampling strategy.</p>

<p>For example, if we want to sample all traces longer than 5 seconds, we can use the following configuration:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">processors</span><span class="pi">:</span>
  <span class="na">tail_sampling</span><span class="pi">:</span>
    <span class="na">decision_wait</span><span class="pi">:</span> <span class="s">10s</span> <span class="c1"># Wait time since the first span of a trace before making a sampling decision, default = 30s</span>
    <span class="na">num_traces</span><span class="pi">:</span> <span class="m">1000</span>   <span class="c1"># Number of traces kept in memory, default = 50000</span>
    <span class="na">policies</span><span class="pi">:</span>
      <span class="pi">[</span>
          <span class="pi">{</span>
            <span class="nv">name</span><span class="pi">:</span> <span class="nv">sample-long-trace-policy</span><span class="pi">,</span>
            <span class="nv">type</span><span class="pi">:</span> <span class="nv">latency</span><span class="pi">,</span>
            <span class="nv">latency</span><span class="pi">:</span> <span class="pi">{</span><span class="nv">threshold_ms</span><span class="pi">:</span> <span class="nv">5000</span><span class="pi">}</span>
          <span class="pi">}</span>
        <span class="pi">]</span>
</code></pre></div></div>

<p>As mentioned before, you need to keep in mind that every single Span for the same Trace must be handled by the same Collector instance, otherwise, the sampling decision will be inconsistent. We’ll see how to do that in a future post.</p>

<h2 id="references">References</h2>

<p>https://opentelemetry.io/docs/concepts/sampling/</p>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="opentelemetry" /><category term="observability" /><category term="monitoring" /><category term="distributed-tracing" /><category term="sampling" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Context Propagation in OpenTelemetry</title><link href="/context-propagation-in-opentelemetry/" rel="alternate" type="text/html" title="Context Propagation in OpenTelemetry" /><published>2023-04-30T00:00:00+00:00</published><updated>2023-04-30T00:00:00+00:00</updated><id>/context-propagation-in-opentelemetry</id><content type="html" xml:base="/context-propagation-in-opentelemetry/"><![CDATA[<p>This is the second post in a series about <a href="https://opentelemetry.io/">OpenTelemetry</a>. In the <a href="/getting-started-with-opentelemetry/">previous post</a>, we introduced OpenTelemetry is and why it is important. In this post we will go over context propagation and how it works in OpenTelemetry.</p>

<p><img src="/assets/img/context-propagation.png" alt="Context propagation graph" /></p>

<p>While instrumenting a single service may be useful, the real power of OpenTelemetry comes from the ability to instrument multiple services and then correlate the data between them. This is done by propagating a context between services. This context contains information about the request, such as the trace ID, span ID, and other metadata. This allows the spans from multiple services to be correlated into a single trace, which can then be used to understand the flow of a request through the system.</p>

<h2 id="how-does-it-work">How does it work?</h2>

<p>One thing to note is that OpenTelemetry does not specify how the context is propagated. Instead, it provides a mechanism for injecting and extracting the context, and it is up to the user to decide how to do this. This allows OpenTelemetry to be integrated with a wide variety of frameworks and libraries, even if they do not support OpenTelemetry directly.</p>

<p>The most common way to propagate context is using HTTP headers. This is because HTTP is the most common protocol used for communication between services, however, we can use several other mechanisms, such as gRPC metadata, or even Kafka headers.</p>

<h2 id="common-formats">Common formats</h2>

<p>OpenTelemetry supports several different context propagation formats, the most common ones are:</p>

<h3 id="w3c-trace-context">W3C Trace Context</h3>

<p>The <a href="https://www.w3.org/TR/trace-context/">W3C Trace Context specification</a> was created to standardize the propagation of tracing information across services. It defines a set of HTTP headers that can be used to propagate the context between the various nodes in a system.</p>

<p>The headers are <code class="language-plaintext highlighter-rouge">traceparent</code> and <code class="language-plaintext highlighter-rouge">tracestate</code>. The <code class="language-plaintext highlighter-rouge">traceparent</code> header contains the trace ID, span ID, and sampling state. The <code class="language-plaintext highlighter-rouge">tracestate</code> header can contain additional metadata about the Trace in the form of a small list of key-value pairs, and is mostly used to convey vendor-specific information.</p>

<p>The format for the <code class="language-plaintext highlighter-rouge">traceparent</code> header is as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>traceparent: {Version}-{TraceId}-{SpanId}-{TraceFlags}
</code></pre></div></div>

<p>Receiving an HTTP request with <code class="language-plaintext highlighter-rouge">W3C Trace Context</code> context propagation might look something like this:</p>

<div class="language-http highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">GET</span> <span class="nn">/my-service</span> <span class="k">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Host</span><span class="p">:</span> <span class="s">myhost.com</span>
<span class="na">traceparent</span><span class="p">:</span> <span class="s">00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01</span>
<span class="na">tracestate</span><span class="p">:</span> <span class="s">abc=00f067aa0ba902b7,xyz=99f067aa0ba902b7</span>
</code></pre></div></div>

<h3 id="b3-zipkin">B3 (Zipkin)</h3>

<p>The B3 format was born out of the need to propagate tracing information between services using Zipkin. It is now supported by several other tracing systems, such as Jaeger and AWS X-Ray. It was designed to be simple and easy to implement, and it is one of the most widely used formats for context propagation.</p>

<p>As an example, receiving an HTTP request with <code class="language-plaintext highlighter-rouge">B3 multi-header</code> context propagation might look something like this:</p>

<div class="language-http highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">GET</span> <span class="nn">/my-service</span> <span class="k">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Host</span><span class="p">:</span> <span class="s">myhost.com</span>
<span class="na">X-B3-TraceId</span><span class="p">:</span> <span class="s">f102024f34f30692b676c13f47cbcf03</span>
<span class="na">X-B3-SpanId</span><span class="p">:</span> <span class="s">e2695f90dfd76b09</span>
<span class="na">X-B3-Sampled</span><span class="p">:</span> <span class="s">1</span>
</code></pre></div></div>

<p>The same request using <code class="language-plaintext highlighter-rouge">B3 single-header</code> would look like this:</p>

<div class="language-http highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">GET</span> <span class="nn">/my-service</span> <span class="k">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Host</span><span class="p">:</span> <span class="s">myhost.com</span>
<span class="na">b3</span><span class="p">:</span> <span class="s">f102024f34f30692b676c13f47cbcf03-e2695f90dfd76b09-1</span>
</code></pre></div></div>

<p>Where the format for the <code class="language-plaintext highlighter-rouge">b3</code> header is as:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b3={TraceId}-{SpanId}-{SamplingState}
</code></pre></div></div>

<h2 id="choosing-a-format">Choosing a format</h2>

<p>You might be asking, how should I know what format best suits my needs?
The answer mostly depends on the ecosystem you are working with.</p>

<p>If you own all the services in your system, you can just stick with the default format, <code class="language-plaintext highlighter-rouge">W3C Trace Context</code>. However, if you are integrating with other services that already publish tracing information, you might need to use a different format, such as <code class="language-plaintext highlighter-rouge">B3</code>. In the end, the goal is to have a consistent format across all services, so that the context can be propagated correctly and Traces can contain all the information needed to understand the flow of a request through the system.</p>

<p>For example, <a href="istio.io">Istio</a> (Kubernetes Service Mesh) uses <code class="language-plaintext highlighter-rouge">B3 multi-header</code> as the default format (Zipkin tracer), so if you or any other services in your ecosystem are using Istio, you should probably consider using <code class="language-plaintext highlighter-rouge">B3</code> as well.</p>

<p>There are a few other proprietary formats, such as the ones from <a href="https://lightstep.com/">Lightstep</a> and <a href="https://www.datadoghq.com/">Datadog</a>, but the goal of OpenTelemetry is to provide a vendor-neutral solution, so you should probably avoid using them. Most vendors of tracing backends already support the standard formats, so there is no need to tie your application to proprietary solutions.</p>

<h2 id="extracting-and-injecting-context">Extracting and injecting context</h2>

<p>By now you should have a better understanding of what context propagation is and how it works. Now, let’s see how we can use OpenTelemetry to extract and inject context.</p>

<p>Thankfully OpenTelemetry defines abstractions for extracting and injecting context, so we don’t need to worry about the details of each format while adding support for a specific library. Generically we just need a way to allow propagators to read (extract) and write (inject) the headers.</p>

<h3 id="injecting-context-on-the-client">Injecting context on the client</h3>

<p>The example below shows how we can add support to a specific Java HTTP client, in this case, AsyncHttpClient, to inject the context into the HTTP request headers:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Span</span> <span class="n">span</span> <span class="o">=</span> <span class="n">getTracer</span><span class="o">().</span><span class="na">spanBuilder</span><span class="o">(</span><span class="s">"get /my-endpoint"</span><span class="o">)</span>
    <span class="o">.</span><span class="na">setSpanKind</span><span class="o">(</span><span class="nc">SpanKind</span><span class="o">.</span><span class="na">CLIENT</span><span class="o">)</span>
    <span class="o">.</span><span class="na">startSpan</span><span class="o">();</span>

<span class="k">try</span> <span class="o">(</span><span class="nc">Scope</span> <span class="n">scope</span> <span class="o">=</span> <span class="n">span</span><span class="o">.</span><span class="na">makeCurrent</span><span class="o">())</span> <span class="o">{</span>
    <span class="nc">BoundRequestBuilder</span> <span class="n">builder</span> <span class="o">=</span> <span class="n">asyncHttpClient</span><span class="o">.</span><span class="na">prepareGet</span><span class="o">(</span><span class="s">"http://localhost:8080/my-service"</span><span class="o">);</span>
    <span class="o">...</span>
    <span class="n">getOpenTelemetry</span><span class="o">().</span><span class="na">getPropagators</span><span class="o">().</span><span class="na">getTextMapPropagator</span><span class="o">()</span>
        <span class="o">.</span><span class="na">inject</span><span class="o">(</span><span class="nc">Context</span><span class="o">.</span><span class="na">current</span><span class="o">(),</span> <span class="n">builder</span><span class="o">,</span> <span class="nc">AsyncHttpClientTextMapSetter</span><span class="o">.</span><span class="na">INSTANCE</span><span class="o">);</span>
    <span class="o">...</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
    <span class="n">span</span><span class="o">.</span><span class="na">end</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>First, we get our instance of <code class="language-plaintext highlighter-rouge">OpenTelemetry</code>, which we can use to access the <code class="language-plaintext highlighter-rouge">Propagators</code> API. Then we call the <code class="language-plaintext highlighter-rouge">getTextMapPropagator()</code> method to get the <code class="language-plaintext highlighter-rouge">TextMapPropagator</code> for the current context propagation format. Finally, we call the <code class="language-plaintext highlighter-rouge">inject()</code> method, passing the current context, the object that will be used to inject the context, and a <code class="language-plaintext highlighter-rouge">TextMapSetter</code> that will be used to set the headers.</p>

<p>The <code class="language-plaintext highlighter-rouge">TextMapSetter</code> is an interface that defines a single method, <code class="language-plaintext highlighter-rouge">set()</code>, which receives the object that will be used to inject the context, the header key, and the header value. The <code class="language-plaintext highlighter-rouge">TextMapSetter</code> is responsible for setting the header on the object, and it is library-specific. For example, the <code class="language-plaintext highlighter-rouge">TextMapSetter</code> for <code class="language-plaintext highlighter-rouge">AsyncHttpClient</code> (specifically for <code class="language-plaintext highlighter-rouge">BoundRequestBuilder</code>) would look like this:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">AsyncHttpClientTextMapSetter</span> <span class="kd">implements</span> <span class="nc">TextMapSetter</span><span class="o">&lt;</span><span class="nc">BoundRequestBuilder</span><span class="o">&gt;</span> <span class="o">{</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="nc">AsyncHttpClientTextMapSetter</span> <span class="no">INSTANCE</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">AsyncHttpClientTextMapSetter</span><span class="o">();</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">set</span><span class="o">(</span><span class="nd">@Nullable</span> <span class="nc">BoundRequestBuilder</span> <span class="n">carrier</span><span class="o">,</span> <span class="nc">String</span> <span class="n">key</span><span class="o">,</span> <span class="nc">String</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">carrier</span><span class="o">.</span><span class="na">addHeader</span><span class="o">(</span><span class="n">key</span><span class="o">,</span> <span class="n">value</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This is all you need to do to flow the context from the client to the server. The same concept applies to other libraries and frameworks, and they don’t even have to be HTTP-based! Here’s an example using Kafka headers to propagate context:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="py">record</span> <span class="p">=</span> <span class="nc">ProducerRecord</span><span class="p">(</span><span class="n">topic</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>

<span class="n">openTelemetry</span><span class="p">.</span><span class="n">propagators</span><span class="p">.</span><span class="n">textMapPropagator</span><span class="p">.</span><span class="nf">inject</span><span class="p">(</span><span class="nc">Context</span><span class="p">.</span><span class="nf">current</span><span class="p">(),</span> <span class="n">record</span><span class="p">)</span> <span class="p">{</span> <span class="n">holder</span><span class="p">,</span> <span class="n">headerName</span><span class="p">,</span> <span class="n">headerValue</span> <span class="p">-&gt;</span>
    <span class="n">holder</span><span class="o">?.</span><span class="nf">headers</span><span class="p">()</span><span class="o">?.</span><span class="nf">add</span><span class="p">(</span><span class="n">headerName</span><span class="p">,</span> <span class="n">headerValue</span><span class="p">.</span><span class="nf">toByteArray</span><span class="p">(</span><span class="nc">Charsets</span><span class="p">.</span><span class="nc">UTF_8</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="extracting-context-on-the-server">Extracting context on the server</h3>

<p>The same principles apply to the server side. The example below shows how we can extract the context using <code class="language-plaintext highlighter-rouge">HttpServletRequest</code> (Spring Boot):</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// originalRequest is an instance of HttpServletRequest, </span>
<span class="c1">// added to the method signature in the Spring Boot controller method</span>

<span class="nc">Context</span> <span class="n">extractedContext</span> <span class="o">=</span> <span class="n">openTelemetry</span><span class="o">.</span><span class="na">getPropagators</span><span class="o">().</span><span class="na">getTextMapPropagator</span><span class="o">()</span>
    <span class="o">.</span><span class="na">extract</span><span class="o">(</span><span class="nc">Context</span><span class="o">.</span><span class="na">current</span><span class="o">(),</span> <span class="n">originalRequest</span><span class="o">,</span> <span class="nc">HttpServletRequestTextMapGetter</span><span class="o">.</span><span class="na">INSTANCE</span><span class="o">);</span>
</code></pre></div></div>

<p>Here we get the <code class="language-plaintext highlighter-rouge">TextMapPropagator</code> for the current context propagation format, and then we call the <code class="language-plaintext highlighter-rouge">extract()</code> method, passing the current context, the object that contains the headers, and a <code class="language-plaintext highlighter-rouge">TextMapGetter</code> that will be used to get the headers.</p>

<p>The <code class="language-plaintext highlighter-rouge">TextMapGetter</code> is an interface that defines two methods, <code class="language-plaintext highlighter-rouge">keys()</code> and <code class="language-plaintext highlighter-rouge">get()</code>. The <code class="language-plaintext highlighter-rouge">keys()</code> method returns an <code class="language-plaintext highlighter-rouge">Iterable</code> of header keys, and the <code class="language-plaintext highlighter-rouge">get()</code> method receives the object that contains the headers and the header key, and returns the header value. The <code class="language-plaintext highlighter-rouge">TextMapGetter</code> is also library-specific. For example, the <code class="language-plaintext highlighter-rouge">TextMapGetter</code> for <code class="language-plaintext highlighter-rouge">HttpServletRequest</code> would look like this:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HttpServletRequestTextMapGetter</span> <span class="kd">implements</span> <span class="nc">TextMapGetter</span><span class="o">&lt;</span><span class="nc">HttpServletRequest</span><span class="o">&gt;</span> <span class="o">{</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="nc">HttpServletRequestTextMapGetter</span> <span class="no">INSTANCE</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HttpServletRequestTextMapGetter</span><span class="o">();</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">Iterable</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="nf">keys</span><span class="o">(</span><span class="nc">HttpServletRequest</span> <span class="n">carrier</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nc">Collections</span><span class="o">.</span><span class="na">list</span><span class="o">(</span><span class="n">carrier</span><span class="o">.</span><span class="na">getHeaderNames</span><span class="o">());</span>
    <span class="o">}</span>

    <span class="nd">@Nullable</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">String</span> <span class="nf">get</span><span class="o">(</span><span class="nd">@Nullable</span> <span class="nc">HttpServletRequest</span> <span class="n">carrier</span><span class="o">,</span> <span class="nc">String</span> <span class="n">key</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">carrier</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="n">key</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Once we have the extracted context, we can use it to create a new <code class="language-plaintext highlighter-rouge">Span</code>:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span> <span class="o">(</span><span class="nc">Scope</span> <span class="n">contextScope</span> <span class="o">=</span> <span class="n">extractedContext</span><span class="o">.</span><span class="na">makeCurrent</span><span class="o">())</span> <span class="o">{</span>

    <span class="nc">Span</span> <span class="n">requestSpan</span> <span class="o">=</span> <span class="n">tracer</span><span class="o">.</span><span class="na">spanBuilder</span><span class="o">(</span><span class="s">"Request to /my-endpoint"</span><span class="o">)</span>
        <span class="o">.</span><span class="na">setSpanKind</span><span class="o">(</span><span class="nc">SpanKind</span><span class="o">.</span><span class="na">SERVER</span><span class="o">)</span>
        <span class="o">.</span><span class="na">startSpan</span><span class="o">();</span>

    <span class="k">try</span> <span class="o">(</span><span class="nc">Scope</span> <span class="n">scope</span> <span class="o">=</span> <span class="n">requestSpan</span><span class="o">.</span><span class="na">makeCurrent</span><span class="o">())</span> <span class="o">{</span>
        <span class="o">...</span>
    <span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
        <span class="n">requestSpan</span><span class="o">.</span><span class="na">end</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<h2 id="a-note-on-spankind">A note on SpanKind</h2>

<p>You may have noticed that we set the <code class="language-plaintext highlighter-rouge">SpanKind</code> to <code class="language-plaintext highlighter-rouge">SERVER</code> and <code class="language-plaintext highlighter-rouge">CLIENT</code> when creating the <code class="language-plaintext highlighter-rouge">Span</code> for the server side and client side respectively. This is important because it allows the tracing backend to differentiate between client and server spans, which is required by many tracing backends to generate service graphs/dependency graphs.</p>

<p>This is what a service graph looks like in Grafana Tempo (a tracing backend):</p>

<p><img src="/assets/img/grafana-tempo-service-graph.png" alt="Service map in Grafana Tempo" /></p>

<h2 id="references">References</h2>

<ul>
  <li><a href="https://www.w3.org/TR/trace-context/">W3C Trace Context specification</a></li>
  <li><a href="https://github.com/openzipkin/b3-propagation">B3 format specification</a></li>
  <li><a href="https://github.com/open-telemetry/opentelemetry-java/blob/main/api/all/src/main/java/io/opentelemetry/api/trace/propagation/W3CTraceContextPropagator.java">W3C Trace Context propagator in OpenTelemetry Java SDK</a></li>
  <li><a href="https://github.com/open-telemetry/opentelemetry-java/tree/main/extensions/trace-propagators/src/main/java/io/opentelemetry/extension/trace/propagation">Context propagation extensions in OpenTelemetry Java SDK</a></li>
  <li><a href="https://grafana.com/docs/tempo/latest/metrics-generator/service_graphs/">Grafana Tempo Service Graphs</a></li>
</ul>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="opentelemetry" /><category term="observability" /><category term="monitoring" /><category term="distributed-tracing" /><category term="context-propagation" /><summary type="html"><![CDATA[This is the second post in a series about OpenTelemetry. In the previous post, we introduced OpenTelemetry is and why it is important. In this post we will go over context propagation and how it works in OpenTelemetry.]]></summary></entry><entry><title type="html">Getting Started with OpenTelemetry</title><link href="/getting-started-with-opentelemetry/" rel="alternate" type="text/html" title="Getting Started with OpenTelemetry" /><published>2023-04-25T00:00:00+00:00</published><updated>2023-04-25T00:00:00+00:00</updated><id>/getting-started-with-opentelemetry</id><content type="html" xml:base="/getting-started-with-opentelemetry/"><![CDATA[<p>In this series of posts, I’ll be exploring OpenTelemetry and how it can help you improve the observability of your applications. I will focus on the tracing capabilities of OpenTelemetry, but I’ll also touch on metrics and logs - and specifically how they can be linked together to decrease the time to detect and resolve issues in your applications.</p>

<h2 id="what-is-opentelemetry">What is OpenTelemetry?</h2>

<p>OpenTelemetry was born from the merger of two existing projects: OpenTracing and OpenCensus. It is a set of tools, APIs, and SDKs that allow you to instrument your applications to collect telemetry data. This data can then be used to generate metrics, logs, and traces.</p>

<p>The fundamentals of what OpenTelemetry is can be found on the <a href="https://opentelemetry.io/docs/reference/specification/">official</a> specification page](https://opentelemetry.io/docs/reference/specification/). The specification is a great place to start if you want to understand the concepts behind OpenTelemetry.</p>

<p>In short, the specification sets the rules for how the data is collected and how it is represented. The specification is then implemented by the different language-specific SDKs. The SDKs are the libraries that you will use to instrument your applications.</p>

<h2 id="signals">Signals</h2>

<p>OpenTelemetry defines three different signals: metrics, logs, and traces. These signals are used to represent different aspects of your application’s behavior.</p>

<p>Most applications already generate logs. Logs are a good way to understand what is happening in your application, but they can be hard to parse and analyze. Metrics are a better way to understand the behavior of your application, but they are not always enough to understand the root cause of an issue. Traces are a great way to understand the flow of your application, but they can be hard to correlate with other signals.</p>

<p>These three signals are the holy trinity of observability. When linked together, they can help you understand the behavior of your application and detect and resolve issues faster, decreasing the support and maintenance costs of your applications.</p>

<h2 id="distributed-tracing">Distributed Tracing</h2>

<p>With <strong>Tracing</strong> you can follow the flow of a request through your application. This can help you understand what behavior was executed, how much time it took, and what resources were used. Even in the context of a single service, it can provide incredible value, but Tracing really shines when you have a distributed system.</p>

<p>With the advent of microservices, or generally in complex architectures with many different services involved, it can be hard to know all the services that are called in a single user-journey. Distributed tracing can help you understand the flow of a request through your system, <strong>even if it involves multiple services</strong>.</p>

<p><img src="/assets/img/sample-trace.png" alt="Sample trace for a user-journey" /></p>

<p>You may already be wondering what type of data needs to be collected to create such a visualization.
In essence, <strong>a trace is a collection of spans</strong>. A span represents a single operation (unit of work) in your application.</p>

<p>A span can be a single method call, a database query, an HTTP request, etc. A trace is a collection of spans that are linked together to represent a single user journey.</p>

<p>But how can you have multiple services contributing to the same trace? How can you link spans from different services together? This is where <strong>context propagation</strong> comes into play.</p>

<h2 id="context-propagation">Context Propagation</h2>

<p>Context Propagation is the fundamental concept that powers distributed tracing. It allows you to link spans from different services together to create a trace.</p>

<p>OpenTelemetry defines two sub-concepts within context propagation: <strong>context</strong> and <strong>propagation</strong>.
While <strong>context</strong> is the data that is passed between services, <strong>propagation</strong> is the mechanism that allows you to pass the context between services and processes, so it serializes and deserializes the context as needed to create what we call <strong>TraceContext</strong>.</p>

<p>The context is an abstract concept that is generically represented by a set of key-value pairs. However, it can be better understood by looking at a concrete example. By default, OpenTelemetry uses the <a href="https://www.w3.org/TR/trace-context/">W3C Trace Context</a> specification to represent the context. There are other formats, such as <a href="https://github.com/openzipkin/b3-propagation">B3</a> and <a href="https://www.jaegertracing.io/docs/1.22/client-libraries/#propagation-format">Jaeger</a>.</p>

<p>These are usually represented as HTTP headers, but they can also be represented as metadata in gRPC calls, or as message headers in a message queue. We’ll get into more detail on how you should choose a context format and how to handle propagation in several different scenarios in a future post.</p>

<h2 id="instrumentation">Instrumentation</h2>

<p>The first thing you need to know about instrumenting your application to extract these signals is that there are two different ways to do it: <strong>manual</strong> and <strong>automatic</strong>.</p>

<p>There is no silver bullet here, and you will end up using a combination of both depending on the services you manage. However, it is important to understand the differences between the two approaches.</p>

<h3 id="automatic-instrumentation">Automatic Instrumentation</h3>

<p>In most cases, this is where you should start to get the most value out of OpenTelemetry, in the least time possible. 
Automatic instrumentation is the process of instrumenting your application by using a library that automatically instruments your application for you.</p>

<p>If we have a Java application, this will be a <a href="https://opentelemetry.io/docs/instrumentation/java/automatic/">Java agent</a>. If we have a <a href="https://opentelemetry.io/docs/instrumentation/js/instrumentation/">JavaScript/Node.js application</a>, this will be a JavaScript file included during the run/execution phase. If we have a <a href="https://opentelemetry.io/docs/instrumentation/python/automatic/">Python</a> application, this will be a Python agent, and so on.</p>

<p>The main advantage of automatic instrumentation is that it is easy to get started with. In most cases, you just need to add a dependency to your application and you are good to go. The downside is that you may not get all the data you need, or you may get too much data. You may also not be able to customize the instrumentation to your needs.</p>

<p>For example, in Java you only need to download the <a href="https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar">Java agent JAR</a> and add it to your application’s classpath like so:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>java <span class="nt">-javaagent</span>:opentelemetry-javaagent.jar <span class="se">\</span>
     <span class="nt">-Dotel</span>.service.name<span class="o">=</span>your-service-name
     <span class="nt">-jar</span> my-service.jar
</code></pre></div></div>

<p>Or using environment variables:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">JAVA_TOOL_OPTIONS</span><span class="o">=</span><span class="s2">"-javaagent:path/to/opentelemetry-javaagent.jar"</span>
<span class="nb">export </span><span class="nv">OTEL_SERVICE_NAME</span><span class="o">=</span><span class="s2">"my-service-name"</span>
java <span class="nt">-jar</span> my-service.jar
</code></pre></div></div>

<p>We then have the possibility of adding configuration options to the agent to customize the instrumentation. For example, we can configure the agent to only instrument specific libraries, or to exclude <a href="https://opentelemetry.io/docs/instrumentation/java/automatic/agent-config/#suppressing-specific-agent-instrumentation">specific libraries</a> from being instrumented using the format <code class="language-plaintext highlighter-rouge">-Dotel.instrumentation.[name].enabled=false</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>java <span class="nt">-javaagent</span>:opentelemetry-javaagent.jar <span class="se">\</span>
     <span class="nt">-Dotel</span>.service.name<span class="o">=</span>my-service-name
     <span class="nt">-Dotel</span>.instrumentation.jdbc.enabled<span class="o">=</span><span class="nb">false</span>
     <span class="nt">-jar</span> my-service.jar
</code></pre></div></div>

<p>You can also find all available options, including context propagation and exporter formats, sampling and many other things in the <a href="https://opentelemetry.io/docs/instrumentation/java/automatic/agent-config/">Java agent configuration page</a>.</p>

<p>Due to the nature of this type of instrumentation, be aware that there may be a performance impact - make sure you run load tests before and after this change, especially if you are using something like a Java agent.</p>

<h3 id="manual-instrumentation">Manual Instrumentation</h3>

<p>Manual instrumentation is the process of instrumenting your application by using the OpenTelemetry SDKs directly. This is usually done by adding the SDKs as dependencies to your application and then using them to instrument your application.</p>

<p>The main advantage of manual instrumentation is that you have full control over what is instrumented and how. The downside is that it is usually more complex and time-consuming to get started with.</p>

<p>For example, in Java you need to add the following dependencies to your application:</p>

<div class="language-groovy highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">dependencies</span> <span class="o">{</span>
    <span class="n">implementation</span> <span class="s1">'io.opentelemetry:opentelemetry-api:&lt;version&gt;'</span>
    <span class="n">implementation</span> <span class="s1">'io.opentelemetry:opentelemetry-sdk:&lt;version&gt;'</span>
    <span class="n">implementation</span> <span class="s1">'io.opentelemetry:opentelemetry-exporter-otlp:&lt;version&gt;'</span>
    <span class="n">implementation</span> <span class="s1">'io.opentelemetry:opentelemetry-semconv:&lt;version&gt;-alpha'</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The latest version of these libraries can be found on the OpenTelemetry <a href="https://github.com/open-telemetry/opentelemetry-java#releases">GitHub releases page</a>.</p>

<p>You can then use the SDK to create a tracer and start creating spans:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Span</span> <span class="n">span</span> <span class="o">=</span> <span class="n">tracer</span><span class="o">.</span><span class="na">spanBuilder</span><span class="o">(</span><span class="s">"my-span"</span><span class="o">).</span><span class="na">startSpan</span><span class="o">();</span>

<span class="k">try</span> <span class="o">(</span><span class="nc">Scope</span> <span class="n">scope</span> <span class="o">=</span> <span class="n">span</span><span class="o">.</span><span class="na">makeCurrent</span><span class="o">())</span> <span class="o">{</span>
    <span class="c1">// do some work</span>
    <span class="n">span</span><span class="o">.</span><span class="na">setAttribute</span><span class="o">(</span><span class="s">"key"</span><span class="o">,</span> <span class="s">"value"</span><span class="o">);</span>
    <span class="n">span</span><span class="o">.</span><span class="na">addEvent</span><span class="o">(</span><span class="s">"event"</span><span class="o">);</span>
    <span class="n">span</span><span class="o">.</span><span class="na">setStatus</span><span class="o">(</span><span class="nc">Status</span><span class="o">.</span><span class="na">OK</span><span class="o">);</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
    <span class="n">span</span><span class="o">.</span><span class="na">end</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>You’ll also need some boilerplate code to configure the SDK and the exporter:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="nc">Resource</span> <span class="n">resource</span> <span class="o">=</span> <span class="nc">Resource</span><span class="o">.</span><span class="na">getDefault</span><span class="o">()</span>
        <span class="o">.</span><span class="na">merge</span><span class="o">(</span><span class="nc">Resource</span><span class="o">.</span><span class="na">create</span><span class="o">(</span>
            <span class="nc">Attributes</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="nc">ResourceAttributes</span><span class="o">.</span><span class="na">SERVICE_NAME</span><span class="o">,</span> <span class="s">"my-service-name"</span><span class="o">)</span>
        <span class="o">));</span>

    <span class="nc">SpanExporter</span> <span class="n">spanExporter</span> <span class="o">=</span> <span class="nc">OtlpGrpcSpanExporter</span>
        <span class="o">.</span><span class="na">builder</span><span class="o">()</span>
        <span class="o">.</span><span class="na">setEndpoint</span><span class="o">(</span><span class="s">"http://localhost:4317"</span><span class="o">)</span> <span class="c1">// this is the default for OTLP over gRPC</span>
        <span class="o">.</span><span class="na">build</span><span class="o">();</span>

    <span class="nc">SdkTracerProvider</span> <span class="n">sdkTracerProvider</span> <span class="o">=</span> <span class="nc">SdkTracerProvider</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
        <span class="o">.</span><span class="na">addSpanProcessor</span><span class="o">(</span><span class="nc">BatchSpanProcessor</span><span class="o">.</span><span class="na">builder</span><span class="o">(</span><span class="n">spanExporter</span><span class="o">).</span><span class="na">build</span><span class="o">())</span>
        <span class="o">.</span><span class="na">setResource</span><span class="o">(</span><span class="n">resource</span><span class="o">)</span>
        <span class="o">.</span><span class="na">build</span><span class="o">();</span>

    <span class="c1">// W3C format for context propagation</span>
    <span class="nc">TextMapPropagator</span> <span class="n">propagator</span> <span class="o">=</span> <span class="nc">W3CTraceContextPropagator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">();</span>
    <span class="c1">// or you could use B3 (multi header format)</span>
    <span class="c1">// TextMapPropagator propagator = B3Propagator.injectingMultiHeaders();  </span>

    <span class="nc">OpenTelemetry</span> <span class="n">openTelemetry</span> <span class="o">=</span> <span class="nc">OpenTelemetrySdk</span><span class="o">.</span><span class="na">builder</span><span class="o">()</span>
        <span class="o">.</span><span class="na">setTracerProvider</span><span class="o">(</span><span class="n">sdkTracerProvider</span><span class="o">)</span>
        <span class="o">.</span><span class="na">setPropagators</span><span class="o">(</span><span class="nc">ContextPropagators</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="n">propagator</span><span class="o">))</span>
        <span class="o">.</span><span class="na">buildAndRegisterGlobal</span><span class="o">();</span>
</code></pre></div></div>

<p>I’ll leave the details of manual instrumentation for a future post, namely how to configure the SDK and the exporter, when we should create spans, how to propagate context, and how to integrate OpenTelemetry manual instrumentation with popular frameworks.</p>

<p>Later on, we’ll also talk about using OpenTelemetry Collector to offload the burden of exporting data to a backend, and how to take full advantage of a Tracing backend to achieve observability nirvana.</p>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="opentelemetry" /><category term="observability" /><category term="monitoring" /><category term="distributed-tracing" /><summary type="html"><![CDATA[In this series of posts, I’ll be exploring OpenTelemetry and how it can help you improve the observability of your applications. I will focus on the tracing capabilities of OpenTelemetry, but I’ll also touch on metrics and logs - and specifically how they can be linked together to decrease the time to detect and resolve issues in your applications.]]></summary></entry><entry><title type="html">Practical Docker - Apache, PHP and MySQL (CakePHP example)</title><link href="/practical-docker-apache-php-and-mysql-cakephp-example/" rel="alternate" type="text/html" title="Practical Docker - Apache, PHP and MySQL (CakePHP example)" /><published>2016-02-21T00:00:00+00:00</published><updated>2016-02-21T00:00:00+00:00</updated><id>/practical-docker-apache-php-and-mysql-cakephp-example</id><content type="html" xml:base="/practical-docker-apache-php-and-mysql-cakephp-example/"><![CDATA[<p>I will begin this series of posts about docker with a practical example using a simple Apache + PHP with MySQL setup. We’ll be using a basic CakePHP application as the example Web App.</p>

<p>This guide assumes that you have already done the docker setup in your development machine.</p>

<h3 id="mysql">MySQL</h3>

<p>We’ll be using a separate docker container for MySQL, for the sake of isolation and also because it will bring benefits when you are trying to scale out your application. For example, you may want to run MySQL in a separate machine for performance, or have multiple MySQL hosts load balanced to handle the scale of your app.</p>

<p>In the file below, you have many sections that are commented-out and that you can customize for your own environment. For example, you may choose to avoid the MySQL root user at all, and create your custom user. I’ve also set the default charset and collation to utf8mb4 / utf8mb4_general_ci, but you can change it to what makes more sense to you.</p>

<p>The final Dockerfile for MySQL looks like this:</p>

<div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">FROM</span><span class="s"> mysql/mysql-server:latest</span>

<span class="c"># ROOT PASSWORD</span>
<span class="c"># to secure your installation, you should avoid MYSQL_ROOT_PASSWORD and </span>
<span class="c"># instead set MYSQL_RANDOM_ROOT_PASSWORD and MYSQL_ONETIME_PASSWORD to yes</span>

<span class="k">ENV</span><span class="s"> MYSQL_ROOT_PASSWORD=secret</span>
<span class="c">#ENV MYSQL_RANDOM_ROOT_PASSWORD=yes</span>
<span class="c">#ENV MYSQL_ONETIME_PASSWORD=yes</span>

<span class="c"># NEW USER AND DATABASE</span>
<span class="c"># you can specify the name of a database to be created during initialization.</span>
<span class="c"># if you specify also an username and password, the mysql user will be created </span>
<span class="c"># with full control over that database.</span>

<span class="k">ENV</span><span class="s"> MYSQL_DATABASE=sample-database</span>
<span class="c">#ENV MYSQL_USER=sample-username</span>
<span class="c">#ENV MYSQL_PASSWORD=sample-password</span>

<span class="c"># SERVER DEFAULT CHARSET AND COLLATION</span>

<span class="k">RUN </span><span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"/default-character-set/d"</span> /etc/my.cnf
<span class="k">RUN </span><span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"/</span><span class="se">\[</span><span class="s2">mysqld]/a skip-character-set-client-handshake"</span> /etc/my.cnf
<span class="k">RUN </span><span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"/</span><span class="se">\[</span><span class="s2">mysqld]/a collation-server=utf8mb4_general_ci"</span> /etc/my.cnf
<span class="k">RUN </span><span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"/</span><span class="se">\[</span><span class="s2">mysqld]/a character-set-server=utf8mb4"</span> /etc/my.cnf
<span class="k">RUN </span><span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"/</span><span class="se">\[</span><span class="s2">mysqld]/a init_connect= 'SET NAMES utf8mb4' "</span> /etc/my.cnf
<span class="k">RUN </span><span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"/</span><span class="se">\[</span><span class="s2">mysqld]/a init_connect=‘SET collation_connection = utf8mb4_general_ci' "</span> /etc/my.cnf

<span class="k">EXPOSE</span><span class="s"> 3306</span>
</code></pre></div></div>

<p>To use this, you need to run the following commands (in this case, I’m running this while inside the folder where the Dockerfile is, hence the “dot” after the image name):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">-t</span> danielbcorreia/mysql <span class="nb">.</span>
docker run <span class="nt">-d</span> <span class="nt">-p</span> 3306:3306 <span class="nt">--name</span> mysql danielbcorreia/mysql
docker ps <span class="nt">-a</span>
</code></pre></div></div>

<p>You’ll see something like this:</p>

<pre><code class="language-plain">CONTAINER ID        IMAGE                           COMMAND                   CREATED             STATUS                         PORTS                    NAMES
1d7da0649a04        danielbcorreia/mysql            "/entrypoint.sh mysql"    30 seconds ago      Up 4 seconds                   0.0.0.0:3306-&amp;gt;3306/tcp   mysql
</code></pre>

<p>This means that your container is now active, and you can try to connect using any MySQL client. I’ve used MySQL Workbench for this, keep in mind that the host is the IP address of your Virtual Machine (if you are using Windows) or localhost if you are using your own linux box. The username and password are the ones specified on the Dockerfile. If you used the same as above, then you can access with root/secret.</p>

<p>If you were able to connect, that means that your container is now running correctly.</p>

<h3 id="apache--php">Apache + PHP</h3>

<p>Before starting, you will need to install/download CakePHP into a folder, usually you can do it this way:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-s</span> https://getcomposer.org/installer | php
php composer.phar create-project <span class="nt">--prefer-dist</span> cakephp/app my-app
</code></pre></div></div>

<p>We’ll be working inside the “my-app” folder that composer created for CakePHP.
First we need to check the requirements for our web application. Since we are using CakePHP, we’ll need the following extensions:</p>
<ul>
  <li>intl</li>
  <li>mbstring</li>
  <li>pdo_mysql</li>
</ul>

<p>We’ll also need to enable mod_rewrite for Apache. Since we are messing with the PHP extensions, we’ll add some common ones like GD and mcrypt.</p>

<p>This is the final Dockerfile (note that i’m using PHP7, but you can change it according to the tags here <a href="https://hub.docker.com/_/php/" target="_blank">PHP Docker Hub</a>):</p>

<div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">FROM</span><span class="s"> php:7-apache</span>
<span class="k">COPY</span><span class="s"> . /var/www/html/</span>

<span class="k">RUN </span>a2enmod rewrite

<span class="k">RUN </span>apt-get update <span class="o">&amp;&amp;</span> apt-get <span class="nb">install</span> <span class="nt">-y</span> <span class="se">\
</span>        libfreetype6-dev <span class="se">\
</span>        libjpeg62-turbo-dev <span class="se">\
</span>        libmcrypt-dev <span class="se">\
</span>        libpng12-dev <span class="se">\
</span>        zlib1g-dev <span class="se">\
</span>        libicu-dev <span class="se">\
</span>        g++ <span class="se">\
</span>    <span class="o">&amp;&amp;</span> docker-php-ext-configure intl <span class="se">\
</span>    <span class="o">&amp;&amp;</span> docker-php-ext-install <span class="nt">-j</span><span class="si">$(</span><span class="nb">nproc</span><span class="si">)</span> iconv mcrypt intl pdo pdo_mysql mbstring <span class="se">\
</span>    <span class="o">&amp;&amp;</span> docker-php-ext-configure gd <span class="nt">--with-freetype-dir</span><span class="o">=</span>/usr/include/ <span class="nt">--with-jpeg-dir</span><span class="o">=</span>/usr/include/ <span class="se">\
</span>    <span class="o">&amp;&amp;</span> docker-php-ext-install <span class="nt">-j</span><span class="si">$(</span><span class="nb">nproc</span><span class="si">)</span> gd

<span class="k">RUN </span><span class="nb">chmod</span> <span class="nt">-R</span> 777 /var/www/html/tmp/
<span class="k">RUN </span><span class="nb">chmod</span> <span class="nt">-R</span> 777 /var/www/html/logs/

<span class="k">EXPOSE</span><span class="s"> 80</span>
</code></pre></div></div>

<p>To run this, you need to run the following:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">-t</span> danielbcorreia/cakephp-apache <span class="nb">.</span>
docker run <span class="nt">-d</span> <span class="nt">-p</span> 80:80 <span class="nt">--name</span> cakephp danielbcorreia/cakephp-apache
docker ps <span class="nt">-a</span>
</code></pre></div></div>

<p>Note that right now, both containers are independent from each other. Your should be able to access http://{your-ip} and see the CakePHP application running, but with a warning regarding the database connection.</p>

<p>To fix this, we’ll begin with changing the CakePHP configuration file (for CakePHP 3 you should change the /config/app.php file). Search for the datasource section and replace the configuration to match your MySQL Dockerfile configuration:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s1">'Datasources'</span> <span class="o">=&gt;</span> <span class="p">[</span>
        <span class="s1">'default'</span> <span class="o">=&gt;</span> <span class="p">[</span>
            <span class="mf">...</span>
            <span class="s1">'host'</span> <span class="o">=&gt;</span> <span class="s1">'mysql'</span><span class="p">,</span> <span class="cm">/* this is the name that you provided on the --link parameter of docker */</span>
            <span class="s1">'username'</span> <span class="o">=&gt;</span> <span class="s1">'root'</span><span class="p">,</span>
            <span class="s1">'password'</span> <span class="o">=&gt;</span> <span class="s1">'secret'</span><span class="p">,</span>
            <span class="s1">'database'</span> <span class="o">=&gt;</span> <span class="s1">'sample-database'</span><span class="p">,</span>
            <span class="s1">'encoding'</span> <span class="o">=&gt;</span> <span class="s1">'utf8mb4'</span><span class="p">,</span>
            <span class="mf">...</span>
        <span class="p">],</span>
        <span class="mf">...</span>
    <span class="p">]</span>
</code></pre></div></div>

<p><strong>Note that the “host” property is the name of the link that we will provide in the next step, not the image name!</strong></p>

<p>To link these two images together, you should first rebuild the cakephp image:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker stop cakephp
docker <span class="nb">rm </span>cakephp
docker build <span class="nt">-t</span> danielbcorreia/cakephp-apache <span class="nb">.</span>
</code></pre></div></div>

<p>Then run the image, linking it to the mysql container:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-d</span> <span class="nt">-p</span> 80:80 <span class="nt">--name</span> cakephp <span class="nt">--link</span> mysql:mysql danielbcorreia/cakephp-apache
</code></pre></div></div>

<p>IF you access http://{your-ip} now, you should have the CakePHP page with the MySQL connection active.</p>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="docker" /><category term="php" /><category term="apache" /><category term="mysql" /><category term="cakephp" /><summary type="html"><![CDATA[I will begin this series of posts about docker with a practical example using a simple Apache + PHP with MySQL setup. We’ll be using a basic CakePHP application as the example Web App.]]></summary></entry><entry><title type="html">OutputCacheProvider for Redis</title><link href="/outputcacheprovider-for-redis/" rel="alternate" type="text/html" title="OutputCacheProvider for Redis" /><published>2014-07-20T00:00:00+00:00</published><updated>2014-07-20T00:00:00+00:00</updated><id>/outputcacheprovider-for-redis</id><content type="html" xml:base="/outputcacheprovider-for-redis/"><![CDATA[<p>Following this series of posts about caching and OutputCache in particular, I will now show you how to use Redis to store the output cache items in your ASP.NET MVC application. You can use the same concepts to store in any other data store, such as AppFabric, MongoDb, File System, etc.</p>

<p>First, we will need a Redis client. In this implementation i’m using <a href="https://www.nuget.org/packages/StackExchange.Redis/" target="_blank">StackExchange.Redis</a>, so you will need to run this in the package manager console (or via nuget package manager UI):</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Install-Package</span><span class="w"> </span><span class="nx">StackExchange.Redis</span><span class="w">
</span></code></pre></div></div>

<p>Next, let’s implement the provider. The first thing you should do is to create a class that inherits from System.Web.Caching.OutputCacheProvider, and then provide implementations for Add, Set, Get and Remove methods. The stubs look 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">RedisOutputCacheProvider</span> <span class="p">:</span> <span class="n">OutputCacheProvider</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">override</span> <span class="kt">object</span> <span class="nf">Add</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</span><span class="p">,</span> <span class="kt">object</span> <span class="n">entry</span><span class="p">,</span> <span class="n">DateTime</span> <span class="n">utcExpiry</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>

    <span class="k">public</span> <span class="k">override</span> <span class="kt">object</span> <span class="nf">Get</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</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>

    <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Remove</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</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>

    <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Set</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</span><span class="p">,</span> <span class="kt">object</span> <span class="n">entry</span><span class="p">,</span> <span class="n">DateTime</span> <span class="n">utcExpiry</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>
<span class="p">}</span>
</code></pre></div></div>

<p>Next, we will connect to the Redis cluster. Since i’m only using my local development machine for testing, i’ll create a ConnectionMultiplexer like so:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">private</span> <span class="k">static</span> <span class="n">ConnectionMultiplexer</span> <span class="n">Redis</span> <span class="p">=</span> <span class="n">ConnectionMultiplexer</span><span class="p">.</span><span class="nf">Connect</span><span class="p">(</span><span class="s">"localhost:6379"</span><span class="p">);</span>
</code></pre></div></div>

<p>Also, since this Redis client needs to receive a byte[] when storing the entries, we will need to handle the serialization as well. I created an abstraction for this, also because I wanted to test with different serializers:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">interface</span> <span class="nc">IItemSerializer</span>
<span class="p">{</span>
    <span class="kt">byte</span><span class="p">[]</span> <span class="nf">Serialize</span><span class="p">(</span><span class="kt">object</span> <span class="n">item</span><span class="p">);</span>
    <span class="kt">object</span> <span class="nf">Deserialize</span><span class="p">(</span><span class="kt">byte</span><span class="p">[]</span> <span class="n">itemBytes</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Now, for the provider implementation:</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">RedisOutputCacheProvider</span> <span class="p">:</span> <span class="n">OutputCacheProvider</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="k">static</span> <span class="n">ConnectionMultiplexer</span> <span class="n">Redis</span> <span class="p">=</span> <span class="n">ConnectionMultiplexer</span><span class="p">.</span><span class="nf">Connect</span><span class="p">(</span><span class="s">"localhost:6379"</span><span class="p">);</span>
    <span class="k">private</span> <span class="k">static</span> <span class="n">IItemSerializer</span> <span class="n">Serializer</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">BinaryFormatterItemSerializer</span><span class="p">();</span>

    <span class="k">public</span> <span class="k">override</span> <span class="kt">object</span> <span class="nf">Add</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</span><span class="p">,</span> <span class="kt">object</span> <span class="n">entry</span><span class="p">,</span> <span class="n">DateTime</span> <span class="n">utcExpiry</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// return the existing value if any</span>
        <span class="kt">var</span> <span class="n">existingValue</span> <span class="p">=</span> <span class="nf">Get</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">existingValue</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">return</span> <span class="n">existingValue</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="kt">var</span> <span class="n">expiration</span> <span class="p">=</span> <span class="n">utcExpiry</span> <span class="p">-</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">UtcNow</span><span class="p">;</span>
        <span class="kt">var</span> <span class="n">entryBytes</span> <span class="p">=</span> <span class="n">Serializer</span><span class="p">.</span><span class="nf">Serialize</span><span class="p">(</span><span class="n">entry</span><span class="p">);</span>

        <span class="kt">var</span> <span class="n">db</span> <span class="p">=</span> <span class="n">Redis</span><span class="p">.</span><span class="nf">GetDatabase</span><span class="p">();</span>

        <span class="c1">// set the cache item with the defined expiration, only if an item does not exist</span>
        <span class="n">db</span><span class="p">.</span><span class="nf">StringSet</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">entryBytes</span><span class="p">,</span> <span class="n">expiration</span><span class="p">,</span> <span class="n">When</span><span class="p">.</span><span class="n">NotExists</span><span class="p">);</span>

        <span class="k">return</span> <span class="n">entry</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Set</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</span><span class="p">,</span> <span class="kt">object</span> <span class="n">entry</span><span class="p">,</span> <span class="n">DateTime</span> <span class="n">utcExpiry</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">expiration</span> <span class="p">=</span> <span class="n">utcExpiry</span> <span class="p">-</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">UtcNow</span><span class="p">;</span>
        <span class="kt">var</span> <span class="n">entryBytes</span> <span class="p">=</span> <span class="n">Serializer</span><span class="p">.</span><span class="nf">Serialize</span><span class="p">(</span><span class="n">entry</span><span class="p">);</span>

        <span class="kt">var</span> <span class="n">db</span> <span class="p">=</span> <span class="n">Redis</span><span class="p">.</span><span class="nf">GetDatabase</span><span class="p">();</span>

        <span class="c1">// set the cache item with the defined expiration, overriding existing items</span>
        <span class="n">db</span><span class="p">.</span><span class="nf">StringSet</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">entryBytes</span><span class="p">,</span> <span class="n">expiration</span><span class="p">,</span> <span class="n">When</span><span class="p">.</span><span class="n">Always</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">override</span> <span class="kt">object</span> <span class="nf">Get</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">db</span> <span class="p">=</span> <span class="n">Redis</span><span class="p">.</span><span class="nf">GetDatabase</span><span class="p">();</span>

        <span class="kt">var</span> <span class="n">valueBytes</span> <span class="p">=</span> <span class="n">db</span><span class="p">.</span><span class="nf">StringGet</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(!</span><span class="n">valueBytes</span><span class="p">.</span><span class="n">HasValue</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="kt">var</span> <span class="k">value</span> <span class="p">=</span> <span class="n">Serializer</span><span class="p">.</span><span class="nf">Deserialize</span><span class="p">(</span><span class="n">valueBytes</span><span class="p">);</span>

        <span class="k">return</span> <span class="k">value</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Remove</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">db</span> <span class="p">=</span> <span class="n">Redis</span><span class="p">.</span><span class="nf">GetDatabase</span><span class="p">();</span>

        <span class="c1">// signal key removal but don't wait for the result</span>
        <span class="n">db</span><span class="p">.</span><span class="nf">KeyDelete</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The provider implementation must follow the documentation guidelines in the <a href="http://msdn.microsoft.com/en-us/library/system.web.caching.outputcacheprovider(v=vs.100).aspx" target="_blank">MSDN page</a>.</p>

<p>In particular, these are the main design rules for the Add method:</p>
<ul>
  <li>If there is already a value in the cache for the specified key, the provider must return that value.</li>
  <li>The Add method stores the data if it is not already in the cache.</li>
  <li>If the data is in the cache, the Add method returns it.</li>
</ul>

<p>In the example above, i’m using a implementation of the IItemSerializer interface that uses the BinaryFormatter for the serialization:</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">BinaryFormatterItemSerializer</span> <span class="p">:</span> <span class="n">IItemSerializer</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="kt">byte</span><span class="p">[]</span> <span class="nf">Serialize</span><span class="p">(</span><span class="kt">object</span> <span class="n">item</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">formatter</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">BinaryFormatter</span><span class="p">();</span>

        <span class="kt">byte</span><span class="p">[]</span> <span class="n">itemBytes</span><span class="p">;</span>

        <span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">ms</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MemoryStream</span><span class="p">())</span>
        <span class="p">{</span>
            <span class="n">formatter</span><span class="p">.</span><span class="nf">Serialize</span><span class="p">(</span><span class="n">ms</span><span class="p">,</span> <span class="n">item</span><span class="p">);</span>
            <span class="n">itemBytes</span> <span class="p">=</span> <span class="n">ms</span><span class="p">.</span><span class="nf">ToArray</span><span class="p">();</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="n">itemBytes</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="kt">object</span> <span class="nf">Deserialize</span><span class="p">(</span><span class="kt">byte</span><span class="p">[]</span> <span class="n">bytes</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">formatter</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">BinaryFormatter</span><span class="p">();</span>

        <span class="kt">object</span> <span class="n">item</span><span class="p">;</span>
        <span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">ms</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MemoryStream</span><span class="p">(</span><span class="n">bytes</span><span class="p">))</span>
        <span class="p">{</span>
            <span class="n">item</span> <span class="p">=</span> <span class="n">formatter</span><span class="p">.</span><span class="nf">Deserialize</span><span class="p">(</span><span class="n">ms</span><span class="p">);</span>
        <span class="p">}</span>

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

<h3 id="unit-testing">Unit testing</h3>

<p>I wrote some unit tests so that we can check that everything is working correctly before using it in our application. The first test checks all the basic functionality, and the second one checks the ability of the cache provider to remove expired items:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">TestClass</span><span class="p">]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">RedisOutputCacheProviderTests</span>
<span class="p">{</span>
    <span class="p">[</span><span class="n">TestMethod</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">CanAddAndGetAndSetAndRemoveItem</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">key</span> <span class="p">=</span> <span class="s">"mykey"</span> <span class="p">+</span> <span class="n">Guid</span><span class="p">.</span><span class="nf">NewGuid</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">provider</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">RedisOutputCacheProvider</span><span class="p">();</span>

        <span class="c1">// test add and get</span>

        <span class="n">provider</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="s">"myvalue"</span><span class="p">,</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">UtcNow</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromMinutes</span><span class="p">(</span><span class="m">1</span><span class="p">)));</span>

        <span class="kt">var</span> <span class="k">value</span> <span class="p">=</span> <span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="n">provider</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>

        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">"myvalue"</span><span class="p">,</span> <span class="k">value</span><span class="p">);</span>

        <span class="c1">// test set and get</span>

        <span class="n">provider</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="s">"anothervalue"</span><span class="p">,</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">UtcNow</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromMinutes</span><span class="p">(</span><span class="m">1</span><span class="p">)));</span>

        <span class="kt">var</span> <span class="n">valueAfterSet</span> <span class="p">=</span> <span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="n">provider</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>

        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">"anothervalue"</span><span class="p">,</span> <span class="n">valueAfterSet</span><span class="p">);</span>

        <span class="c1">// test remove and get</span>

        <span class="n">provider</span><span class="p">.</span><span class="nf">Remove</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>

        <span class="kt">var</span> <span class="n">valueAfterRemove</span> <span class="p">=</span> <span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="n">provider</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>
        <span class="n">Assert</span><span class="p">.</span><span class="n">Is</span> <span class="nf">Null</span><span class="p">(</span><span class="n">valueAfterRemove</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="p">[</span><span class="n">TestMethod</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">EntryExpiresAfterAbsoluteTime</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">key</span> <span class="p">=</span> <span class="s">"mykey"</span> <span class="p">+</span> <span class="n">Guid</span><span class="p">.</span><span class="nf">NewGuid</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">provider</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">RedisOutputCacheProvider</span><span class="p">();</span>

        <span class="c1">// add the value and check that it is in cache</span>

        <span class="n">provider</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="s">"myvalue"</span><span class="p">,</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">UtcNow</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromSeconds</span><span class="p">(</span><span class="m">3</span><span class="p">)));</span>
        <span class="kt">var</span> <span class="k">value</span> <span class="p">=</span> <span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="n">provider</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">"myvalue"</span><span class="p">,</span> <span class="k">value</span><span class="p">);</span>

        <span class="k">await</span> <span class="n">Task</span><span class="p">.</span><span class="nf">Delay</span><span class="p">(</span><span class="m">3000</span><span class="p">);</span>

        <span class="kt">var</span> <span class="n">valueAfterExpiration</span> <span class="p">=</span> <span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="n">provider</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>
        <span class="n">Assert</span><span class="p">.</span><span class="n">Is</span> <span class="nf">Null</span><span class="p">(</span><span class="n">valueAfterExpiration</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="configure-your-web-application">Configure your web application</h3>

<p>After checking that the basic behavior is fine, we can integrate the provider into our web application. Assuming that you are already using the OutputCacheAttribute, you can do this by adding the following xml to your web.config:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;system.web&gt;</span>
  (...)
  <span class="nt">&lt;caching&gt;</span>
    <span class="nt">&lt;outputcache</span> <span class="na">defaultprovider=</span><span class="s">"RedisOutputCache"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;providers&gt;</span>
        <span class="nt">&lt;add</span> <span class="na">name=</span><span class="s">"RedisOutputCache"</span> <span class="na">type=</span><span class="s">"YourNamespace.RedisOutputCacheProvider, YourAssemblyName"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;/add&gt;&lt;/providers&gt;</span>
    <span class="nt">&lt;/outputcache&gt;</span>
  <span class="nt">&lt;/caching&gt;</span>
  (...)
<span class="nt">&lt;/system.web&gt;</span>
</code></pre></div></div>

<p>Then, if you go back to your web application, your OutputCache attributes should all be using this new provider!</p>

<h3 id="further-work">Further work</h3>

<p>I was also experimenting with a faster binary serializer, protobuf-net. It works for unit tests, but since the type that the OutputCache is trying to store is <strong>internal</strong>, we cannot use this implementation at the moment. I will try to figure out a way to use protobuf-net for this, and if you have any suggestions please drop a comment below:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="k">using</span> <span class="nn">ProtoBuf</span><span class="p">;</span>
<span class="p">...</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">ProtoBufItemSerializer</span> <span class="p">:</span> <span class="n">IItemSerializer</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="kt">byte</span><span class="p">[]</span> <span class="nf">Serialize</span><span class="p">(</span><span class="kt">object</span> <span class="n">entry</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">item</span> <span class="p">=</span> <span class="k">new</span> <span class="n">CacheItem</span> <span class="p">{</span> <span class="n">Value</span> <span class="p">=</span> <span class="n">entry</span> <span class="p">};</span>

        <span class="kt">byte</span><span class="p">[]</span> <span class="n">itemBytes</span><span class="p">;</span>

        <span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">ms</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MemoryStream</span><span class="p">())</span>
        <span class="p">{</span>
            <span class="n">Serializer</span><span class="p">.</span><span class="n">Serialize</span><span class="p">&lt;</span><span class="n">cacheitem</span><span class="p">&gt;(</span><span class="n">ms</span><span class="p">,</span> <span class="n">item</span><span class="p">);</span>
            <span class="n">itemBytes</span> <span class="p">=</span> <span class="n">ms</span><span class="p">.</span><span class="nf">ToArray</span><span class="p">();</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="n">itemBytes</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="kt">object</span> <span class="nf">Deserialize</span><span class="p">(</span><span class="kt">byte</span><span class="p">[]</span> <span class="n">bytes</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">CacheItem</span> <span class="n">item</span><span class="p">;</span>
        <span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">ms</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MemoryStream</span><span class="p">(</span><span class="n">bytes</span><span class="p">))</span>
        <span class="p">{</span>
            <span class="n">item</span> <span class="p">=</span> <span class="n">Serializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">cacheitem</span><span class="p">&gt;(</span><span class="n">ms</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="n">item</span><span class="p">.</span><span class="n">Value</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="p">[</span><span class="n">ProtoContract</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">class</span> <span class="nc">CacheItem</span>
    <span class="p">{</span>
        <span class="p">[</span><span class="nf">ProtoMember</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="n">DynamicType</span> <span class="p">=</span> <span class="k">true</span><span class="p">)]</span>
        <span class="k">public</span> <span class="kt">object</span> <span class="n">Value</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Finally, since I didn’t want my web application to fail when temporary connection issues to the Redis cluster arise, I wrapped all the implementations in a try-catch, so that if the cache fails, MVC will ignore the cache and execute the action.</p>

<p>Example for the Get method:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">override</span> <span class="kt">object</span> <span class="nf">Get</span><span class="p">(</span><span class="kt">string</span> <span class="n">key</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">try</span>
    <span class="p">{</span>
        <span class="c1">// implementation goes here</span>
    <span class="p">}</span>
    <span class="k">catch</span> <span class="p">(</span><span class="n">RedisConnectionException</span> <span class="n">e</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">Trace</span><span class="p">.</span><span class="nf">TraceError</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="nf">ToString</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>
</code></pre></div></div>

<p>You can test this by loading up your web application, making a request to a OutputCached action, and then shutting down redis and reloading the page. The page should still show up, but the content is being regenerated in every request.</p>

<h3 id="invalidating-cache-when-data-changes">Invalidating cache when data changes</h3>

<p>You can invalidate a cache item over the response context. As an example, I created one more action in my controller to invalidate the Index item cache:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="kt">string</span> <span class="nf">InvalidateCache</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">Response</span><span class="p">.</span><span class="nf">RemoveOutputCacheItem</span><span class="p">(</span><span class="n">Url</span><span class="p">.</span><span class="nf">Action</span><span class="p">(</span><span class="s">"Index"</span><span class="p">,</span> <span class="s">"Home"</span><span class="p">));</span>
    <span class="k">return</span> <span class="s">"Done"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="code-on-github">Code on GitHub</h3>

<p>I created a repository on github to host these and other OutputCache-related extensions. You can find the full code at <a href="https://github.com/danielbcorreia/OutputCacheExtensions" target="_blank">https://github.com/danielbcorreia/OutputCacheExtensions</a>.</p>

<p>If you have any comments or suggestions about this article, go ahead and write in the comments.</p>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="cache" /><category term="redis" /><category term="mvc" /><category term="performance" /><category term="dotnet" /><summary type="html"><![CDATA[Following this series of posts about caching and OutputCache in particular, I will now show you how to use Redis to store the output cache items in your ASP.NET MVC application. You can use the same concepts to store in any other data store, such as AppFabric, MongoDb, File System, etc.]]></summary></entry><entry><title type="html">ASP.NET MVC OutputCache Vary by Current User</title><link href="/asp-net-mvc-vary-by-current-user/" rel="alternate" type="text/html" title="ASP.NET MVC OutputCache Vary by Current User" /><published>2014-07-19T00:00:00+00:00</published><updated>2014-07-19T00:00:00+00:00</updated><id>/asp-net-mvc-vary-by-current-user</id><content type="html" xml:base="/asp-net-mvc-vary-by-current-user/"><![CDATA[<p>Caching user-specific data is a common requirement in web applications. Most times the first thing that you do when you sign in a user in your website is redirect them to a dashboard that is unique for that user. When the user spends a lot of time on his dashboard, you need to make sure that you can improve his experience without compromising your ability to fetch all the relevant data from all the different parts of your system.</p>

<p>In ASP.NET MVC, the easier way to cache the full rendered page is to use the OutputCacheAttribute, like so:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Authorize</span><span class="p">]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">DashboardController</span> <span class="p">:</span> <span class="n">Controller</span> 
<span class="p">{</span>
    <span class="p">[</span><span class="nf">OutputCache</span><span class="p">(</span><span class="n">Duration</span> <span class="p">=</span> <span class="m">3600</span><span class="p">)]</span>
    <span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">Index</span><span class="p">()</span> 
    <span class="p">{</span>
       <span class="c1">// Your awesome code goes here</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The previous code would make the Index action stay in cache for one hour. This works great for public content, but for user-specific content you must complement the cache key, so that different users don’t see each-other’s cache.</p>

<p>To do this, we use the VaryByCustom property of the OutputCacheAttribute, like this:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Authorize</span><span class="p">]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">DashboardController</span> <span class="p">:</span> <span class="n">Controller</span> 
<span class="p">{</span>
    <span class="p">[</span><span class="nf">OutputCache</span><span class="p">(</span><span class="n">Duration</span> <span class="p">=</span> <span class="m">3600</span><span class="p">,</span> <span class="n">VaryByCustom</span> <span class="p">=</span> <span class="s">"User"</span><span class="p">)]</span>
    <span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">Index</span><span class="p">()</span> 
    <span class="p">{</span>
       <span class="c1">// Your awesome code goes here</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And you also need to handle that “User” value in a method that is called over the HttpApplication: the GetVaryByCustomString method.
So, you need to <strong>go to your Global.asax.cs</strong> and override that method:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">override</span> <span class="kt">string</span> <span class="nf">GetVaryByCustomString</span><span class="p">(</span><span class="n">HttpContext</span> <span class="n">context</span><span class="p">,</span> <span class="kt">string</span> <span class="n">arg</span><span class="p">)</span> 
<span class="p">{</span> 
    <span class="k">if</span> <span class="p">(</span><span class="n">arg</span><span class="p">.</span><span class="nf">Equals</span><span class="p">(</span><span class="s">"User"</span><span class="p">,</span> <span class="n">StringComparison</span><span class="p">.</span><span class="n">InvariantCultureIgnoreCase</span><span class="p">))</span> 
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">user</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">User</span><span class="p">.</span><span class="n">Identity</span><span class="p">.</span><span class="n">Name</span><span class="p">;</span> <span class="c1">// TODO here you have to pick an unique identifier from the current user identity</span>
        <span class="k">return</span> <span class="kt">string</span><span class="p">.</span><span class="nf">Format</span><span class="p">(</span><span class="s">"{0}@{1}"</span><span class="p">,</span> <span class="n">userIdentifier</span><span class="p">.</span><span class="n">Name</span><span class="p">,</span> <span class="n">userIdentifier</span><span class="p">.</span><span class="n">Container</span><span class="p">);</span> 
    <span class="p">}</span>

    <span class="k">return</span> <span class="k">base</span><span class="p">.</span><span class="nf">GetVaryByCustomString</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">arg</span><span class="p">);</span> 
<span class="p">}</span>
</code></pre></div></div>

<p>Or, if you don’t set a custom principal in your pipeline, you can look for the session id like so:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">private</span> <span class="k">static</span> <span class="n">SessionStateSection</span> <span class="n">SessionStateSection</span> <span class="p">=</span> <span class="p">(</span><span class="n">System</span><span class="p">.</span><span class="n">Web</span><span class="p">.</span><span class="n">Configuration</span><span class="p">.</span><span class="n">SessionStateSection</span><span class="p">)</span><span class="n">ConfigurationManager</span><span class="p">.</span><span class="nf">GetSection</span><span class="p">(</span><span class="s">"system.web/sessionState"</span><span class="p">);</span>

<span class="k">public</span> <span class="k">override</span> <span class="kt">string</span> <span class="nf">GetVaryByCustomString</span><span class="p">(</span><span class="n">HttpContext</span> <span class="n">context</span><span class="p">,</span> <span class="kt">string</span> <span class="n">arg</span><span class="p">)</span> 
<span class="p">{</span> 
    <span class="k">if</span> <span class="p">(</span><span class="n">arg</span><span class="p">.</span><span class="nf">Equals</span><span class="p">(</span><span class="s">"User"</span><span class="p">,</span> <span class="n">StringComparison</span><span class="p">.</span><span class="n">InvariantCultureIgnoreCase</span><span class="p">))</span> 
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">cookieName</span> <span class="p">=</span>  <span class="n">SessionStateSection</span><span class="p">.</span><span class="n">CookieName</span><span class="p">;</span>
        <span class="kt">var</span> <span class="n">cookie</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">Request</span><span class="p">.</span><span class="n">Cookies</span><span class="p">[</span><span class="n">cookieName</span><span class="p">];</span>
        <span class="k">return</span> <span class="n">cookie</span><span class="p">.</span><span class="n">Value</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="k">base</span><span class="p">.</span><span class="nf">GetVaryByCustomString</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">arg</span><span class="p">);</span> 
<span class="p">}</span>
</code></pre></div></div>

<p>I’m using the session state configuration section to get the session cookie name, so that if you changed the default “ASP.NET_SessionId” it will still work.</p>

<p>I hope you will find this handy. If you have more cache subjects you would like me to write about, please write in the comments.
In the next post I expect to demonstrate how to implement an OutputCacheAttribute that that enables you to choose another cache provider instead of the memory cache, so that you can use a distributed cache system like AppFabric or a Redis Cluster to store your rendered pages.</p>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="cache" /><category term="mvc" /><category term="performance" /><category term="dotnet" /><summary type="html"><![CDATA[Caching user-specific data is a common requirement in web applications. Most times the first thing that you do when you sign in a user in your website is redirect them to a dashboard that is unique for that user. When the user spends a lot of time on his dashboard, you need to make sure that you can improve his experience without compromising your ability to fetch all the relevant data from all the different parts of your system.]]></summary></entry><entry><title type="html">Benchmark Driven Development and Parsing binary data in JavaScript</title><link href="/benchmark-dd-and-javascript-binary-data/" rel="alternate" type="text/html" title="Benchmark Driven Development and Parsing binary data in JavaScript" /><published>2014-04-13T00:00:00+00:00</published><updated>2014-04-13T00:00:00+00:00</updated><id>/benchmark-dd-and-javascript-binary-data</id><content type="html" xml:base="/benchmark-dd-and-javascript-binary-data/"><![CDATA[<p>I’ve come across an interesting read on the development of a mysql client for Node.js. The full article can be found here:</p>

<p><a href="https://github.com/felixge/faster-than-c" title="https://github.com/felixge/faster-than-c" target="_blank">https://github.com/felixge/faster-than-c</a></p>

<p>It’s a very interesting read on the competition among similar open-source projects nowadays, but what really made me think was the concept of Benchmark Driven Development. It is awesome, and i’ve seen projects like <a href="http://webscalesql.org/" title="WebScaleSql" target="_blank">WebScaleSql</a> use it but not naming it that.</p>

<p>Other thing that was impressive was the fact that in a given point in time, the mentioned mysql libraries had so much throughput that they could take down the actual mysql server. In fact, that could look that way with a single DB server, but with a cluster with many read-only slaves I think we could still use it (the article does not specify the type of commands that are being executed, so i’m assuming that they are talking about reads. scaling writes is much harder).</p>

<p>Anyway, I recommend that you read that article. It’s a 5 minute read, and it’s worth it.</p>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="bdd" /><category term="benchmark" /><category term="mysql" /><category term="nodejs" /><category term="performance" /><summary type="html"><![CDATA[I’ve come across an interesting read on the development of a mysql client for Node.js. The full article can be found here:]]></summary></entry><entry><title type="html">MEO Wallet API Client in .NET/C#</title><link href="/meo-wallet-api-client-in-dotnet-csharp/" rel="alternate" type="text/html" title="MEO Wallet API Client in .NET/C#" /><published>2014-04-13T00:00:00+00:00</published><updated>2014-04-13T00:00:00+00:00</updated><id>/meo-wallet-api-client-in-dotnet-csharp</id><content type="html" xml:base="/meo-wallet-api-client-in-dotnet-csharp/"><![CDATA[<p>I’ve been playing with the <a href="https://developers.wallet.pt/" title="MEO Wallet API" target="_blank">MEO Wallet API</a> that was released in a “preview” environment at the first day of <a href="http://codebits.eu" title="Codebits " target="_blank">Codebits</a>.</p>

<p>In the very same day I had a working prototype of a slot machine, where you could buy credits to play with MEO Wallet. In the next day, we deployed it and added a redeem feature, so that users could cash-out after a jackpot.</p>

<p>Well, I decided to reuse some of the code that we did at Codebits to develop a generic MEO Wallet API Client. It was designed for .NET 4.5, uses HttpClient and has a demo project that you can play with.</p>

<p>Check it out: <a href="https://github.com/danielbcorreia/MeoWalletDotNetClient" target="_blank">https://github.com/danielbcorreia/MeoWalletDotNetClient</a></p>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="async" /><category term="codebits" /><category term="httpclient" /><category term="meowallet" /><category term="dotnet" /><summary type="html"><![CDATA[I’ve been playing with the MEO Wallet API that was released in a “preview” environment at the first day of Codebits.]]></summary></entry><entry><title type="html">Quick-start to MVC4 Bundling</title><link href="/quick-start-to-mvc4-bundling/" rel="alternate" type="text/html" title="Quick-start to MVC4 Bundling" /><published>2012-11-04T00:00:00+00:00</published><updated>2012-11-04T00:00:00+00:00</updated><id>/quick-start-to-mvc4-bundling</id><content type="html" xml:base="/quick-start-to-mvc4-bundling/"><![CDATA[<p>After using MVC4’s bundling in a couple of web apps I got to a simple recipe:</p>

<p>Add the NuGet package <strong>Microsoft.AspNet.Web.Optimization</strong> (<a href="http://nuget.org/packages/Microsoft.AspNet.Web.Optimization/1.0.0">http://nuget.org/packages/Microsoft.AspNet.Web.Optimization/1.0.0</a>)</p>

<p>On your Global.asax.cs file, add the following call on <strong>Application_Start</strong>:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">BundleConfig</span><span class="p">.</span><span class="nf">RegisterBundles</span><span class="p">(</span><span class="n">BundleTable</span><span class="p">.</span><span class="n">Bundles</span><span class="p">);</span>
</code></pre></div></div>

<p>Create a class called <strong>BundleConfig</strong> in your <strong>App_Start</strong> folder, with a method named <strong>RegisterBundles</strong>:</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">BundleConfig</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">RegisterBundles</span><span class="p">(</span><span class="n">BundleCollection</span> <span class="n">bundles</span><span class="p">)</span>
  <span class="p">{</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>If you want to use optimizations on your debug environment, add the following line on top of the <strong>RegisterBundles</strong> method:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">BundleTable</span><span class="p">.</span><span class="n">EnableOptimizations</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span> <span class="c1">// force to show on debug mode</span>
</code></pre></div></div>

<p>Add your bundles to the <strong>RegisterBundles</strong> method, such as:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">bundles</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">StyleBundle</span><span class="p">(</span><span class="s">"~/css/global"</span><span class="p">).</span><span class="nf">Include</span><span class="p">(</span><span class="s">"~/Content/site.css"</span><span class="p">));</span>
</code></pre></div></div>

<p>If you are like me and you use virtual paths for css bundles that don’t match the real location of the files, you will have problems using the StyleBundle with relative image URIs. To solve this without changing your original css files, you can create a custom IBundleTransform that resolves the image path. My solution is largely based on this stackoverflow answer: <a href="http://stackoverflow.com/a/13019337/732733">http://stackoverflow.com/a/13019337/732733</a></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">RelativePathResolverTransform</span> <span class="p">:</span> <span class="n">IBundleTransform</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">void</span> <span class="nf">Process</span><span class="p">(</span><span class="n">BundleContext</span> <span class="n">context</span><span class="p">,</span> <span class="n">BundleResponse</span> <span class="n">response</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">response</span><span class="p">.</span><span class="n">Content</span> <span class="p">=</span> <span class="n">String</span><span class="p">.</span><span class="n">Empty</span><span class="p">;</span>

    <span class="n">Regex</span> <span class="n">pattern</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Regex</span><span class="p">(</span><span class="s">@"url\s*\(\s*([""']?)([^:)]+)\1\s*\)"</span><span class="p">,</span> <span class="n">RegexOptions</span><span class="p">.</span><span class="n">IgnoreCase</span><span class="p">);</span>
    <span class="c1">// open each of the files</span>
    <span class="k">foreach</span> <span class="p">(</span><span class="n">FileInfo</span> <span class="n">cssFileInfo</span> <span class="k">in</span> <span class="n">response</span><span class="p">.</span><span class="n">Files</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">cssFileInfo</span><span class="p">.</span><span class="n">Exists</span><span class="p">)</span>
      <span class="p">{</span>
        <span class="c1">// apply the RegEx to the file (to change relative paths)</span>
        <span class="kt">string</span> <span class="n">contents</span> <span class="p">=</span> <span class="n">File</span><span class="p">.</span><span class="nf">ReadAllText</span><span class="p">(</span><span class="n">cssFileInfo</span><span class="p">.</span><span class="n">FullName</span><span class="p">);</span>
        <span class="n">MatchCollection</span> <span class="n">matches</span> <span class="p">=</span> <span class="n">pattern</span><span class="p">.</span><span class="nf">Matches</span><span class="p">(</span><span class="n">contents</span><span class="p">);</span>
        <span class="c1">// Ignore the file if no match </span>
        <span class="k">if</span> <span class="p">(</span><span class="n">matches</span><span class="p">.</span><span class="n">Count</span> <span class="p">&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="m">0</span><span class="p">)</span>
        <span class="p">{</span>
          <span class="kt">string</span> <span class="n">cssFilePath</span> <span class="p">=</span> <span class="n">cssFileInfo</span><span class="p">.</span><span class="n">DirectoryName</span><span class="p">;</span>
          <span class="kt">string</span> <span class="n">cssVirtualPath</span> <span class="p">=</span> <span class="nf">RelativeFromAbsolutePath</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">HttpContext</span><span class="p">,</span> <span class="n">cssFilePath</span><span class="p">);</span>

          <span class="k">foreach</span> <span class="p">(</span><span class="n">Match</span> <span class="n">match</span> <span class="k">in</span> <span class="n">matches</span><span class="p">)</span>
          <span class="p">{</span>
            <span class="c1">// this is a path that is relative to the CSS file</span>
            <span class="kt">string</span> <span class="n">relativeToCSS</span> <span class="p">=</span> <span class="n">match</span><span class="p">.</span><span class="n">Groups</span><span class="p">[</span><span class="m">2</span><span class="p">].</span><span class="n">Value</span><span class="p">;</span>
            <span class="c1">// combine the relative path to the cssAbsolute</span>
            <span class="kt">string</span> <span class="n">absoluteToUrl</span> <span class="p">=</span> <span class="n">Path</span><span class="p">.</span><span class="nf">GetFullPath</span><span class="p">(</span><span class="n">Path</span><span class="p">.</span><span class="nf">Combine</span><span class="p">(</span><span class="n">cssFilePath</span><span class="p">,</span> <span class="n">relativeToCSS</span><span class="p">));</span>

            <span class="c1">// make this server relative</span>
            <span class="kt">string</span> <span class="n">serverRelativeUrl</span> <span class="p">=</span> <span class="nf">RelativeFromAbsolutePath</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">HttpContext</span><span class="p">,</span> <span class="n">absoluteToUrl</span><span class="p">);</span>

            <span class="kt">string</span> <span class="n">quote</span> <span class="p">=</span> <span class="n">match</span><span class="p">.</span><span class="n">Groups</span><span class="p">[</span><span class="m">1</span><span class="p">].</span><span class="n">Value</span><span class="p">;</span>
            <span class="kt">string</span> <span class="n">replace</span> <span class="p">=</span> <span class="n">String</span><span class="p">.</span><span class="nf">Format</span><span class="p">(</span><span class="s">"url({0}{1}{0})"</span><span class="p">,</span> <span class="n">quote</span><span class="p">,</span> <span class="n">serverRelativeUrl</span><span class="p">);</span>
            <span class="n">contents</span> <span class="p">=</span> <span class="n">contents</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">match</span><span class="p">.</span><span class="n">Groups</span><span class="p">[</span><span class="m">0</span><span class="p">].</span><span class="n">Value</span><span class="p">,</span> <span class="n">replace</span><span class="p">);</span>
          <span class="p">}</span>
        <span class="p">}</span>
        <span class="c1">// copy the result into the response.</span>
        <span class="n">response</span><span class="p">.</span><span class="n">Content</span> <span class="p">=</span> <span class="n">String</span><span class="p">.</span><span class="nf">Format</span><span class="p">(</span><span class="s">"{0}\r\n{1}"</span><span class="p">,</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">,</span> <span class="n">contents</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="k">private</span> <span class="k">static</span> <span class="kt">string</span> <span class="nf">RelativeFromAbsolutePath</span><span class="p">(</span><span class="n">HttpContextBase</span> <span class="n">context</span><span class="p">,</span> <span class="kt">string</span> <span class="n">path</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">Request</span><span class="p">;</span>
    <span class="kt">var</span> <span class="n">applicationPath</span> <span class="p">=</span> <span class="n">request</span><span class="p">.</span><span class="n">PhysicalApplicationPath</span><span class="p">;</span>
    <span class="kt">var</span> <span class="n">virtualDir</span> <span class="p">=</span> <span class="n">request</span><span class="p">.</span><span class="n">ApplicationPath</span><span class="p">;</span>
    <span class="n">virtualDir</span> <span class="p">=</span> <span class="n">virtualDir</span> <span class="p">==</span> <span class="s">"/"</span> <span class="p">?</span> <span class="n">virtualDir</span> <span class="p">:</span> <span class="p">(</span><span class="n">virtualDir</span> <span class="p">+</span> <span class="s">"/"</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">path</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="n">applicationPath</span><span class="p">,</span> <span class="n">virtualDir</span><span class="p">).</span><span class="nf">Replace</span><span class="p">(</span><span class="s">@"\"</span><span class="p">,</span> <span class="s">"/"</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>To make it easier to use, I also added a custom Bundle:</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">ImageRelativeStyleBundle</span> <span class="p">:</span> <span class="n">StyleBundle</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="nf">ImageRelativeStyleBundle</span><span class="p">(</span><span class="kt">string</span> <span class="n">virtualPath</span><span class="p">)</span>
        <span class="p">:</span> <span class="k">base</span><span class="p">(</span><span class="n">virtualPath</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">Transforms</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">RelativePathResolverTransform</span><span class="p">());</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="nf">ImageRelativeStyleBundle</span><span class="p">(</span><span class="kt">string</span> <span class="n">virtualPath</span><span class="p">,</span> <span class="kt">string</span> <span class="n">cdnPath</span><span class="p">)</span>
        <span class="p">:</span> <span class="k">base</span><span class="p">(</span><span class="n">virtualPath</span><span class="p">,</span> <span class="n">cdnPath</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">Transforms</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">RelativePathResolverTransform</span><span class="p">());</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>You can use it like this:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">bundles</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">ImageRelativeStyleBundle</span><span class="p">(</span><span class="s">"~/css/jqueryui"</span><span class="p">).</span><span class="nf">Include</span>
<span class="p">(</span>
  <span class="s">"~/Content/themes/base/jquery.ui.core.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.resizable.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.selectable.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.accordion.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.autocomplete.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.button.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.dialog.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.slider.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.tabs.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.datepicker.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.progressbar.css"</span><span class="p">,</span>
  <span class="s">"~/Content/themes/base/jquery.ui.theme.css"</span>
<span class="p">));</span>
</code></pre></div></div>

<p>To use bundles in your views, I recommend adding the System.Web.Optimization namespace to /Views/Web.config, on the namespaces section:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;namespaces&gt;</span>
  ...
  <span class="nt">&lt;add</span> <span class="na">namespace=</span><span class="s">"System.Web.Optimization"</span><span class="nt">&gt;&lt;/add&gt;</span>
<span class="nt">&lt;/namespaces&gt;</span>
</code></pre></div></div>

<p>Now you just need to call Styles.Render(“~/css/jqueryui”) for the example above to work. For javascript you can use the Scripts.Render(“virtualpath”) call. If you need to specify custom attributes to your element, such as the media attribute for print css versions, you can build the element yourself and use the Styles.Url method, like so:</p>

<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">&lt;</span><span class="n">link</span> <span class="n">href</span><span class="p">=</span><span class="s">"@Styles.Url("</span> <span class="p">~=</span><span class="s">""</span> <span class="n">css</span><span class="p">=</span><span class="s">""</span> <span class="n">print</span><span class="s">")"</span><span class="p">=</span><span class="s">""</span> <span class="n">rel</span><span class="p">=</span><span class="s">"stylesheet"</span> <span class="n">type</span><span class="p">=</span><span class="s">"text/css"</span> <span class="n">media</span><span class="p">=</span><span class="s">"print"</span><span class="p">&gt;</span>
</code></pre></div></div>

<p>I’ve successfully (but also painfully) integrated MVC4’s bundling and minification with dotless, for LESS CSS support. I’ll explain the necessary steps on the next blog post.</p>

<hr />

<p><strong>Update</strong></p>

<p>In this post’s comments, Kenneth commented on the lack of support for debug mode when using Styles.Url in a link tag. To solve this issue, I’ve created some methods that add this functionality.</p>

<p>Notes: Because the Style class and its methods are static I can’t just overload their behavior nor add another extension method, so instead I added a separate class that you could use instead of Style. I took advantage of the DEBUG compilation constant to avoid some string manipulation on a production/release environment.</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">Bundles</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">static</span> <span class="n">IHtmlString</span> <span class="nf">Render</span><span class="p">(</span><span class="kt">string</span> <span class="n">path</span><span class="p">,</span> <span class="kt">object</span> <span class="n">htmlAttributes</span><span class="p">)</span>
  <span class="p">{</span>
      <span class="k">return</span> <span class="nf">Render</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="k">new</span> <span class="nf">RouteValueDictionary</span><span class="p">(</span><span class="n">htmlAttributes</span><span class="p">));</span>
  <span class="p">}</span>

  <span class="k">public</span> <span class="k">static</span> <span class="n">IHtmlString</span> <span class="nf">Render</span><span class="p">(</span><span class="kt">string</span> <span class="n">path</span><span class="p">,</span> <span class="n">IDictionary</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">,</span> <span class="kt">object</span><span class="p">=</span><span class="s">""</span><span class="p">&gt;</span> <span class="n">htmlAttributes</span><span class="p">)</span>
  <span class="p">{</span>
      <span class="kt">var</span> <span class="n">attributes</span> <span class="p">=</span> <span class="nf">BuildHtmlStringFrom</span><span class="p">(</span><span class="n">htmlAttributes</span><span class="p">);</span>

<span class="cp">#if DEBUG
</span>      <span class="kt">var</span> <span class="n">originalHtml</span> <span class="p">=</span> <span class="n">Styles</span><span class="p">.</span><span class="nf">Render</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="nf">ToHtmlString</span><span class="p">();</span>
      <span class="kt">string</span> <span class="n">tagsWithAttributes</span> <span class="p">=</span> <span class="n">originalHtml</span><span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="s">"/&gt;"</span><span class="p">,</span> <span class="n">attributes</span> <span class="p">+</span> <span class="s">"/&gt;"</span><span class="p">);</span>
      <span class="k">return</span> <span class="n">MvcHtmlString</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="n">tagsWithAttributes</span><span class="p">);</span>
<span class="cp">#endif
</span>
      <span class="kt">string</span> <span class="n">tagWithAttribute</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="nf">Format</span><span class="p">(</span>
        <span class="s">"&lt;link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\"{1}&gt;"</span><span class="p">,</span> 
        <span class="n">Styles</span><span class="p">.</span><span class="nf">Url</span><span class="p">(</span><span class="n">path</span><span class="p">),</span> <span class="n">attributes</span><span class="p">);</span>

      <span class="k">return</span> <span class="n">MvcHtmlString</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="n">tagWithAttribute</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="k">private</span> <span class="k">static</span> <span class="kt">string</span> <span class="nf">BuildHtmlStringFrom</span><span class="p">(</span><span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">KeyValuePair</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">,</span> <span class="kt">object</span><span class="p">=</span><span class="s">""</span><span class="p">&gt;&gt;</span> <span class="n">htmlAttributes</span><span class="p">)</span>
  <span class="p">{</span>
      <span class="kt">var</span> <span class="n">builder</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">StringBuilder</span><span class="p">();</span>

      <span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">attribute</span> <span class="k">in</span> <span class="n">htmlAttributes</span><span class="p">)</span>
      <span class="p">{</span>
        <span class="n">builder</span><span class="p">.</span><span class="nf">AppendFormat</span><span class="p">(</span><span class="s">" {0}=\"{1}\""</span><span class="p">,</span> <span class="n">attribute</span><span class="p">.</span><span class="n">Key</span><span class="p">,</span> <span class="n">attribute</span><span class="p">.</span><span class="n">Value</span><span class="p">);</span>
      <span class="p">}</span>

      <span class="k">return</span> <span class="n">builder</span><span class="p">.</span><span class="nf">ToString</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Usage:</strong></p>
<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">@Bundles</span><span class="p">.</span><span class="nf">Render</span><span class="p">(</span><span class="s">"~/css/print"</span><span class="p">,</span> <span class="k">new</span> <span class="p">{</span> <span class="n">media</span> <span class="p">=</span> <span class="s">"print"</span> <span class="p">})</span>
</code></pre></div></div>]]></content><author><name>Daniel Correia</name><email>danielbcorreia@gmail.com</email></author><category term="asp.net" /><category term="bundling" /><category term="css" /><category term="mvc" /><category term="mvc4" /><category term="optimization" /><category term="performance" /><category term="web" /><category term="dotnet" /><summary type="html"><![CDATA[After using MVC4’s bundling in a couple of web apps I got to a simple recipe:]]></summary></entry></feed>