# OpenTelemetry .NET SDK

[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.svg)](https://www.nuget.org/packages/OpenTelemetry)
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.svg)](https://www.nuget.org/packages/OpenTelemetry)

* [Installation](#installation)
* [Introduction](#introduction)
* [Getting started with Logging](#getting-started-with-logging)
* [Getting started with Metrics](#getting-started-with-metrics)
* [Getting started with Tracing](#getting-started-with-tracing)
* [Troubleshooting](#troubleshooting)
  * [Configuration Parameters](#configuration-parameters)
  * [Remarks](#remarks)
* [References](#references)

## Installation

```shell
dotnet add package OpenTelemetry
```

## Introduction

OpenTelemetry SDK is a reference implementation of the OpenTelemetry API. It
implements the Tracing API, the Metrics API, and the Context API.  Once a valid
SDK is installed and configured, all the OpenTelemetry API methods, which were
no-ops without an SDK, will start emitting telemetry.
This SDK also supports [ILogger](https://docs.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger)
integration.

The SDK deals with concerns such as sampling, processing pipeline, exporting
telemetry to a particular backend etc. In most cases, users indirectly install
and enable the SDK, when they install a particular exporter.

## Getting started with Logging

If you are new to logging, it is recommended to first follow the [getting
started in 5 minutes](../../docs/logs/getting-started/README.md) guide to get up
and running.

While [OpenTelemetry
logging](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/overview.md)
specification is an experimental signal, `ILogger` is the de-facto logging API
provided by the .NET runtime and is a stable API recommended for production use.
This repo ships an OpenTelemetry
[provider](https://docs.microsoft.com/dotnet/core/extensions/logging-providers),
which provides the ability to enrich logs emitted with `ILogger` with
`ActivityContext`, and export them to multiple destinations, similar to tracing.
`ILogger` based API will become the OpenTelemetry .NET implementation of
OpenTelemetry logging.

## Getting started with Metrics

If you are new to
[metrics](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md),
it is first recommended to follow the [getting started in 5
minutes](../../docs/metrics/getting-started/README.md) guide to get up and
running.

For a more detailed explanation of SDK metric features see [Customizing
OpenTelemetry .NET SDK for
Metrics](../../docs/metrics/customizing-the-sdk/README.md).

## Getting started with Tracing

If you are new to
[traces](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md),
it is recommended to first follow the [getting started in 5
minutes](../../docs/trace/getting-started/README.md) guide to get up and
running.

For a more detailed explanation of SDK tracing features see [Customizing
OpenTelemetry .NET SDK for
Tracing](../../docs/trace/customizing-the-sdk/README.md).

## Troubleshooting

All the components shipped from this repo uses
[EventSource](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource)
for its internal logging. The name of the `EventSource` used by OpenTelemetry
SDK is "OpenTelemetry-Sdk". To know the `EventSource` names used by other
components, refer to the individual readme files.

While it is possible to view these logs using tools such as
[PerfView](https://github.com/microsoft/perfview),
[dotnet-trace](https://docs.microsoft.com/dotnet/core/diagnostics/dotnet-trace)
etc., this SDK also ships a [self-diagnostics](#self-diagnostics) feature, which
helps troubleshooting.

## Self-diagnostics

OpenTelemetry SDK ships with built-in self-diagnostics feature. This feature,
when enabled, will listen to internal logs generated by all OpenTelemetry
components (i.e EventSources whose name starts with "OpenTelemetry-") and writes
them to a log file.

The self-diagnostics feature can be enabled/changed/disabled while the process
is running (without restarting the process). The SDK will attempt to read the
configuration file every `10` seconds in non-exclusive read-only mode. The SDK
will create or overwrite a file with new logs according to the configuration.
This file will not exceed the configured max size and will be overwritten in a
circular way.

To enable self-diagnostics, go to the
[current working directory](https://en.wikipedia.org/wiki/Working_directory) of
your process and create a configuration file named `OTEL_DIAGNOSTICS.json` with
the following content:

```json
{
    "LogDirectory": ".",
    "FileSize": 1024,
    "LogLevel": "Error"
}
```

To disable self-diagnostics, delete the above file.

Tip: In most cases, you could just drop the file along your application.
On Windows, you can use [Process Explorer](https://docs.microsoft.com/sysinternals/downloads/process-explorer),
double click on the process to pop up Properties dialog and find "Current
directory" in "Image" tab.
Internally, it looks for the configuration file located in
[GetCurrentDirectory](https://docs.microsoft.com/dotnet/api/system.io.directory.getcurrentdirectory),
and then [AppContext.BaseDirectory](https://docs.microsoft.com/dotnet/api/system.appcontext.basedirectory).
You can also find the exact directory by calling these methods from your code.

### Configuration Parameters

1. `LogDirectory` is the directory where the output log file will be stored. It
   can be an absolute path or a relative path to the current directory.

2. `FileSize` is a positive integer, which specifies the log file size in
   [KiB](https://en.wikipedia.org/wiki/Kibibyte). This value must be between 1 MiB
   and 128 MiB (inclusive), or it will be rounded to the closest upper or lower
   limit. The log file will never exceed this configured size, and will be
   overwritten in a circular way.

3. `LogLevel` is the lowest level of the events to be captured. It has to be one
   of the
   [values](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventlevel#fields)
   of the [`EventLevel`
   enum](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventlevel).
   The level signifies the severity of an event. Lower severity levels encompass
   higher severity levels. For example, `Warning` includes the `Error` and
   `Critical` levels.

### Remarks

A `FileSize`-KiB log file named as `ExecutableName.ProcessId.log` (e.g.
`foobar.exe.12345.log`) will be generated at the specified directory
`LogDirectory`, into which logs are written to.

If the SDK fails to parse the `LogDirectory`, `FileSize` or `LogLevel` fields as
the specified format, the configuration file will be treated as invalid and no
log file would be generated.

When the `LogDirectory` or `FileSize` is found to be changed, the SDK will create
or overwrite a file with new logs according to the new configuration. The
configuration file has to be no more than 4 KiB. In case the file is larger than
4 KiB, only the first 4 KiB of content will be read.

The log file might not be a proper text file format to achieve the goal of having
minimal overhead and bounded resource usage: it may have trailing `NUL`s if log
text is less than configured size; once write operation reaches the end, it will
start from beginning and overwrite existing text.

## References

* [OpenTelemetry Project](https://opentelemetry.io/)
* [OpenTelemetry Tracing SDK specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md)
* [OpenTelemetry Logging specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/overview.md)
