Instrumenting Apps with Application Insights
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
Lesson: Instrumenting Applications with Azure Application Insights
Introduction: Why Observability Matters
In the modern landscape of distributed systems and microservices, knowing that your application is "running" is no longer enough. You need to know how it is behaving, how it is performing for the end user, and precisely where it is failing when things go wrong. Application Insights, a feature of Azure Monitor, is an extensible Application Performance Management (APM) service for developers and DevOps professionals. It acts as the "eyes and ears" of your production environment, allowing you to capture telemetry, analyze performance bottlenecks, and diagnose exceptions in real time.
Instrumenting your application is the process of embedding hooks into your code, configuration, or infrastructure that emit data about the application's internal state. Without proper instrumentation, you are essentially flying blind. You might know that a server is responding, but you won't know if a specific database query is taking three seconds to complete or if a specific user segment is experiencing 404 errors during the checkout process. This lesson will guide you through the process of instrumenting applications, moving from basic configuration to advanced telemetry collection, and establishing a culture of observability.
The Foundation of Telemetry
Before diving into code, it is essential to understand what exactly we are collecting. Application Insights revolves around the concept of telemetry—data points that describe the health and activity of your application. These telemetry items are stored in a centralized Azure Log Analytics workspace, where they can be queried, graphed, and alerted upon.
The primary types of telemetry include:
- Requests: These represent the incoming HTTP requests to your application. They track the URL, duration, response code, and the outcome (success or failure).
- Dependencies: These are the calls your application makes to external services, such as database queries, REST API calls, or calls to Azure Storage.
- Exceptions: These are handled and unhandled errors that occur within your code. They include the full stack trace, which is critical for debugging.
- Traces: These are custom log messages (often referred to as logs or traces) that you inject into your code to provide context during execution.
- Events: Custom events allow you to track user behavior, such as clicking a "Buy Now" button or completing a registration flow.
- Metrics: These are numerical values that represent the state of your application, such as CPU usage, memory consumption, or business-specific counts like "items added to cart."
Callout: Telemetry vs. Logs While logs are often just text files on a disk, telemetry is structured data. Because telemetry is structured (meaning it has fields like 'Duration', 'Timestamp', and 'ResultCode'), you can perform complex analytics across millions of records. You can calculate the 95th percentile of response times or correlate a specific database dependency failure with a user's session ID.
Getting Started: Auto-Instrumentation vs. Manual Instrumentation
There are two primary ways to get telemetry into Application Insights: auto-instrumentation and manual instrumentation. Understanding the distinction between these two is the first step toward a successful implementation strategy.
Auto-Instrumentation (The "Zero-Code" Approach)
For many platforms, such as .NET, Java, and Node.js, you can enable Application Insights without changing a single line of code. By installing the Application Insights agent or enabling the extension in the Azure App Service environment, the runtime environment automatically intercepts calls to common libraries.
- Pros: Extremely fast setup, provides immediate visibility into request/dependency patterns, and requires no maintenance as the application code changes.
- Cons: Limited visibility into custom business logic, generic naming conventions for operations, and potential for "noise" if the application environment is chatty.
Manual Instrumentation (The "SDK" Approach)
Manual instrumentation involves adding the Application Insights SDK to your project and writing code to track specific events, custom metrics, or specific business transactions.
- Pros: Full control over what is tracked, the ability to add custom properties to telemetry, and the ability to track business-specific workflows.
- Cons: Requires code changes, testing, and ongoing maintenance as the application evolves.
Note: Most successful teams use a hybrid approach. They use auto-instrumentation to capture the "baseline" (requests, dependencies, and exceptions) and supplement it with manual instrumentation to capture business-critical events and custom traces.
Step-by-Step: Instrumenting a .NET Application
Let us walk through the process of manually instrumenting a .NET application using the Application Insights SDK. This approach provides the highest level of detail.
1. Install the SDK
First, add the NuGet package to your application. If you are using the .NET CLI, run the following command:
dotnet add package Microsoft.ApplicationInsights.AspNetCore
2. Configure the Service
In your Program.cs or Startup.cs file, you need to register the Application Insights service. This tells the application how to connect to your Azure resource.
// In Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add Application Insights to the DI container
builder.Services.AddApplicationInsightsTelemetry(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]);
var app = builder.Build();
3. Injecting the Telemetry Client
The TelemetryClient is your primary tool for sending custom telemetry data. You can inject this into your controllers, services, or middleware.
public class OrderService
{
private readonly TelemetryClient _telemetryClient;
public OrderService(TelemetryClient telemetryClient)
{
_telemetryClient = telemetryClient;
}
public void ProcessOrder(int orderId)
{
// Custom event tracking
var properties = new Dictionary<string, string> { { "OrderId", orderId.ToString() } };
_telemetryClient.TrackEvent("OrderProcessed", properties);
}
}
By adding the OrderId as a property, you can later filter your telemetry in the Azure portal to see all events associated with a specific order, which is invaluable for troubleshooting specific customer issues.
Advanced Instrumentation: Custom Metrics and Tracing
Sometimes, tracking events isn't enough. You need to track numerical trends. Custom metrics are designed for high-performance, aggregate data tracking.
Tracking Custom Metrics
Suppose you want to monitor the "StockLevel" of an item in real time. Instead of logging every single update, you can track the metric.
// Track a custom metric
_telemetryClient.GetMetric("StockLevel").TrackValue(currentStock);
Application Insights automatically aggregates these values, reducing the amount of data sent over the network while still providing you with precise graphs of your stock levels over time.
Using Telemetry Initializers
If you find yourself manually adding the same properties (like Environment or Region) to every single telemetry item, use a TelemetryInitializer. This allows you to enrich all telemetry globally.
public class MyTelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
telemetry.Context.GlobalProperties["Environment"] = "Production";
telemetry.Context.GlobalProperties["Version"] = "1.0.4";
}
}
Register this in your Program.cs:
builder.Services.AddSingleton<ITelemetryInitializer, MyTelemetryInitializer>();
Best Practices for Effective Instrumentation
Instrumenting an application is not just about writing code; it is about gathering data that is actually useful. Poorly planned instrumentation can lead to "data drowning," where you have millions of logs but cannot find the information you need.
1. Consistency in Naming
Decide on a naming convention early. If one developer logs an event as UserLogin and another logs it as User_Login_Attempt, your reports will be fragmented. Establish a naming standard (e.g., Category_ActionName) and stick to it across your entire team.
2. Avoid Sensitive Data
Never log personally identifiable information (PII) such as passwords, credit card numbers, or social security numbers. Application Insights is a powerful tool, but it should not become a repository for sensitive data that violates compliance policies.
3. Use Correlation IDs
When an application spans multiple services, it is critical to pass a correlation ID (often the Request-Id or Trace-Id) from service to service. Application Insights uses this to build an "Application Map," which visually links your services and shows exactly where a request failed in the chain.
Warning: Performance Impact While the Application Insights SDK is designed to be lightweight, excessive logging—especially inside tight loops—can impact application performance. Always monitor the impact of your logging and use sampling if your application generates massive volumes of telemetry.
4. Implement Sampling
If your application receives millions of requests, you do not necessarily need to log every single one to understand the health of the system. Adaptive sampling automatically reduces the volume of telemetry sent to Azure when the rate of data exceeds a certain threshold, ensuring you don't hit your data ingestion limits or incur unexpected costs.
Comparison: Instrumentation Strategies
| Strategy | Effort | Granularity | Maintenance |
|---|---|---|---|
| Auto-Instrumentation | Low | Low (Standard metrics only) | Low |
| SDK-based Manual | High | High (Custom events/metrics) | Medium |
| OpenTelemetry (OTel) | Medium | High (Standardized) | Low/Medium |
Callout: The Rise of OpenTelemetry OpenTelemetry is an industry-standard framework that allows you to instrument your code once and send that data to any backend, including Application Insights. If you want to avoid "vendor lock-in," instrumenting your code using the OpenTelemetry SDK is the modern industry standard. It provides a consistent way to collect traces, metrics, and logs, and Azure has first-class support for OTel exporters.
Common Pitfalls and Troubleshooting
Even with the best intentions, instrumentation can go wrong. Here are the most common mistakes developers make and how to avoid them.
1. Missing Connection Strings
The most common error is forgetting to set the APPLICATIONINSIGHTS_CONNECTION_STRING in the environment variables. If the SDK cannot find the connection string, it will fail silently and no data will be sent.
- Fix: Always include a check in your startup code that throws an exception if the connection string is missing in a production environment.
2. Over-Logging
Logging every single variable in a function creates "log spam." This makes it impossible to see the "signal" through the "noise."
- Fix: Only log events that indicate a state change or a significant business transaction. Use the log levels (
Information,Warning,Error,Critical) appropriately. OnlyErrorandCriticalshould be used for failures.
3. Ignoring the Application Map
Developers often ignore the Application Map, preferring to look at raw log tables. The Application Map is the single most effective tool for identifying bottlenecks.
- Fix: If you see a red line between your web app and your database on the map, click it. It will immediately show you the failing queries and the latency distribution.
4. Forgetting to Dispose of Clients
In some cases, if you manually create telemetry clients rather than using the dependency-injected version, you might forget to dispose of them. This can lead to memory leaks in long-running processes.
- Fix: Always use the dependency injection pattern provided by the SDK to let the framework manage the lifecycle of your telemetry clients.
Managing Costs and Data Retention
Application Insights is billed based on the amount of data ingested. If you instrument your application to log everything, your bill will grow quickly.
- Daily Caps: You can set a daily cap on your Application Insights resource to prevent runaway costs. If the limit is reached, the service will stop collecting data for the rest of the day.
- Data Retention: By default, data is kept for 90 days. You can adjust this from 30 days up to 730 days. Be mindful that longer retention periods increase the storage cost of your Log Analytics workspace.
- Sampling: Use adaptive sampling (enabled by default in many SDKs) to keep costs predictable while maintaining statistically significant data.
Practical Scenario: Debugging a Failing API Call
Imagine your users report that the "Update Profile" feature is timing out. Here is how you use your instrumentation to solve it:
- Check the Application Map: You see a red link between your "User Service" and the "Profile Database."
- Drill Down: Click the red link. You see a list of failed dependency calls.
- Analyze the Exception: Click one of the failed dependency items. You see the exact SQL query that failed and the corresponding stack trace.
- Correlate: Look at the "Related Items" tab to see all logs that happened during that specific request. You notice that just before the SQL timeout, there was a series of heavy data processing operations.
- Resolution: You identify that an unoptimized LINQ query is causing a table scan. You add an index to the database, deploy, and use the "Live Metrics" view in Application Insights to verify the latency drops immediately.
Quick Reference Table: Telemetry Types
| Telemetry Type | Purpose | Use Case |
|---|---|---|
| Request | Track incoming traffic | API endpoint performance |
| Dependency | Track outbound calls | Database, Cache, or API usage |
| Exception | Track failures | Catching bugs in code |
| Trace | Log messages | Debugging complex logic |
| Event | Business tracking | User sign-ups, clicks |
| Metric | Numerical aggregation | CPU, Memory, Business KPIs |
Summary of Best Practices
- Instrument Early: Start with auto-instrumentation during development to get immediate baseline data.
- Use DI: Always use Dependency Injection for the
TelemetryClientto ensure proper lifecycle management. - Standardize: Agree on naming conventions for custom events and metrics across your team.
- Monitor Costs: Set a daily cap and configure alerts to notify you if data ingestion spikes unexpectedly.
- Correlate: Always ensure your distributed services pass along correlation headers so the Application Map can function correctly.
- Avoid PII: Scrub your data before sending it to ensure no sensitive user information is stored in your logs.
- Leverage OTel: When starting a new project, consider using OpenTelemetry to ensure your instrumentation remains portable and modern.
Key Takeaways
- Observability is mandatory: In modern systems, instrumentation is not optional; it is the core requirement for maintaining stable and performant production services.
- Hybrid instrumentation works best: Combine the ease of auto-instrumentation for standard telemetry with the precision of manual instrumentation for business-specific logic.
- Data quality over quantity: High volumes of noise make troubleshooting harder. Focus on collecting meaningful events that describe the user journey and system health.
- The Application Map is your best friend: Visualizing dependencies is the fastest way to identify the source of performance issues in distributed architectures.
- Proactive monitoring pays off: By instrumenting correctly, you move from "reactive firefighting" (waiting for users to report bugs) to "proactive observability" (finding and fixing bottlenecks before they affect the user).
- Cost Management: Instrumentation must be balanced against operational costs. Use sampling and daily caps to keep your budget under control.
- Industry Standards: Adopting OpenTelemetry ensures that your observability investment remains relevant and compatible with the broader ecosystem, preventing vendor lock-in.
By following these guidelines and implementing a thoughtful instrumentation strategy, you transform your application from a "black box" into a transparent system that provides clear, actionable insights into its own performance and health. This maturity is what separates a good development team from a great one.
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