void WriteLogLine() { LogEntry Info = null; if (InfoQueue.TryDequeue(out Info)) { string S; StringBuilder SB = new StringBuilder(); SB.Append(Pad(Info.CorrelationId, Lengths["CorrelationId"])); SB.Append(Pad(Info.TimeStampUtc.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss.ff"), Lengths["Time"])); SB.Append(Pad(Info.HostName, Lengths["Host"])); SB.Append(Pad(Info.UserName, Lengths["User"])); SB.Append(Pad(Info.Level.ToString(), Lengths["Level"])); SB.Append(Pad(Info.EventId != null ? Info.EventId.ToString() : "", Lengths["EventId"])); SB.Append(Pad(Info.Category, Lengths["Category"])); S = ""; if (Info.Scopes != null && Info.Scopes.Count > 0) { LogScopeInfo SI = Info.Scopes.Last(); if (!string.IsNullOrWhiteSpace(SI.Text)) { S = SI.Text; } else { } } SB.Append(Pad(S, Lengths["Scope"])); string Text = Info.Text; /* writing properties is too much for a text file logger * if (Info.StateProperties != null && Info.StateProperties.Count > 0) * { * Text = Text + " Properties = " + * Newtonsoft.Json.JsonConvert.SerializeObject(Info.StateProperties); * } */ if (!string.IsNullOrWhiteSpace(Text)) { SB.Append(Text.Replace("\r\n", " ").Replace("\r", " ").Replace("\n", " ")); } SB.AppendLine(); WriteLine(SB.ToString()); SB.Clear(); } }
void ILogger.Log <TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter) { if ((this as ILogger).IsEnabled(logLevel)) { CorrelationContextAccessor CorrelationContextAccessor = new CorrelationContextAccessor(); LogEntry Info = new LogEntry(); Info.CorrelationId = CorrelationContextAccessor.CorrelationContext == null ? "" : CorrelationContextAccessor.CorrelationContext.CorrelationId; Info.Category = this.Category; Info.Level = logLevel; // well, the passed default formatter function // does not take the exception into account // SEE: https://github.com/aspnet/Extensions/blob/master/src/Logging/Logging.Abstractions/src/LoggerExtensions.cs Info.Text = exception?.Message ?? state.ToString(); // formatter(state, exception) Info.Exception = exception; Info.EventId = eventId; Info.State = state; // well, you never know what it really is if (state is string) { Info.StateText = state.ToString(); } // in case we have to do with a message template, // let's get the keys and values (for Structured Logging providers) // SEE: https://docs.microsoft.com/en-us/aspnet/core/ // fundamentals/logging#log-message-template // SEE: https://softwareengineering.stackexchange.com/ // questions/312197/benefits-of-structured-logging-vs-basic-logging else if (state is IEnumerable <KeyValuePair <string, object> > Properties) { Info.StateProperties = new Dictionary <string, object>(); foreach (KeyValuePair <string, object> item in Properties) { Info.StateProperties[item.Key] = item.Value; } } // gather info about scope(s), if any if (Provider.ScopeProvider != null) { Provider.ScopeProvider.ForEachScope((value, loggingProps) => { if (Info.Scopes == null) { Info.Scopes = new List <LogScopeInfo>(); } LogScopeInfo Scope = new LogScopeInfo(); Info.Scopes.Add(Scope); if (value is string) { Scope.Text = value.ToString(); } else if (value is IEnumerable <KeyValuePair <string, object> > props) { if (Scope.Properties == null) { Scope.Properties = new Dictionary <string, object>(); } foreach (var pair in props) { Scope.Properties[pair.Key] = pair.Value; } } }, state); } Provider.WriteLog(Info); } }