diff --git a/.travis.yml b/.travis.yml
index ba8d764..79d1441 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@ matrix:
- os: linux # Ubuntu 14.04
dist: trusty
sudo: required
- dotnet: 1.0.4
+ dotnet: 2.0.0
script:
- ./build.sh
\ No newline at end of file
diff --git a/CHANGES.md b/CHANGES.md
index 2d917bb..9434222 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,20 +1,33 @@
-##2.2.0
-- [#47] Tooling updates to VS2017
+## 2.4.0
+- [#62](https://github.com/serilog/serilog-sinks-splunk/issues/62) Default fields added by serilog to splunk
+- [#63](https://github.com/serilog/serilog-sinks-splunk/issues/63) Possible thread leak when ILogger instances are disposed
-##2.1.2
-- [#43](https://github.com/serilog/serilog-sinks-splunk/pull/43) - Extend sink & static configuration to allow for custom JSON formatter.
+## 2.3.0
+- [#59](https://github.com/serilog/serilog-sinks-splunk/issues/59) Added ability to use custom fields with HEC. See http://dev.splunk.com/view/event-collector/SP-CAAAFB6.
-##2.1.1
+## 2.2.1
+- [#47](https://github.com/serilog/serilog-sinks-splunk/issues/47) Tooling updates to VS2017
+- [#48](https://github.com/serilog/serilog-sinks-splunk/issues/48)
+- [#49](https://github.com/serilog/serilog-sinks-splunk/issues/49)
+- [#52](https://github.com/serilog/serilog-sinks-splunk/issues/52)
+
+## 2.1.3
+- [#45](https://github.com/serilog/serilog-sinks-splunk/issues/45) - Deadlock fix on UI thread.
+
+## 2.1.2
+- [#43](https://github.com/serilog/serilog-sinks-splunk/issues/43) - Extend sink & static configuration to allow for custom JSON formatter.
+
+## 2.1.1
- [#38](https://github.com/serilog/serilog-sinks-splunk/issues/38) - Fix for HttpEventlogCollector and sourceType
- Clean up of sample app using examples of host, sourcetype, source override
-##2.1.0
+## 2.1.0
* Change to use a standalone formatter
-* Resolves #32 & #26 by exposing `HttpMessageHandler`
-* Resolves #30 by ignoring OSX build and including tests in `build.sh` for TravisCI
+* Resolves - [#32](https://github.com/serilog/serilog-sinks-splunk/issues/32) & - [#26](https://github.com/serilog/serilog-sinks-splunk/issues/26) by exposing `HttpMessageHandler`
+* Resolves - [#30](https://github.com/serilog/serilog-sinks-splunk/issues/30) by ignoring OSX build and including tests in `build.sh` for TravisCI
-##2.0
+## 2.0
- Support for DotNet Core
- Event Collector fluent interface changed to `.WriteTo.EventCollector`
- Event Collector Sink targeting core
@@ -22,22 +35,22 @@
- Updated Event Collector HTTP Client to add URI endpoint to host: "services/collector" if not included.
- Event Collector changed to use epoch time [#15](https://github.com/serilog/serilog-sinks-splunk/pull/15)
-##1.8
+## 1.8
- Event Collector changed to use epoch time [#15](https://github.com/serilog/serilog-sinks-splunk/pull/15)
-##1.7
+## 1.7
- Better support for formatting including [#578](https://github.com/serilog/serilog/issues/578)
- Cleanup on Event Collector
-##1.6.50
+## 1.6.50
- Streaming support for Event Collector
-##1.6.42
+## 1.6.42
- Added support for Splunk 6.3 Event Collector
- Deprecated Splunk HTTP Sink using Management Port/API
-##1.5.30
+## 1.5.30
- Added switch for template rendering
- ##1.5.0
+## 1.5.0
- Moved the sink from its [original location](https://github.com/serilog/serilog)
diff --git a/build.sh b/build.sh
index 69a9e8d..9c61ab2 100755
--- a/build.sh
+++ b/build.sh
@@ -5,10 +5,11 @@ dotnet restore
for path in src/**/*.csproj; do
dotnet build -f netstandard1.1 -c Release ${path}
+ dotnet build -f netstandard1.3 -c Release ${path}
done
for path in test/*.Tests/*.csproj; do
- dotnet test -f netcoreapp1.0 -c Release ${path}
+ dotnet test -f netcoreapp2.0 -c Release ${path}
done
-dotnet build -f netcoreapp1.0 -c Release sample/Sample/Sample.csproj
\ No newline at end of file
+dotnet build -f netcoreapp2.0 -c Release sample/Sample/Sample.csproj
\ No newline at end of file
diff --git a/sample/Sample/Program.cs b/sample/Sample/Program.cs
index fff3420..f07930c 100644
--- a/sample/Sample/Program.cs
+++ b/sample/Sample/Program.cs
@@ -47,7 +47,7 @@ private static void WithCompactSplunkFormatter(int eventsToCreate)
// Vanilla Test with full uri specified
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
SPLUNK_FULL_ENDPOINT,
Program.EventCollectorToken, new CompactSplunkJsonFormatter())
@@ -70,7 +70,7 @@ public static void OverridingSource(int eventsToCreate)
// Override Source
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
SPLUNK_ENDPOINT,
Program.EventCollectorToken,
@@ -92,7 +92,7 @@ public static void OverridingSourceType(int eventsToCreate)
// Override Source
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
SPLUNK_ENDPOINT,
Program.EventCollectorToken,
@@ -114,7 +114,7 @@ public static void OverridingHost(int eventsToCreate)
// Override Host
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
SPLUNK_ENDPOINT,
Program.EventCollectorToken,
@@ -136,7 +136,7 @@ public static void UsingFullUri(int eventsToCreate)
// Vanilla Test with full uri specified
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
SPLUNK_FULL_ENDPOINT,
Program.EventCollectorToken)
@@ -158,7 +158,7 @@ public static void UsingHostOnly(int eventsToCreate)
// Vanilla Tests just host
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
SPLUNK_ENDPOINT,
Program.EventCollectorToken)
@@ -179,7 +179,7 @@ public static void WithNoTemplate(int eventsToCreate)
// No Template
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
SPLUNK_ENDPOINT,
Program.EventCollectorToken,
@@ -201,7 +201,7 @@ public static void UsingSSL(int eventsToCreate)
// SSL
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
SPLUNK_ENDPOINT,
Program.EventCollectorToken)
@@ -228,7 +228,7 @@ public static void AddCustomFields(int eventsToCreate)
// Override Source
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
- .WriteTo.LiterateConsole()
+ .WriteTo.Console()
.WriteTo.EventCollector(
splunkHost: SPLUNK_ENDPOINT
, eventCollectorToken: SPLUNK_HEC_TOKEN
diff --git a/sample/Sample/Sample.csproj b/sample/Sample/Sample.csproj
index ea50423..541aaa2 100644
--- a/sample/Sample/Sample.csproj
+++ b/sample/Sample/Sample.csproj
@@ -2,12 +2,12 @@
Exe
- netcoreapp1.0
+ netcoreapp2.0
-
-
+
+
diff --git a/src/Serilog.Sinks.Splunk/Serilog.Sinks.Splunk.csproj b/src/Serilog.Sinks.Splunk/Serilog.Sinks.Splunk.csproj
index a73a5aa..322d1c9 100644
--- a/src/Serilog.Sinks.Splunk/Serilog.Sinks.Splunk.csproj
+++ b/src/Serilog.Sinks.Splunk/Serilog.Sinks.Splunk.csproj
@@ -2,9 +2,9 @@
The Splunk Sink for Serilog
- 2.3.0
+ 2.3.1
Matthew Erbs, Serilog Contributors
- net45;netstandard1.1
+ net45;netstandard1.1;netstandard1.3
true
Serilog.Sinks.Splunk
Serilog.Sinks.Splunk
@@ -27,15 +27,17 @@
-
-
-
-
-
+
+
+
+
+
-
+
+
+
diff --git a/src/Serilog.Sinks.Splunk/Sinks/Splunk/EventCollectorSink.cs b/src/Serilog.Sinks.Splunk/Sinks/Splunk/EventCollectorSink.cs
index 647fe6b..cdfe05f 100644
--- a/src/Serilog.Sinks.Splunk/Sinks/Splunk/EventCollectorSink.cs
+++ b/src/Serilog.Sinks.Splunk/Sinks/Splunk/EventCollectorSink.cs
@@ -13,33 +13,30 @@
// limitations under the License.
using System;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
-using System.Threading;
using System.Threading.Tasks;
-using Serilog.Core;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Formatting;
+using Serilog.Sinks.PeriodicBatching;
namespace Serilog.Sinks.Splunk
{
///
/// A sink to log to the Event Collector available in Splunk 6.3
///
- public class EventCollectorSink : ILogEventSink, IDisposable
+ public class EventCollectorSink : PeriodicBatchingSink
{
private readonly string _splunkHost;
private readonly string _uriPath;
- private readonly int _batchSizeLimitLimit;
private readonly ITextFormatter _jsonFormatter;
- private readonly ConcurrentQueue _queue;
private readonly EventCollectorClient _httpClient;
+
///
/// Taken from Splunk.Logging.Common
///
@@ -115,6 +112,7 @@ public EventCollectorSink(
messageHandler)
{
}
+
///
/// Creates a new instance of the sink with Customfields
///
@@ -152,12 +150,11 @@ public EventCollectorSink(
uriPath,
batchIntervalInSeconds,
batchSizeLimit,
- new SplunkJsonFormatter(renderTemplate, formatProvider, source, sourceType, host, index,fields),
+ new SplunkJsonFormatter(renderTemplate, formatProvider, source, sourceType, host, index, fields),
messageHandler)
{
}
-
///
/// Creates a new instance of the sink
///
@@ -176,67 +173,25 @@ public EventCollectorSink(
int batchSizeLimit,
ITextFormatter jsonFormatter,
HttpMessageHandler messageHandler = null)
+ : base(batchSizeLimit, TimeSpan.FromSeconds(batchIntervalInSeconds))
{
_uriPath = uriPath;
_splunkHost = splunkHost;
- _queue = new ConcurrentQueue();
_jsonFormatter = jsonFormatter;
- _batchSizeLimitLimit = batchSizeLimit;
- var batchInterval = TimeSpan.FromSeconds(batchIntervalInSeconds);
_httpClient = messageHandler != null
? new EventCollectorClient(eventCollectorToken, messageHandler)
: new EventCollectorClient(eventCollectorToken);
-
- var cancellationToken = new CancellationToken();
-
- RepeatAction.OnInterval(
- batchInterval,
- async () => await ProcessQueue(),
- cancellationToken);
}
///
- /// Emits the provided log event from a sink
+ /// Emit a batch of log events, running asynchronously.
///
- ///
- public void Emit(LogEvent logEvent)
- {
- if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
-
- _queue.Enqueue(logEvent);
- }
-
- private async Task ProcessQueue()
- {
- try
- {
- do
- {
- var count = 0;
- var events = new Queue();
- LogEvent next;
-
- while (count < _batchSizeLimitLimit && _queue.TryDequeue(out next))
- {
- count++;
- events.Enqueue(next);
- }
-
- if (events.Count == 0)
- return;
-
- await Send(events);
-
- } while (true);
- }
- catch (Exception ex)
- {
- SelfLog.WriteLine("Exception while emitting batch from {0}: {1}", this, ex);
- }
- }
-
- private async Task Send(IEnumerable events)
+ /// The events to emit.
+ ///
+ /// Override either or , not both.
+ ///
+ protected override async Task EmitBatchAsync(IEnumerable events)
{
var allEvents = new StringWriter();
@@ -248,56 +203,22 @@ private async Task Send(IEnumerable events)
var request = new EventCollectorRequest(_splunkHost, allEvents.ToString(), _uriPath);
var response = await _httpClient.SendAsync(request).ConfigureAwait(false);
- if (response.IsSuccessStatusCode)
- {
- //Do Nothing?
- }
- else
+ if (!response.IsSuccessStatusCode)
{
//Application Errors sent via HTTP Event Collector
if (HttpEventCollectorApplicationErrors.Any(x => x == response.StatusCode))
{
+ // By not throwing an exception here the PeriodicBatchingSink will assume the batch succeeded and not send it again.
SelfLog.WriteLine(
"A status code of {0} was received when attempting to send to {1}. The event has been discarded and will not be placed back in the queue.",
response.StatusCode.ToString(), _splunkHost);
}
else
{
- //Put the item back in the queue & retry on next go
- SelfLog.WriteLine(
- "A status code of {0} was received when attempting to send to {1}. The event has been placed back in the queue",
- response.StatusCode.ToString(), _splunkHost);
-
- foreach (var logEvent in events)
- {
- _queue.Enqueue(logEvent);
- }
+ // EnsureSuccessStatusCode will throw an exception and the PeriodicBatchingSink will catch/log the exception and retry the batch.
+ response.EnsureSuccessStatusCode();
}
}
}
-
- ///
- public void Dispose()
- {
- Dispose(true);
- }
-
- ///
- protected virtual void Dispose(bool disposing)
- {
- if (!disposing) return;
-
- var remainingEvents = new List();
-
- while (!_queue.IsEmpty)
- {
- LogEvent next;
- _queue.TryDequeue(out next);
- remainingEvents.Add(next);
- }
-
- Send(remainingEvents).Wait();
- _httpClient.Dispose();
- }
}
}
diff --git a/src/Serilog.Sinks.Splunk/Sinks/Splunk/RepeatAction.cs b/src/Serilog.Sinks.Splunk/Sinks/Splunk/RepeatAction.cs
deleted file mode 100644
index ee39d6f..0000000
--- a/src/Serilog.Sinks.Splunk/Sinks/Splunk/RepeatAction.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 Serilog Contributors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Serilog.Sinks.Splunk
-{
- internal static class RepeatAction
- {
- public static Task OnInterval(TimeSpan pollInterval, Action action, CancellationToken token,
- TaskCreationOptions taskCreationOptions, TaskScheduler taskScheduler)
- {
- return Task.Factory.StartNew(() =>
- {
- for (;;)
- {
- if (token.WaitCancellationRequested(pollInterval))
- break;
- action();
- }
- }, token, taskCreationOptions, taskScheduler);
- }
-
- public static Task OnInterval(TimeSpan pollInterval, Action action, CancellationToken token)
- {
- return OnInterval(pollInterval, action, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
- }
-
- public static bool WaitCancellationRequested(this CancellationToken token, TimeSpan timeout)
- {
- return token.WaitHandle.WaitOne(timeout);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Serilog.Sinks.Splunk/Sinks/Splunk/SplunkJsonFormatter.cs b/src/Serilog.Sinks.Splunk/Sinks/Splunk/SplunkJsonFormatter.cs
index cc6b64f..55b197e 100644
--- a/src/Serilog.Sinks.Splunk/Sinks/Splunk/SplunkJsonFormatter.cs
+++ b/src/Serilog.Sinks.Splunk/Sinks/Splunk/SplunkJsonFormatter.cs
@@ -22,6 +22,7 @@
namespace Serilog.Sinks.Splunk
{
+ ///
///
/// Renders log events into a default JSON format for consumption by Splunk.
///
@@ -29,12 +30,13 @@ public class SplunkJsonFormatter : ITextFormatter
{
static readonly JsonValueFormatter ValueFormatter = new JsonValueFormatter();
- readonly bool _renderTemplate;
- readonly IFormatProvider _formatProvider;
- readonly string _suffix;
+ private readonly bool _renderTemplate;
+ private readonly IFormatProvider _formatProvider;
+ private readonly string _suffix;
+ ///
///
- /// Construct a .
+ /// Construct a .
///
/// Supplies culture-specific formatting information, or null.
/// If true, the template used will be rendered and written to the output as a property named MessageTemplate
diff --git a/test/Serilog.Sinks.Splunk.Tests/Serilog.Sinks.Splunk.Tests.csproj b/test/Serilog.Sinks.Splunk.Tests/Serilog.Sinks.Splunk.Tests.csproj
index 93f3e28..40da3da 100644
--- a/test/Serilog.Sinks.Splunk.Tests/Serilog.Sinks.Splunk.Tests.csproj
+++ b/test/Serilog.Sinks.Splunk.Tests/Serilog.Sinks.Splunk.Tests.csproj
@@ -1,7 +1,7 @@
- net452;netcoreapp1.0
+ net452;netcoreapp2.0
Serilog.Sinks.Splunk.Tests
Serilog.Sinks.Splunk.Tests
true
@@ -25,8 +25,12 @@
-
-
+
+
+
+
+
+