Skip to content

Commit 8fcb0ce

Browse files
committed
fix the LogstashJsonFomatter trailing comma bug reported in #18
closes #18
1 parent 4ad9526 commit 8fcb0ce

13 files changed

+288
-176
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Collections.Generic;
2+
3+
namespace Serilog.Sinks.Network.Test
4+
{
5+
public interface DataReceiver
6+
{
7+
List<string> ReceivedData { get; }
8+
}
9+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Linq;
3+
using System.Net;
4+
using System.Threading.Tasks;
5+
using FluentAssertions;
6+
using Serilog.Core;
7+
using Serilog.Formatting;
8+
using Serilog.Sinks.Network.Formatters;
9+
using Xunit;
10+
11+
namespace Serilog.Sinks.Network.Test
12+
{
13+
public class JsonFormatter
14+
{
15+
private TCPServer _server;
16+
private Logger _logger;
17+
18+
19+
private void ConfigureTestLogger(ITextFormatter formatter = null)
20+
{
21+
var port = new Random().Next(50003) + 10000;
22+
_server = new TCPServer(IPAddress.Loopback, port);
23+
_server.Start();
24+
25+
_logger = new LoggerConfiguration()
26+
.WriteTo.TCPSink(IPAddress.Loopback, port, formatter)
27+
.CreateLogger();
28+
}
29+
30+
[Fact]
31+
public void MustNotLogATrailingCommaWhenThereAreNoProperties()
32+
{
33+
ConfigureTestLogger(new LogstashJsonFormatter());
34+
var arbitraryMessage = nameof(JsonFormatter) + "MustNotLogATrailingCommaWhenThereAreNoProperties" + Guid.NewGuid();
35+
36+
_logger.Information(arbitraryMessage);
37+
38+
var receivedData = ServerPoller.PollForReceivedData(_server);
39+
var loggedData = receivedData?.TrimEnd('\n');
40+
41+
var logMessageWithTrailingComma = $"\"message\":\"{arbitraryMessage}\",}}";
42+
loggedData.Should().NotEndWith(logMessageWithTrailingComma);
43+
}
44+
45+
[Fact]
46+
public void CanStillLogMessagesWithExceptions()
47+
{
48+
ConfigureTestLogger(new LogstashJsonFormatter());
49+
var arbitraryMessage = nameof(JsonFormatter) + "CanStillLogMessagesWithExceptions" + Guid.NewGuid();
50+
51+
_logger.Information(new Exception("exploding"), arbitraryMessage);
52+
53+
var receivedData = ServerPoller.PollForReceivedData(_server);
54+
55+
receivedData.Should().Contain("\"exception\":\"System.Exception: exploding\"}");
56+
}
57+
}
58+
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
22
<Project Sdk="Microsoft.NET.Sdk">
33
<PropertyGroup>
44
<TargetFramework>netcoreapp1.1</TargetFramework>
55
</PropertyGroup>
66
<ItemGroup>
7-
<PackageReference Include="xunit" Version="2.3.0-beta2-build3683"/>
8-
<PackageReference Include="Newtonsoft.Json" Version="10.0.3"/>
9-
<PackageReference Include="FluentAssertions" Version="4.19.3"/>
10-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0"/>
11-
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0"/>
12-
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0-beta2-build3683"/>
7+
<PackageReference Include="xunit" Version="2.3.0-beta2-build3683" />
8+
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
9+
<PackageReference Include="FluentAssertions" Version="4.19.3" />
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
11+
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
12+
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0-beta2-build3683" />
1313
</ItemGroup>
1414
<ItemGroup>
15-
<ProjectReference Include="..\Serilog.Sinks.Network\Serilog.Sinks.Network.csproj"/>
15+
<ProjectReference Include="..\Serilog.Sinks.Network\Serilog.Sinks.Network.csproj" />
1616
</ItemGroup>
1717
</Project>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Linq;
4+
5+
namespace Serilog.Sinks.Network.Test
6+
{
7+
internal static class ServerPoller
8+
{
9+
public static string PollForReceivedData(DataReceiver dataReceiver)
10+
{
11+
var stopwatch = Stopwatch.StartNew();
12+
string receivedData = null;
13+
while (string.IsNullOrEmpty(receivedData))
14+
{
15+
receivedData = dataReceiver.ReceivedData.SingleOrDefault();
16+
if (stopwatch.Elapsed > TimeSpan.FromSeconds(3))
17+
{
18+
throw new NoDataReceivedWithinThreeSeconds();
19+
}
20+
}
21+
22+
return receivedData;
23+
}
24+
}
25+
26+
internal class NoDataReceivedWithinThreeSeconds : Exception
27+
{
28+
}
29+
}

Serilog.Sinks.Network.Test/TCPTests.cs

Lines changed: 0 additions & 81 deletions
This file was deleted.

Serilog.Sinks.Network.Test/TcpServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Serilog.Sinks.Network.Test
99
{
10-
public class TCPServer
10+
public class TCPServer : DataReceiver
1111
{
1212
private bool _done;
1313
public List<string> ReceivedData { get; }

Serilog.Sinks.Network.Test/UDPTests.cs

Lines changed: 0 additions & 83 deletions
This file was deleted.

Serilog.Sinks.Network.Test/UdpListener.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace Serilog.Sinks.Network.Test
88
{
9-
public class UDPListener
9+
public class UDPListener : DataReceiver
1010
{
1111
private bool _done;
1212
public List<string> ReceivedData { get; }
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Dynamic;
5+
using System.Linq;
6+
using System.Net;
7+
using System.Net.Sockets;
8+
using System.Reflection;
9+
using System.Reflection.Metadata.Ecma335;
10+
using System.Threading;
11+
using System.Threading.Tasks;
12+
using FluentAssertions;
13+
using Newtonsoft.Json;
14+
using Serilog.Formatting;
15+
using Serilog.Formatting.Raw;
16+
using Serilog.Sinks.Network.Formatters;
17+
using Xunit;
18+
19+
namespace Serilog.Sinks.Network.Test
20+
{
21+
public class WhenLoggingViaTCP : IDisposable
22+
{
23+
private ILogger _logger;
24+
private TCPServer _server;
25+
26+
private void ConfigureTestLogger(ITextFormatter formatter = null)
27+
{
28+
var port = new Random().Next(50020) + 10000;
29+
_server = new TCPServer(IPAddress.Loopback, port);
30+
_server.Start();
31+
32+
_logger = new LoggerConfiguration()
33+
.WriteTo.TCPSink(IPAddress.Loopback, port, formatter)
34+
.CreateLogger();
35+
}
36+
37+
[Fact]
38+
public void CanLogHelloWorld_WithLogstashJsonFormatter()
39+
{
40+
ConfigureTestLogger(new LogstashJsonFormatter());
41+
var arbitraryMessage = nameof(WhenLoggingViaTCP) + "CanLogHelloWorld_WithLogstashJsonFormatter" + Guid.NewGuid();
42+
_logger.Information(arbitraryMessage);
43+
var receivedData = ServerPoller.PollForReceivedData(_server);
44+
receivedData.Should().Contain($"\"message\":\"{arbitraryMessage}\"");
45+
}
46+
47+
[Fact]
48+
public void CanLogHelloWorld_WithDefaultFormatter()
49+
{
50+
ConfigureTestLogger();
51+
var arbitraryMessage = nameof(WhenLoggingViaTCP) + "CanLogHelloWorld_WithDefaultFormatter" + Guid.NewGuid();
52+
_logger.Information(arbitraryMessage);
53+
54+
var receivedData = ServerPoller.PollForReceivedData(_server);
55+
56+
receivedData.Should().Contain($"\"message\":\"{arbitraryMessage}\"");
57+
}
58+
59+
[Fact]
60+
public void CanLogHelloWorld_WithRawFormatter()
61+
{
62+
ConfigureTestLogger(new RawFormatter());
63+
var arbitraryMessage = nameof(WhenLoggingViaTCP) + "CanLogHelloWorld_WithRawFormatter" + Guid.NewGuid();
64+
_logger.Information(arbitraryMessage);
65+
var receivedData = ServerPoller.PollForReceivedData(_server);
66+
receivedData.Should().Contain($"Information: \"{arbitraryMessage}\"");
67+
}
68+
69+
[Fact]
70+
public void CanLogWithProperties()
71+
{
72+
ConfigureTestLogger();
73+
_logger.Information("TCP Hello {location}", "world");
74+
var receivedData = ServerPoller.PollForReceivedData(_server);
75+
dynamic payload = JsonConvert.DeserializeObject<ExpandoObject>(receivedData);
76+
Assert.Equal("Information", payload.level);
77+
Assert.Equal("TCP Hello \"world\"", payload.message);
78+
Assert.Equal("world", payload.location);
79+
}
80+
81+
public void Dispose()
82+
{
83+
_server.Stop();
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)