Log Retention ve Storage Stratejileri¶
Log saklama ve depolama stratejileri, maliyeti kontrol altında tutarken gerekli verilere erişimi sağlar; yanlış yönetim disk tükenmesine veya veri kaybına yol açar.
1. Retention Policy Belirlememek¶
❌ Yanlış Kullanım: Tüm logları süresiz saklamak.
builder.Host.UseSerilog((context, config) => config
.WriteTo.File("logs/app.log"));
// Loglar sonsuza kadar birikir, disk dolar
✅ İdeal Kullanım: Seviye bazlı retention policy belirleyin.
builder.Host.UseSerilog((context, config) => config
.WriteTo.File("logs/app-.log",
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 30, // 30 gün
fileSizeLimitBytes: 100_000_000, // 100MB per dosya
rollOnFileSizeLimit: true)
.WriteTo.File("logs/error-.log",
restrictedToMinimumLevel: LogEventLevel.Error,
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 90)); // Hatalar 90 gün
// Elasticsearch ILM
// Hot: 7 gün - SSD, hızlı arama
// Warm: 30 gün - HDD, yavaş ama erişilebilir
// Cold: 90 gün - compress, nadiren erişim
// Delete: 90 gün sonra sil
2. Log Volume Kontrolü Yapmamak¶
❌ Yanlış Kullanım: Her isteği detaylı loglamak.
app.Use(async (context, next) =>
{
_logger.LogInformation("Request: {Method} {Path} Headers: {Headers} Body: {Body}",
context.Request.Method, context.Request.Path,
context.Request.Headers, await ReadBodyAsync(context));
await next();
_logger.LogInformation("Response: {StatusCode} Body: {Body}",
context.Response.StatusCode, responseBody);
// Günde milyonlarca log satırı, storage maliyeti patlar
});
✅ İdeal Kullanım: Akıllı filtreleme ile log hacmini kontrol edin.
builder.Host.UseSerilog((context, config) => config
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
.MinimumLevel.Override("System.Net.Http", LogEventLevel.Warning)
.Filter.ByExcluding(logEvent =>
{
if (logEvent.Properties.TryGetValue("RequestPath", out var path))
{
var pathStr = path.ToString();
return pathStr.Contains("/health") || pathStr.Contains("/metrics");
}
return false;
}));
3. Tek Depolama Katmanı Kullanmak¶
❌ Yanlış Kullanım: Tüm logları aynı storage’da tutmak.
elasticsearch:
volumes:
- es-data:/usr/share/elasticsearch/data
# Tüm loglar aynı SSD'de, maliyet yüksek
✅ İdeal Kullanım: Tiered storage ile maliyeti optimize edin.
# Elasticsearch ILM Policy
# PUT _ilm/policy/log-tiered-storage
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": { "max_size": "10gb", "max_age": "1d" },
"set_priority": { "priority": 100 }
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": { "number_of_shards": 1 },
"forcemerge": { "max_num_segments": 1 },
"set_priority": { "priority": 50 }
}
},
"cold": {
"min_age": "30d",
"actions": {
"freeze": {},
"set_priority": { "priority": 0 }
}
},
"delete": {
"min_age": "90d",
"actions": { "delete": {} }
}
}
}
}
4. Backup Stratejisi Olmamak¶
❌ Yanlış Kullanım: Log verilerini yedeklememek.
# Elasticsearch node çöktüğünde tüm loglar kaybolur
# Replica olmadan çalışma
✅ İdeal Kullanım: Snapshot ve backup stratejisi uygulayın.
// PUT _snapshot/log-backup
{
"type": "fs",
"settings": {
"location": "/backup/elasticsearch",
"compress": true
}
}
// PUT _slm/policy/daily-snapshots
{
"schedule": "0 30 2 * * ?",
"name": "<daily-snap-{now/d}>",
"repository": "log-backup",
"config": {
"indices": ["app-*"],
"ignore_unavailable": true
},
"retention": {
"expire_after": "30d",
"min_count": 5,
"max_count": 30
}
}
5. Log Archival Yapmamak¶
❌ Yanlış Kullanım: Eski logları silmek veya erişilemez bırakmak.
// 30 günden eski loglar siliniyor
// Compliance gereksinimleri karşılanamıyor
// Geçmiş sorunlar analiz edilemiyor
✅ İdeal Kullanım: Eski logları ucuz storage’a arşivleyin.
public class LogArchivalService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken ct)
{
var timer = new PeriodicTimer(TimeSpan.FromDays(1));
while (await timer.WaitForNextTickAsync(ct))
{
var oldIndices = await GetIndicesOlderThan(TimeSpan.FromDays(60));
foreach (var index in oldIndices)
{
// S3/Blob Storage'a arşivle
await _archiveService.ArchiveIndexAsync(index);
// Elasticsearch'ten sil
await _elasticClient.Indices.DeleteAsync(index);
_logger.LogInformation("Index arşivlendi ve silindi: {Index}", index);
}
}
}
}