# Observability Guide - Serilog & OpenTelemetry

## Tổng quan

Dự án đã được tích hợp **Serilog** (Structured Logging) và **OpenTelemetry** (Distributed Tracing) để hỗ trợ giám sát và debug ứng dụng khi chạy trên production/Docker.

## Serilog - Structured Logging

### Tính năng

- **JSON Format**: Log được ghi dưới dạng JSON, dễ dàng parse và filter
- **Multiple Sinks**: Console, File, Seq, Elasticsearch
- **Enrichment**: Tự động thêm thông tin như Environment, MachineName, ThreadId
- **Rolling Files**: Tự động rotate log files theo ngày/tuần/tháng

### Cấu hình trong appsettings.json

```json
{
  "Serilog": {
    "MinimumLevel": "Information",
    "Override": {
      "Microsoft": "Warning",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.EntityFrameworkCore": "Warning"
    },
    "WriteToConsole": true,
    "WriteToFile": true,
    "FilePath": "logs/log-.txt",
    "RollingInterval": "Day",
    "RetainedFileCountLimit": 31,
    "SeqUrl": "http://localhost:5341",
    "ElasticsearchUrl": null
  }
}
```

### Sử dụng trong Code

```csharp
using Serilog;

public class MyService
{
    private readonly ILogger _logger;

    public MyService(ILogger logger)
    {
        _logger = logger;
    }

    public void DoSomething()
    {
        // Structured logging với properties
        _logger.Information(
            "Processing order {OrderId} for user {UserId}",
            orderId,
            userId
        );

        // Log với exception
        try
        {
            // ...
        }
        catch (Exception ex)
        {
            _logger.Error(ex, "Failed to process order {OrderId}", orderId);
        }
    }
}
```

### Log Levels

- **Verbose**: Chi tiết nhất, dùng cho debug
- **Debug**: Thông tin debug
- **Information**: Thông tin thông thường (mặc định)
- **Warning**: Cảnh báo
- **Error**: Lỗi
- **Fatal**: Lỗi nghiêm trọng, ứng dụng có thể crash

### Tích hợp với Seq (Development)

1. Chạy Seq trong Docker:
```bash
docker run -d --name seq -p 5341:80 -e ACCEPT_EULA=Y datalust/seq:latest
```

2. Cập nhật appsettings.json:
```json
{
  "Serilog": {
    "SeqUrl": "http://localhost:5341"
  }
}
```

3. Xem logs tại: http://localhost:5341

### Tích hợp với ELK Stack (Production)

1. Cài đặt Elasticsearch và Kibana
2. Cập nhật appsettings.json với ElasticsearchUrl
3. Xem logs trong Kibana dashboard

## OpenTelemetry - Distributed Tracing

### Tính năng

- **Distributed Tracing**: Theo dõi request qua nhiều services
- **Performance Monitoring**: Đo thời gian thực thi từng operation
- **Automatic Instrumentation**: Tự động instrument ASP.NET Core, HTTP Client, EF Core
- **OTLP Export**: Export traces đến các hệ thống như Jaeger, Zipkin, Grafana

### Cấu hình

OpenTelemetry đã được cấu hình tự động trong `Program.cs`:

```csharp
builder.Services.AddOpenTelemetryTracing("MyNewProjectName.WebAPI");
```

### Instrumentation tự động

- **ASP.NET Core**: Tự động trace HTTP requests/responses
- **HTTP Client**: Trace các HTTP calls đến external APIs
- **Entity Framework Core**: Trace database queries

### Xem Traces

#### Option 1: Console (Development)

Traces được export ra console, có thể thấy trong log output.

#### Option 2: OTLP Collector (Production)

1. Chạy OTLP Collector:
```yaml
# docker-compose.yml
services:
  otlp-collector:
    image: otel/opentelemetry-collector:latest
    ports:
      - "4317:4317" # OTLP gRPC receiver
      - "4318:4318" # OTLP HTTP receiver
    volumes:
      - ./otel-collector-config.yaml:/etc/otelcol/config.yaml
```

2. Cấu hình export trong code (nếu cần):
```csharp
.AddOtlpExporter(options =>
{
    options.Endpoint = new Uri("http://otlp-collector:4317");
})
```

3. Export đến Jaeger, Zipkin, hoặc Grafana Tempo

### Tích hợp với Jaeger

1. Chạy Jaeger:
```bash
docker run -d --name jaeger \
  -p 16686:16686 \
  -p 4317:4317 \
  jaegertracing/all-in-one:latest
```

2. Xem traces tại: http://localhost:16686

## Best Practices

### 1. Structured Logging

✅ **Tốt**: Sử dụng structured logging với properties
```csharp
_logger.Information("User {UserId} created order {OrderId}", userId, orderId);
```

❌ **Không tốt**: String interpolation
```csharp
_logger.Information($"User {userId} created order {orderId}");
```

### 2. Log Levels

- **Information**: Business events (user login, order created)
- **Warning**: Unexpected situations (retry, fallback)
- **Error**: Exceptions và failures
- **Debug**: Chi tiết kỹ thuật (chỉ trong development)

### 3. Correlation ID

Sử dụng correlation ID để link logs và traces:

```csharp
// Trong middleware
var correlationId = Guid.NewGuid().ToString();
LogContext.PushProperty("CorrelationId", correlationId);
```

### 4. Sensitive Data

❌ **Không log**:
- Passwords
- Credit card numbers
- API keys
- Personal information (PII)

✅ **Log**:
- User IDs (không phải username/email)
- Order IDs
- Request/Response metadata (không có sensitive data)

## Monitoring trong Docker

Khi chạy trong Docker, logs được ghi vào:
- **Console**: `docker logs <container-name>`
- **Files**: `logs/log-*.txt` trong container
- **Seq/ELK**: Nếu đã cấu hình

### Xem logs trong Docker

```bash
# Xem logs real-time
docker logs -f webapi

# Xem logs với timestamp
docker logs -t webapi

# Xem logs của 100 dòng cuối
docker logs --tail 100 webapi
```

## Troubleshooting

### Logs không xuất hiện

1. Kiểm tra `Serilog:WriteToConsole` trong appsettings.json
2. Kiểm tra `Serilog:MinimumLevel` có quá cao không
3. Kiểm tra Docker logs: `docker logs <container-name>`

### Traces không hiển thị

1. Kiểm tra OpenTelemetry đã được add trong Program.cs
2. Kiểm tra OTLP endpoint nếu dùng collector
3. Kiểm tra network connectivity đến collector

### Performance Impact

- Serilog: Minimal impact, async logging
- OpenTelemetry: ~1-2% overhead, có thể disable trong development nếu cần
