Skip to content

Commit

Permalink
Honour configured logging level
Browse files Browse the repository at this point in the history
  • Loading branch information
stevejgordon committed Feb 7, 2024
1 parent be9148c commit f7b88a3
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 31 deletions.
25 changes: 24 additions & 1 deletion src/Elastic.OpenTelemetry/Diagnostics/DiagnosticErrorLevels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,30 @@ internal static class DiagnosticErrorLevels
{
public const string Critical = "Critical";
public const string Error = "Error";
public const string Warning = "Warn";
public const string Warning = "Warning";
public const string Info = "Info";
public const string Trace = "Trace";

public static LogLevel ToLogLevel(string logLevelString) =>
logLevelString switch
{
Critical => LogLevel.Critical,
Error => LogLevel.Error,
Warning => LogLevel.Warning,
Info => LogLevel.Info,
Trace => LogLevel.Trace,
_ => LogLevel.Unknown,
};

public static string AsString(this LogLevel logLevel) =>
logLevel switch
{
LogLevel.Critical => Critical,
LogLevel.Error => Error,
LogLevel.Warning => Warning,
LogLevel.Info => Info,
LogLevel.Trace => Trace,
LogLevel.Unknown => string.Empty,
_ => string.Empty
};
}
58 changes: 49 additions & 9 deletions src/Elastic.OpenTelemetry/Diagnostics/LogFileWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ private LogFileWriter()

foreach (var item in preAmble)
{
WriteLogPrefix(DiagnosticErrorLevels.Info, builder);
// These preamble entries are ALWAYS logged, regardless of the configured log level
WriteLogPrefix(LogLevel.Info, builder);
builder.Append(item);
_streamWriter.WriteLine(builder.ToString());
builder.Clear();
Expand All @@ -77,17 +78,46 @@ private LogFileWriter()
StringBuilderCache.Release(builder);
}

private static void WriteLogPrefix(string logLevel, StringBuilder builder) =>
private static readonly LogLevel ConfiguredLogLevel = GetConfiguredLogLevel();

public static LogLevel GetConfiguredLogLevel()
{
var logLevel = LogLevel.Info;

var logLevelEnvironmentVariable = Environment.GetEnvironmentVariable(EnvironmentVariables.ElasticOtelLogLevelEnvironmentVariable);

if (!string.IsNullOrEmpty(logLevelEnvironmentVariable))
{
if (logLevelEnvironmentVariable.Equals(DiagnosticErrorLevels.Trace, StringComparison.OrdinalIgnoreCase))
logLevel = LogLevel.Trace;

else if (logLevelEnvironmentVariable.Equals(DiagnosticErrorLevels.Info, StringComparison.OrdinalIgnoreCase))
logLevel = LogLevel.Info;

else if (logLevelEnvironmentVariable.Equals(DiagnosticErrorLevels.Warning, StringComparison.OrdinalIgnoreCase))
logLevel = LogLevel.Warning;

else if (logLevelEnvironmentVariable.Equals(DiagnosticErrorLevels.Error, StringComparison.OrdinalIgnoreCase))
logLevel = LogLevel.Error;

else if (logLevelEnvironmentVariable.Equals(DiagnosticErrorLevels.Critical, StringComparison.OrdinalIgnoreCase))
logLevel = LogLevel.Critical;
}

return logLevel;
}

private static void WriteLogPrefix(LogLevel logLevel, StringBuilder builder) =>
WriteLogPrefix(Environment.CurrentManagedThreadId, DateTime.UtcNow, logLevel, builder);

