# Troubleshooting

> Learn how to troubleshoot OpenTelemetry .NET

---

LLMS index: [llms.txt](/llms.txt)

---

All the components shipped from the OpenTelemetry .NET repositories
([opentelemetry-dotnet][] and [opentelemetry-dotnet-contrib][]) use
[EventSource](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource)
for internal logging. The name of the `EventSource` used by the OpenTelemetry
SDK is "OpenTelemetry-Sdk". To know the `EventSource` names used by other
components, refer to the individual component documentation.

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

## Self-diagnostics

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

The self-diagnostics feature can be enabled, changed, or disabled while the
process is running (without restarting the process). The SDK attempts to read
the configuration file every 10 seconds in non-exclusive read-only mode. The SDK
creates or overwrites a file with new logs according to the configuration. This
file doesn't exceed the configured max size and is 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": 32768,
  "LogLevel": "Warning",
  "FormatMessage": "true"
}
```

To disable self-diagnostics, delete the configuration file.

> [!TIP]
>
> In most cases, you can drop the file alongside your application. On Windows,
> you can use
> [Process Explorer](https://docs.microsoft.com/sysinternals/downloads/process-explorer),
> double-click on the process to open the Properties dialog, and find "Current
> directory" in the "Image" tab.
>
> Internally, the SDK 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

The configuration file supports the following parameters:

#### LogDirectory

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

#### FileSize

A positive integer that specifies the log file size in
[KiB](https://en.wikipedia.org/wiki/Kibibyte). This value must be within the
range `[1024, 131072]` (1 MiB <= size <= 128 MiB), or it will be rounded to the
closest upper or lower limit. The log file never exceeds this configured size
and is overwritten in a circular way.

#### LogLevel

The lowest level of the events to be captured. It must 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.

#### FormatMessage

A boolean value that controls whether log messages should be formatted by
replacing placeholders (`{0}`, `{1}`, etc.) with their actual parameter values.
When set to `false` (default), messages are logged with unformatted placeholders
followed by raw parameter values. When set to `true`, placeholders are replaced
with formatted parameter values for improved readability.

**Example with `FormatMessage: false` (default):**

```text
2025-07-24T01:45:04.1020880Z:Measurements from Instrument '{0}', Meter '{1}' will be ignored. Reason: '{2}'. Suggested action: '{3}'{dotnet.gc.collections}{System.Runtime}{Instrument belongs to a Meter not subscribed by the provider.}{Use AddMeter to add the Meter to the provider.}
```

**Example with `FormatMessage: true`:**

```text
2025-07-24T01:44:44.7059260Z:Measurements from Instrument 'dotnet.gc.collections', Meter 'System.Runtime' will be ignored. Reason: 'Instrument belongs to a Meter not subscribed by the provider.'. Suggested action: 'Use AddMeter to add the Meter to the provider.'
```

### Remarks

A log file named `ExecutableName.ProcessId.log` (for example,
`myapp.exe.12345.log`) is generated at the specified `LogDirectory`, into which
logs are written.

If the SDK fails to parse the `LogDirectory`, `FileSize`, or `LogLevel` fields,
the configuration file is treated as invalid and no log file is generated.

When the `LogDirectory` or `FileSize` is changed, the SDK creates or overwrites
a file with new logs according to the new configuration. The configuration file
must be no more than 4 KiB. If the file is larger than 4 KiB, only the first 4
KiB of content is 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 might have trailing `NUL`
characters if log text is less than configured size; once write operation
reaches the end, it starts from the beginning and overwrites existing text.

[dotnet-trace]: https://docs.microsoft.com/dotnet/core/diagnostics/dotnet-trace
[opentelemetry-dotnet]: https://github.com/open-telemetry/opentelemetry-dotnet
[opentelemetry-dotnet-contrib]:
  https://github.com/open-telemetry/opentelemetry-dotnet-contrib
