Monitoring Metrics Logs and Traces
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Monitoring Azure Solutions: Metrics, Logs, and Traces in Application Insights
Introduction: Why Monitoring Matters
In modern cloud-based architectures, the complexity of distributed systems makes it nearly impossible to diagnose issues by simply looking at a single server or a single block of code. When an application spans multiple microservices, relies on external APIs, and interacts with various database technologies, the "it worked on my machine" mentality becomes a liability. Monitoring is the practice of observing the health, performance, and behavior of your software in production to ensure it meets user expectations and business goals.
Azure Application Insights is an extensible Application Performance Management (APM) service designed for developers and DevOps professionals. It acts as the central nervous system for your applications, providing a deep look into how your code executes, how users interact with your interfaces, and where bottlenecks occur. By understanding the triad of observability—Metrics, Logs, and Traces—you gain the ability to move from reactive firefighting to proactive optimization. This lesson explores these three pillars in depth, providing you with the practical knowledge required to implement, query, and interpret data within the Azure ecosystem.
1. Understanding the Observability Triad
To effectively monitor a system, you must understand what each component of the observability triad contributes to your overall diagnostic capability. While these terms are often used interchangeably, they represent distinct types of data that serve different purposes during an incident or performance review.
Metrics: The Quantitative Pulse
Metrics are numerical representations of data measured over intervals of time. They are excellent for answering questions like "How many requests per second are we handling?" or "What is the average CPU utilization of our web servers?" Because metrics are numeric, they are highly efficient to store and query, making them ideal for dashboards and alert thresholds.
Logs: The Historical Record
Logs provide a descriptive, text-based record of events that occurred within your application. Unlike metrics, which tell you that something happened, logs provide the context of why and how it happened. A log entry might contain a timestamp, a severity level, a machine name, and a detailed message describing an exception, a database connection attempt, or a user login event.
Traces: The Journey of a Request
Traces (or distributed traces) capture the lifecycle of a request as it traverses different services, databases, and queues. In a microservices environment, a single user click might trigger a chain reaction involving a front-end service, an authentication service, and a back-end data store. Traces connect these individual operations, allowing you to visualize the latency at every hop and identify exactly which component is responsible for a delay.
Callout: Metrics vs. Logs vs. Traces Think of metrics as the dashboard in your car—speed, fuel level, and engine temperature. They tell you the current state of the vehicle at a glance. Logs are like the service records and repair notes kept by a mechanic—they provide the history of what has been done to the car. Traces are like a GPS tracker that shows the exact path you took during a road trip, including every stop, turn, and traffic jam you encountered along the way.
2. Implementing Application Insights in Your Code
To start collecting data, you must integrate the Application Insights SDK into your application. Whether you are using .NET, Java, Node.js, or Python, the core concept remains the same: you initialize a telemetry client that sends data to your Azure resource.
Setting up in .NET
For a modern .NET application, the most common approach is to use the Microsoft.ApplicationInsights.AspNetCore NuGet package. After adding the package, you configure it in your Program.cs or Startup.cs file.
// Example: Registering Application Insights in ASP.NET Core
var builder = WebApplication.CreateBuilder(args);
// This line automatically picks up the connection string from appsettings.json
builder.Services.AddApplicationInsightsTelemetry();
var app = builder.Build();
Once registered, the SDK automatically collects basic telemetry such as request duration, response codes, and dependencies (like HTTP calls or SQL queries). However, to get the most out of your monitoring, you should manually track custom events and metrics.
Tracking Custom Events
Custom events allow you to track specific business actions, such as "ProductAddedToCart" or "UserSignedUp." This data is invaluable for understanding user behavior.
public class ShoppingCartService
{
private readonly TelemetryClient _telemetry;
public ShoppingCartService(TelemetryClient telemetry)
{
_telemetry = telemetry;
}
public void AddToCart(string productId)
{
// Business logic here
// Track the custom event
var properties = new Dictionary<string, string> { { "ProductId", productId } };
_telemetry.TrackEvent("ProductAddedToCart", properties);
}
}
Note: Be careful not to include Personally Identifiable Information (PII) in custom event properties. Azure logs are often accessible to various team members, and sensitive data like email addresses or credit card numbers should be sanitized or masked before being sent to Application Insights.
3. Mastering Kusto Query Language (KQL)
The power of Application Insights is unlocked through the Kusto Query Language (KQL). KQL is a high-performance, read-only query language used to process data in Azure Monitor and Log Analytics. If you can write a SELECT statement in SQL, you will find KQL intuitive, though it uses a pipe-delimited syntax that feels more like a command-line pipeline.
Basic Query Structure
A KQL query starts with a table name, followed by a series of operators separated by the pipe character (|).
// Example: Find the 10 most recent exceptions
exceptions
| top 10 by timestamp desc
Filtering and Aggregation
To find meaningful insights, you often need to filter data and aggregate it. For example, if you want to identify which API endpoints are returning the most 500-level errors, you could use:
requests
| where resultCode >= 500
| summarize ErrorCount = count() by name
| sort by ErrorCount desc
Analyzing Performance
You can also calculate the 95th percentile (p95) latency of your requests to understand the experience of the slowest 5% of your users.
requests
| summarize p95_duration = percentile(duration, 95) by bin(timestamp, 1h)
| render timechart
4. Distributed Tracing: Connecting the Dots
Distributed tracing is the most effective way to debug complex microservice architectures. When you use the Application Insights SDK, it automatically injects a "Correlation ID" into the headers of your outgoing HTTP requests. When the downstream service receives this request, it reads the ID and continues the trace.
Enabling W3C Trace Context
To ensure interoperability between services (even those not running on Azure), always ensure that your SDK is configured to use the W3C Trace Context standard. This is the default in newer SDK versions, but it is worth verifying in your configuration files.
Visualizing Traces in the Portal
In the Azure Portal, navigate to your Application Insights resource and select "Transaction Search." From here, you can search for a specific operation_Id. When you click on a request, you will see an "End-to-end transaction details" view. This waterfall chart displays every dependency call, database query, and internal method call associated with that specific request.
Warning: Excessive logging can lead to "telemetry spam." If you log every single database row read or every minor loop iteration, you will not only increase your ingestion costs significantly but also make it harder to find the signal in the noise. Always sample your telemetry, especially in high-traffic environments.
5. Best Practices for Effective Monitoring
Monitoring is not a "set it and forget it" task. It requires a disciplined approach to configuration and maintenance.
- Implement Meaningful Alerts: Avoid "alert fatigue" by setting alerts only on actionable metrics. If an alert doesn't require a human to take action, it should probably just be a dashboard widget, not an email notification.
- Use Availability Tests: Configure "URL Ping" or "Multi-step web tests" to simulate user traffic from different geographic locations. This helps you detect outages before your actual users do.
- Standardize Naming Conventions: Ensure that your custom events, custom metrics, and log properties follow a consistent naming convention across all services. This makes writing KQL queries significantly easier.
- Review Quotas and Sampling: Keep an eye on your data ingestion volume. Azure offers adaptive sampling, which reduces the amount of telemetry sent to the server during high-traffic periods while maintaining statistical accuracy.
- Tagging Resources: Apply Azure resource tags to your Application Insights instances to track costs by environment (e.g.,
Env: Production,Env: Staging).
Comparison Table: Monitoring Strategy Options
| Feature | Metrics | Logs | Traces |
|---|---|---|---|
| Primary Use | Real-time health, alerting | Deep dive, diagnostics | Request path, latency |
| Data Type | Numeric | Text/Structured | Hierarchical/Spans |
| Cost | Low | Higher (storage) | Moderate |
| Retention | Usually 90+ days | Configurable | Tied to logs |
6. Common Pitfalls and Troubleshooting
Even with the best tools, developers often fall into traps that hinder their monitoring efforts. Being aware of these common mistakes can save you hours of frustration.
The "Silent Failure" Trap
Developers sometimes wrap their code in global try-catch blocks and log the error to the console, forgetting that consoles are often transient. If you do not explicitly send the exception to Application Insights using telemetry.TrackException(ex), that error will never appear in your logs. Always ensure your telemetry client is globally accessible and used in your exception handling logic.
Missing Context in Logs
A log entry that says "Database connection failed" is useless without knowing which database, which environment, and what the connection string was. Always enrich your logs with custom dimensions.
// Better logging practice
var telemetry = new TelemetryClient();
telemetry.TrackTrace("Database connection failed", SeverityLevel.Error, new Dictionary<string, string> {
{ "DatabaseName", "OrdersDb" },
{ "Environment", "Production" }
});
Ignoring Sampling Rates
If you are troubleshooting a rare, intermittent bug, you might find that the data you need was dropped because of sampling. During active debugging, you may need to temporarily disable sampling or adjust the sampling rate to ensure 100% of the relevant telemetry is captured. Remember to revert these changes once the issue is resolved to avoid unnecessary costs.
Hardcoding Connection Strings
Never hardcode your Application Insights connection string in your source code. Use Azure Key Vault or Environment Variables to inject the connection string at runtime. This practice prevents accidental exposure of your telemetry endpoint and allows you to rotate keys without redeploying your code.
7. Step-by-Step: Setting Up an Alert
Alerts are the mechanism by which your monitoring strategy becomes proactive. Follow these steps to set up a basic availability alert.
- Navigate to the Resource: Open your Application Insights resource in the Azure Portal.
- Select Alerts: In the left-hand menu, under the "Monitoring" section, click on "Alerts."
- Create New Alert Rule: Click on "+ Create" and then "Alert rule."
- Define Condition: Click "Add condition." Search for a signal like "Failed requests" or "Server response time."
- Configure Logic: Set the threshold (e.g., if failed requests > 5 over the last 5 minutes).
- Action Group: Define an Action Group. This specifies what happens when the alert fires (e.g., send an email to the DevOps team, trigger an Azure Function, or create a ticket in ITSM).
- Review and Create: Give your alert a meaningful name and save it.
Callout: Proactive vs. Reactive Alerts Proactive alerts monitor for trends, such as "CPU usage is trending upward over the last 24 hours," allowing you to scale before a crash. Reactive alerts monitor for immediate failures, such as "HTTP 500 error count exceeded 10 in 1 minute." A healthy system uses a mix of both to ensure total visibility.
8. Deep Dive: Advanced KQL Functions
Beyond simple filtering, KQL provides advanced functions that allow for sophisticated data analysis. Learning these will distinguish a basic user from an advanced troubleshooter.
The join Operator
You can join data from different tables. For example, if you want to correlate your request data with your exception data based on the operation_Id:
requests
| join kind=inner (exceptions) on operation_Id
| project timestamp, name, resultCode, exceptionType, outerMessage
The mv-expand Operator
Sometimes, your custom dimensions are stored as dynamic JSON objects or arrays. The mv-expand operator allows you to flatten these structures so you can perform aggregations on individual items within the array.
Using let Statements
let statements act as variables, making your queries more readable and reusable.
let threshold = 500ms;
requests
| where duration > threshold
| summarize avg(duration) by name
9. Industry Standards and Best Practices Summary
As you build your monitoring strategy, adhere to these industry-standard principles:
- The "Golden Signals": Focus your primary dashboards on the four golden signals: Latency (time to serve a request), Traffic (demand on the system), Errors (rate of requests that fail), and Saturation (how "full" your service is).
- Infrastructure-as-Code (IaC): Treat your Application Insights configuration as part of your infrastructure. Use Bicep or Terraform to deploy the Application Insights resource, ensuring that your monitoring environment is consistent across development, testing, and production.
- Telemetry as a First-Class Citizen: Treat logging and instrumentation as part of your core business logic, not an afterthought. When writing a new feature, ask yourself: "How will I know if this feature is working correctly, and how will I know if it has failed?"
- Regular Audits: Periodically review your log retention policies and data costs. Data growth in Log Analytics can be exponential; ensure you are not paying for logs that are no longer useful.
10. Key Takeaways
To conclude, monitoring is the bridge between writing code and maintaining a successful service. By focusing on metrics, logs, and traces, you gain a multi-dimensional view of your system's health.
- Observability is Triad-Based: Metrics provide the "what," logs provide the "why," and traces provide the "where." You need all three to have a complete picture of your application's state.
- KQL is Essential: Mastering the Kusto Query Language is the single most important skill for a developer working with Azure monitoring. It transforms raw data into actionable intelligence.
- Distributed Tracing is Mandatory: In modern cloud architectures, you cannot debug effectively without tracing. Ensure your correlation IDs are flowing correctly through your services.
- Avoid Alert Fatigue: Be intentional with your alerts. Only notify humans for issues that require immediate intervention. Use dashboards for everything else.
- Context is King: Always enrich your logs with custom dimensions. A log entry without context is just noise; a log entry with context is a diagnostic tool.
- Security First: Never log sensitive information. Ensure PII is scrubbed, and use secure methods for managing connection strings.
- Proactive Maintenance: Treat monitoring as a core development task. Use IaC to deploy your monitoring resources and conduct regular audits of your telemetry data and costs.
By applying these principles, you will be well-equipped to handle the challenges of maintaining complex Azure solutions, ensuring that your applications remain performant, reliable, and easy to troubleshoot when things inevitably go wrong.
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons