Observability notes

How the Full Setup Works Together (Assuming All Are Set Up)

1. ILogger<T> as the unified logging interface

Your app writes logs using ILogger<T>, and the EvLoggingBuilder setup routes these logs to all configured sinks based on:

Example:

_logger.LogWarning("Something might be wrong here");

This log could go to:


Sink Behavior Overview

Sink Captures Triggered By Key Value
Console Logs All levels (e.g., dev only) Local development visibility
Elastic (logs) Logs (structured) All log levels based on config Centralized search and dashboards
Sentry Exceptions and errors Exceptions, logged or unhandled Error visibility with stack traces
Elastic APM Traces, spans, errors Auto and manual instrumentation Performance insights and bottlenecks

How They Complement Each Other

Console

Elastic (logs)

Sentry

Elastic APM


Example Scenario: What Happens When an Error Occurs

Suppose your service throws an exception during a database call.

  1. ILogger.LogError(...) is called.

  2. The log goes to:

    • Console (if dev or forced)
    • Elastic logs (structured, with trace ID)
    • Sentry (captured if severity meets threshold)
  3. Elastic APM also auto-captures:

    • The full trace (request path, DB call span)
    • The exception as part of the trace
  4. Observability tools are connected:

    • Log entry in Kibana links to APM trace ID.
    • Sentry alert shows full stack trace and links to the deployment or release.
    • Prometheus (via /metrics) may show a spike in errors or response times.

Why It’s Not Redundant

Each tool has a distinct lens:

Tool Main Focus Data Type
Console Local dev logs Text
Elastic Centralized logs Structured JSON
Sentry Error debugging Exceptions + context
Elastic APM Performance tracing Spans + metrics

Together they form a complete feedback loop: