Skip to content

Commit b534aab

Browse files
authored
Merge branch 'master' into inner-socket-exception
2 parents 800452e + e35b060 commit b534aab

File tree

14 files changed

+445
-306
lines changed

14 files changed

+445
-306
lines changed

.github/workflows/release.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
env:
9+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
10+
DOTNET_CLI_TELEMETRY_OPTOUT: true
11+
12+
jobs:
13+
release:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
- name: Setup .NET
21+
uses: actions/setup-dotnet@v4
22+
23+
- name: Extract version from tag
24+
id: extract_version
25+
run: echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"
26+
27+
- name: Restore dependencies
28+
run: dotnet restore
29+
30+
- name: Build solution
31+
run: dotnet build --configuration Release --no-restore
32+
33+
- name: Package
34+
run: dotnet pack ./Serilog.Sinks.Network/Serilog.Sinks.Network.csproj -c Release -o ./artifacts /p:Version=${{ steps.extract_version.outputs.version }}
35+
36+
- name: Publish To NuGet
37+
env:
38+
NUGET_KEY: ${{ secrets.NUGET_KEY }}
39+
run: dotnet nuget push ./artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }}

PingPonger/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public static int Main(string[] args)
6868
}
6969
if (options.TCP)
7070
{
71-
logConfig.WriteTo.TCPSink(options.Url, options.Port, new LogstashJsonFormatter());
71+
logConfig.WriteTo.TCPSink(options.Url, options.Port, null, null, new LogstashJsonFormatter());
7272
}
7373
}
7474
else if (options.IP.Length > 0)
@@ -86,7 +86,7 @@ public static int Main(string[] args)
8686
}
8787
if (options.TCP)
8888
{
89-
logConfig.WriteTo.TCPSink(ipAddress, options.Port, new LogstashJsonFormatter());
89+
logConfig.WriteTo.TCPSink(ipAddress, options.Port,null,null, new LogstashJsonFormatter());
9090
}
9191
}
9292
else

