Send Serilog events to Logstash
Configure the Network sink with the correct TCP API and JSON framing, or use rolling files with a collector for a separate delivery path.
A Serilog network sink can send structured events to a Logstash TCP input. Serilog.Sinks.Network exposes TCPSink, not Tcp. For stronger separation between application logging and network delivery, write JSON files and let a collector forward them, while accounting for retention and disk failures.
Option 1: send JSON over TCP
Install the network and console sinks used by the example:
dotnet add package Serilog.Sinks.Network
dotnet add package Serilog.Sinks.Console
Use the explicit URI overload so the transport and port are unambiguous:
using Serilog;
using Serilog.Formatting.Json;
using Serilog.Sinks.Network;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.TCPSink("tcp://logstash-host:5044", new JsonFormatter())
.CreateLogger();
try
{
Log.Information("User {UserId} signed in", 42);
}
finally
{
Log.CloseAndFlush();
}
Configure a raw TCP input on the matching Logstash port:
input {
tcp {
port => 5044
codec => json_lines
}
}
Port 5044 is often used for Beats, but the number does not select a protocol. This example requires tcp, not beats; do not bind both inputs to the same address and port. Add the intended pipeline output separately.
JsonFormatter retains the message template and structured properties. Its UserId value is inside the Properties object, so downstream field references must match that shape. Successful JSON decoding is separate from successful Elasticsearch indexing.
Option 2: write files and forward them
Install Serilog.Sinks.File, then add this to the logger configuration:
.WriteTo.File(new Serilog.Formatting.Json.JsonFormatter(),
"logs/app-.json", rollingInterval: RollingInterval.Day)
A collector such as Filebeat can handle forwarding and retrying independently. Retain files long enough for expected outages and monitor disk space, rotation, and collector state. A file does not guarantee lossless delivery after disk failure, premature deletion, or host replacement.
Check framing, buffering, and transport
- UDP can lose datagrams. Use a transport suited to the delivery requirement, and configure TLS if confidentiality and server authentication are needed. TCP transport alone is not a durable-delivery acknowledgment.
- A JSON-lines stream needs delimiters. The standard
JsonFormatteremits a line ending; custom formatters must do so too. A codec cannot reconstruct boundaries that the sender omitted. - Buffering is implementation-specific. The inspected Network sink implementation already queues events and reconnects. Its bounded in-memory queue can discard old events when full. An extra
WriteTo.Asyncqueue does not make this durable and is not a universal outage fix.
For Guance, the same file output can be collected with DataKit. Parse the actual formatter's fields, then send an exception example and confirm that its stack trace remains part of one event.
Frequently asked questions
Do I need a sink named Logstash?
No. A compatible network or HTTP sink can work when its framing, payload, authentication, and retry behavior match the receiving input. Community packages vary; inspect the selected release instead of assuming support from its name.
Why do several JSON objects arrive stuck together?
TCP is a byte stream. Ensure each serialized event ends with a delimiter and pair that format with json_lines. Switching codecs cannot compensate for an incompatible sender format.
Can I preserve message-template properties?
Yes. JsonFormatter nests them under Properties. CompactJsonFormatter uses CLEF and places ordinary properties at the top level, alongside reserved fields. Configure downstream parsing for whichever schema you choose.
References: Network sink documentation and source and Serilog JSON formatter.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan