如何获取不含路径变量的请求路径,用于Prometheus指标采集
解决方案
核心实现思路
你需要的路由模板无需自行解析路径参数,可直接通过.NET内置的路由相关API从HttpContext中获取。
具体实现步骤
- 首先确认中间件注册顺序:必须放在
UseRouting()之后,UseEndpoints()/MapControllers()/Minimal API映射逻辑之前,否则无法拿到匹配完成的路由端点信息。 - 引用必要的命名空间:
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing;
- 中间件中获取路由模板的代码示例:
public async Task InvokeAsync(HttpContext context) { // 默认取原始路径作为兜底 var metricPath = context.Request.Path.ToString(); // 尝试获取匹配到的路由端点 if (context.GetEndpoint() is RouteEndpoint routeEndpoint) { // 直接拿到路由模板,格式为 /v1/users/{userId} metricPath = routeEndpoint.RoutePattern.RawText ?? metricPath; } // 这里将metricPath作为Prometheus指标的路径标签值即可,不会出现路径参数打散指标的问题 var requestCounter = Metrics.CreateCounter("http_requests_total", "HTTP请求总量", new CounterConfiguration { LabelNames = new[] { "method", "path", "status_code" } }); requestCounter.WithLabels(context.Request.Method, metricPath, context.Response.StatusCode.ToString()).Inc(); await _next(context); }
从DI容器批量获取所有路由模板
如果你需要提前加载系统所有已注册的路由模板做预处理,可以注入IActionDescriptorCollectionProvider服务实现:
public class RouteTemplateService { public List<string> AllRouteTemplates { get; } public RouteTemplateService(IActionDescriptorCollectionProvider descriptorProvider) { AllRouteTemplates = descriptorProvider.ActionDescriptors.Items // 针对Controller模式路由 .OfType<ControllerActionDescriptor>() .Select(x => x.AttributeRouteInfo?.Template) .Concat( // 针对Minimal API模式路由 descriptorProvider.ActionDescriptors.Items .OfType<RouteEndpointActionDescriptor>() .Select(x => x.RoutePattern.RawText) ) .Where(x => !string.IsNullOrEmpty(x)) .Distinct() .ToList(); } }
注意事项
- 该方案同时兼容Controller路由和Minimal API两种开发模式。
- 未匹配到路由的404请求会回退使用原始请求路径作为标签值,你可以根据业务需求过滤这类请求,避免生成无效指标。
内容的提问来源于stack exchange,提问作者Sinaesthetic
相关产品推荐
相关产品推荐

