Modern distributed applications are significantly more complex than traditional monolithic systems. A single user request may pass through multiple microservices, databases, caches, message brokers, and external APIs before returning a response. When performance issues or failures occur, simply reviewing application logs is rarely enough to identify the root cause.

Observability provides a comprehensive view of application behavior by combining logs, metrics, and distributed traces. .NET Aspire simplifies implementing observability by integrating OpenTelemetry into the application lifecycle, enabling developers to monitor distributed systems without extensive custom configuration.

In this article, you'll learn how to implement observability in .NET Aspire using OpenTelemetry, understand the role of logs, metrics, and traces, and build a production-ready monitoring pipeline.

Understanding Observability

What Is Observability?

Observability is the ability to understand the internal state of an application by analyzing the telemetry it produces.

Modern observability consists of three primary pillars:

Together, these signals provide enough context to detect, investigate, and resolve production issues quickly.

Why Observability Matters

Imagine an e-commerce application consisting of several services:

Client
   │
   ▼
API Gateway
   │
   ├────────► Product Service
   │
   ├────────► Inventory Service
   │
   ├────────► Payment Service
   │
   └────────► Notification Service

A customer reports that placing an order takes 12 seconds.

Without observability, developers may spend hours searching logs across multiple services.

With distributed tracing and metrics, they can immediately identify that the delay originates from the Payment Service calling an external payment gateway.

Observability significantly reduces troubleshooting time and improves system reliability.

Configuring .NET Aspire for OpenTelemetry

.NET Aspire includes built-in support for OpenTelemetry.

Configure services during application startup.

var builder = DistributedApplication.CreateBuilder(args);

builder.AddProject<Projects.OrderApi>("orders");

builder.Build().Run();

Why This Configuration?

The distributed application builder establishes communication between application projects and enables Aspire to automatically configure telemetry collection for participating services.

Instead of configuring each microservice independently, Aspire centralizes the setup, reducing duplication and configuration errors.

Adding OpenTelemetry

Register OpenTelemetry services in your application.

builder.Services
    .AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing.AddAspNetCoreInstrumentation();
        tracing.AddHttpClientInstrumentation();
    })
    .WithMetrics(metrics =>
    {
        metrics.AddAspNetCoreInstrumentation();
        metrics.AddRuntimeInstrumentation();
    });

Why Use Automatic Instrumentation?

Automatic instrumentation captures telemetry from ASP.NET Core and HttpClient without requiring developers to manually instrument every request.

This provides immediate visibility into incoming requests, outgoing HTTP calls, and runtime behavior while keeping application code clean.

Collecting Structured Logs

Logging remains one of the most valuable diagnostic tools.

app.Logger.LogInformation(
    "Order {OrderId} created for customer {CustomerId}",
    order.Id,
    order.CustomerId);

Why Use Structured Logging?

Structured logs separate message templates from data values.

Benefits include:

Avoid string concatenation because structured logging platforms cannot efficiently index plain text.

Recording Custom Metrics

Application-specific metrics provide valuable operational insights.

private static readonly Meter Meter =
    new("OrderService");

private static readonly Counter<int> OrdersCreated =
    Meter.CreateCounter<int>("orders.created");

Increment the metric after creating an order.

OrdersCreated.Add(1);

Why Create Custom Metrics?

Runtime metrics provide CPU and memory usage, but business metrics answer operational questions such as:

Custom metrics allow engineering teams to monitor business activity alongside infrastructure health.

Implementing Distributed Tracing

Distributed tracing follows requests across service boundaries.

private static readonly ActivitySource ActivitySource =
    new("OrderService");

Creating an activity:

using var activity =
    ActivitySource.StartActivity("Process Order");

Why Use Activities?

Activities create spans within distributed traces.

When one service calls another, trace context is automatically propagated, allowing developers to visualize the complete request lifecycle across the distributed application.

This dramatically simplifies diagnosing latency issues.

End-to-End Implementation

Consider an online retail platform built with .NET Aspire.

Architecture:

Customer
     │
     ▼
Frontend
     │
     ▼
Order API
     │
 ┌───┴───────────────┐
 ▼                   ▼
Inventory      Payment Service
     │                   │
     └──────────┬────────┘
                ▼
         Notification Service

Workflow:

  1. A customer submits an order.

  2. The Order API creates a distributed trace.

  3. The Inventory Service verifies stock availability.

  4. The Payment Service processes payment.

  5. The Notification Service sends a confirmation email.

  6. Metrics record successful order processing.

  7. Structured logs capture business events.

  8. Distributed traces connect every service involved in the request.

If payment latency suddenly increases, engineers can inspect a single trace and immediately identify which service introduced the delay, eliminating the need to manually correlate logs across multiple applications.

Logs vs Metrics vs Traces

FeatureLogsMetricsDistributed Traces
PurposeEvent detailsSystem healthRequest flow
Data TypeTextNumericRequest timeline
Best ForDebuggingMonitoringRoot cause analysis
Storage VolumeHighLowModerate
AlertingLimitedExcellentModerate

Each telemetry type serves a different purpose, and together they provide a complete picture of application behavior.

Best Practices

Common Mistakes

One common mistake is relying exclusively on logs. While logs provide valuable details, they often lack the context needed to understand request flow across distributed services.

Another issue is creating too many custom metrics. Excessive telemetry increases storage costs and makes dashboards difficult to interpret.

Developers also frequently log sensitive information such as passwords, access tokens, or personal data. Sensitive information should never appear in application logs.

Testing and Validation

Validate your observability implementation before deploying to production.

Recommended validation includes:

Testing observability is just as important as testing application functionality.

Performance Considerations

Telemetry introduces some overhead, but careful configuration minimizes its impact.

Consider these recommendations:

A well-designed observability strategy balances diagnostic value with application performance.

Security Considerations

Observability data often contains operational insights that should be protected.

Follow these recommendations:

Strong observability should improve visibility without compromising security or compliance.

Troubleshooting

Missing Distributed Traces

Verify that OpenTelemetry instrumentation is registered for all participating services and that trace context is propagated between service calls.

Metrics Not Appearing

Confirm that custom meters are registered correctly and that the telemetry exporter is configured for your monitoring platform.

Logs Cannot Be Correlated

Ensure structured logging includes trace and activity identifiers so logs can be linked to distributed traces.

High Telemetry Costs

Review sampling configuration, reduce unnecessary log verbosity, and remove metrics that do not provide operational value.

Conclusion

Observability is a fundamental requirement for modern distributed applications. By combining logs, metrics, and distributed traces, development teams gain the visibility needed to detect issues, understand system behavior, and resolve production problems efficiently. .NET Aspire simplifies OpenTelemetry integration, making it easier to implement a comprehensive observability strategy without extensive configuration. Investing in observability early ensures applications remain reliable, maintainable, and easier to operate as they grow in complexity.