diff --git a/src/Serilog.Sinks.Loggly/LoggerConfigurationLogglyExtensions.cs b/src/Serilog.Sinks.Loggly/LoggerConfigurationLogglyExtensions.cs index 58e060f..1905484 100644 --- a/src/Serilog.Sinks.Loggly/LoggerConfigurationLogglyExtensions.cs +++ b/src/Serilog.Sinks.Loggly/LoggerConfigurationLogglyExtensions.cs @@ -48,6 +48,7 @@ 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. /// in the buffer get sent to the remote Loggly instance /// Logger configuration, allowing configuration to continue. /// A required parameter is null. @@ -62,7 +63,8 @@ public static LoggerConfiguration Loggly( long? eventBodyLimitBytes = 1024 * 1024, LoggingLevelSwitch controlLevelSwitch = null, long? retainedInvalidPayloadsLimitBytes = null, - int? retainedFileCountLimit = null) + int? retainedFileCountLimit = null, + LogglyConfiguration logglyConfig = null) { if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration)); if (bufferFileSizeLimitBytes.HasValue && bufferFileSizeLimitBytes < 0) @@ -74,7 +76,7 @@ public static LoggerConfiguration Loggly( if (bufferBaseFilename == null) { - sink = new LogglySink(formatProvider, batchPostingLimit, defaultedPeriod); + sink = new LogglySink(formatProvider, batchPostingLimit, defaultedPeriod, logglyConfig); } else { @@ -87,7 +89,8 @@ public static LoggerConfiguration Loggly( controlLevelSwitch, retainedInvalidPayloadsLimitBytes, retainedFileCountLimit, - formatProvider); + formatProvider, + logglyConfig); } return loggerConfiguration.Sink(sink, restrictedToMinimumLevel); diff --git a/src/Serilog.Sinks.Loggly/Sinks/Loggly/DurableLogglySink.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/DurableLogglySink.cs index 4247754..9430582 100644 --- a/src/Serilog.Sinks.Loggly/Sinks/Loggly/DurableLogglySink.cs +++ b/src/Serilog.Sinks.Loggly/Sinks/Loggly/DurableLogglySink.cs @@ -34,8 +34,8 @@ public DurableLogglySink( LoggingLevelSwitch levelControlSwitch, long? retainedInvalidPayloadsLimitBytes, int? retainedFileCountLimit = null, - IFormatProvider formatProvider = null - ) + IFormatProvider formatProvider = null, + LogglyConfiguration logglyConfiguration = null) { if (bufferBaseFilename == null) throw new ArgumentNullException(nameof(bufferBaseFilename)); @@ -51,7 +51,8 @@ public DurableLogglySink( levelControlSwitch, retainedInvalidPayloadsLimitBytes, encoding, - retainedFileCountLimit); + retainedFileCountLimit, + logglyConfiguration); //writes events to the file to support connection recovery _sink = new RollingFileSink( 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/LogglyConfigAdapter.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglyConfigAdapter.cs new file mode 100644 index 0000000..ae1a29f --- /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/LogglySink.cs b/src/Serilog.Sinks.Loggly/Sinks/Loggly/LogglySink.cs index 6cefa6f..eb14aa6 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 @@ -47,9 +48,15 @@ public class LogglySink : PeriodicBatchingSink /// 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. + public LogglySink(IFormatProvider formatProvider, int batchSizeLimit, TimeSpan period, LogglyConfiguration logglyConfig) : base (batchSizeLimit, period) { + if (logglyConfig != null) + { + _adapter = new LogglyConfigAdapter(); + _adapter.ConfigureLogglyClient(logglyConfig); + } _client = new LogglyClient(); _converter = new LogEventConverter(formatProvider); } 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 @@ - - - - + + + +