Skip to content

Commit 13c89ef

Browse files
committed
Merge pull request #8 from danielwertheim/feature/injectable-formatter
Feature/injectable formatter
2 parents 712f8d0 + c895d83 commit 13c89ef

File tree

6 files changed

+290
-51
lines changed

6 files changed

+290
-51
lines changed

src/Serilog.Sinks.Splunk.FullNetFx/LoggerConfigurationSplunkExtensions.cs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Net;
1717
using Serilog.Configuration;
1818
using Serilog.Events;
19+
using Serilog.Formatting;
1920
using Serilog.Formatting.Display;
2021
using Serilog.Sinks.Splunk;
2122

@@ -26,6 +27,46 @@ namespace Serilog
2627
/// </summary>
2728
public static class LoggerConfigurationSplunkExtensions
2829
{
30+
/// <summary>
31+
/// Adds a sink that writes log events as to a Splunk instance via UDP.
32+
/// </summary>
33+
/// <param name="loggerConfiguration">The logger config</param>
34+
/// <param name="connectionInfo"></param>
35+
/// <param name="restrictedToMinimumLevel">The minimum log event level required in order to write an event to the sink.</param>
36+
/// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
37+
/// <param name="renderTemplate">If true, the message template is rendered</param>
38+
/// <returns></returns>
39+
public static LoggerConfiguration SplunkViaUdp(
40+
this LoggerSinkConfiguration loggerConfiguration,
41+
SplunkUdpSinkConnectionInfo connectionInfo,
42+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
43+
IFormatProvider formatProvider = null,
44+
bool renderTemplate = true)
45+
{
46+
var sink = new UdpSink(connectionInfo, formatProvider, renderTemplate);
47+
48+
return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
49+
}
50+
51+
/// <summary>
52+
/// Adds a sink that writes log events as to a Splunk instance via UDP.
53+
/// </summary>
54+
/// <param name="loggerConfiguration">The logger config</param>
55+
/// <param name="connectionInfo"></param>
56+
/// <param name="formatter">Custom formatter to use if you e.g. do not want to use the JsonFormatter.</param>
57+
/// <param name="restrictedToMinimumLevel">The minimum log event level required in order to write an event to the sink.</param>
58+
/// <returns></returns>
59+
public static LoggerConfiguration SplunkViaUdp(
60+
this LoggerSinkConfiguration loggerConfiguration,
61+
SplunkUdpSinkConnectionInfo connectionInfo,
62+
ITextFormatter formatter,
63+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
64+
{
65+
var sink = new UdpSink(connectionInfo, formatter);
66+
67+
return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
68+
}
69+
2970
/// <summary>
3071
/// Adds a sink that writes log events as to a Splunk instance via UDP.
3172
/// </summary>
@@ -37,6 +78,7 @@ public static class LoggerConfigurationSplunkExtensions
3778
/// <param name="renderTemplate">If ture, the message template will be rendered</param>
3879
/// <returns></returns>
3980
/// <remarks>TODO: Add link to splunk configuration and wiki</remarks>
81+
[Obsolete("Use the overload accepting a connection info object instead. This overload will be removed.", false)]
4082
public static LoggerConfiguration SplunkViaUdp(
4183
this LoggerSinkConfiguration loggerConfiguration,
4284
string host,
@@ -62,6 +104,7 @@ public static LoggerConfiguration SplunkViaUdp(
62104
/// <param name="renderTemplate">If ture, the message template is rendered</param>
63105
/// <returns>The logger configuration</returns>
64106
/// <remarks>TODO: Add link to splunk configuration and wiki</remarks>
107+
[Obsolete("Use the overload accepting a connection info object instead. This overload will be removed.", false)]
65108
public static LoggerConfiguration SplunkViaUdp(
66109
this LoggerSinkConfiguration loggerConfiguration,
67110
IPAddress hostAddresss,
@@ -75,6 +118,46 @@ public static LoggerConfiguration SplunkViaUdp(
75118
return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
76119
}
77120

121+
/// <summary>
122+
/// Adds a sink that writes log events as to a Splunk instance via TCP.
123+
/// </summary>
124+
/// <param name="loggerConfiguration">The logger config</param>
125+
/// <param name="connectionInfo"></param>
126+
/// <param name="restrictedToMinimumLevel">The minimum log event level required in order to write an event to the sink.</param>
127+
/// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
128+
/// <param name="renderTemplate">If true, the message template is rendered</param>
129+
/// <returns></returns>
130+
public static LoggerConfiguration SplunkViaTcp(
131+
this LoggerSinkConfiguration loggerConfiguration,
132+
SplunkTcpSinkConnectionInfo connectionInfo,
133+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
134+
IFormatProvider formatProvider = null,
135+
bool renderTemplate = true)
136+
{
137+
var sink = new TcpSink(connectionInfo, formatProvider, renderTemplate);
138+
139+
return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
140+
}
141+
142+
/// <summary>
143+
/// Adds a sink that writes log events as to a Splunk instance via TCP.
144+
/// </summary>
145+
/// <param name="loggerConfiguration">The logger config</param>
146+
/// <param name="connectionInfo"></param>
147+
/// <param name="formatter">Custom formatter to use if you e.g. do not want to use the JsonFormatter.</param>
148+
/// <param name="restrictedToMinimumLevel">The minimum log event level required in order to write an event to the sink.</param>
149+
/// <returns></returns>
150+
public static LoggerConfiguration SplunkViaTcp(
151+
this LoggerSinkConfiguration loggerConfiguration,
152+
SplunkTcpSinkConnectionInfo connectionInfo,
153+
ITextFormatter formatter,
154+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
155+
{
156+
var sink = new TcpSink(connectionInfo, formatter);
157+
158+
return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
159+
}
160+
78161
/// <summary>
79162
/// Adds a sink that writes log events as to a Splunk instance via TCP.
80163
/// </summary>
@@ -86,6 +169,7 @@ public static LoggerConfiguration SplunkViaUdp(
86169
/// <param name="renderTemplate">If true, the message template is rendered</param>
87170
/// <returns></returns>
88171
/// <remarks>TODO: Add link to splunk configuration and wiki</remarks>
172+
[Obsolete("Use the overload accepting a connection info object instead. This overload will be removed.", false)]
89173
public static LoggerConfiguration SplunkViaTcp(
90174
this LoggerSinkConfiguration loggerConfiguration,
91175
IPAddress hostAddresss,
@@ -110,6 +194,7 @@ public static LoggerConfiguration SplunkViaTcp(
110194
/// <param name="renderTemplate">If ture, the message template is rendered</param>
111195
/// <returns></returns>
112196
/// <remarks>TODO: Add link to splunk configuration and wiki</remarks>
197+
[Obsolete("Use the overload accepting a connection info object instead. This overload will be removed.", false)]
113198
public static LoggerConfiguration SplunkViaTcp(
114199
this LoggerSinkConfiguration loggerConfiguration,
115200
string host,
@@ -122,6 +207,5 @@ public static LoggerConfiguration SplunkViaTcp(
122207

123208
return loggerConfiguration.Sink(sink, restrictedToMinimumLevel);
124209
}
125-
126210
}
127211
}

src/Serilog.Sinks.Splunk.FullNetFx/Serilog.Sinks.Splunk.FullNetFx.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@
8585
<Link>Properties\CommonAssemblyInfo.cs</Link>
8686
</Compile>
8787
<Compile Include="LoggerConfigurationSplunkExtensions.cs" />
88+
<Compile Include="Sinks\Splunk\SplunkTcpSinkConnectionInfo.cs" />
89+
<Compile Include="Sinks\Splunk\SplunkUdpSinkConnectionInfo.cs" />
8890
<Compile Include="Sinks\Splunk\TcpSink.cs" />
8991
<Compile Include="Sinks\Splunk\UdpSink.cs" />
9092
</ItemGroup>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System.Net;
2+
3+
namespace Serilog.Sinks.Splunk
4+
{
5+
/// <summary>
6+
/// Defines connection info used to connect against Splunk
7+
/// using TCP.
8+
/// </summary>
9+
public class SplunkTcpSinkConnectionInfo
10+
{
11+
/// <summary>
12+
/// Default size of the socket writer queue.
13+
/// </summary>
14+
public const int DefaultMaxQueueSize = 10000;
15+
16+
/// <summary>
17+
/// Splunk host.
18+
/// </summary>
19+
public IPAddress Host { get; }
20+
21+
/// <summary>
22+
/// Splunk port.
23+
/// </summary>
24+
public int Port { get; }
25+
26+
/// <summary>
27+
/// Max Queue size for the TCP socket writer.
28+
/// See <see cref="DefaultMaxQueueSize"/> for default value (10000).
29+
/// </summary>
30+
public int MaxQueueSize { get; set; } = DefaultMaxQueueSize;
31+
32+
/// <summary>
33+
/// Creates an instance of <see cref="SplunkTcpSinkConnectionInfo"/> used
34+
/// for defining connection info for connecting using TCP against Splunk.
35+
/// </summary>
36+
/// <param name="host">Splunk host.</param>
37+
/// <param name="port">Splunk TCP port.</param>
38+
public SplunkTcpSinkConnectionInfo(string host, int port) : this(IPAddress.Parse(host), port){ }
39+
40+
/// <summary>
41+
/// Creates an instance of <see cref="SplunkTcpSinkConnectionInfo"/> used
42+
/// for defining connection info for connecting using TCP against Splunk.
43+
/// </summary>
44+
/// <param name="host">Splunk host.</param>
45+
/// <param name="port">Splunk TCP port.</param>
46+
public SplunkTcpSinkConnectionInfo(IPAddress host, int port)
47+
{
48+
Host = host;
49+
Port = port;
50+
}
51+
}
52+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System.Net;
2+
3+
namespace Serilog.Sinks.Splunk
4+
{
5+
/// <summary>
6+
/// Defines connection info used to connect against Splunk
7+
/// using UDP.
8+
/// </summary>
9+
public class SplunkUdpSinkConnectionInfo
10+
{
11+
/// <summary>
12+
/// Splunk host.
13+
/// </summary>
14+
public IPAddress Host { get; }
15+
16+
/// <summary>
17+
/// Splunk port.
18+
/// </summary>
19+
public int Port { get; }
20+
21+
/// <summary>
22+
/// Creates an instance of <see cref="SplunkUdpSinkConnectionInfo"/> used
23+
/// for defining connection info for connecting using UDP against Splunk.
24+
/// </summary>
25+
/// <param name="host">Splunk host.</param>
26+
/// <param name="port">Splunk UDP port.</param>
27+
public SplunkUdpSinkConnectionInfo(string host, int port) : this(IPAddress.Parse(host), port){ }
28+
29+
/// <summary>
30+
/// Creates an instance of <see cref="SplunkUdpSinkConnectionInfo"/> used
31+
/// for defining connection info for connecting using UDP against Splunk.
32+
/// </summary>
33+
/// <param name="host">Splunk host.</param>
34+
/// <param name="port">Splunk UDP port.</param>
35+
public SplunkUdpSinkConnectionInfo(IPAddress host, int port)
36+
{
37+
Host = host;
38+
Port = port;
39+
}
40+
}
41+
}

src/Serilog.Sinks.Splunk.FullNetFx/Sinks/Splunk/TcpSink.cs

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
using System;
1616
using System.IO;
1717
using System.Net;
18-
using System.Net.Sockets;
1918
using System.Text;
2019
using Serilog.Core;
2120
using Serilog.Events;
22-
using Serilog.Formatting.Json;
21+
using Serilog.Formatting;
2322
using Splunk.Logging;
2423

2524
namespace Serilog.Sinks.Splunk
@@ -29,68 +28,97 @@ namespace Serilog.Sinks.Splunk
2928
/// </summary>
3029
public class TcpSink : ILogEventSink, IDisposable
3130
{
32-
readonly JsonFormatter _jsonFormatter;
31+
readonly ITextFormatter _formatter;
3332
private TcpSocketWriter _writer;
3433

3534
/// <summary>
36-
/// Creates an instance of the Splunk TCP Sink
35+
/// Creates an instance of the Splunk TCP Sink.
3736
/// </summary>
38-
/// <param name="hostAddress">The Splunk Host</param>
39-
/// <param name="port">The UDP port configured in Splunk</param>
37+
/// <param name="connectionInfo">Connection info used for connecting against Splunk.</param>
4038
/// <param name="formatProvider">Optional format provider</param>
4139
/// <param name="renderTemplate">If true, the message template will be rendered</param>
42-
4340
public TcpSink(
44-
IPAddress hostAddress,
45-
int port,
41+
SplunkTcpSinkConnectionInfo connectionInfo,
4642
IFormatProvider formatProvider = null,
4743
bool renderTemplate = true)
4844
{
49-
var reconnectionPolicy = new ExponentialBackoffTcpReconnectionPolicy();
50-
51-
_writer = new TcpSocketWriter(hostAddress, port, reconnectionPolicy, 10000);
45+
_writer = CreateSocketWriter(connectionInfo);
46+
_formatter = CreateDefaultFormatter(formatProvider, renderTemplate);
47+
}
5248

53-
_jsonFormatter = new SplunkJsonFormatter(renderMessage: true, formatProvider: formatProvider, renderTemplate: renderTemplate);
49+
/// <summary>
50+
/// Creates an instance of the Splunk TCP Sink.
51+
/// </summary>
52+
/// <param name="connectionInfo">Connection info used for connecting against Splunk.</param>
53+
/// <param name="formatter">Custom formatter to use if you e.g. do not want to use the JsonFormatter.</param>
54+
public TcpSink(
55+
SplunkTcpSinkConnectionInfo connectionInfo,
56+
ITextFormatter formatter)
57+
{
58+
_writer = CreateSocketWriter(connectionInfo);
59+
_formatter = formatter;
5460
}
5561

5662
/// <summary>
5763
/// Creates an instance of the Splunk TCP Sink
5864
/// </summary>
5965
/// <param name="host">The Splunk Host</param>
60-
/// <param name="port">The UDP port configured in Splunk</param>
66+
/// <param name="port">The TCP port configured in Splunk</param>
6167
/// <param name="formatProvider">Optional format provider</param>
6268
/// <param name="renderTemplate">If true, the message template will be rendered</param>
69+
[Obsolete("Use the overload accepting a connection info object instead. This overload will be removed.", false)]
6370
public TcpSink(
6471
string host,
6572
int port,
6673
IFormatProvider formatProvider = null,
67-
bool renderTemplate = true)
74+
bool renderTemplate = true) : this(new SplunkTcpSinkConnectionInfo(host, port), formatProvider, renderTemplate)
75+
{
76+
}
77+
78+
/// <summary>
79+
/// Creates an instance of the Splunk TCP Sink
80+
/// </summary>
81+
/// <param name="hostAddress">The Splunk Host</param>
82+
/// <param name="port">The TCP port configured in Splunk</param>
83+
/// <param name="formatProvider">Optional format provider</param>
84+
/// <param name="renderTemplate">If true, the message template will be rendered</param>
85+
[Obsolete("Use the overload accepting a connection info object instead. This overload will be removed.", false)]
86+
public TcpSink(
87+
IPAddress hostAddress,
88+
int port,
89+
IFormatProvider formatProvider = null,
90+
bool renderTemplate = true) : this(new SplunkTcpSinkConnectionInfo(hostAddress, port), formatProvider, renderTemplate)
91+
{
92+
}
93+
94+
private static TcpSocketWriter CreateSocketWriter(SplunkTcpSinkConnectionInfo connectionInfo)
6895
{
6996
var reconnectionPolicy = new ExponentialBackoffTcpReconnectionPolicy();
70-
var ipAddress = IPAddress.Parse(host);
7197

72-
_writer = new TcpSocketWriter(ipAddress, port, reconnectionPolicy, 10000);
98+
return new TcpSocketWriter(connectionInfo.Host, connectionInfo.Port, reconnectionPolicy, connectionInfo.MaxQueueSize);
99+
}
73100

74-
_jsonFormatter = new SplunkJsonFormatter(renderMessage: true, formatProvider: formatProvider, renderTemplate: renderTemplate);
101+
private static SplunkJsonFormatter CreateDefaultFormatter(IFormatProvider formatProvider, bool renderTemplate)
102+
{
103+
return new SplunkJsonFormatter(renderMessage: true, formatProvider: formatProvider, renderTemplate: renderTemplate);
75104
}
76105

77106
/// <inheritdoc/>
78107
public void Emit(LogEvent logEvent)
79108
{
80-
var sw = new StringWriter();
109+
var sb = new StringBuilder();
81110

82-
_jsonFormatter.Format(logEvent, sw);
111+
using (var sw = new StringWriter(sb))
112+
_formatter.Format(logEvent, sw);
83113

84-
var message = sw.ToString();
85-
86-
_writer.Enqueue(message);
114+
_writer.Enqueue(sb.ToString());
87115
}
88116

89117
/// <inheritdoc/>
90118
public void Dispose()
91119
{
92-
_writer.Dispose();
120+
_writer?.Dispose();
121+
_writer = null;
93122
}
94123
}
95-
}
96-
124+
}

0 commit comments

Comments
 (0)