Libraries/src/Amazon.Lambda.RuntimeSupport/Helpers/Logging/DefaultLogMessageFormatter.cs (79 lines of code) (raw):

#if NET6_0_OR_GREATER using System.Text; namespace Amazon.Lambda.RuntimeSupport.Helpers.Logging { /// <summary> /// The default log message formatter that log the message as a simple string. Replacing any message properties /// in the message with provided arguments. The message will be prefixed with the timestamp, request id and /// log level unless constructed passing in false for addPrefix. /// /// This formatter matches is the logging format introduced as part of the .NET 6 managed runtime. /// </summary> public class DefaultLogMessageFormatter : AbstractLogMessageFormatter { /// <summary> /// If true timestamp, request id and log level are added as a prefix to every log message. /// </summary> public bool AddPrefix { get; } /// <summary> /// Constructs an instance of DefaultLogMessageFormatter. /// </summary> /// <param name="addPrefix">If true timestamp, request id and log level are added as a prefix to every log message.</param> public DefaultLogMessageFormatter(bool addPrefix) { AddPrefix = addPrefix; } /// <summary> /// Format the log message applying in message property replacements and adding a prefix unless disabled. /// </summary> /// <param name="state"></param> /// <returns></returns> public override string FormatMessage(MessageState state) { string message; // If there are no arguments then this is not a parameterized log message so skip parsing logic. if(state.MessageArguments?.Length == 0) { message = state.MessageTemplate; } else { // Parse the message template for any message properties like "{count}". var messageProperties = ParseProperties(state.MessageTemplate); // Replace any message properties in the message template with the provided argument values. message = ApplyMessageProperties(state.MessageTemplate, messageProperties, state.MessageArguments); } var displayLevel = state.Level != null ? ConvertLogLevelToLabel(state.Level.Value) : null; var sb = new StringBuilder( 25 + // Length for timestamp (state.AwsRequestId?.Length).GetValueOrDefault() + displayLevel.Length + (message?.Length).GetValueOrDefault() + 5 // Padding for tabs ); if (AddPrefix) { sb.Append(FormatTimestamp(state)); sb.Append('\t'); sb.Append(state.AwsRequestId); if (!string.IsNullOrEmpty(displayLevel)) { sb.Append('\t'); sb.Append(displayLevel); } sb.Append('\t'); } if (!string.IsNullOrEmpty(message)) { sb.Append(message); } if (state.Exception != null) { if (!string.IsNullOrEmpty(message)) { sb.Append('\n'); } sb.Append(state.Exception.ToString()); } return sb.ToString(); } /// <summary> /// Convert LogLevel enums to the the same string label that console provider for Microsoft.Extensions.Logging.ILogger uses. /// </summary> /// <param name="level"></param> /// <returns></returns> private string ConvertLogLevelToLabel(LogLevelLoggerWriter.LogLevel level) { switch (level) { case LogLevelLoggerWriter.LogLevel.Trace: return "trce"; case LogLevelLoggerWriter.LogLevel.Debug: return "dbug"; case LogLevelLoggerWriter.LogLevel.Information: return "info"; case LogLevelLoggerWriter.LogLevel.Warning: return "warn"; case LogLevelLoggerWriter.LogLevel.Error: return "fail"; case LogLevelLoggerWriter.LogLevel.Critical: return "crit"; } return level.ToString(); } } } #endif