Skip to content

Commit

Permalink
[SelfDiagnosticsModule] Add user guide for troubleshooting (#1477)
Browse files Browse the repository at this point in the history
* Add troubleshooting doc to enable self diagnostics module

* Add explanation on EventLevel and parsing failure behavior.

* Change the configuration file name to OTEL_DIAGNOSTICS.json

* Add more explanation

* Rename EventLevel to LogLevel

* Add link to EventLevel enum

Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
  • Loading branch information
xiang17 and cijothomas authored Nov 9, 2020
1 parent b956a5f commit 32a500c
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 15 deletions.
22 changes: 11 additions & 11 deletions src/OpenTelemetry/Internal/SelfDiagnosticsConfigParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace OpenTelemetry.Internal
{
internal class SelfDiagnosticsConfigParser
{
private const string ConfigFileName = "DiagnosticsConfiguration.json";
private const string ConfigFileName = "OTEL_DIAGNOSTICS.json";
private const int FileSizeLowerLimit = 1024; // Lower limit for log file size in KB: 1MB
private const int FileSizeUpperLimit = 128 * 1024; // Upper limit for log file size in KB: 128MB

Expand All @@ -39,19 +39,19 @@ internal class SelfDiagnosticsConfigParser
private static readonly Regex FileSizeRegex = new Regex(
@"""FileSize""\s*:\s*(?<FileSize>\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);

private static readonly Regex EventLevelRegex = new Regex(
@"""EventLevel""\s*:\s*""(?<EventLevel>.*?)""", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex LogLevelRegex = new Regex(
@"""LogLevel""\s*:\s*""(?<LogLevel>.*?)""", RegexOptions.IgnoreCase | RegexOptions.Compiled);

// This class is called in SelfDiagnosticsConfigRefresher.UpdateMemoryMappedFileFromConfiguration
// in both main thread and the worker thread.
// In theory the variable won't be access at the same time because worker thread first Task.Delay for a few seconds.
private byte[] configBuffer;

public bool TryGetConfiguration(out string logDirectory, out int fileSizeInKB, out EventLevel eventLevel)
public bool TryGetConfiguration(out string logDirectory, out int fileSizeInKB, out EventLevel logLevel)
{
logDirectory = null;
fileSizeInKB = 0;
eventLevel = EventLevel.LogAlways;
logLevel = EventLevel.LogAlways;
try
{
using FileStream file = File.Open(ConfigFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
Expand Down Expand Up @@ -84,12 +84,12 @@ public bool TryGetConfiguration(out string logDirectory, out int fileSizeInKB, o
fileSizeInKB = FileSizeUpperLimit;
}

if (!TryParseEventLevel(configJson, out var eventLevelString))
if (!TryParseLogLevel(configJson, out var logLevelString))
{
return false;
}

eventLevel = (EventLevel)Enum.Parse(typeof(EventLevel), eventLevelString);
logLevel = (EventLevel)Enum.Parse(typeof(EventLevel), logLevelString);
return true;
}
catch (Exception)
Expand All @@ -114,11 +114,11 @@ internal static bool TryParseFileSize(string configJson, out int fileSizeInKB)
return fileSizeResult.Success && int.TryParse(fileSizeResult.Groups["FileSize"].Value, out fileSizeInKB);
}

internal static bool TryParseEventLevel(string configJson, out string eventLevel)
internal static bool TryParseLogLevel(string configJson, out string logLevel)
{
var eventLevelResult = EventLevelRegex.Match(configJson);
eventLevel = eventLevelResult.Groups["EventLevel"].Value;
return eventLevelResult.Success && !string.IsNullOrWhiteSpace(eventLevel);
var logLevelResult = LogLevelRegex.Match(configJson);
logLevel = logLevelResult.Groups["LogLevel"].Value;
return logLevelResult.Success && !string.IsNullOrWhiteSpace(logLevel);
}
}
}
48 changes: 48 additions & 0 deletions src/OpenTelemetry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,54 @@ using var otel = Sdk.CreateTracerProvider(b => b
* [Building your own Processor](../../docs/trace/extending-the-sdk/README.md#processor)
* [Building your own Sampler](../../docs/trace/extending-the-sdk/README.md#sampler)

### Troubleshooting

Self diagnostics module is provided to help troubleshooting. When enabled,
internal events generated by OpenTelemetry will be written to a log file.
These events contain important debugging information and error messages.

To enable self diagnostics, go to the current directory of your process and
create a configuration file named `OTEL_DIAGNOSTICS.json` with the following
content:

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

`LogDirectory` is the directory of the output file. It can be an absolute path
or a relative path to the current directory. `FileSize` is a positive integer,
which specifies the log file size in
[KiB](https://en.wikipedia.org/wiki/Kibibyte).
`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, which are higher in severity. See
[here](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventlevel)
for more.)

The SDK will attempt to open the configuration file in non-exclusive read-only
mode, read the file and parse it as the configuration file every 3 seconds. 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. Otherwise, it will create or overwrite a
`FileSize`-KiB file at the specific directory `LogDirectory` with the log file
named as `ExecutableName.ProcessId.log` (e.g. `foobar.exe.12345.log`).

Note that the `FileSize` has to be between 1 MiB and 128 MiB (inclusive), or it
will be rounded to the closest upper or lower limit. 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.

## References

* [OpenTelemetry Project](https://opentelemetry.io/)
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ public void SelfDiagnosticsConfigParser_TryParseFileSize_MissingField()

[Fact]
[Trait("Platform", "Any")]
public void SelfDiagnosticsConfigParser_TryParseEventLevel()
public void SelfDiagnosticsConfigParser_TryParseLogLevel()
{
string configJson = @"{
""LogDirectory"": ""Diagnostics"",
""FileSize"": 1024,
""EventLevel"": ""Error""
""LogLevel"": ""Error""
}";
Assert.True(SelfDiagnosticsConfigParser.TryParseEventLevel(configJson, out string eventLevelString));
Assert.Equal("Error", eventLevelString);
Assert.True(SelfDiagnosticsConfigParser.TryParseLogLevel(configJson, out string logLevelString));
Assert.Equal("Error", logLevelString);
}
}
}

0 comments on commit 32a500c

Please sign in to comment.