How Application Insights names requests, and how to change operation_Name
A request's name is its low-cardinality group: the HTTP method plus the route template, such as GET /orders/{id}, never the raw URL. The classic SDK sets it, and operation_Name on every related item, with OperationNameTelemetryInitializer. With SDK 3.x and the OpenTelemetry distros the request is the server span, and OpenTelemetry names it method plus http.route, or the method alone when no route matched. To rename, change RequestTelemetry.Name and the operation name together in 2.x, or the activity's DisplayName in an OpenTelemetry processor.
The Performance and Failures views, every “slowest operations” chart and most alert queries group by request name. When names are wrong, either too many (a row per user ID) or too few (everything called GET), every one of those views stops being useful.
What a request records
Each incoming request becomes one row in requests (AppRequests):
name: the logical group, meant to be low-cardinality. For HTTP, Microsoft’s data model describes it as the method and URL path template, likeGET /values/{id}.url: the actual URL, with all query string parameters.resultCode: the HTTP status code, or another value such as an exception type for non-HTTP requests.success: a separate judgement, set by the SDK or by you.duration,idandsourcefor timing and correlation.
And every related item (dependencies, logs, exceptions) carries operation_Name: the name of the request or page view that started the operation. That makes renaming a two-part job. Change the request’s name without its operation name and the request row moves to a new group while its children stay in the old one.
The web SDK sends names as they are, and the portal groups them case-sensitively: GET /Home/Index and GET /home/INDEX are two rows.
Classic SDK 2.x
In the .NET SDK 2.x (deprecated, retiring March 31, 2027), OperationNameTelemetryInitializer sets both the request’s Name and the Operation.Name of every item. In classic ASP.NET it builds the name from the HTTP method and the MVC controller and action that handled the request.
Rename the current request
To change the name from inside the request (a Web API action that knows a better name, say), get the request telemetry from the HTTP context. In ASP.NET Core:
var request = HttpContext.Features.Get<RequestTelemetry>();
if (request is not null)
{
request.Name = "POST /orders/{id}/cancel";
request.Context.Operation.Name = request.Name;
}
Classic ASP.NET stores it in HttpContext.Current.Items["Microsoft.ApplicationInsights.RequestTelemetry"]. For a rule that applies to many requests, write an initializer that does the same for every RequestTelemetry and sets telemetry.Context.Operation.Name on the other items; see telemetry initializers.
Success and response codes
The SDK marks a request failed when its response code is 400 or above, except 401. That isn’t always what the response means. Microsoft’s data model gives examples: a 404 can mean “no records” in a normal flow, while 206 or 207 can hide a partial failure. An initializer can set Success itself, and the SDK won’t overwrite it:
public class NotFoundIsSuccess : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
if (telemetry is RequestTelemetry r && r.ResponseCode == "404" && r.Name?.StartsWith("GET /api/lookup") == true)
{
r.Success = true;
r.Properties["Overridden404"] = "true";
}
}
}
Tagging overridden items, as Microsoft’s own sample does, keeps them findable.
Static files and missing 404s
In classic ASP.NET, requests are recorded by RequestTrackingTelemetryModule, an HTTP module registered in web.config. Its default configuration excludes a list of handlers, including System.Web.StaticFileHandler, the bundling handler and the assembly resource loader, so static files and bundles don’t appear as requests by design. The module records requests that pass through ASP.NET; if a 404 never shows up, check first whether ASP.NET handled that request at all.
Today: SDK 3.x and the Microsoft OpenTelemetry Distro
SDK 3.x removed OperationNameTelemetryInitializer; names now come from OpenTelemetry instrumentation, as they do in the Microsoft OpenTelemetry Distro. The request is the server span, so OpenTelemetry’s HTTP naming rule applies:
- A server span is named
{method} {http.route}, for exampleGET /orders/{id}. - If there’s no low-cardinality route, the name is just the method:
GET. - Instrumentation must never fall back to the raw URL path.
That last rule is why apps on OpenTelemetry often see a large GET group: middleware that answers without routing, health endpoints and unmatched URLs all land there.
Rename in a processor
Microsoft’s examples rename by changing the activity’s DisplayName when the span ends. Here, unmatched GET requests get a name from their first path segment:
using System.Diagnostics;
using System.Linq;
using OpenTelemetry;
public class RequestNameProcessor : BaseProcessor<Activity>
{
public override void OnEnd(Activity activity)
{
if (activity.Kind == ActivityKind.Server && activity.DisplayName == "GET")
{
var path = activity.GetTagItem("url.path") as string ?? "";
var first = path.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
activity.DisplayName = first is null ? "GET /" : $"GET /{first}/*";
}
}
}
Register it with builder.Services.ConfigureOpenTelemetryTracerProvider((sp, t) => t.AddProcessor(new RequestNameProcessor())) before the distro (or SDK 3.x) registration. Keep the result low-cardinality: never put IDs in a name. In Python, call span.update_name(...) in a span processor. Microsoft doesn’t document the exact span-to-operation_Name mapping for every framework, so check a few rows in requests and traces after any change.
One known gap to be aware of: Microsoft lists “the operation name is missing from dependency telemetry” as a known issue of the OpenTelemetry exporters, which affects the Failures and Performance views for dependencies.
Success with OpenTelemetry
OpenTelemetry leaves the status of a server span unset for 4xx responses. Microsoft’s sample notes that the Azure Monitor exporter then treats any 4xx as a failure, and shows a processor that sets the status to Ok for 4xx on server spans to count them as successful; the status code itself is unchanged. Apply that only to the routes where a 4xx is normal.
Java and query strings
Java 3.x produces parameterized operation names, where 2.x sometimes used full paths; telemetry processors (preview) can rebuild the old style from http.request.method and url.path. And because url keeps the query string, apps that put tokens in URLs should turn on the .NET distro’s query redaction (OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION and the HttpClient equivalent set to false).
Requests that aren’t HTTP
A request is any unit of work your app starts on someone else’s behalf, so queue messages, scheduled jobs and console batch steps can be requests too, and naming them matters just as much. In 2.x, wrap the work in telemetryClient.StartOperation<RequestTelemetry>("ProcessOrderMessage"); the name you pass becomes the request name, and items tracked inside the using block belong to that operation.
With OpenTelemetry, start an activity from your own ActivitySource (registered with AddSource) and give it a kind. Microsoft documents that ActivityKind.Server and ActivityKind.Consumer map to requests, while Client, Producer and the default Internal map to dependencies:
using var activity = MessagingSource.StartActivity("ProcessOrderMessage", ActivityKind.Consumer);
Choose the name the same way as for HTTP: the kind of work, not the message ID.
Find naming problems in KQL
Names with many distinct URLs are fine (that’s a template doing its job); names that each match one URL suggest IDs leaking into names:
requests
| where timestamp > ago(1d)
| summarize requests = sum(itemCount), urls = dcount(url) by name
| order by requests desc
Pair it with the latency by operation and failed requests by result code queries once names are clean.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Thousands of request names | IDs or raw paths in names | Use route templates; rename in an initializer or processor |
One huge GET group (OpenTelemetry) | No route matched | Rename unmatched spans in a processor |
| Same route split in two | Case differences in URLs | Normalise case when renaming |
| Children grouped under the old name | Only Name changed in 2.x | Set Context.Operation.Name too |
| 404s counted as failures | Default success rule | Override per route |
| Static files missing (classic ASP.NET) | Excluded handlers | Expected; remove the handler from the list only if you need them |
Queries for this topic
-
Requests slower than a threshold, by operation
requests latency
Returns: One row per operation that had at least one request over the threshold, with its total requests, the number over the threshold and that number as a percentage.
-
Request latency p50, p95 and p99 by operation
requests latency
Returns: One row per operation name with its request count and its p50, p95 and p99 duration in milliseconds, slowest p95 first.
Frequently asked questions
What is the difference between name and operation_Name?
name belongs to the request row itself. operation_Name is a context field on every item in the operation (dependencies, traces, exceptions) and carries the name of the request or page view that started it, so you can ask which exceptions happen under GET /orders/{id}.
Which HTTP status codes count as failed requests?
Microsoft's data model treats a request as successful when the response code is below 400 or exactly 401. With the OpenTelemetry exporter, Microsoft's own sample notes that 4xx responses on server spans count as failures unless the span status is set to Ok.
Why are so many requests named just GET?
OpenTelemetry names a server span after its route. When no route matched (middleware that answers directly, a 404 or a static file), there is no low-cardinality target, so the name is the method alone. Rename those spans in a processor if you need them separated.
Sources, checked
- Application Insights telemetry data model (request and context fields)
- Monitor .NET and Node.js applications with Application Insights (Classic API 2.x)
- Semantic conventions for HTTP spans (OpenTelemetry)
- Add and modify OpenTelemetry in Application Insights
- Migrate Application Insights Classic API SDKs to OpenTelemetry (Java operation names)
- Troubleshoot OpenTelemetry issues in .NET (known issues)
- Configure OpenTelemetry in Application Insights (redact URL query strings)