{"id":32386,"date":"2021-03-18T14:32:09","date_gmt":"2021-03-18T21:32:09","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=32386"},"modified":"2021-03-18T17:19:10","modified_gmt":"2021-03-19T00:19:10","slug":"opentelemetry-net-reaches-v1-0","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/opentelemetry-net-reaches-v1-0\/","title":{"rendered":"OpenTelemetry .NET reaches v1.0"},"content":{"rendered":"<p>As modern application environments are polyglot, distributed, and increasingly complex, observing your application to identify and react to failures has become challenging. In early 2019, two popular instrumentation projects, OpenTracing and OpenCensus, merged to create <a href=\"https:\/\/opentelemetry.io\">OpenTelemetry<\/a>, a new standard for observability telemetry.<\/p>\n<h2>What is OpenTelemetry?<\/h2>\n<p>By standardizing how different applications and frameworks collect and emit observability telemetry, OpenTelemetry aims to solve some of the challenges posed by these environments.\nThe OpenTelemetry project is comprised of:<\/p>\n<ul>\n<li>A vendor-neutral specification for observability telemetry (distributed tracing, metrics, etc.)<\/li>\n<li>API packages that implement the public interfaces used for instrumentation<\/li>\n<li>SDKs used by applications to configure instrumentation and interfaces for plugin authors to write exporters<\/li>\n<li>Exporters that enable you to send your data to the telemetry backend of your choice<\/li>\n<\/ul>\n<p>This rich ecosystem of components has led to OpenTelemetry becoming ubiquitous in the observability telemetry space. Under the stewardship of the <a href=\"https:\/\/www.cncf.io\/\">Cloud Native Computing Foundation<\/a>, it already has a vibrant ecosystem of contributors and maintainers and is contributed to and used by many large companies. If you aren&#8217;t interested in OpenTelemetry yet, you soon will be because of the following benefits that it provides:<\/p>\n<h3>Interoperable<\/h3>\n<p>Since different languages implement the same shared specification including the wire protocol for propagating observability telemetry, you can monitor your distributed application with complete interoperability. For example, you can have a frontend service in .NET call into a backend service in Node.js, and track your distributed operation across both these services.<\/p>\n<h3>Vendor neutral<\/h3>\n<p>As the collection of observability telemetry becomes standardized by OpenTelemetry, you can choose your telemetry backend without having to change your instrumentation code. You&#8217;re free to pick the platform that offers you the most effective analysis of your data.<\/p>\n<p>Multiple major instrumentation and Application Performance Monitoring (APM) vendors have publicly expressed that OpenTelemetry is a key part of their monitoring solution. It is exciting to have multiple vendors implementations already available that are based on OpenTelemetry.<\/p>\n<ul>\n<li><a href=\"https:\/\/blog.newrelic.com\/product-news\/new-relic-opentelemetry-net\/\">New Relic\u2019s OpenTelemetry .NET Offering Reaches V1.0<\/a><\/li>\n<li><a href=\"https:\/\/www.nuget.org\/packages\/Azure.Monitor.OpenTelemetry.Exporter\/1.0.0-beta.2\">Pre-release Azure Monitor OpenTelemetry Exporter<\/a><\/li>\n<li><a href=\"https:\/\/aws.amazon.com\/blogs\/opensource\/aws-distro-for-opentelemetry-adds-net-tracing-support\/\">AWS Distro for OpenTelemetry adds .NET tracing support<\/a><\/li>\n<\/ul>\n<p>In addition to the SaaS offerings for observability telemetry, OpenTelemetry also works well with existing open source distributed tracing tools such as <a href=\"https:\/\/www.jaegertracing.io\/\">Jaeger<\/a> and <a href=\"https:\/\/zipkin.io\/\">Zipkin<\/a>.<\/p>\n<h3>Future proof<\/h3>\n<p>OpenTelemetry aims to build instrumentation into libraries and frameworks moving forward. When newer libraries and frameworks emerge, you can easily monitor them using shared instrumentation libraries.<\/p>\n<h2>What\u2019s new in OpenTelemetry?<\/h2>\n<p>In February 2021, the <a href=\"https:\/\/medium.com\/opentelemetry\/opentelemetry-specification-v1-0-0-tracing-edition-72dd08936978\">OpenTelemetry specification reached v1.0<\/a>. With the v1.0 specification, OpenTelemetry implementations are now offering stability guarantees for distributed tracing. Shortly after the stabilization of the specification, OpenTelemetry .NET, the canonical distribution of the OpenTelemetry SDK implementation in .NET, also <a href=\"https:\/\/medium.com\/opentelemetry\/opentelemetry-net-reaches-v1-0-e7c5e975fd44\">announced their v1.0<\/a> release which includes the following:<\/p>\n<ul>\n<li>The v1.0 release of <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry.Api\/\">OpenTelemetry .NET APIs<\/a>: Tracing API, Baggage API, Context API and Propagators API.<\/li>\n<li><a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry\/\">An SDK<\/a> providing controls for sampling, processing, and export.<\/li>\n<li>Exporters to <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry.Exporter.Jaeger\/\">Jaeger<\/a>, <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry.Exporter.Zipkin\/\">Zipkin<\/a> and the <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry.Exporter.OpenTelemetryProtocol\/\">OpenTelemetry Protocol (OTLP)<\/a><\/li>\n<li>Documentation, which includes <a href=\"https:\/\/github.com\/open-telemetry\/opentelemetry-dotnet\/tree\/main\/examples\">samples<\/a>, <a href=\"https:\/\/github.com\/open-telemetry\/opentelemetry-dotnet\/tree\/main\/docs\/trace\/getting-started\">getting started guides<\/a> and guides for <a href=\"https:\/\/github.com\/open-telemetry\/opentelemetry-specification\/blob\/main\/specification\/glossary.md#plugin-author\"> plugin authors<\/a> to <a href=\"https:\/\/github.com\/open-telemetry\/opentelemetry-dotnet\/tree\/main\/docs\/trace\/extending-the-sdk\"> extend the SDK<\/a><\/li>\n<\/ul>\n<h2>Getting started with OpenTelemetry<\/h2>\n<p>OpenTelemetry helps solving concerns ranging from emitting observability data, processing of the data, and controlling how the data is exported. Despite the cross-cutting nature of these concerns, care has been taken to separate them.<\/p>\n<h3>Application Developers<\/h3>\n<p>If you are an application developer, you can configure your application to use the OpenTelemetry .NET SDK and its instrumentation packages to collect distributed tracing.<\/p>\n<p>Here&#8217;s an example that shows you how to add instrumentation to a console application using the <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry\/\">OpenTelemetry<\/a> and <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry.Exporter.Console\/\">OpenTelemetry.Exporter.Console<\/a> packages.<\/p>\n<pre class=\"prettyprint\">public class Program\r\n{\r\n    public static void Main()\r\n    {\r\n        using var tracerProvider = Sdk.CreateTracerProviderBuilder()\r\n            .SetSampler(new AlwaysOnSampler())\r\n            \/\/ Add more libraries\r\n            .AddSource(\"Sample\")\r\n            \/\/ Add more exporters\r\n            .AddConsoleExporter()\r\n            .Build();\r\n\r\n        \/\/ ...\r\n        \/\/ Rest of application\r\n        \/\/ ...\r\n\r\n    }\r\n}<\/pre>\n<p>The OpenTelemetry SDK also integrates with the hosted application model used by ASP.NET Core (and the worker service). Here&#8217;s an example that shows you how to instrument an ASP.NET Core application using the <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry\/\">OpenTelemetry<\/a>, <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry.Extensions.Hosting\/1.0.0-rc2\">OpenTelemetry.Extensions.Hosting<\/a> and <a href=\"https:\/\/www.nuget.org\/packages\/OpenTelemetry.Exporter.Zipkin\/\">OpenTelemetry.Exporter.Zipkin<\/a> packages.<\/p>\n<pre class=\"prettyprint\">public class Startup\r\n{\r\n    public Startup(IConfiguration configuration) =&gt; Configuration = configuration;\r\n\r\n    public IConfiguration Configuration { get; }\r\n\r\n    public void ConfigureServices(IServiceCollection services)\r\n    {\r\n        services.AddOpenTelemetryTracing((builder) =&gt; builder\r\n            .AddAspNetCoreInstrumentation()\r\n            .AddHttpClientInstrumentation()\r\n            .AddZipkinExporter(zipkinOptions =&gt;\r\n            {\r\n                zipkinOptions.Endpoint = new Uri(Configuration.GetConnectionString(\"zipkin\"));\r\n            }));\r\n    }\r\n}<code class=\"csharp\">\r\n<\/code><\/pre>\n<h3>Library Authors<\/h3>\n<p>If you are not a library author, you can skip this section. Popular libraries in the .NET ecosystem (ASP.NET Core, grpc-dotnet, SQLClient) are already instrumented and ready for to you consume observability telemetry.<\/p>\n<p>The <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.diagnostics\">System.Diagnostics APIs<\/a> in .NET contain an implementation of the OpenTelemetry API specification. In addition to these APIs shipping as part of .NET 5, they are also available on NuGet as part of the <a href=\"https:\/\/www.nuget.org\/packages\/System.Diagnostics.DiagnosticSource\/5.0.1\">System.Diagnostics.DiagnosticsSource<\/a> package and supported on all supported version of .NET including .NET Framework 4.5+ and .NET Core 2.1+. This is the only package reference you require to add distributed tracing support to your library.<\/p>\n<p>Here&#8217;s an example that shows how you might instrument your library:<\/p>\n<pre><code class=\"csharp\">class Program\r\n{\r\n    static ActivitySource s_source = new ActivitySource(\"Sample\");\r\n\r\n    static async Task Main(string[] args)\r\n    {\r\n        await DoSomeWork();\r\n        Console.WriteLine(\"Example work done\");\r\n    }\r\n\r\n    static async Task DoSomeWork()\r\n    {\r\n        using (Activity? activity = s_source.StartActivity(\"SomeWork\"))\r\n        {\r\n            await StepOne();\r\n            await StepTwo();\r\n        }\r\n    }\r\n\r\n    static async Task StepOne()\r\n    {\r\n        using (Activity? activity = s_source.StartActivity(\"StepOne\"))\r\n        {\r\n            await Task.Delay(500);\r\n        }\r\n    }\r\n\r\n    static async Task StepTwo()\r\n    {\r\n        using (Activity? activity = s_source.StartActivity(\"StepTwo\"))\r\n        {\r\n            await Task.Delay(1000);\r\n        }\r\n    }\r\n}\r\n<\/code><\/pre>\n<h3>Analyzing tracing data<\/h3>\n<p>Once you&#8217;ve exported your distributed tracing data, you can analyze it to view your recorded traces and the causal links between all the spans that comprise these traces. I&#8217;ve included a screenshot below of the simple application we just saw in the Zipkin UI where we can see the spans <strong><em>stepone<\/em><\/strong> and <strong><em>steptwo<\/em><\/strong> parented under the <strong><em>somework<\/em><\/strong> span.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/zipkin.png\"><img decoding=\"async\" class=\"alignnone wp-image-32390 size-full\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/zipkin.png\" alt=\"OpenTelemetry .NET reaches v1.0\" width=\"1811\" height=\"1087\" srcset=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/zipkin.png 1811w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/zipkin-300x180.png 300w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/zipkin-1024x615.png 1024w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/zipkin-768x461.png 768w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/zipkin-1536x922.png 1536w\" sizes=\"(max-width: 1811px) 100vw, 1811px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>Feedback<\/h2>\n<p>We&#8217;re super excited to continue to improving the observability of all applications built on .NET and OpenTelemetry is a giant stride for us in that direction. We would love to hear your feedback! Let us know in comments below or join the rapidly growing OpenTelemetry .NET community.<\/p>\n<p>You can join the contributors on the <a href=\"https:\/\/github.com\/open-telemetry\/opentelemetry-dotnet\">opentelemetry-dotnet<\/a> repo, join the <a href=\"https:\/\/app.slack.com\/client\/T08PSQ7BQ\/C01N3BC2W7Q\">OpenTelemetry .NET channel on the CNCF Slack instance<\/a> (create a CNCF Slack account <a href=\"http:\/\/slack.cncf.io\/\">here<\/a>), or participate in the <a href=\"https:\/\/github.com\/open-telemetry\/opentelemetry-dotnet#contributing\">weekly community meetings<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to get started with OpenTelemetry .NET<\/p>\n","protected":false},"author":1233,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[],"class_list":["post-32386","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet"],"acf":[],"blog_post_summary":"<p>Learn how to get started with OpenTelemetry .NET<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/32386","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/1233"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=32386"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/32386\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=32386"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=32386"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=32386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}