.NET Core 3.1中OpenTelemetry追踪添加自定义属性及Session访问问题
为什么Startup中无法访问Session,以及如何给OpenTelemetry追踪添加会话ID属性
为什么Startup里访问不了Session?
Session是和单个HTTP请求绑定的,必须依赖当前请求的HttpContext才能获取。但Startup类是在应用启动初始化阶段执行的,这时候还没有任何用户请求进来,根本不存在对应的HttpContext和会话数据,所以自然没法直接访问Session。
实现给OpenTelemetry追踪添加会话ID的方法
1. 自定义OpenTelemetry Activity处理器
写一个继承BaseProcessor<Activity>的处理器,通过IHttpContextAccessor拿到当前请求的上下文,从中提取SessionID并添加到追踪标签里。
public class SessionIdTraceProcessor : BaseProcessor<Activity> { private readonly IHttpContextAccessor _httpContextAccessor; public SessionIdTraceProcessor(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public override void OnStart(Activity activity) { var httpContext = _httpContextAccessor.HttpContext; if (httpContext?.Session?.Id != null) { activity.SetTag("session.id", httpContext.Session.Id); } } }
然后在Program/Startup里注册这个处理器(记得先注册IHttpContextAccessor):
// 注册HttpContext访问器 builder.Services.AddHttpContextAccessor(); // 配置OpenTelemetry追踪 builder.Services.AddOpenTelemetry() .WithTracing(tracing => tracing .AddProcessor<SessionIdTraceProcessor>() // 这里继续添加你的其他追踪配置,比如数据源、导出器等 );
2. 用自定义中间件注入会话ID
写一个中间件,在请求管道里获取SessionID,手动添加到当前的追踪Activity中。注意这个中间件要放在Session中间件之后,确保Session已经初始化。
public class SessionIdTraceMiddleware { private readonly RequestDelegate _next; public SessionIdTraceMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var currentActivity = Activity.Current; if (currentActivity != null && context.Session.Id != null) { currentActivity.AddTag("session.id", context.Session.Id); } await _next(context); } }
注册中间件:
// 先启用Session中间件 app.UseSession(); // 再注册自定义的追踪中间件 app.UseMiddleware<SessionIdTraceMiddleware>();
3. 针对MVC/Razor Pages用ActionFilter
如果是MVC或Razor Pages应用,可以写一个ActionFilter,在请求进入Action时添加SessionID到追踪属性。
public class SessionIdTraceFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { var currentActivity = Activity.Current; if (currentActivity != null && context.HttpContext.Session.Id != null) { currentActivity.SetTag("session.id", context.HttpContext.Session.Id); } } public void OnActionExecuted(ActionExecutedContext context) { // 无需额外操作 } }
注册过滤器:
builder.Services.AddControllersWithViews(options => { options.Filters.Add<SessionIdTraceFilter>(); });
内容的提问来源于stack exchange,提问作者pradeep
相关产品推荐
相关产品推荐

