diff --git a/Felfel.Logging/Felfel.Logging.csproj b/Felfel.Logging/Felfel.Logging.csproj
index 4627125..594be2d 100644
--- a/Felfel.Logging/Felfel.Logging.csproj
+++ b/Felfel.Logging/Felfel.Logging.csproj
@@ -15,9 +15,9 @@
https://github.com/felfel/logging-dotnet
https://github.com/felfel/logging-dotnet
http://gravatar.com/avatar/2ac36575f81dd95ffbebc8a6eb0315e5?s=400
- 1.0.15
- 1.0.15.0
- 1.0.15.0
+ 1.0.19
+ 1.0.19.0
+ 1.0.19.0
diff --git a/Felfel.Logging/ILogger.cs b/Felfel.Logging/ILogger.cs
new file mode 100644
index 0000000..27bb669
--- /dev/null
+++ b/Felfel.Logging/ILogger.cs
@@ -0,0 +1,40 @@
+namespace Felfel.Logging
+{
+
+ ///
+ /// Primary façade for structured logging.
+ ///
+ /// Used to infer the .
+ public interface ILogger : ILogger
+ {
+ }
+
+
+ ///
+ /// Primary façade for structured logging.
+ ///
+ public interface ILogger
+ {
+ ///
+ /// Logger context, which will be part of the serialized data unless explicitly
+ /// set through the property. Identifies messages
+ /// that belong together (along with the at finer
+ /// granularity).
+ ///
+ string Context { get; }
+
+ ///
+ /// Concatenates the the and the
+ /// of a log entry
+ /// in order to ensure a qualified (and unique) payload type name.
+ ///
+ bool PrefixPayloadType { get; set; }
+
+ ///
+ /// Schedules a new log entry for logging. You probably should use one of the convenience
+ /// overloads such as Warn, Info or Debug that can be found
+ /// in .
+ ///
+ void Log(LogEntry entry);
+ }
+}
\ No newline at end of file
diff --git a/Felfel.Logging/LogEntry.cs b/Felfel.Logging/LogEntry.cs
index 2a44ab8..20d424f 100644
--- a/Felfel.Logging/LogEntry.cs
+++ b/Felfel.Logging/LogEntry.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace Felfel.Logging
{
@@ -55,5 +56,10 @@ public class LogEntry
/// Optional exception information, if any.
///
public Exception Exception { get; set; }
+
+ ///
+ /// Allows framework level enrichment of log entires with additional properties.
+ ///
+ public Dictionary ContextData { get; } = new Dictionary();
}
}
\ No newline at end of file
diff --git a/Felfel.Logging/LogEntryDto.cs b/Felfel.Logging/LogEntryDto.cs
index b5c9009..8bb67b1 100644
--- a/Felfel.Logging/LogEntryDto.cs
+++ b/Felfel.Logging/LogEntryDto.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using Newtonsoft.Json;
namespace Felfel.Logging
@@ -70,6 +71,13 @@ public class LogEntryDto
///
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public ExceptionInfo ExceptionInfo { get; set; }
+
+ ///
+ /// Optional exception information, if any. Not rendered in JSON if no
+ /// exception was registered.
+ ///
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+ public Dictionary ContextData { get; set; }
}
diff --git a/Felfel.Logging/LogEntryParser.cs b/Felfel.Logging/LogEntryParser.cs
index 95c29a1..02dfa70 100644
--- a/Felfel.Logging/LogEntryParser.cs
+++ b/Felfel.Logging/LogEntryParser.cs
@@ -56,7 +56,8 @@ public static LogEntryDto ParseLogEntry(LogEntry entry, string appName, string e
Message = String.IsNullOrEmpty(message) ? null : message,
PayloadType = entry.PayloadType,
Payload = payload,
- ExceptionInfo = exceptionInfo
+ ExceptionInfo = exceptionInfo,
+ ContextData = entry.ContextData.Count == 0 ? null : entry.ContextData
};
}
}
diff --git a/Felfel.Logging/LogEntrySink.cs b/Felfel.Logging/LogEntrySink.cs
index 756ffb1..0457275 100644
--- a/Felfel.Logging/LogEntrySink.cs
+++ b/Felfel.Logging/LogEntrySink.cs
@@ -56,22 +56,30 @@ protected virtual LogEntryDto ExtractLogEntry(LogEvent logEvent)
if (logEntry == null)
{
- //something went wrong
+ //no log entry to unwrap - assume just a regular Serilog message that didn't come through the custom API
+ var logLevel = ParseLevel(logEvent.Level);
logEntry = new LogEntry
{
TimestampOverride = logEvent.Timestamp,
- LogLevel = LogLevel.Fatal,
+ LogLevel = logLevel,
+ Message = logEvent.RenderMessage(),
Exception = logEvent.Exception,
- Context = $"{nameof(HttpSink)}.Error",
- Payload = new
- {
- Error = "Could not unwrap log entry.",
- Message = logEvent.RenderMessage(),
- Level = logEvent.Level.ToString()
- }
+ Context = $"{AppName}.{logLevel}"
};
}
+ //extract all other properties and add them to the context object
+ var props = logEvent.Properties.Where(p => !p.Key.Equals(Logger.EntryPropertyName));
+ foreach (var prop in props)
+ {
+ var scalarValue = prop.Value as ScalarValue;
+ if (scalarValue != null)
+ {
+ //insert (override duplicate keys)
+ logEntry.ContextData[prop.Key] = scalarValue.Value;
+ }
+ }
+
var dto = LogEntryParser.ParseLogEntry(logEntry, AppName, Environment);
return dto;
}
@@ -81,6 +89,24 @@ protected virtual LogEntryDto ExtractLogEntry(LogEvent logEvent)
}
}
+ private LogLevel ParseLevel(LogEventLevel level)
+ {
+ switch (level)
+ {
+ case LogEventLevel.Debug:
+ case LogEventLevel.Verbose:
+ return LogLevel.Debug;
+ case LogEventLevel.Information:
+ return LogLevel.Info;
+ case LogEventLevel.Warning:
+ return LogLevel.Warning;
+ case LogEventLevel.Error:
+ return LogLevel.Error;
+ default:
+ return LogLevel.Fatal;
+ }
+ }
+
///
/// Wraps an exception that occurred during logging into
@@ -100,4 +126,4 @@ protected virtual LogEntryDto ProcessLoggingException(Exception e)
};
}
}
-}
\ No newline at end of file
+}
diff --git a/Felfel.Logging/Logger.cs b/Felfel.Logging/Logger.cs
index 288bc0e..0734da7 100644
--- a/Felfel.Logging/Logger.cs
+++ b/Felfel.Logging/Logger.cs
@@ -5,13 +5,29 @@
namespace Felfel.Logging
{
+ public class Logger : Logger, ILogger
+ {
+ ///
+ /// Creates a new logger instance using the type name
+ /// as the .
+ ///
+ /// If true, the
+ /// will be automatically prefixed with the logger's in order
+ /// to create a qualified payload name, which reduces the risk of potential
+ /// duplicates across app/service.
+ ///
+ public Logger(bool prefixPayloadType = true) : base(typeof(T).Name, prefixPayloadType)
+ {
+ }
+ }
+
///
/// Primary façade for structured logging.
/// Having static builder methods is not a good practice, but will do for now given that
/// we do not leverate dependency injection on our legacy infrastructure. You probably should not
/// duplicate this pattern.
///
- public class Logger
+ public class Logger : ILogger
{
internal const string EntryPropertyName = nameof(LogEntry);
@@ -31,9 +47,9 @@ public class Logger
/// of a log entry
/// in order to ensure a qualified (and unique) payload type name.
///
- public bool PrefixPayloadType { get; }
+ public bool PrefixPayloadType { get; set; }
- private Logger(string context, bool prefixPayloadType)
+ protected Logger(string context, bool prefixPayloadType)
{
Context = context;
PrefixPayloadType = prefixPayloadType;
@@ -50,9 +66,9 @@ private Logger(string context, bool prefixPayloadType)
/// to create a qualified payload name, which reduces the risk of potential
/// duplicates across app/service.
///
- public static Logger Create(bool prefixPayloadType = true)
+ public static ILogger Create(bool prefixPayloadType = true)
{
- return Create(typeof(T), prefixPayloadType);
+ return new Logger(prefixPayloadType);
}
///
@@ -67,9 +83,9 @@ public static Logger Create(bool prefixPayloadType = true)
/// to create a qualified payload name, which reduces the risk of potential
/// duplicates across app/service.
///
- public static Logger Create(Type contextType, bool prefixPayloadType = true)
+ public static ILogger Create(Type contextType, bool prefixPayloadType = true)
{
- return Create(contextType.Name);
+ return Create(contextType.Name, prefixPayloadType);
}
///
@@ -83,7 +99,7 @@ public static Logger Create(Type contextType, bool prefixPayloadType = true)
/// to create a qualified payload name, which reduces the risk of potential
/// duplicates across app/service.
///
- public static Logger Create(string context = "", bool prefixPayloadType = true)
+ public static ILogger Create(string context = "", bool prefixPayloadType = true)
{
return new Logger(context, prefixPayloadType);
}
diff --git a/Felfel.Logging/LoggerExtensions.cs b/Felfel.Logging/LoggerExtensions.cs
index e6a9c2f..3f709fb 100644
--- a/Felfel.Logging/LoggerExtensions.cs
+++ b/Felfel.Logging/LoggerExtensions.cs
@@ -7,8 +7,7 @@ namespace Felfel.Logging
///
public static class LoggerExtensions
{
- private static void WriteEntry(Logger logger, LogLevel level, string payloadType, object data,
- Exception exception, string message)
+ private static void WriteEntry(ILogger logger, LogLevel level, string payloadType, object data, Exception exception, string message)
{
LogEntry entry = new LogEntry
{
@@ -22,102 +21,102 @@ private static void WriteEntry(Logger logger, LogLevel level, string payloadType
logger.Log(entry);
}
- public static void Debug(this Logger logger, string message)
+ public static void Debug(this ILogger logger, string message)
{
WriteEntry(logger, LogLevel.Debug, null, null, null, message);
}
- public static void Debug(this Logger logger, string payloadType, object data, string message = null)
+ public static void Debug(this ILogger logger, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Debug, payloadType, data, null, message);
}
- public static void Debug(this Logger logger, Exception exception, string message = null)
+ public static void Debug(this ILogger logger, Exception exception, string message = null)
{
WriteEntry(logger, LogLevel.Debug, "", null, exception, message);
}
- public static void Debug(this Logger logger, Exception exception, string payloadType, object data, string message = null)
+ public static void Debug(this ILogger logger, Exception exception, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Debug, payloadType, data, exception, message);
}
- public static void Information(this Logger logger, string message)
+ public static void Information(this ILogger logger, string message)
{
WriteEntry(logger, LogLevel.Info, null, null, null, message);
}
- public static void Information(this Logger logger, string payloadType, object data, string message = null)
+ public static void Information(this ILogger logger, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Info, payloadType, data, null, message);
}
- public static void Information(this Logger logger, Exception exception, string message = null)
+ public static void Information(this ILogger logger, Exception exception, string message = null)
{
WriteEntry(logger, LogLevel.Info, "", null, exception, message);
}
- public static void Information(this Logger logger, Exception exception, string payloadType, object data, string message = null)
+ public static void Information(this ILogger logger, Exception exception, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Info, payloadType, data, exception, message);
}
- public static void Warning(this Logger logger, string message)
+ public static void Warning(this ILogger logger, string message)
{
WriteEntry(logger, LogLevel.Warning, null, null, null, message);
}
- public static void Warning(this Logger logger, string payloadType, object data, string message = null)
+ public static void Warning(this ILogger logger, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Warning, payloadType, data, null, message);
}
- public static void Warning(this Logger logger, Exception exception, string message = null)
+ public static void Warning(this ILogger logger, Exception exception, string message = null)
{
WriteEntry(logger, LogLevel.Warning, "", null, exception, message);
}
- public static void Warning(this Logger logger, Exception exception, string payloadType, object data, string message = null)
+ public static void Warning(this ILogger logger, Exception exception, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Warning, payloadType, data, exception, message);
}
- public static void Error(this Logger logger, string message)
+ public static void Error(this ILogger logger, string message)
{
WriteEntry(logger, LogLevel.Error, null, null, null, message);
}
- public static void Error(this Logger logger, string payloadType, object data, string message = null)
+ public static void Error(this ILogger logger, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Error, payloadType, data, null, message);
}
- public static void Error(this Logger logger, Exception exception, string message = null)
+ public static void Error(this ILogger logger, Exception exception, string message = null)
{
WriteEntry(logger, LogLevel.Error, "", null, exception, message);
}
- public static void Error(this Logger logger, Exception exception, string payloadType, object data, string message = null)
+ public static void Error(this ILogger logger, Exception exception, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Error, payloadType, data, exception, message);
}
- public static void Fatal(this Logger logger, string message)
+ public static void Fatal(this ILogger logger, string message)
{
WriteEntry(logger, LogLevel.Fatal, null, null, null, message);
}
- public static void Fatal(this Logger logger, string payloadType, object data, string message = null)
+ public static void Fatal(this ILogger logger, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Fatal, payloadType, data, null, message);
}
- public static void Fatal(this Logger logger, Exception exception, string message = null)
+ public static void Fatal(this ILogger logger, Exception exception, string message = null)
{
WriteEntry(logger, LogLevel.Fatal, "", null, exception, message);
}
- public static void Fatal(this Logger logger, Exception exception, string payloadType, object data, string message = null)
+ public static void Fatal(this ILogger logger, Exception exception, string payloadType, object data, string message = null)
{
WriteEntry(logger, LogLevel.Fatal, payloadType, data, exception, message);
}