A high-performance Serilog formatter that outputs compact JSON optimized for AWS CloudWatch metric filters and structured log analysis.
The standard Serilog CompactJsonFormatter uses @ prefixed properties for metadata (like @l for level, @t for timestamp, etc.). However, these @ prefixed properties are not compatible with AWS CloudWatch metric filters, which cannot parse escaped metadata keys.
This formatter solves that problem by replacing the @ prefix with _ (underscore) while maintaining all the performance benefits of the original compact formatter.
- CloudWatch Compatible: Uses
_prefix instead of@for metadata fields - High Performance: Based on the official Serilog compact formatter
- Single-line JSON: Optimized for log ingestion and analysis
- Full Serilog Integration: Drop-in replacement for
CompactJsonFormatter - Trace Support: Includes trace ID and span ID support
- Multi-targeting: Supports .NET 8.0 and .NET 9.0
dotnet add package LayeredCraft.Logging.CompactJsonFormatterusing LayeredCraft.Logging.CompactJsonFormatter;
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new CompactJsonFormatter())
.CreateLogger();
Log.Information("Hello, {Name}!", "World");using LayeredCraft.Logging.CompactJsonFormatter;
using Serilog;
using Serilog.Formatting.Json;
var customValueFormatter = new JsonValueFormatter(typeTagName: "$type");
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new CompactJsonFormatter(customValueFormatter))
.CreateLogger();using LayeredCraft.Logging.CompactJsonFormatter;
using Serilog;
using Serilog.Sinks.AwsCloudWatch;
Log.Logger = new LoggerConfiguration()
.WriteTo.AmazonCloudWatch(
logGroup: "/aws/lambda/my-function",
region: RegionEndpoint.USEast1,
formatter: new CompactJsonFormatter())
.CreateLogger();{"@t":"2025-01-14T10:30:00.000Z","@l":"Information","@mt":"Hello, {Name}!","Name":"World"}{"_t":"2025-01-14T10:30:00.000Z","_l":"Information","_mt":"Hello, {Name}!","Name":"World"}| Serilog Standard | LayeredCraft | Description |
|---|---|---|
@t |
_t |
Timestamp |
@l |
_l |
Log Level |
@mt |
_mt |
Message Template |
@m |
_m |
Rendered Message |
@r |
_r |
Renderings |
@x |
_x |
Exception |
@tr |
_tr |
Trace ID |
@sp |
_sp |
Span ID |
With the underscore prefix, you can easily create CloudWatch metric filters:
[_l="Error"]
[_l="Warning" && _t > "2025-01-01"]
compact-json-formatter/
├── src/
│ ├── LayeredCraft.Logging.CompactJsonFormatter.csproj
│ └── CompactJsonFormatter.cs
├── test/
│ └── LayeredCraft.Logging.CompactJsonFormatter.Tests.csproj
├── .github/
│ ├── workflows/
│ │ ├── build.yaml
│ │ └── pr-build.yaml
│ └── dependabot.yml
├── Directory.Build.props
├── README.md
├── CLAUDE.md
└── icon.png
dotnet builddotnet testdotnet pack- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for your changes
- Ensure all tests pass
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- LayeredCraft.StructuredLogging - Structured logging extensions for .NET