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:
Logs – Detailed records of application events.
Metrics – Numeric measurements collected over time.
Distributed Traces – The complete journey of a request across multiple services.
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:
Easier searching
Better filtering
Improved dashboards
More effective alerting
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:
How many orders were processed?
How many invoices failed?
How many users signed in?
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:
A customer submits an order.
The Order API creates a distributed trace.
The Inventory Service verifies stock availability.
The Payment Service processes payment.
The Notification Service sends a confirmation email.
Metrics record successful order processing.
Structured logs capture business events.
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
| Feature | Logs | Metrics | Distributed Traces |
|---|---|---|---|
| Purpose | Event details | System health | Request flow |
| Data Type | Text | Numeric | Request timeline |
| Best For | Debugging | Monitoring | Root cause analysis |
| Storage Volume | High | Low | Moderate |
| Alerting | Limited | Excellent | Moderate |
Each telemetry type serves a different purpose, and together they provide a complete picture of application behavior.
Best Practices
Enable OpenTelemetry early in development.
Use structured logging consistently.
Create business-specific metrics.
Instrument external service calls.
Propagate trace context across services.
Avoid excessive logging at high traffic volumes.
Correlate logs with trace identifiers.
Monitor telemetry storage costs in production.
Configure dashboards and alerts for critical metrics.
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:
Verify logs are generated correctly.
Confirm metrics appear in monitoring dashboards.
Ensure distributed traces span multiple services.
Simulate service failures.
Test external dependency failures.
Validate correlation identifiers.
Perform load testing while monitoring telemetry.
Verify alerts trigger under expected conditions.
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:
Use sampling for high-volume distributed traces.
Log only meaningful business events.
Avoid excessive debug logging in production.
Export telemetry asynchronously.
Aggregate metrics instead of recording excessive detail.
Monitor telemetry pipeline latency.
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:
Never log passwords or authentication tokens.
Mask personally identifiable information (PII).
Encrypt telemetry during transmission.
Restrict access to monitoring dashboards.
Apply role-based access control for observability platforms.
Define retention policies for logs and traces.
Audit access to monitoring systems.
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.
Jasen FiciPosted Aug 6, 2026, 12:58 PM
Thanks for sharing this article. We featured it in DotNetNews here: https://dotnetnews.co/archive/the-net-news-daily-issue-513/