Updated
This commit is contained in:
@@ -3585,6 +3585,357 @@ finally
|
||||
}
|
||||
```
|
||||
|
||||
## Complete Code Examples
|
||||
|
||||
### Example 1: Production ASP.NET Core Application
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
// In Program.cs
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add EonaCat logging
|
||||
builder.Services.AddEonaCatLogging(config =>
|
||||
{
|
||||
config
|
||||
.WithApplicationName("MyApi")
|
||||
.WithMinimumLevel(LogLevel.Information)
|
||||
.WriteToConsole(useColors: true)
|
||||
.WriteToFile(
|
||||
directory: "./logs",
|
||||
maxFileSize: 100 * 1024 * 1024,
|
||||
maxDirectorySize: 5L * 1024 * 1024 * 1024,
|
||||
compression: CompressionFormat.GZip)
|
||||
.WriteToSlack(
|
||||
webhookUrl: builder.Configuration["Slack:WebhookUrl"],
|
||||
minimumLevel: LogLevel.Error)
|
||||
.WriteToElasticSearch(
|
||||
elasticSearchUrl: builder.Configuration["Elasticsearch:Url"],
|
||||
indexName: "myapi-logs")
|
||||
.BoostWithMachineName()
|
||||
.BoostWithProcessId()
|
||||
.BoostWithCorrelationId()
|
||||
.BoostWithCallerInfo();
|
||||
});
|
||||
|
||||
// Enable advanced telemetry
|
||||
builder.Services.AddEonaCatNamedLoggers(new LoggerDIOptions
|
||||
{
|
||||
EnableTelemetry = true,
|
||||
EnableTracing = true,
|
||||
EnablePerformanceMonitoring = true,
|
||||
EnableHealthMonitoring = true
|
||||
});
|
||||
|
||||
builder.Services.AddEonaCatTracing();
|
||||
|
||||
var app = builder.Build();
|
||||
app.UseHttpsRedirection();
|
||||
app.UseRouting();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.MapControllers();
|
||||
|
||||
var logger = app.Services.GetRequiredService<ILoggerFactory>()
|
||||
.CreateLogger("Application");
|
||||
|
||||
logger.Information("Application starting",
|
||||
("Version", "1.0.0"),
|
||||
("Environment", app.Environment.EnvironmentName));
|
||||
|
||||
app.Run();
|
||||
```
|
||||
|
||||
### Example 2: Console Application with Multiple Flows
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
await using var logger = new LogBuilder("ConsoleApp")
|
||||
.WithMinimumLevel(LogLevel.Debug)
|
||||
.WithTimestampMode(TimestampMode.Utc)
|
||||
.WriteToConsole(useColors: true)
|
||||
.WriteToFile("./logs", filePrefix: "app", maxFileSize: 50 * 1024 * 1024)
|
||||
.WriteToAudit("./audit", auditLevel: AuditLevel.WarningAndAbove)
|
||||
.WriteToMemory(capacity: 100)
|
||||
.WriteToEmail(
|
||||
smtpHost: "smtp.gmail.com", smtpPort: 587, useSsl: true,
|
||||
username: "email@gmail.com", password: "app-password",
|
||||
from: "logs@company.com", to: "admin@company.com",
|
||||
subjectPrefix: "[CRITICAL]", minimumLevel: LogLevel.Critical)
|
||||
.RedisFlow(host: "redis.local", channel: "myapp:logs")
|
||||
.BoostWithMachineName()
|
||||
.BoostWithProcessId()
|
||||
.BoostWithCorrelationId()
|
||||
.Build();
|
||||
|
||||
try
|
||||
{
|
||||
logger.Information("Application started");
|
||||
await ProcessDataAsync(logger);
|
||||
logger.Information("Application completed successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Critical(ex, "Unhandled exception");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await logger.FlushAsync();
|
||||
}
|
||||
}
|
||||
|
||||
static async Task ProcessDataAsync(ILogger logger)
|
||||
{
|
||||
logger.Information("Processing started");
|
||||
logger.Debug("Starting batch", ("BatchId", 123), ("Count", 5000));
|
||||
await Task.Delay(1000);
|
||||
logger.Information("Batch processed", ("Imported", 4998), ("Errors", 2));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 3: Service with Dependency Injection & Telemetry
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
public class OrderService
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly ITelemetryAggregator _telemetry;
|
||||
private readonly ISpanFactory _spans;
|
||||
|
||||
public OrderService(ILogger logger, ITelemetryAggregator telemetry, ISpanFactory spans)
|
||||
{
|
||||
_logger = logger;
|
||||
_telemetry = telemetry;
|
||||
_spans = spans;
|
||||
}
|
||||
|
||||
public async Task<Order> ProcessOrderAsync(string orderId, decimal amount)
|
||||
{
|
||||
using var span = _spans.CreateSpanScope("ProcessOrder");
|
||||
span.SetAttribute("OrderId", orderId);
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Information("Processing order", ("OrderId", orderId), ("Amount", amount));
|
||||
_telemetry.RecordCounter("orders.started", 1);
|
||||
|
||||
var order = new Order { Id = orderId, Amount = amount };
|
||||
await Task.Delay(500);
|
||||
|
||||
_logger.Information("Order processed", ("Status", "Completed"));
|
||||
_telemetry.RecordCounter("orders.completed", 1);
|
||||
_telemetry.RecordGauge("order.revenue", amount);
|
||||
return order;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_telemetry.RecordCounter("orders.failed", 1);
|
||||
span.RecordException(ex);
|
||||
_logger.Error(ex, "Order processing failed", ("OrderId", orderId));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
services.AddEonaCatLogging(config =>
|
||||
{
|
||||
config
|
||||
.WithApplicationName("OrderService")
|
||||
.WriteToConsole()
|
||||
.WriteToFile("./logs")
|
||||
.WriteToDatabase(
|
||||
connectionFactory: () => new SqlConnection("Server=.;Database=Logs;"),
|
||||
tableName: "OrderLogs")
|
||||
.BoostWithCorrelationId();
|
||||
});
|
||||
|
||||
services.AddEonaCatTelemetryAggregation();
|
||||
services.AddEonaCatTracing();
|
||||
services.AddScoped<OrderService>();
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var orderService = sp.GetRequiredService<OrderService>();
|
||||
var order = await orderService.ProcessOrderAsync("ORD-001", 99.99m);
|
||||
|
||||
var telemetry = sp.GetRequiredService<ITelemetryAggregator>();
|
||||
var snapshot = telemetry.GetSnapshot();
|
||||
Console.WriteLine($"Completed: {snapshot.RecordedMetrics["orders.completed"]}");
|
||||
}
|
||||
}
|
||||
|
||||
record Order { public required string Id { get; init; } public required decimal Amount { get; init; } }
|
||||
```
|
||||
|
||||
### Example 4: Advanced Resilience Patterns
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
await using var logger = new LogBuilder("ResilientApp")
|
||||
.WriteToConsole()
|
||||
// Retry with exponential backoff
|
||||
.WriteToRetry(
|
||||
primary: cfg => cfg.WriteToHttp("https://primary-logs.company.com/ingest", batchSize: 50),
|
||||
maxRetries: 3, initialDelayMs: 1000, maxDelayMs: 30000)
|
||||
// Failover to secondary
|
||||
.WriteToFailover(
|
||||
primary: cfg => cfg.WriteToElasticSearch("https://es-primary.company.com:9200", "logs"),
|
||||
secondary: cfg => cfg.WriteToFile("./logs/failover"),
|
||||
recoveryCheckIntervalSeconds: 60)
|
||||
// Rate limiting with deduplication
|
||||
.WriteToThrottled(
|
||||
target: cfg => cfg.WriteToSlack("https://hooks.slack.com/...", LogLevel.Warning),
|
||||
requestsPerSecond: 10, enableDeduplication: true, minimumLevel: LogLevel.Warning)
|
||||
// Circuit breaker
|
||||
.WriteToCircuitBreaker(
|
||||
inner: cfg => cfg.WriteToDatabase(() => new SqlConnection("..."), "Logs"),
|
||||
failureThreshold: 5, successThresholdToClose: 3, timeoutSeconds: 60)
|
||||
.Build();
|
||||
|
||||
logger.Information("Started with resilience");
|
||||
logger.Error(new Exception("Test"), "Error occurred");
|
||||
```
|
||||
|
||||
### Example 5: Remote Logging with LogClient
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack.LogClient;
|
||||
|
||||
var clientOptions = new LogCentralOptions
|
||||
{
|
||||
ServerUrl = "https://logcentral.company.com",
|
||||
ApiKey = "your-api-key",
|
||||
ApplicationName = "DistributedService",
|
||||
ApplicationVersion = "2.1.0",
|
||||
Environment = "Production",
|
||||
BatchSize = 100,
|
||||
FlushIntervalSeconds = 5
|
||||
};
|
||||
|
||||
await using var logger = new LogBuilder("DistributedApp")
|
||||
.WriteToConsole()
|
||||
.WriteToFile("./logs")
|
||||
.WriteToHttp(
|
||||
endpoint: $"{clientOptions.ServerUrl}/api/logs/ingest",
|
||||
batchSize: clientOptions.BatchSize,
|
||||
headers: new Dictionary<string, string>
|
||||
{
|
||||
["X-API-Key"] = clientOptions.ApiKey,
|
||||
["X-App-Name"] = clientOptions.ApplicationName
|
||||
})
|
||||
.BoostWithMachineName()
|
||||
.Build();
|
||||
|
||||
logger.Information("Connected to central logging", ("Server", clientOptions.ServerUrl));
|
||||
```
|
||||
|
||||
### Example 6: Log Processing and Analysis
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
await using var logger = new LogBuilder("AnalysisApp")
|
||||
.WriteToConsole()
|
||||
.WriteToMemory(capacity: 10000)
|
||||
.Build();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
if (i % 10 == 0)
|
||||
logger.Warning($"Iteration {i}");
|
||||
else
|
||||
logger.Information($"Processing item {i}");
|
||||
}
|
||||
|
||||
var memoryFlow = logger.GetFlowOfType<MemoryFlow>();
|
||||
var events = memoryFlow.GetEvents();
|
||||
|
||||
var errorCount = events.Count(e => e.Level == LogLevel.Error);
|
||||
var warningCount = events.Count(e => e.Level == LogLevel.Warning);
|
||||
Console.WriteLine($"Errors: {errorCount}, Warnings: {warningCount}");
|
||||
```
|
||||
|
||||
### Example 7: Custom Modifiers for Universal Enrichment
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
var requestId = "REQ-" + Guid.NewGuid().ToString().Substring(0, 8);
|
||||
var userId = "USER-123";
|
||||
|
||||
await using var logger = new LogBuilder("EnrichedApp")
|
||||
.WriteToConsole()
|
||||
.WriteToFile("./logs")
|
||||
.AddModifier((ref LogEventBuilder builder) =>
|
||||
{
|
||||
builder.WithProperty("RequestId", requestId);
|
||||
builder.WithProperty("UserId", userId);
|
||||
builder.WithProperty("Host", Environment.MachineName);
|
||||
})
|
||||
.Build();
|
||||
|
||||
logger.Information("Operation started");
|
||||
logger.Warning("Potential issue detected");
|
||||
logger.Error(new Exception("Failed"), "Operation failed");
|
||||
|
||||
// All logs automatically include RequestId, UserId, Host
|
||||
```
|
||||
|
||||
### Example 8: Structured Logging and Complex Properties
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
await using var logger = new LogBuilder("StructuredApp")
|
||||
.WriteToConsole()
|
||||
.WriteToFile("./logs", outputFormat: FileOutputFormat.Json)
|
||||
.Build();
|
||||
|
||||
// Simple tuple properties (fast)
|
||||
logger.Information("User action",
|
||||
("UserId", 42),
|
||||
("Action", "login"),
|
||||
("Ip", "192.168.1.1"));
|
||||
|
||||
// Dictionary properties
|
||||
var contextDict = new Dictionary<string, object>
|
||||
{
|
||||
{ "OrderId", "ORD-123" },
|
||||
{ "Items", 5 },
|
||||
{ "Total", 199.99m }
|
||||
};
|
||||
logger.Information("Order processed", contextDict);
|
||||
|
||||
// Exception with context
|
||||
try
|
||||
{
|
||||
throw new InvalidOperationException("Database connection failed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Operation failed",
|
||||
("Retries", 3),
|
||||
("TimeoutMs", 5000),
|
||||
("DatabaseName", "ProductDb"));
|
||||
}
|
||||
```
|
||||
|
||||
## Debugging Logging Problems
|
||||
|
||||
Check diagnostics first:
|
||||
@@ -3607,380 +3958,4 @@ If events are missing:
|
||||
4. Check remote destination connectivity.
|
||||
5. Enable retry/failover.
|
||||
|
||||
## Summary
|
||||
|
||||
EonaCat.LogStack combines:
|
||||
|
||||
- High performance logging
|
||||
- Structured events
|
||||
- Multi-target flows
|
||||
- Runtime telemetry
|
||||
- Distributed tracing support
|
||||
- Diagnostics
|
||||
- Resilience features
|
||||
- Security-focused audit logging
|
||||
|
||||
The library is designed to scale from small console tools to distributed production services.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Complete Code Examples
|
||||
|
||||
### Example 1: Production ASP.NET Core Application
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
// In Program.cs
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add EonaCat logging
|
||||
builder.Services.AddEonaCatLogging(config =>
|
||||
{
|
||||
config
|
||||
.WithApplicationName("MyApi")
|
||||
.WithMinimumLevel(LogLevel.Information)
|
||||
.WriteToConsole(useColors: true)
|
||||
.WriteToFile(
|
||||
directory: "./logs",
|
||||
maxFileSize: 100 * 1024 * 1024,
|
||||
maxDirectorySize: 5L * 1024 * 1024 * 1024,
|
||||
compression: CompressionFormat.GZip)
|
||||
.WriteToSlack(
|
||||
webhookUrl: builder.Configuration["Slack:WebhookUrl"],
|
||||
minimumLevel: LogLevel.Error)
|
||||
.WriteToElasticSearch(
|
||||
elasticSearchUrl: builder.Configuration["Elasticsearch:Url"],
|
||||
indexName: "myapi-logs")
|
||||
.BoostWithMachineName()
|
||||
.BoostWithProcessId()
|
||||
.BoostWithCorrelationId()
|
||||
.BoostWithCallerInfo();
|
||||
});
|
||||
|
||||
// Enable advanced telemetry
|
||||
builder.Services.AddEonaCatNamedLoggers(new LoggerDIOptions
|
||||
{
|
||||
EnableTelemetry = true,
|
||||
EnableTracing = true,
|
||||
EnablePerformanceMonitoring = true,
|
||||
EnableHealthMonitoring = true
|
||||
});
|
||||
|
||||
builder.Services.AddEonaCatTracing();
|
||||
|
||||
var app = builder.Build();
|
||||
app.UseHttpsRedirection();
|
||||
app.UseRouting();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.MapControllers();
|
||||
|
||||
var logger = app.Services.GetRequiredService<ILoggerFactory>()
|
||||
.CreateLogger("Application");
|
||||
|
||||
logger.Information("Application starting",
|
||||
("Version", "1.0.0"),
|
||||
("Environment", app.Environment.EnvironmentName));
|
||||
|
||||
app.Run();
|
||||
```
|
||||
|
||||
### Example 2: Console Application with Multiple Flows
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
await using var logger = new LogBuilder("ConsoleApp")
|
||||
.WithMinimumLevel(LogLevel.Debug)
|
||||
.WithTimestampMode(TimestampMode.Utc)
|
||||
.WriteToConsole(useColors: true)
|
||||
.WriteToFile("./logs", filePrefix: "app", maxFileSize: 50 * 1024 * 1024)
|
||||
.WriteToAudit("./audit", auditLevel: AuditLevel.WarningAndAbove)
|
||||
.WriteToMemory(capacity: 100)
|
||||
.WriteToEmail(
|
||||
smtpHost: "smtp.gmail.com", smtpPort: 587, useSsl: true,
|
||||
username: "email@gmail.com", password: "app-password",
|
||||
from: "logs@company.com", to: "admin@company.com",
|
||||
subjectPrefix: "[CRITICAL]", minimumLevel: LogLevel.Critical)
|
||||
.RedisFlow(host: "redis.local", channel: "myapp:logs")
|
||||
.BoostWithMachineName()
|
||||
.BoostWithProcessId()
|
||||
.BoostWithCorrelationId()
|
||||
.Build();
|
||||
|
||||
try
|
||||
{
|
||||
logger.Information("Application started");
|
||||
await ProcessDataAsync(logger);
|
||||
logger.Information("Application completed successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Critical(ex, "Unhandled exception");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await logger.FlushAsync();
|
||||
}
|
||||
}
|
||||
|
||||
static async Task ProcessDataAsync(ILogger logger)
|
||||
{
|
||||
logger.Information("Processing started");
|
||||
logger.Debug("Starting batch", ("BatchId", 123), ("Count", 5000));
|
||||
await Task.Delay(1000);
|
||||
logger.Information("Batch processed", ("Imported", 4998), ("Errors", 2));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 3: Service with Dependency Injection & Telemetry
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
public class OrderService
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly ITelemetryAggregator _telemetry;
|
||||
private readonly ISpanFactory _spans;
|
||||
|
||||
public OrderService(ILogger logger, ITelemetryAggregator telemetry, ISpanFactory spans)
|
||||
{
|
||||
_logger = logger;
|
||||
_telemetry = telemetry;
|
||||
_spans = spans;
|
||||
}
|
||||
|
||||
public async Task<Order> ProcessOrderAsync(string orderId, decimal amount)
|
||||
{
|
||||
using var span = _spans.CreateSpanScope("ProcessOrder");
|
||||
span.SetAttribute("OrderId", orderId);
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Information("Processing order", ("OrderId", orderId), ("Amount", amount));
|
||||
_telemetry.RecordCounter("orders.started", 1);
|
||||
|
||||
var order = new Order { Id = orderId, Amount = amount };
|
||||
await Task.Delay(500);
|
||||
|
||||
_logger.Information("Order processed", ("Status", "Completed"));
|
||||
_telemetry.RecordCounter("orders.completed", 1);
|
||||
_telemetry.RecordGauge("order.revenue", amount);
|
||||
return order;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_telemetry.RecordCounter("orders.failed", 1);
|
||||
span.RecordException(ex);
|
||||
_logger.Error(ex, "Order processing failed", ("OrderId", orderId));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
services.AddEonaCatLogging(config =>
|
||||
{
|
||||
config
|
||||
.WithApplicationName("OrderService")
|
||||
.WriteToConsole()
|
||||
.WriteToFile("./logs")
|
||||
.WriteToDatabase(
|
||||
connectionFactory: () => new SqlConnection("Server=.;Database=Logs;"),
|
||||
tableName: "OrderLogs")
|
||||
.BoostWithCorrelationId();
|
||||
});
|
||||
|
||||
services.AddEonaCatTelemetryAggregation();
|
||||
services.AddEonaCatTracing();
|
||||
services.AddScoped<OrderService>();
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var orderService = sp.GetRequiredService<OrderService>();
|
||||
var order = await orderService.ProcessOrderAsync("ORD-001", 99.99m);
|
||||
|
||||
var telemetry = sp.GetRequiredService<ITelemetryAggregator>();
|
||||
var snapshot = telemetry.GetSnapshot();
|
||||
Console.WriteLine($"Completed: {snapshot.RecordedMetrics["orders.completed"]}");
|
||||
}
|
||||
}
|
||||
|
||||
record Order { public required string Id { get; init; } public required decimal Amount { get; init; } }
|
||||
```
|
||||
|
||||
### Example 4: Advanced Resilience Patterns
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
await using var logger = new LogBuilder("ResilientApp")
|
||||
.WriteToConsole()
|
||||
// Retry with exponential backoff
|
||||
.WriteToRetry(
|
||||
primary: cfg => cfg.WriteToHttp("https://primary-logs.company.com/ingest", batchSize: 50),
|
||||
maxRetries: 3, initialDelayMs: 1000, maxDelayMs: 30000)
|
||||
// Failover to secondary
|
||||
.WriteToFailover(
|
||||
primary: cfg => cfg.WriteToElasticSearch("https://es-primary.company.com:9200", "logs"),
|
||||
secondary: cfg => cfg.WriteToFile("./logs/failover"),
|
||||
recoveryCheckIntervalSeconds: 60)
|
||||
// Rate limiting with deduplication
|
||||
.WriteToThrottled(
|
||||
target: cfg => cfg.WriteToSlack("https://hooks.slack.com/...", LogLevel.Warning),
|
||||
requestsPerSecond: 10, enableDeduplication: true, minimumLevel: LogLevel.Warning)
|
||||
// Circuit breaker
|
||||
.WriteToCircuitBreaker(
|
||||
inner: cfg => cfg.WriteToDatabase(() => new SqlConnection("..."), "Logs"),
|
||||
failureThreshold: 5, successThresholdToClose: 3, timeoutSeconds: 60)
|
||||
.Build();
|
||||
|
||||
logger.Information("Started with resilience");
|
||||
logger.Error(new Exception("Test"), "Error occurred");
|
||||
```
|
||||
|
||||
### Example 5: Remote Logging with LogClient
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack.LogClient;
|
||||
|
||||
var clientOptions = new LogCentralOptions
|
||||
{
|
||||
ServerUrl = "https://logcentral.company.com",
|
||||
ApiKey = "your-api-key",
|
||||
ApplicationName = "DistributedService",
|
||||
ApplicationVersion = "2.1.0",
|
||||
Environment = "Production",
|
||||
BatchSize = 100,
|
||||
FlushIntervalSeconds = 5
|
||||
};
|
||||
|
||||
await using var logger = new LogBuilder("DistributedApp")
|
||||
.WriteToConsole()
|
||||
.WriteToFile("./logs")
|
||||
.WriteToHttp(
|
||||
endpoint: $"{clientOptions.ServerUrl}/api/logs/ingest",
|
||||
batchSize: clientOptions.BatchSize,
|
||||
headers: new Dictionary<string, string>
|
||||
{
|
||||
["X-API-Key"] = clientOptions.ApiKey,
|
||||
["X-App-Name"] = clientOptions.ApplicationName
|
||||
})
|
||||
.BoostWithMachineName()
|
||||
.Build();
|
||||
|
||||
logger.Information("Connected to central logging", ("Server", clientOptions.ServerUrl));
|
||||
```
|
||||
|
||||
### Example 6: Log Processing and Analysis
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
await using var logger = new LogBuilder("AnalysisApp")
|
||||
.WriteToConsole()
|
||||
.WriteToMemory(capacity: 10000)
|
||||
.Build();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
if (i % 10 == 0)
|
||||
logger.Warning($"Iteration {i}");
|
||||
else
|
||||
logger.Information($"Processing item {i}");
|
||||
}
|
||||
|
||||
var memoryFlow = logger.GetFlowOfType<MemoryFlow>();
|
||||
var events = memoryFlow.GetEvents();
|
||||
|
||||
var errorCount = events.Count(e => e.Level == LogLevel.Error);
|
||||
var warningCount = events.Count(e => e.Level == LogLevel.Warning);
|
||||
Console.WriteLine($"Errors: {errorCount}, Warnings: {warningCount}");
|
||||
```
|
||||
|
||||
### Example 7: Custom Modifiers for Universal Enrichment
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
var requestId = "REQ-" + Guid.NewGuid().ToString().Substring(0, 8);
|
||||
var userId = "USER-123";
|
||||
|
||||
await using var logger = new LogBuilder("EnrichedApp")
|
||||
.WriteToConsole()
|
||||
.WriteToFile("./logs")
|
||||
.AddModifier((ref LogEventBuilder builder) =>
|
||||
{
|
||||
builder.WithProperty("RequestId", requestId);
|
||||
builder.WithProperty("UserId", userId);
|
||||
builder.WithProperty("Host", Environment.MachineName);
|
||||
})
|
||||
.Build();
|
||||
|
||||
logger.Information("Operation started");
|
||||
logger.Warning("Potential issue detected");
|
||||
logger.Error(new Exception("Failed"), "Operation failed");
|
||||
|
||||
// All logs automatically include RequestId, UserId, Host
|
||||
```
|
||||
|
||||
### Example 8: Structured Logging and Complex Properties
|
||||
|
||||
```csharp
|
||||
using EonaCat.LogStack;
|
||||
|
||||
await using var logger = new LogBuilder("StructuredApp")
|
||||
.WriteToConsole()
|
||||
.WriteToFile("./logs", outputFormat: FileOutputFormat.Json)
|
||||
.Build();
|
||||
|
||||
// Simple tuple properties (fast)
|
||||
logger.Information("User action",
|
||||
("UserId", 42),
|
||||
("Action", "login"),
|
||||
("Ip", "192.168.1.1"));
|
||||
|
||||
// Dictionary properties
|
||||
var contextDict = new Dictionary<string, object>
|
||||
{
|
||||
{ "OrderId", "ORD-123" },
|
||||
{ "Items", 5 },
|
||||
{ "Total", 199.99m }
|
||||
};
|
||||
logger.Information("Order processed", contextDict);
|
||||
|
||||
// Exception with context
|
||||
try
|
||||
{
|
||||
throw new InvalidOperationException("Database connection failed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Operation failed",
|
||||
("Retries", 3),
|
||||
("TimeoutMs", 5000),
|
||||
("DatabaseName", "ProductDb"));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- **[GitHub Repository](https://git.saey.me/EonaCat/EonaCat.logstack)** - Source code and issues
|
||||
- **[NuGet Package](https://www.nuget.org/packages/EonaCat.LogStack)** - Official package
|
||||
- **[Supported Targets](#supported-targets)** - .NET versions and frameworks
|
||||
- **[Installation](#installation)** - Getting started guide
|
||||
---
|
||||
Reference in New Issue
Block a user