diff --git a/src/Serilog.Sinks.Loggly/LoggerConfigurationLogglyExtensions.cs b/src/Serilog.Sinks.Loggly/LoggerConfigurationLogglyExtensions.cs
index 58e060f..a099461 100644
--- a/src/Serilog.Sinks.Loggly/LoggerConfigurationLogglyExtensions.cs
+++ b/src/Serilog.Sinks.Loggly/LoggerConfigurationLogglyExtensions.cs
@@ -48,6 +48,8 @@ public static class LoggerConfigurationLogglyExtensions
/// The limit is soft in that it can be exceeded by any single error payload, but in that case only that single error
/// payload will be retained.
/// number of files to retain for the buffer. If defined, this also controls which records
+ /// Used to configure underlying LogglyClient programmaticaly. Otherwise use app.Config.
+ /// Decides if the sink should include specific properties in the log message
/// in the buffer get sent to the remote Loggly instance
/// Logger configuration, allowing configuration to continue.
/// A required parameter is null.
@@ -62,7 +64,9 @@ public static LoggerConfiguration Loggly(
long? eventBodyLimitBytes = 1024 * 1024,
LoggingLevelSwitch controlLevelSwitch = null,
long? retainedInvalidPayloadsLimitBytes = null,
- int? retainedFileCountLimit = null)
+ int? retainedFileCountLimit = null,
+ LogglyConfiguration logglyConfig = null,
+ LogIncludes includes = null)
{
if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration));
if (bufferFileSizeLimitBytes.HasValue && bufferFileSizeLimitBytes < 0)
@@ -74,7 +78,7 @@ public static LoggerConfiguration Loggly(
if (bufferBaseFilename == null)
{
- sink = new LogglySink(formatProvider, batchPostingLimit, defaultedPeriod);
+ sink = new LogglySink(formatProvider, batchPostingLimit, defaultedPeriod, logglyConfig, includes);
}
else
{
@@ -87,7 +91,9 @@ public static LoggerConfiguration Loggly(
controlLevelSwitch,
retainedInvalidPayloadsLimitBytes,
retainedFileCountLimit,
- formatProvider);
+ formatProvider,
+ logglyConfig,
+ includes);
}
return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
diff --git a/src/Serilog.Sinks.Loggly/Properties/AssemblyInfo.cs b/src/Serilog.Sinks.Loggly/Properties/AssemblyInfo.cs
index 5269bcb..ac76148 100644
--- a/src/Serilog.Sinks.Loggly/Properties/AssemblyInfo.cs
+++ b/src/Serilog.Sinks.Loggly/Properties/AssemblyInfo.cs
@@ -2,7 +2,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyVersion("3.1.0.0")]
[assembly: CLSCompliant(true)]
diff --git a/src/Serilog.Sinks.Loggly/Serilog.Sinks.Loggly.csproj b/src/Serilog.Sinks.Loggly/Serilog.Sinks.Loggly.csproj
index 1090cc6..c2f3c1d 100644
--- a/src/Serilog.Sinks.Loggly/Serilog.Sinks.Loggly.csproj
+++ b/src/Serilog.Sinks.Loggly/Serilog.Sinks.Loggly.csproj
@@ -2,7 +2,7 @@
Serilog sink for Loggly.com service
- 5.1.1
+ 5.2.0
Serilog Contributors;Michiel van Oudheusden
net45;netstandard1.5
Serilog.Sinks.Loggly
diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/DurableLogglySink.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/DurableLogglySink.cs
index 4247754..cbb01b1 100644
--- a/src/Serilog.Sinks.Loggly/Sinks/Loggly/DurableLogglySink.cs
+++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/DurableLogglySink.cs
@@ -34,8 +34,9 @@ public DurableLogglySink(
LoggingLevelSwitch levelControlSwitch,
long? retainedInvalidPayloadsLimitBytes,
int? retainedFileCountLimit = null,
- IFormatProvider formatProvider = null
- )
+ IFormatProvider formatProvider = null,
+ LogglyConfiguration logglyConfiguration = null,
+ LogIncludes includes = null)
{
if (bufferBaseFilename == null) throw new ArgumentNullException(nameof(bufferBaseFilename));
@@ -51,12 +52,13 @@ public DurableLogglySink(
levelControlSwitch,
retainedInvalidPayloadsLimitBytes,
encoding,
- retainedFileCountLimit);
+ retainedFileCountLimit,
+ logglyConfiguration);
//writes events to the file to support connection recovery
_sink = new RollingFileSink(
bufferBaseFilename + "-{Date}.json",
- new LogglyFormatter(formatProvider), //serializes as LogglyEvent
+ new LogglyFormatter(formatProvider, includes), //serializes as LogglyEvent
bufferFileSizeLimitBytes,
retainedFileCountLimit,
encoding);
diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/HttpLogShipper.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/HttpLogShipper.cs
index ef00ffe..01b82dc 100644
--- a/src/Serilog.Sinks.Loggly/Sinks/Loggly/HttpLogShipper.cs
+++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/HttpLogShipper.cs
@@ -43,7 +43,8 @@ class HttpLogShipper : IDisposable
readonly IFileSystemAdapter _fileSystemAdapter = new FileSystemAdapter();
readonly FileBufferDataProvider _bufferDataProvider;
readonly InvalidPayloadLogger _invalidPayloadLogger;
-
+ readonly LogglyConfigAdapter _adapter;
+
public HttpLogShipper(
string bufferBaseFilename,
int batchPostingLimit,
@@ -52,7 +53,8 @@ public HttpLogShipper(
LoggingLevelSwitch levelControlSwitch,
long? retainedInvalidPayloadsLimitBytes,
Encoding encoding,
- int? retainedFileCountLimit)
+ int? retainedFileCountLimit,
+ LogglyConfiguration logglyConfiguration)
{
_batchPostingLimit = batchPostingLimit;
_retainedFileCountLimit = retainedFileCountLimit;
@@ -60,6 +62,12 @@ public HttpLogShipper(
_controlledSwitch = new ControlledLevelSwitch(levelControlSwitch);
_connectionSchedule = new ExponentialBackoffConnectionSchedule(period);
+ if (logglyConfiguration != null)
+ {
+ _adapter = new LogglyConfigAdapter();
+ _adapter.ConfigureLogglyClient(logglyConfiguration);
+ }
+
_logglyClient = new LogglyClient(); //we'll use the loggly client instead of HTTP directly
//create necessary path elements
diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogEventConverter.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogEventConverter.cs
index 1fe2ea2..29c17e8 100644
--- a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogEventConverter.cs
+++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogEventConverter.cs
@@ -16,10 +16,12 @@ namespace Serilog.Sinks.Loggly
public class LogEventConverter
{
readonly IFormatProvider _formatProvider;
+ private readonly LogIncludes _includes;
- public LogEventConverter(IFormatProvider formatProvider = null)
+ public LogEventConverter(IFormatProvider formatProvider = null, LogIncludes includes = null)
{
_formatProvider = formatProvider;
+ _includes = includes ?? new LogIncludes();
}
public LogglyEvent CreateLogglyEvent(LogEvent logEvent)
@@ -28,9 +30,11 @@ public LogglyEvent CreateLogglyEvent(LogEvent logEvent)
var isHttpTransport = LogglyConfig.Instance.Transport.LogTransport == LogTransport.Https;
logglyEvent.Syslog.Level = ToSyslogLevel(logEvent);
-
-
- logglyEvent.Data.AddIfAbsent("Message", logEvent.RenderMessage(_formatProvider));
+
+ if (_includes.IncludeMessage)
+ {
+ logglyEvent.Data.AddIfAbsent("Message", logEvent.RenderMessage(_formatProvider));
+ }
foreach (var key in logEvent.Properties.Keys)
{
@@ -39,20 +43,20 @@ public LogglyEvent CreateLogglyEvent(LogEvent logEvent)
logglyEvent.Data.AddIfAbsent(key, simpleValue);
}
- if (isHttpTransport)
+ if (isHttpTransport && _includes.IncludeLevel)
{
// syslog will capture these via the header
logglyEvent.Data.AddIfAbsent("Level", logEvent.Level.ToString());
}
- if (logEvent.Exception != null)
+ if (logEvent.Exception != null && _includes.IncludeExceptionWhenExists)
{
logglyEvent.Data.AddIfAbsent("Exception", GetExceptionInfo(logEvent.Exception));
}
+
return logglyEvent;
}
-
static SyslogLevel ToSyslogLevel(LogEvent logEvent)
{
SyslogLevel syslogLevel;
diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogIncludes.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogIncludes.cs
new file mode 100644
index 0000000..288e4aa
--- /dev/null
+++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogIncludes.cs
@@ -0,0 +1,20 @@
+namespace Serilog.Sinks.Loggly
+{
+ public class LogIncludes
+ {
+ ///
+ /// Adds Serilog Level to all log events. Defaults to true.
+ ///
+ public bool IncludeLevel { get; set; } = true;
+
+ ///
+ /// Adds Serilog Message to all log events. Defaults to true.
+ ///
+ public bool IncludeMessage { get; set; } = true;
+
+ ///
+ /// Adds Serilog Exception to log events when an exception exists. Defaults to true.
+ ///
+ public bool IncludeExceptionWhenExists { get; set; } = true;
+ }
+}
\ No newline at end of file
diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyConfigAdapter.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyConfigAdapter.cs
new file mode 100644
index 0000000..ce4ea46
--- /dev/null
+++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyConfigAdapter.cs
@@ -0,0 +1,41 @@
+using System;
+using Loggly.Config;
+
+namespace Serilog.Sinks.Loggly
+{
+ class LogglyConfigAdapter
+ {
+ public void ConfigureLogglyClient(LogglyConfiguration logglyConfiguration)
+ {
+ var config = LogglyConfig.Instance;
+
+ if (!string.IsNullOrWhiteSpace(logglyConfiguration.ApplicationName))
+ config.ApplicationName = logglyConfiguration.ApplicationName;
+
+ if (string.IsNullOrWhiteSpace(logglyConfiguration.CustomerToken))
+ throw new ArgumentNullException("CustomerToken", "CustomerToken is required");
+
+ config.CustomerToken = logglyConfiguration.CustomerToken;
+ config.IsEnabled = logglyConfiguration.IsEnabled;
+
+ foreach (var tag in logglyConfiguration.Tags)
+ {
+ config.TagConfig.Tags.Add(tag);
+ }
+
+ config.ThrowExceptions = logglyConfiguration.ThrowExceptions;
+
+ if (logglyConfiguration.LogTransport != TransportProtocol.Https)
+ config.Transport.LogTransport = (LogTransport)Enum.Parse(typeof(LogTransport), logglyConfiguration.LogTransport.ToString());
+
+ if (!string.IsNullOrWhiteSpace(logglyConfiguration.EndpointHostName))
+ config.Transport.EndpointHostname = logglyConfiguration.EndpointHostName;
+
+ if (logglyConfiguration.EndpointPort > 0 && logglyConfiguration.EndpointPort <= ushort.MaxValue)
+ config.Transport.EndpointPort = logglyConfiguration.EndpointPort;
+
+ config.Transport.IsOmitTimestamp = logglyConfiguration.OmitTimestamp;
+ config.Transport = config.Transport.GetCoercedToValidConfig();
+ }
+ }
+}
diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyConfiguration.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyConfiguration.cs
new file mode 100644
index 0000000..ec1b4a5
--- /dev/null
+++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyConfiguration.cs
@@ -0,0 +1,57 @@
+using System.Collections.Generic;
+
+namespace Serilog.Sinks.Loggly
+{
+ public class LogglyConfiguration
+ {
+ public string ApplicationName { get; set; }
+ public string CustomerToken { get; set; }
+ public List Tags { get; set; }
+ public bool IsEnabled { get; set; } = true;
+ public bool ThrowExceptions { get; set; }
+
+ ///
+ /// Defaults to Https
+ ///
+ public TransportProtocol LogTransport { get; set; }
+
+ ///
+ /// Defaults to logs-01.loggly.com
+ ///
+ public string EndpointHostName { get; set; }
+
+ ///
+ /// Defaults to default port for selected LogTransport.
+ /// E.g. https is 443, SyslogTcp/-Udp is 514 and SyslogSecure is 6514.
+ ///
+ public int EndpointPort { get; set; }
+
+ ///
+ /// Defines if timestamp should automatically be added to the json body when using Https
+ ///
+ public bool OmitTimestamp { get; set; }
+ }
+
+ public enum TransportProtocol
+ {
+ ///
+ /// Https.
+ ///
+ Https,
+
+ ///
+ /// SyslogSecure.
+ ///
+ SyslogSecure,
+
+ ///
+ /// SyslogUdp.
+ ///
+ SyslogUdp,
+
+ ///
+ /// SyslogTcp.
+ ///
+ SyslogTcp,
+ }
+}
diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyFormatter.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyFormatter.cs
index 52dd9c9..903e327 100644
--- a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyFormatter.cs
+++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyFormatter.cs
@@ -28,11 +28,11 @@ class LogglyFormatter : ITextFormatter
readonly JsonSerializer _serializer = JsonSerializer.Create();
readonly LogEventConverter _converter;
- public LogglyFormatter(IFormatProvider formatProvider)
+ public LogglyFormatter(IFormatProvider formatProvider, LogIncludes includes)
{
//the converter should receive the format provider used, in order to
// handle dateTimes and dateTimeOffsets in a controlled manner
- _converter = new LogEventConverter(formatProvider);
+ _converter = new LogEventConverter(formatProvider, includes);
}
public void Format(LogEvent logEvent, TextWriter output)
{
diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglySink.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglySink.cs
index 6cefa6f..149fc1b 100644
--- a/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglySink.cs
+++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglySink.cs
@@ -29,6 +29,7 @@ public class LogglySink : PeriodicBatchingSink
{
readonly LogEventConverter _converter;
readonly LogglyClient _client;
+ readonly LogglyConfigAdapter _adapter;
///
/// A reasonable default for the number of events posted in
@@ -41,17 +42,34 @@ public class LogglySink : PeriodicBatchingSink
///
public static readonly TimeSpan DefaultPeriod = TimeSpan.FromSeconds(5);
+ ///
+ /// Construct a sink that saves logs to the specified storage account. Properties are being send as data and the level is used as tag.
+ ///
+ /// The maximum number of events to post in a single batch.
+ /// The time to wait between checking for event batches.
+ /// Supplies culture-specific formatting information, or null.
+ public LogglySink(IFormatProvider formatProvider, int batchSizeLimit, TimeSpan period) : this(formatProvider, batchSizeLimit, period, null, null)
+ {
+ }
+
///
/// Construct a sink that saves logs to the specified storage account. Properties are being send as data and the level is used as tag.
///
/// The maximum number of events to post in a single batch.
/// The time to wait between checking for event batches.
/// Supplies culture-specific formatting information, or null.
- public LogglySink(IFormatProvider formatProvider, int batchSizeLimit, TimeSpan period)
+ /// Used to configure underlying LogglyClient programmaticaly. Otherwise use app.Config.
+ /// Decides if the sink should include specific properties in the log message
+ public LogglySink(IFormatProvider formatProvider, int batchSizeLimit, TimeSpan period, LogglyConfiguration logglyConfig, LogIncludes includes)
: base (batchSizeLimit, period)
{
+ if (logglyConfig != null)
+ {
+ _adapter = new LogglyConfigAdapter();
+ _adapter.ConfigureLogglyClient(logglyConfig);
+ }
_client = new LogglyClient();
- _converter = new LogEventConverter(formatProvider);
+ _converter = new LogEventConverter(formatProvider, includes);
}
///
diff --git a/test/Serilog.Sinks.Loggly.Tests/ExceptionSerialization.cs b/test/Serilog.Sinks.Loggly.Tests/ExceptionSerialization.cs
index 7e20b6a..81391b5 100644
--- a/test/Serilog.Sinks.Loggly.Tests/ExceptionSerialization.cs
+++ b/test/Serilog.Sinks.Loggly.Tests/ExceptionSerialization.cs
@@ -17,7 +17,7 @@ public class ExceptionSerialization
public void ReturnFalseGivenValueOf1()
{
var writer = new StringWriter();
- var formatter = new LogglyFormatter(null);
+ var formatter = new LogglyFormatter(null, null);
try
{
ThrowException();
diff --git a/test/Serilog.Sinks.Loggly.Tests/Serilog.Sinks.Loggly.Tests.csproj b/test/Serilog.Sinks.Loggly.Tests/Serilog.Sinks.Loggly.Tests.csproj
index 1b67e3f..7cd58f0 100644
--- a/test/Serilog.Sinks.Loggly.Tests/Serilog.Sinks.Loggly.Tests.csproj
+++ b/test/Serilog.Sinks.Loggly.Tests/Serilog.Sinks.Loggly.Tests.csproj
@@ -32,10 +32,10 @@
-
-
-
-
+
+
+
+