C# / .NET SDK
GitHubOfficial .NET SDK for LogWard with automatic batching, retry logic with exponential backoff, circuit breaker pattern, query API, distributed tracing, and ASP.NET Core middleware support.
Installation
.NET CLI
bash
dotnet add package LogWard.SDKPackage Manager
powershell
Install-Package LogWard.SDKQuick Start
csharp
using LogWard.SDK;
using LogWard.SDK.Models;
var client = new LogWardClient(new ClientOptions
{
ApiUrl = "http://localhost:8080",
ApiKey = "lp_your_api_key_here"
});
// Send logs
client.Info("api-gateway", "Server started", new() { ["port"] = 3000 });
client.Error("database", "Connection failed", new Exception("Timeout"));
// Graceful shutdown
await client.DisposeAsync();Features
- ✅ Automatic batching with configurable size and interval
- ✅ Retry logic with exponential backoff
- ✅ Circuit breaker pattern for fault tolerance
- ✅ Max buffer size with drop policy to prevent memory leaks
- ✅ Query API for searching and filtering logs
- ✅ Trace ID context for distributed tracing
- ✅ Global metadata added to all logs
- ✅ Structured error serialization
- ✅ Internal metrics (logs sent, errors, latency)
- ✅ ASP.NET Core middleware for auto-logging HTTP requests
- ✅ Dependency injection support
- ✅ Full async/await support
- ✅ Thread-safe
Configuration
csharp
var client = new LogWardClient(new ClientOptions
{
// Required
ApiUrl = "http://localhost:8080",
ApiKey = "lp_your_api_key_here",
// Batching
BatchSize = 100, // Max logs per batch (default: 100)
FlushIntervalMs = 5000, // Flush interval in ms (default: 5000)
// Buffer management
MaxBufferSize = 10000, // Max logs in buffer (default: 10000)
// Retry with exponential backoff (1s → 2s → 4s)
MaxRetries = 3, // Max retry attempts (default: 3)
RetryDelayMs = 1000, // Initial retry delay (default: 1000)
// Circuit breaker
CircuitBreakerThreshold = 5, // Failures before circuit opens (default: 5)
CircuitBreakerResetMs = 30000, // Circuit reset timeout (default: 30000)
// Metrics & debugging
EnableMetrics = true, // Enable metrics collection (default: true)
Debug = false, // Enable debug logging (default: false)
// Global context
GlobalMetadata = new()
{
["env"] = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"),
["version"] = "1.0.0",
["hostname"] = Environment.MachineName
},
// Auto trace IDs
AutoTraceId = false, // Auto-generate trace IDs (default: false)
// HTTP settings
HttpTimeoutSeconds = 30 // HTTP request timeout (default: 30)
});Logging Methods
Basic Logging
csharp
// Log levels: debug, info, warn, error, critical
client.Debug("service-name", "Debug message");
client.Info("service-name", "Info message", new() { ["userId"] = 123 });
client.Warn("service-name", "Warning message");
client.Error("service-name", "Error message", new() { ["custom"] = "data" });
client.Critical("service-name", "Critical message");Error Logging with Auto-Serialization
The SDK automatically serializes exceptions with full stack traces:
csharp
try
{
throw new InvalidOperationException("Database timeout");
}
catch (Exception ex)
{
// Automatically serializes error with stack trace
client.Error("database", "Query failed", ex);
}
// Generated metadata:
// {
// "error": {
// "name": "InvalidOperationException",
// "message": "Database timeout",
// "stack": "at Program.Main() in ..."
// }
// }Custom Log Entry
csharp
client.Log(new LogEntry
{
Service = "custom-service",
Level = LogLevel.Info,
Message = "Custom log",
Time = DateTime.UtcNow.ToString("O"),
Metadata = new() { ["key"] = "value" },
TraceId = "custom-trace-id"
});Trace ID Context
Track requests across services with trace IDs for distributed tracing.
Manual Trace ID
csharp
client.SetTraceId("request-123");
client.Info("api", "Request received");
client.Info("database", "Querying users");
client.Info("api", "Response sent");
client.SetTraceId(null); // Clear contextScoped Trace ID
csharp
client.WithTraceId("request-456", () =>
{
client.Info("api", "Processing in context");
client.Warn("cache", "Cache miss");
});
// Trace ID automatically restored after blockAuto-Generated Trace ID
csharp
client.WithNewTraceId(() =>
{
client.Info("worker", "Background job started");
client.Info("worker", "Job completed");
});Query API
Search and retrieve logs programmatically.
Basic Query
csharp
var result = await client.QueryAsync(new QueryOptions
{
Service = "api-gateway",
Level = LogLevel.Error,
From = DateTime.UtcNow.AddDays(-1),
To = DateTime.UtcNow,
Limit = 100,
Offset = 0
});
Console.WriteLine($"Found {result.Total} logs");
foreach (var log in result.Logs)
{
Console.WriteLine($"{log.Time}: {log.Message}");
}Full-Text Search
csharp
var result = await client.QueryAsync(new QueryOptions
{
Query = "timeout",
Limit = 50
});Get Logs by Trace ID
csharp
var logs = await client.GetByTraceIdAsync("trace-123");
Console.WriteLine($"Trace has {logs.Count} logs");Aggregated Statistics
csharp
var stats = await client.GetAggregatedStatsAsync(new AggregatedStatsOptions
{
From = DateTime.UtcNow.AddDays(-7),
To = DateTime.UtcNow,
Interval = "1h", // "1m" | "5m" | "1h" | "1d"
Service = "api-gateway" // Optional
});
Console.WriteLine("Time series:");
foreach (var entry in stats.Timeseries)
{
Console.WriteLine($" {entry.Bucket}: {entry.Total} logs");
}Metrics
Track SDK performance and health with built-in metrics.
csharp
var metrics = client.GetMetrics();
Console.WriteLine($"Logs sent: {metrics.LogsSent}");
Console.WriteLine($"Logs dropped: {metrics.LogsDropped}");
Console.WriteLine($"Errors: {metrics.Errors}");
Console.WriteLine($"Retries: {metrics.Retries}");
Console.WriteLine($"Avg latency: {metrics.AvgLatencyMs}ms");
Console.WriteLine($"Circuit breaker trips: {metrics.CircuitBreakerTrips}");
// Get circuit breaker state
Console.WriteLine($"Circuit state: {client.GetCircuitBreakerState()}"); // Closed | Open | HalfOpen
// Reset metrics
client.ResetMetrics();ASP.NET Core Integration
Setup with Dependency Injection
Add LogWard to your ASP.NET Core application with full middleware support:
csharp
// Program.cs
using LogWard.SDK;
using LogWard.SDK.Middleware;
using LogWard.SDK.Models;
var builder = WebApplication.CreateBuilder(args);
// Add LogWard
builder.Services.AddLogWard(new ClientOptions
{
ApiUrl = builder.Configuration["LogWard:ApiUrl"]!,
ApiKey = builder.Configuration["LogWard:ApiKey"]!,
GlobalMetadata = new()
{
["env"] = builder.Environment.EnvironmentName
}
});
var app = builder.Build();
// Add middleware for auto-logging HTTP requests
app.UseLogWard(options =>
{
options.ServiceName = "my-api";
options.LogRequests = true;
options.LogResponses = true;
options.LogErrors = true;
options.SkipHealthCheck = true;
options.SkipPaths.Add("/metrics");
});
app.MapGet("/", () => "Hello World!");
app.Run();Middleware Options
| Option | Type | Default | Description |
|---|---|---|---|
ServiceName | string | "aspnet-api" | Service name in logs |
LogRequests | bool | true | Log incoming requests |
LogResponses | bool | true | Log outgoing responses |
LogErrors | bool | true | Log unhandled exceptions |
IncludeHeaders | bool | false | Include request headers |
SkipHealthCheck | bool | true | Skip /health endpoints |
SkipPaths | HashSet<string> | {} | Paths to skip |
TraceIdHeader | string | "X-Trace-Id" | Header for trace ID |
Using LogWard in Controllers
csharp
[ApiController]
[Route("[controller]")]
public class WeatherController : ControllerBase
{
private readonly LogWardClient _logger;
public WeatherController(LogWardClient logger)
{
_logger = logger;
}
[HttpGet]
public IActionResult Get()
{
_logger.Info("weather-api", "Fetching weather data");
try
{
// ... business logic
return Ok(new { Temperature = 25 });
}
catch (Exception ex)
{
_logger.Error("weather-api", "Failed to fetch weather", ex);
throw;
}
}
}Best Practices
1. Always Dispose on Shutdown
Always call
client.DisposeAsync() on shutdown to ensure
buffered logs are flushed. With ASP.NET Core, register a shutdown handler: csharp
app.Lifetime.ApplicationStopping.Register(async () =>
{
var logger = app.Services.GetRequiredService<LogWardClient>();
await logger.FlushAsync();
});2. Use Global Metadata
Set global metadata (environment, version, hostname) at initialization
to avoid repeating it in every log call.
3. Enable Debug Mode in Development
csharp
var client = new LogWardClient(new ClientOptions
{
ApiUrl = "...",
ApiKey = "...",
Debug = builder.Environment.IsDevelopment()
});4. Monitor Metrics in Production
csharp
// Periodic health check
_ = Task.Run(async () =>
{
while (true)
{
await Task.Delay(TimeSpan.FromMinutes(1));
var metrics = client.GetMetrics();
if (metrics.LogsDropped > 0)
{
Console.WriteLine($"Warning: {metrics.LogsDropped} logs dropped");
}
if (client.GetCircuitBreakerState() == CircuitState.Open)
{
Console.WriteLine("Error: Circuit breaker is OPEN!");
}
}
});Supported Frameworks
- .NET 6.0
- .NET 7.0
- .NET 8.0