Appearance
Observability Overview β
Microtec ERP implements three-pillar observability: Logs, Traces, and Metrics. All observability signals are collected via Serilog and OpenTelemetry and routed to environment-appropriate backends.
Three-Pillar Model β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Microtec ERP Service β
β β
β βββββββββββ βββββββββββββββ ββββββββββββββββββββ β
β β Serilog β β OTLP β β Health Checks β β
β β (Logs) β β (Traces + β β /health endpointβ β
β β β β Metrics) β β β β
β ββββββ¬βββββ ββββββββ¬βββββββ ββββββββββ¬ββββββββββ β
βββββββββΌββββββββββββββββββΌββββββββββββββββββββΌββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββ ββββββββββββββββ ββββββββββββββββ
β Dev: β β Dev: β β Gateway β
β Seq β β Jaeger β β Aggregates β
β :1234 β β :16686 β β /health β
β β β Prometheus β β checks β
β Cloud: β β :9090 β β β
β App β β β β Cloud: β
β Insightsβ β Cloud: β β App Insightsβ
ββββββββββββ β App Insightsβ β Availabilityβ
ββββββββββββββββ ββββββββββββββββPillar 1: Logs (Serilog) β
Technology: Serilog with structured logging
Local Development β
- Backend: Serilog β Seq at
http://localhost:1234 - Frontend: Angular console logger β Browser DevTools
Cloud Environments β
- Backend: Serilog β Application Insights (via Serilog.Sinks.ApplicationInsights)
- Enrichers: Correlation ID (
X-Correlation-ID), tenant ID, user ID, service name, environment
See seq-logging.md for detailed Serilog configuration.
Pillar 2: Traces (OpenTelemetry) β
Technology: OpenTelemetry .NET SDK with OTLP exporter
Local Development β
- OTLP HTTP:
http://localhost:4318 - OTLP gRPC:
http://localhost:4317 - Trace viewer: Jaeger UI at
http://localhost:16686
Cloud Environments β
- Azure Monitor OpenTelemetry exporter β Application Insights
- Distributed traces available in Application Insights Transaction Search and End-to-End Transaction view
What Is Auto-Instrumented β
| Library | Traces Generated |
|---|---|
| ASP.NET Core | Incoming HTTP requests, response codes, duration |
| EF Core | Database queries with SQL text (dev only) |
| HttpClient | Outbound HTTP calls with URLs and status codes |
| Azure Service Bus | Message send/receive operations |
| Redis (StackExchange) | Cache get/set operations |
See opentelemetry.md for configuration details.
Pillar 3: Metrics (OpenTelemetry) β
Technology: OpenTelemetry Metrics API with OTLP exporter
Local Development β
- Prometheus scrape endpoint:
/metricsper service - Prometheus server:
http://localhost:9090 - Grafana dashboard:
http://localhost:3000
Cloud Environments β
- OpenTelemetry metrics β Azure Monitor exporter β Application Insights metrics
- Custom dashboards in Azure Portal workbooks
Default Metrics Collected β
| Metric | Type | Description |
|---|---|---|
http.server.request.duration | Histogram | Incoming request latency (P50/P95/P99) |
http.server.active_requests | UpDownCounter | Concurrent in-flight requests |
db.client.operation.duration | Histogram | Database query latency |
messaging.process.duration | Histogram | Message processing time |
Custom: tenant.active_count | ObservableGauge | Active tenants |
Health Checks β
Per-Service Endpoint β
Every microservice exposes /health with readiness and liveness checks:
csharp
// In Program.cs
builder.Services.AddHealthChecks()
.AddSqlServer(connectionString, name: "sql")
.AddRedis(redisConnectionString, name: "redis")
.AddAzureServiceBus(connectionString, name: "servicebus")
.AddCheck<TenantDbHealthCheck>("tenant-db");
app.MapHealthChecks("/health", new HealthCheckOptions
{
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});Response format:
json
{
"status": "Healthy",
"totalDuration": "00:00:00.0234567",
"entries": {
"sql": { "status": "Healthy", "duration": "00:00:00.0123" },
"redis": { "status": "Healthy", "duration": "00:00:00.0050" },
"servicebus": { "status": "Healthy", "duration": "00:00:00.0060" }
}
}Gateway Aggregation β
The Gateway.API aggregates health checks from all downstream services and exposes a combined /health endpoint. This single endpoint is used by:
- Azure Front Door health probes
- Production monitoring alerts
- Pipeline deployment verification
Local Development Stack β
The full observability stack runs locally via Docker Compose in dev/:
| Service | Port | Purpose |
|---|---|---|
| Seq | 1234 | Structured log viewer |
| Jaeger | 16686 | Distributed trace viewer |
| Prometheus | 9090 | Metrics scrape and query |
| Grafana | 3000 | Metrics dashboards |
| OpenTelemetry Collector | 4317, 4318 | OTLP receiver and router |
Start all observability services:
bash
cd dev
docker compose up -d seq jaeger prometheus grafana otel-collectorCloud Observability Stack β
In all cloud environments (dev through production), observability is unified in Azure Monitor:
| Signal | Source | Destination |
|---|---|---|
| Logs | Serilog HTTP sink | Application Insights |
| Traces | OTLP β Azure Monitor exporter | Application Insights |
| Metrics | OTLP β Azure Monitor exporter | Application Insights |
| Health | /health probes | Application Insights Availability |
| Container logs | Container Apps runtime | Log Analytics Workspace |
Correlation and Context Propagation β
All signals share the same correlation context using W3C Trace Context (traceparent/tracestate headers):
Client β Gateway (generates trace ID: abc123)
β traceparent: 00-abc123-00-01
βΌ
Accounting API (inherits trace ID: abc123)
β traceparent: 00-abc123-11-01
βΌ
SQL Database (query tagged with trace ID: abc123)The X-Correlation-ID header is also propagated as a Serilog log enricher for log-level correlation.