-
Notifications
You must be signed in to change notification settings - Fork 0
Integration Guides
Thushar.Logging works the same everywhere: configure once at startup, then log. Below are copy-paste setups for the most common hosts.
Configure at the top of Main, then use the logger anywhere:
using Thushar.Logging;
Log.Configure(o => o
.SetMinimumLevel(LogLevel.Debug)
.AddTraceId());
Log.Information("Worker starting");
using (Log.BeginTraceScope())
{
Log.Debug("Loading config");
Log.Information("Ready");
}For production/cloud, switch to JSON so your aggregator can parse it:
Log.Configure(o => o.UseStructured());Configure in Program.cs, then add a tiny middleware that opens a trace scope per request
so every log line in a request shares one id.
using Thushar.Logging;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// 1. Configure the static logger once at startup.
Log.Configure(o => o
.UseStructured()
.SetMinimumLevel(LogLevel.Information)
.AddTraceId());
// 2. One trace scope per request. Reuse an incoming correlation id if present.
app.Use(async (context, next) =>
{
var correlationId = context.Request.Headers["X-Correlation-ID"].FirstOrDefault()
?? context.TraceIdentifier;
using (Log.BeginTraceScope(correlationId))
{
Log.Information("{method} {path}", context.Request.Method, context.Request.Path);
await next();
Log.Information("Responded {statusCode}", context.Response.StatusCode);
}
});
app.MapGet("/orders/{id}", (int id) =>
{
Log<OrdersEndpoint>.Information("Fetching order"); // adds class + method
return Results.Ok(new { id });
});
app.Run();
class OrdersEndpoint { }Every line within a request now carries the same traceId, so you can pull up the full story
of a single request in your log tool.
Lambda has no DI container, which is exactly where a static logger shines. Configure in the function constructor — it runs once on cold start and is reused across warm invocations — then open a trace scope per invocation using the request id.
using Amazon.Lambda.Core;
using Thushar.Logging;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace MyLambda;
public class Function
{
public Function()
{
// Runs on cold start. JSON is ideal for CloudWatch Logs Insights.
Log.Configure(o => o
.UseStructured()
.SetMinimumLevel(LogLevel.Information)
.AddColorIcon(false) // CloudWatch doesn't need emoji
.AddTraceId());
}
public string FunctionHandler(string input, ILambdaContext context)
{
using (Log.BeginTraceScope(context.AwsRequestId))
{
Log<Function>.Information("Received input");
if (string.IsNullOrWhiteSpace(input))
{
Log.Warning("Empty input received");
return string.Empty;
}
return input.ToUpperInvariant();
}
}
}Because the entries are JSON with a shared traceId, CloudWatch Logs Insights queries like
fields @timestamp, message | filter traceId = "…" reconstruct a single invocation instantly.
Tip: turn off the color icon (
AddColorIcon(false)) for CloudWatch and other text sinks that don't render emoji cleanly.
A library can log without forcing any logging dependency on its consumers — there's nothing to
inject. Just call Log / Log<T>:
namespace Acme.Payments;
public class PaymentProcessor
{
public void Charge(decimal amount)
{
Log<PaymentProcessor>.Information("Charging"); // class + method context
// ...
}
}The application at the top decides output format and level via Log.Configure(...). If the
app never configures it, the library's logs simply use the defaults. (If you're writing a
widely-distributed library, consider whether a static logger is appropriate for your consumers
— see the FAQ.)
Thushar.Logging · a zero-dependency static logger for .NET
📦 NuGet · 💻 GitHub · 🐛 Issues · 📸 Instagram
dotnet add package Thushar.Logging
Getting around
Features
Using it
Under the hood