Serilog.Sinks.Network.Test/JsonFormatter.cs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
using System;
22
using System.Net;
3+
using System.Net.Sockets;
4+
using System.Threading.Tasks;
35
using FluentAssertions;
4-
using Serilog.Core;
56
using Serilog.Formatting;
67
using Serilog.Sinks.Network.Formatters;
78
using Xunit;
@@ -10,45 +11,43 @@ namespace Serilog.Sinks.Network.Test
1011
{
1112
public class JsonFormatter
1213
{
13-
private TCPServer _server;
14-
private Logger _logger;
15-
16-
17-
private void ConfigureTestLogger(ITextFormatter formatter = null)
14+
private static LoggerAndSocket ConfigureTestLogger(ITextFormatter formatter = null)
1815
{
19-
var port = new Random().Next(50003) + 10000;
20-
_server = new TCPServer(IPAddress.Loopback, port);
21-
_server.Start();
16+
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
17+
socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
18+
socket.Listen();
2219

23-
_logger = new LoggerConfiguration()
24-
.WriteTo.TCPSink(IPAddress.Loopback, port, formatter)
20+
var logger = new LoggerConfiguration()
21+
.WriteTo.TCPSink(IPAddress.Loopback, ((IPEndPoint)socket.LocalEndPoint!).Port, null, null, formatter)
2522
.CreateLogger();
23+
24+
return new LoggerAndSocket { Logger = logger, Socket = socket };
2625
}
2726

2827
[Fact]
29-
public void MustNotLogATrailingCommaWhenThereAreNoProperties()
28+
public async Task MustNotLogATrailingCommaWhenThereAreNoProperties()
3029
{
31-
ConfigureTestLogger(new LogstashJsonFormatter());
30+
using var fixture = ConfigureTestLogger(new LogstashJsonFormatter());
3231
var arbitraryMessage = nameof(JsonFormatter) + "MustNotLogATrailingCommaWhenThereAreNoProperties" + Guid.NewGuid();
3332

34-
_logger.Information(arbitraryMessage);
33+
fixture.Logger.Information(arbitraryMessage);
3534

36-
var receivedData = ServerPoller.PollForReceivedData(_server);
35+
var receivedData = await ServerPoller.PollForReceivedData(fixture.Socket);
3736
var loggedData = receivedData?.TrimEnd('\n');
3837

3938
var logMessageWithTrailingComma = $"\"message\":\"{arbitraryMessage}\",}}";
4039
loggedData.Should().NotEndWith(logMessageWithTrailingComma);
4140
}
4241

4342
[Fact]
44-
public void CanStillLogMessagesWithExceptions()
43+
public async Task CanStillLogMessagesWithExceptions()
4544
{
46-
ConfigureTestLogger(new LogstashJsonFormatter());
45+
using var fixture = ConfigureTestLogger(new LogstashJsonFormatter());
4746
var arbitraryMessage = nameof(JsonFormatter) + "CanStillLogMessagesWithExceptions" + Guid.NewGuid();
4847

49-
_logger.Information(new Exception("exploding"), arbitraryMessage);
48+
fixture.Logger.Information(new Exception("exploding"), arbitraryMessage);
5049

51-
var receivedData = ServerPoller.PollForReceivedData(_server);
50+
var receivedData = await ServerPoller.PollForReceivedData(fixture.Socket);
5251

5352
receivedData.Should().Contain("\"exception\":\"System.Exception: exploding\"}");
5453
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.Net.Sockets;
2+
3+
namespace Serilog.Sinks.Network.Test
4+
{
5+
public record LoggerAndSocket : System.IDisposable
6+
{
7+
public required ILogger Logger;
8+
public required Socket Socket;
9+
public void Dispose()
10+
{
11+
Socket.Dispose();
12+
}
13+
}
14+
15+
}
Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,46 @@
11
using System;
2-
using System.Diagnostics;
3-
using System.Linq;
2+
using System.Collections.Generic;
3+
using System.Net.Sockets;
4+
using System.Text;
5+
using System.Threading;
6+
using System.Threading.Tasks;
47

58
namespace Serilog.Sinks.Network.Test
69
{
710
internal static class ServerPoller
811
{
9-
public static string PollForReceivedData(DataReceiver dataReceiver)
12+
public static async Task<string> PollForReceivedData(Socket socket, bool udp = false)
1013
{
11-
var stopwatch = Stopwatch.StartNew();
12-
string receivedData = null;
13-
while (string.IsNullOrEmpty(receivedData))
14+
var buffer = new byte[1000];
15+
var cts = new CancellationTokenSource();
16+
cts.CancelAfter(TimeSpan.FromSeconds(30.0));
17+
var result = new List<byte>();
18+
19+
Socket clientSocket;
20+
if (udp)
21+
{
22+
clientSocket = socket;
23+
}
24+
else
1425
{
15-
receivedData = dataReceiver.ReceivedData.SingleOrDefault();
16-
if (stopwatch.Elapsed > TimeSpan.FromSeconds(5))
26+
clientSocket = await socket.AcceptAsync(cts.Token);
27+
}
28+
var isDone = false;
29+
while (!isDone)
30+
{
31+
int readResult = await clientSocket.ReceiveAsync(buffer, SocketFlags.None, cts.Token);
32+
for (var i = 0; i < readResult; i++)
1733
{
18-
throw new NoDataReceivedWithinFiveSeconds();
34+
result.Add(buffer[i]);
1935
}
20-
}
2136

22-
return receivedData;
37+
if (readResult < buffer.Length)
38+
{
39+
isDone = true;
40+
}
41+
}
42+
43+
return Encoding.ASCII.GetString(result.ToArray());
2344
}
2445
}
25-
26-
internal class NoDataReceivedWithinFiveSeconds : Exception
27-
{
28-
}
2946
}

Serilog.Sinks.Network.Test/WhenLoggingViaTCP.cs

Lines changed: 0 additions & 78 deletions
This file was deleted.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using System.Dynamic;
3+
using System.Net;
4+
using System.Net.Sockets;
5+
using System.Threading.Tasks;
6+
using FluentAssertions;
7+
using FluentAssertions.Execution;
8+
using Newtonsoft.Json;
9+
using Serilog.Formatting;
10+
using Serilog.Formatting.Compact;
11+
using Serilog.Sinks.Network.Formatters;
12+
using Xunit;
13+
14+
namespace Serilog.Sinks.Network.Test
15+
{
16+
public class WhenLoggingViaTcp
17+
{
18+
private static LoggerAndSocket ConfigureTestLogger(ITextFormatter formatter = null)
19+
{
20+
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
21+
socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
22+
socket.Listen();
23+
24+
var logger = new LoggerConfiguration()
25+
.WriteTo.TCPSink(IPAddress.Loopback, ((IPEndPoint)socket.LocalEndPoint!).Port, null, null, formatter)
26+
.CreateLogger();
27+
28+
return new LoggerAndSocket { Logger = logger, Socket = socket };
29+
}
30+
31+
[Fact]
32+
public async Task CanLogHelloWorld_WithLogstashJsonFormatter()
33+
{
34+
using var fixture = ConfigureTestLogger(new LogstashJsonFormatter());
35+
var arbitraryMessage = nameof(WhenLoggingViaTcp) + "CanLogHelloWorld_WithLogstashJsonFormatter" + Guid.NewGuid();
36+
fixture.Logger.Information(arbitraryMessage);
37+
var receivedData = await ServerPoller.PollForReceivedData(fixture.Socket);
38+
receivedData.Should().Contain($"\"message\":\"{arbitraryMessage}\"");
39+
}
40+
41+
[Fact]
42+
public async Task CanLogHelloWorld_WithDefaultFormatter()
43+
{
44+
using var fixture = ConfigureTestLogger();
45+
var arbitraryMessage = nameof(WhenLoggingViaTcp) + "CanLogHelloWorld_WithDefaultFormatter" + Guid.NewGuid();
46+
fixture.Logger.Information(arbitraryMessage);
47+
48+
var receivedData = await ServerPoller.PollForReceivedData(fixture.Socket);
49+
50+
receivedData.Should().Contain($"\"message\":\"{arbitraryMessage}\"");
51+
}
52+
53+
[Fact]
54+
public async Task CanLogHelloWorld_WithRawFormatter()
55+
{
56+
using var fixture =ConfigureTestLogger(new CompactJsonFormatter());
57+
var arbitraryMessage = nameof(WhenLoggingViaTcp) + "CanLogHelloWorld_WithCompactJsonFormatter" + Guid.NewGuid();
58+
fixture.Logger.Information(arbitraryMessage);
59+
var receivedData = await ServerPoller.PollForReceivedData(fixture.Socket);
60+
receivedData.Should().Contain($"\"{arbitraryMessage}\"");
61+
}
62+
63+
[Fact]
64+
public async Task CanLogWithProperties()
65+
{
66+
using var fixture = ConfigureTestLogger();
67+
fixture.Logger.Information("TCP Hello {location}", "world");
68+
var receivedData = await ServerPoller.PollForReceivedData(fixture.Socket);
69+
dynamic payload = JsonConvert.DeserializeObject<ExpandoObject>(receivedData);
70+
if (payload == null)
71+
{
72+
throw new AssertionFailedException("expected payload not null");
73+
}
74+
Assert.Equal("Information", payload.level);
75+
Assert.Equal("TCP Hello \"world\"", payload.message);
76+
Assert.Equal("world", payload.location);
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)