如何在Blazor Server中配置Application Insights以在追踪中包含认证用户
问题根因
你编写的UserTelemetryInitializer依赖IHttpContextAccessor获取用户信息,而Blazor Server基于SignalR长连接运行:只有首次建立连接的握手阶段存在标准HTTP上下文,后续所有组件交互、日志输出的执行上下文都脱离了HTTP请求生命周期,IHttpContextAccessor无法拿到有效的HttpContext,导致用户ID赋值为空。
解决方案
步骤1:注册必要服务
先确保你已经注册了IHttpContextAccessor和ICircuitAccessor,用于分别获取HTTP请求和Blazor Circuit上下文的用户信息:
// 放在服务注册最前面 services.AddHttpContextAccessor(); services.AddScoped<ICircuitAccessor, CircuitAccessor>();
步骤2:修改TelemetryInitializer,适配Blazor长连接场景
修改初始化器逻辑,优先从HTTP上下文取用户,HTTP上下文为空时从Blazor Circuit上下文取用户:
public class UserTelemetryInitializer : ITelemetryInitializer { private readonly IHttpContextAccessor _httpContextAccessor; private readonly ICircuitAccessor _circuitAccessor; public UserTelemetryInitializer(IHttpContextAccessor httpContextAccessor, ICircuitAccessor circuitAccessor) { _httpContextAccessor = httpContextAccessor; _circuitAccessor = circuitAccessor; } public void Initialize(ITelemetry telemetry) { var userId = string.Empty; // 优先取HTTP上下文的用户(适用于普通请求、Blazor握手阶段) if (_httpContextAccessor.HttpContext?.User.Identity?.IsAuthenticated == true) { userId = _httpContextAccessor.HttpContext.User.Identity.Name; } // HTTP上下文为空时,取Blazor Circuit的用户(适用于长连接运行阶段) else if (_circuitAccessor.Circuit?.User.Identity?.IsAuthenticated == true) { userId = _circuitAccessor.Circuit.User.Identity.Name; } if (!string.IsNullOrEmpty(userId)) { telemetry.Context.User.Id = userId; telemetry.Context.User.AuthenticatedUserId = userId; } } }
步骤3:验证注册顺序
确保UserTelemetryInitializer的注册在AddApplicationInsightsTelemetry之前:
services.AddSingleton<ITelemetryInitializer, UserTelemetryInitializer>(); services.AddApplicationInsightsTelemetry(options => options.ConnectionString = Configuration.GetValue<string>("APPINSIGHTS_CONNECTIONSTRING"));
完成以上修改后,Blazor组件输出的日志就可以正常关联到登录用户ID了。
内容的提问来源于stack exchange,提问作者Liero
相关产品推荐
相关产品推荐

