Skip to content

Commit

Permalink
Add docs and rename examples
Browse files Browse the repository at this point in the history
  • Loading branch information
stevejgordon committed Mar 22, 2024
1 parent d2c3b9f commit 8861f27
Show file tree
Hide file tree
Showing 94 changed files with 204 additions and 48 deletions.
42 changes: 20 additions & 22 deletions Elastic.OpenTelemetry.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ VisualStudioVersion = 17.9.34321.82
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.OpenTelemetry", "src\Elastic.OpenTelemetry\Elastic.OpenTelemetry.csproj", "{79C08F0E-7220-486C-AC0C-E3B287EB0B18}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.Elastic.OpenTelemetry", "examples\Example.Elastic.OpenTelemetry\Example.Elastic.OpenTelemetry.csproj", "{32DF4F56-1773-49E9-A8AE-0573F0AA57DE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E622CFF2-C6C4-40FB-BE42-7C4F2B38B75A}"
ProjectSection(SolutionItems) = preProject
src\Directory.Build.props = src\Directory.Build.props
Expand All @@ -29,15 +27,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.OpenTelemetry.Tests
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = ".github", ".github\.github.csproj", "{B701E33D-D777-4BD4-A4EC-1F63FE69AF7A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.Elastic.OpenTelemetry.AspNetCore", "examples\Example.Elastic.OpenTelemetry.AspNetCore\Example.Elastic.OpenTelemetry.AspNetCore.csproj", "{EC81FA30-C765-4F04-8679-86F16DA3CC65}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.OpenTelemetry.EndToEndTests", "tests\Elastic.OpenTelemetry.EndToEndTests\Elastic.OpenTelemetry.EndToEndTests.csproj", "{B970DBE1-6A04-4014-A285-6A9F36421025}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.Elastic.OpenTelemetry.Worker", "examples\Example.Elastic.OpenTelemetry.Worker\Example.Elastic.OpenTelemetry.Worker.csproj", "{4377A059-16E0-4D5D-AC03-44C09BCE5BC4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.MinimalApi", "examples\Example.MinimalApi\Example.MinimalApi.csproj", "{397D7E8D-39C2-41D6-9D4D-F1D35666926A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.OpenTelemetry.EndToEndTests", "tests\Elastic.OpenTelemetry.EndToEndTests\Elastic.OpenTelemetry.EndToEndTests.csproj", "{B970DBE1-6A04-4014-A285-6A9F36421025}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.AspNetCore.Mvc", "examples\Example.AspNetCore.Mvc\Example.AspNetCore.Mvc.csproj", "{6D7D5234-BE86-46E0-A871-153FE96CD644}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.OpenTelemetry.AspNetCore", "src\Elastic.OpenTelemetry.AspNetCore\Elastic.OpenTelemetry.AspNetCore.csproj", "{2139F902-B10D-475D-8A38-F78962CEBFD3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.Console", "examples\Example.Console\Example.Console.csproj", "{849FAC2E-8303-4154-8560-31B22194800E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.MinimalApi", "examples\Example.MinimalApi\Example.MinimalApi.csproj", "{397D7E8D-39C2-41D6-9D4D-F1D35666926A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.WorkerService", "examples\Example.WorkerService\Example.WorkerService.csproj", "{863CAB86-5EB0-4E9F-B01D-F51687EC6597}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -49,10 +47,6 @@ Global
{79C08F0E-7220-486C-AC0C-E3B287EB0B18}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79C08F0E-7220-486C-AC0C-E3B287EB0B18}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79C08F0E-7220-486C-AC0C-E3B287EB0B18}.Release|Any CPU.Build.0 = Release|Any CPU
{32DF4F56-1773-49E9-A8AE-0573F0AA57DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32DF4F56-1773-49E9-A8AE-0573F0AA57DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32DF4F56-1773-49E9-A8AE-0573F0AA57DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32DF4F56-1773-49E9-A8AE-0573F0AA57DE}.Release|Any CPU.Build.0 = Release|Any CPU
{872D0721-A4F2-405C-B0AB-036B340F1907}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{872D0721-A4F2-405C-B0AB-036B340F1907}.Debug|Any CPU.Build.0 = Debug|Any CPU
{872D0721-A4F2-405C-B0AB-036B340F1907}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -69,14 +63,6 @@ Global
{B701E33D-D777-4BD4-A4EC-1F63FE69AF7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B701E33D-D777-4BD4-A4EC-1F63FE69AF7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B701E33D-D777-4BD4-A4EC-1F63FE69AF7A}.Release|Any CPU.Build.0 = Release|Any CPU
{EC81FA30-C765-4F04-8679-86F16DA3CC65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EC81FA30-C765-4F04-8679-86F16DA3CC65}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC81FA30-C765-4F04-8679-86F16DA3CC65}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC81FA30-C765-4F04-8679-86F16DA3CC65}.Release|Any CPU.Build.0 = Release|Any CPU
{4377A059-16E0-4D5D-AC03-44C09BCE5BC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4377A059-16E0-4D5D-AC03-44C09BCE5BC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4377A059-16E0-4D5D-AC03-44C09BCE5BC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4377A059-16E0-4D5D-AC03-44C09BCE5BC4}.Release|Any CPU.Build.0 = Release|Any CPU
{B970DBE1-6A04-4014-A285-6A9F36421025}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B970DBE1-6A04-4014-A285-6A9F36421025}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B970DBE1-6A04-4014-A285-6A9F36421025}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -85,18 +71,30 @@ Global
{397D7E8D-39C2-41D6-9D4D-F1D35666926A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{397D7E8D-39C2-41D6-9D4D-F1D35666926A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{397D7E8D-39C2-41D6-9D4D-F1D35666926A}.Release|Any CPU.Build.0 = Release|Any CPU
{6D7D5234-BE86-46E0-A871-153FE96CD644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D7D5234-BE86-46E0-A871-153FE96CD644}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D7D5234-BE86-46E0-A871-153FE96CD644}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D7D5234-BE86-46E0-A871-153FE96CD644}.Release|Any CPU.Build.0 = Release|Any CPU
{849FAC2E-8303-4154-8560-31B22194800E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{849FAC2E-8303-4154-8560-31B22194800E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{849FAC2E-8303-4154-8560-31B22194800E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{849FAC2E-8303-4154-8560-31B22194800E}.Release|Any CPU.Build.0 = Release|Any CPU
{863CAB86-5EB0-4E9F-B01D-F51687EC6597}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{863CAB86-5EB0-4E9F-B01D-F51687EC6597}.Debug|Any CPU.Build.0 = Debug|Any CPU
{863CAB86-5EB0-4E9F-B01D-F51687EC6597}.Release|Any CPU.ActiveCfg = Release|Any CPU
{863CAB86-5EB0-4E9F-B01D-F51687EC6597}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{79C08F0E-7220-486C-AC0C-E3B287EB0B18} = {E622CFF2-C6C4-40FB-BE42-7C4F2B38B75A}
{32DF4F56-1773-49E9-A8AE-0573F0AA57DE} = {4E95C87B-655B-4BC3-8F2A-DF06B7AAB7E9}
{22BF9223-3A6D-4197-8527-3E4E43A98A81} = {AAD39891-0B70-47FA-A212-43E1AAE5DF56}
{EC81FA30-C765-4F04-8679-86F16DA3CC65} = {4E95C87B-655B-4BC3-8F2A-DF06B7AAB7E9}
{4377A059-16E0-4D5D-AC03-44C09BCE5BC4} = {4E95C87B-655B-4BC3-8F2A-DF06B7AAB7E9}
{B970DBE1-6A04-4014-A285-6A9F36421025} = {AAD39891-0B70-47FA-A212-43E1AAE5DF56}
{397D7E8D-39C2-41D6-9D4D-F1D35666926A} = {4E95C87B-655B-4BC3-8F2A-DF06B7AAB7E9}
{6D7D5234-BE86-46E0-A871-153FE96CD644} = {4E95C87B-655B-4BC3-8F2A-DF06B7AAB7E9}
{849FAC2E-8303-4154-8560-31B22194800E} = {4E95C87B-655B-4BC3-8F2A-DF06B7AAB7E9}
{863CAB86-5EB0-4E9F-B01D-F51687EC6597} = {4E95C87B-655B-4BC3-8F2A-DF06B7AAB7E9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {573B2B5F-8CBB-4D52-A55A-4E65E282AAFB}
Expand Down
161 changes: 158 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,163 @@

# Elastic OpenTelemetry Distribution

This is Elastic's distribution of OpenTelemetry for .NET.
The `Elastic.OpenTelemetry` package contains an Elastic distribution of the
[OpenTelemetry SDK for .NET](https://opentelemetry.io/docs/languages/net). A distribution
is a wrapper around an upstream OpenTelemetry repository with some customizations. For
more details about distributions in general, visit the
[OpenTelemetry documentation](https://opentelemetry.io/docs/concepts/distributions).

## Getting Started
The Elastic distribution includes some Elastic-specific processors to ensure the best
compatibility when exporting OpenTelemetry signal data to an Elastic backend such
as Elastic APM server. The distribution also preconfigures the collection of tracing
and metrics signals, applying some opinionated defaults, such as which sources are
collected by default. The distribution also ensures that the OTLP exporter is enabled
by default.

TODO
The distribution includes extension methods to fully control the creation of the
underlying tracer and metric providers, providing a helpful set of defaults
to get developers up and running quickly with collecting and exporting OpenTelemetry
signals.

## Getting started

This guide will show you how to get started with Elastic OpenTelemetry distribution for .NET.

As the distribution is a lightweight wrapper around the OpenTelemetry SDK, you should be broadly
familiar with the OpenTelemetry SDK concepts and instrumenting applications using the Microsoft
diagnostic APIs. If you are not, we recommend you read the
[OpenTelemetry SDK documentation](https://opentelemetry.io/docs/languages/net) first.

> **_IMPORTANT:_** The Elastic distribution is currently in early alpha release status. It is not yet feature
complete and may contain bugs. We are actively working on improving the distribution and
adding new features.
>
> If you would like to experience the alpha and help us improve the distribution by providing
early feedback, you can follow the steps below to get started.

### Prerequisites

The current documentation and examples are written with .NET 6 and newer applications in mind.
Before continuing, ensure that you have a supported
[.NET SDK version](https://dotnet.microsoft.com/en-us/download/dotnet) installed locally.

### Installation

To get started with the Elastic OpenTelemetry distribution, you must add the Elastic OpenTelemetry
NuGet package to your project. This can be achieved by adding the package reference to your project file.

```
<PackageReference Include="Elastic.OpenTelemetry" Version="0.1.0-alpha.1" />
```

After adding the package reference, you can start using the Elastic OpenTelemetry distribution
in your application. The distribution includes a transitive dependency on the OpenTelemetry SDK,
so you do not need to add the OpenTelemetry SDK package to your project, although doing so will
cause no harm and may be used to opt into newer SDK versions before the Elastic distribution
references them.

The Elastic OpenTelemetry distribution is designed to be easy to use and integrate into your
applications. This includes applications which have previously used the OpenTelemetry SDK directly.
In situations where the OpenTelemetry SDK is already used, the only required change is
to add the `Elastic.OpenTelemetry` NuGet package to the project. Doing so will automatically
switch to the opinionated configuration provided by the Elastic distribution.

### ASP.NET Core usage

A common requirement is to instrument ASP.NET Core applications based on the `Microsoft.Extensions.Hosting`
libraries which provide dependency injection via an `IServiceProvider`.

The OpenTelemetry SDK and the Elastic distribution provide extension methods to enable observability
features in your application by adding a few lines of code.

In this section, we'll focus on instrumenting an ASP.NET Core minimal API application using the Elastic
OpenTelemetry distribution. Similar steps can also be used to instrument other ASP.NET Core workloads
and other host-based applications such as [worker services](https://learn.microsoft.com/en-us/dotnet/core/extensions/workers).

> **_NOTE:_** These examples assume the use of the top-level statements feature introduced in C# 9.0 and the
default choice for applications created using the latest templates.

To take advantage of the OpenTelemetry SDK instrumentation for ASP.NET Core, add the following
NuGet package to your project:

```
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
```

This package includes instrumentation to collect traces for requests handled by ASP.NET Core endpoints.

> **_NOTE:_** The ASP.NET Core instrumentation is not included by default in the Elastic OpenTelemetry distribution.
As with all optional instrumentation libraries, you can choose to include them in your application by
adding a suitable package reference.

Inside the `Program.cs` file of the ASP.NET Core application, add the following two using directives:

```c#
using OpenTelemetry;
using OpenTelemetry.Trace;
```

The OpenTelemetry SDK provides extension methods on the `IServiceCollection` to support enabling the
providers and configuring the SDK. The Elastic distribution overrides the default SDK registration,
adding several opinionated defaults.

In the minimal API template, the `WebApplicationBuilder` exposes a `Services` property that can be used
to register services with the dependency injection container. To enable tracing and metrics collection,
ensure that the OpenTelemetry SDK is registered.

```c#
var builder = WebApplication.CreateBuilder(args);

builder.Services
.AddHttpClient() <1>
.AddOpenTelemetry() <2>
.WithTracing(t => t.AddAspNetCoreInstrumentation()); <3>
```
<1> The `AddHttpClient` method registers the `IHttpClientFactory` service with the dependency
injection container. This is NOT required to enable OpenTelemetry, but the example endpoint will use it to
send an HTTP request.

<2> The `AddOpenTelemetry` method registers the OpenTelemetry SDK with the dependency injection
container. When available, the Elastic distribution will override this to add opinionated defaults.

<3> Configure tracing to instrument requests handled by ASP.NET Core.

With these limited changes to the `Program.cs` file, the application is now configured to use the
OpenTelemetry SDK and the Elastic distribution to collect traces and metrics, which are exported via
OTLP.

To demonstrate the tracing capabilities, add a simple endpoint to the application:

```c#
app.MapGet("/", async (IHttpClientFactory httpClientFactory) =>
{
using var client = httpClientFactory.CreateClient();

await Task.Delay(100);
var response = await client.GetAsync("http://elastic.co"); <1>
await Task.Delay(50);

return response.StatusCode == System.Net.HttpStatusCode.OK ? Results.Ok() : Results.StatusCode(500);
});
```
<1> Using this URL will require two redirects, allowing us to see multiple spans in the trace.

The Elastic distribution will automatically enable the exporting of signals via the OTLP exporter. This
exporter requires that endpoint(s) are configured. A common mechanism for configuring endpoints is
via environment variables.

This demo uses an Elastic Cloud deployment as the destination for our observability data. From Kibana
running in Elastic Cloud, navigate to the observability set up guides. Select the OpenTelemetry option
to view the configuration details that should be supplied to the application.

![Elastic Cloud OpenTelemetry configuration](docs/images/elastic-cloud-opentelemetry-configuration.png)

Configure environment variables for the application either in `launchSettings.json` or in the environment
where the application is running.

Once configured, run the application and make a request to the root endpoint. A trace will be generated
and exported to the OTLP endpoint.

To view the traces, you can use the Elastic APM UI.

![Minimal API request trace sample in the Elastic APM UI](docs/images/trace-sample-minimal-api.png)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;

namespace Example.Elastic.OpenTelemetry.AspNetCore.Controllers;
namespace Example.AspNetCore.Mvc.Controllers;

public class E2EController : Controller
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System.Diagnostics;
using System.Net;
using Example.Elastic.OpenTelemetry.AspNetCore.Models;
using Example.AspNetCore.Mvc.Models;
using Microsoft.AspNetCore.Mvc;

namespace Example.Elastic.OpenTelemetry.AspNetCore.Controllers;
namespace Example.AspNetCore.Mvc.Controllers;

public class HomeController(IHttpClientFactory httpClientFactory) : Controller
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
namespace Example.Elastic.OpenTelemetry.AspNetCore.Models

namespace Example.AspNetCore.Mvc.Models
{
public class ErrorViewModel
{
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
using Example.Elastic.OpenTelemetry;

using Example.Console;

Console.WriteLine("Starting sample application.");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System.Diagnostics;
using Elastic.OpenTelemetry;
using Elastic.OpenTelemetry.Extensions;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

namespace Example.Elastic.OpenTelemetry;
namespace Example.Console;

internal static class Usage
{
Expand Down
4 changes: 4 additions & 0 deletions examples/Example.MinimalApi/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System.Diagnostics;
using Example.Api;
using OpenTelemetry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using Example.Elastic.OpenTelemetry.Worker;
using Example.WorkerService;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System.Diagnostics;
using System.Diagnostics.Metrics;

namespace Example.Elastic.OpenTelemetry.Worker;
namespace Example.WorkerService;

public class Worker(ILogger<Worker> logger) : BackgroundService
{
Expand Down
2 changes: 1 addition & 1 deletion src/Elastic.OpenTelemetry/AgentBuilderOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

Expand Down
Loading

0 comments on commit 8861f27

Please sign in to comment.