private static void WriteLogPrefix(int managedThreadId, DateTime dateTime, string level, StringBuilder builder)
private static void WriteLogPrefix(int managedThreadId, DateTime dateTime, LogLevel level, StringBuilder builder)
{
builder.Append('[')
.Append(dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff"))
.Append("][")
.Append(managedThreadId == -1 ? "-" : managedThreadId)
.Append("][")
.Append(level)
.Append(level.AsString())
.Append(']');

var length = builder.Length;
Expand All @@ -105,20 +135,30 @@ private static void WriteLogPrefix(int managedThreadId, DateTime dateTime, strin

public Task WritingTask { get; }

public void WriteCriticalLogLine(IDiagnosticEvent diagnosticEvent, string message) =>
WriteLogLine(diagnosticEvent, LogLevel.Critical, message);

public void WriteErrorLogLine(IDiagnosticEvent diagnosticEvent, string message) =>
WriteLogLine(diagnosticEvent, DiagnosticErrorLevels.Error, message);
WriteLogLine(diagnosticEvent, LogLevel.Error, message);

public void WriteWarningLogLine(IDiagnosticEvent diagnosticEvent, string message) =>
WriteLogLine(diagnosticEvent, LogLevel.Warning, message);

public void WriteInfoLogLine(IDiagnosticEvent diagnosticEvent, string message) =>
WriteLogLine(diagnosticEvent, DiagnosticErrorLevels.Info, message);
WriteLogLine(diagnosticEvent, LogLevel.Info, message);

public void WriteTraceLogLine(IDiagnosticEvent diagnosticEvent, string message) =>
WriteLogLine(diagnosticEvent, DiagnosticErrorLevels.Trace, message);
WriteLogLine(diagnosticEvent, LogLevel.Trace, message);

public void WriteLogLine(IDiagnosticEvent diagnosticEvent, string logLevel, string message) =>
public void WriteLogLine(IDiagnosticEvent diagnosticEvent, LogLevel logLevel, string message) =>
WriteLogLine(diagnosticEvent.Activity, diagnosticEvent.ManagedThreadId, diagnosticEvent.DateTime, logLevel, message);

public void WriteLogLine(Activity? activity, int managedThreadId, DateTime dateTime, string logLevel, string logLine)
public void WriteLogLine(Activity? activity, int managedThreadId, DateTime dateTime, LogLevel logLevel, string logLine)
{
// We skip logging for any log level higher (numerically) than the configured log level
if (logLevel > ConfiguredLogLevel)
return;

var builder = StringBuilderCache.Acquire();
WriteLogPrefix(managedThreadId, dateTime, logLevel, builder);
builder.Append(logLine);
Expand Down
14 changes: 14 additions & 0 deletions src/Elastic.OpenTelemetry/Diagnostics/LogLevel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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 Elastic.OpenTelemetry.Diagnostics;

internal enum LogLevel
{
Unknown = 0,
Critical = 1,
Error = 2,
Warning = 3,
Info = 4,
Trace = 5
}
39 changes: 18 additions & 21 deletions src/Elastic.OpenTelemetry/Diagnostics/LoggingEventListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,17 @@ public LoggingEventListener(LogFileWriter logFileWriter)
{
_logFileWriter = logFileWriter;

var eventLevel = Environment.GetEnvironmentVariable(EnvironmentVariables.ElasticOtelLogLevelEnvironmentVariable);
var eventLevel = LogFileWriter.GetConfiguredLogLevel();

if (!string.IsNullOrEmpty(eventLevel))
_eventLevel = eventLevel switch
{
_eventLevel = eventLevel.ToLowerInvariant() switch
{
"trace" => EventLevel.Verbose,
"info" => EventLevel.Informational,
"warning" => EventLevel.Warning,
"error" => EventLevel.Error,
"critical" => EventLevel.Critical,
_ => EventLevel.Informational // fallback to info level
};
}
LogLevel.Trace => EventLevel.Verbose,
LogLevel.Info => EventLevel.Informational,
LogLevel.Warning => EventLevel.Warning,
LogLevel.Error => EventLevel.Error,
LogLevel.Critical => EventLevel.Critical,
_ => EventLevel.Informational // fallback to info level
};
}

public override void Dispose()
Expand Down Expand Up @@ -70,24 +67,24 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData)
// TODO - We can only get the OS thread ID from the args - Do we send that instead??
// As per this issue - https://github.com/dotnet/runtime/issues/13125 - OnEventWritten may be on a different thread
// so we can't use the Environment.CurrentManagedThreadId value here.
_logFileWriter.WriteLogLine(null, -1, eventData.TimeStamp, GetLevel(eventData), StringBuilderCache.GetStringAndRelease(builder));
_logFileWriter.WriteLogLine(null, -1, eventData.TimeStamp, GetLogLevel(eventData), StringBuilderCache.GetStringAndRelease(builder));
}
catch (Exception)
{
// TODO - We might want to block writing further events if we reach here as it's
// likely a file access issue
}

static string GetLevel(EventWrittenEventArgs eventData) =>
static LogLevel GetLogLevel(EventWrittenEventArgs eventData) =>
eventData.Level switch
{
EventLevel.Critical => DiagnosticErrorLevels.Critical,
EventLevel.Error => DiagnosticErrorLevels.Error,
EventLevel.Warning => DiagnosticErrorLevels.Warning,
EventLevel.Informational => DiagnosticErrorLevels.Info,
EventLevel.Verbose => DiagnosticErrorLevels.Trace,
EventLevel.LogAlways => "N/A",
_ => throw new Exception("Unhandled event data level")
EventLevel.Critical => LogLevel.Critical,
EventLevel.Error => LogLevel.Error,
EventLevel.Warning => LogLevel.Warning,
EventLevel.Informational => LogLevel.Info,
EventLevel.Verbose => LogLevel.Trace,
EventLevel.LogAlways => LogLevel.Unknown,
_ => LogLevel.Unknown
};

static void CreateLogMessage(EventWrittenEventArgs eventData, StringBuilder builder)
Expand Down

0 comments on commit f7b88a3

Please sign in to comment.