You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Function(.NET 8)中Serilog.ClientInfo增强器无日志输出问题

解决.NET 8 Azure Function中Serilog无法获取HttpContext的问题

核心原因

.NET 8 Azure Functions默认使用隔离进程模型,该模型下HttpContextAccessor无法直接获取请求上下文——因为隔离进程的执行环境和传统ASP.NET Core不同,需通过FunctionContext来访问Http相关信息。

解决方案步骤

1. 用IFunctionContextAccessor替代HttpContextAccessor

在隔离进程模型中,获取当前请求上下文要依赖IFunctionContextAccessor,而非HttpContextAccessor。该服务已由Functions runtime默认注册,无需手动添加。

2. 自定义Serilog增强器提取Http信息

创建自定义增强器,通过IFunctionContextAccessor获取函数上下文,再从中提取HttpContext及请求头、IP等信息:

public class HttpRequestEnricher : ILogEventEnricher
{
    private readonly IFunctionContextAccessor _functionContextAccessor;

    public HttpRequestEnricher(IFunctionContextAccessor functionContextAccessor)
    {
        _functionContextAccessor = functionContextAccessor;
    }

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        var functionContext = _functionContextAccessor.FunctionContext;
        if (functionContext == null) return;

        // 从函数上下文提取HttpContext
        if (functionContext.Features.TryGetValue(typeof(HttpContext), out var httpContextObj) && 
            httpContextObj is HttpContext httpContext)
        {
            // 添加请求头信息
            if (httpContext.Request.Headers.TryGetValue("X-Platform", out var platform))
            {
                logEvent.AddOrUpdateProperty(propertyFactory.CreateProperty("XPlatform", platform.ToString()));
            }
            if (httpContext.Request.Headers.TryGetValue("X-App-Version", out var version))
            {
                logEvent.AddOrUpdateProperty(propertyFactory.CreateProperty("X-App-Version", version.ToString()));
            }

            // 添加客户端IP
            var clientIp = httpContext.Connection.RemoteIpAddress?.ToString();
            if (!string.IsNullOrEmpty(clientIp))
            {
                logEvent.AddOrUpdateProperty(propertyFactory.CreateProperty("ClientIp", clientIp));
            }
        }
    }
}

3. 重新配置Serilog与依赖注入

修改启动配置,注册自定义增强器并添加到Serilog配置中:

var sinkOptions = new MSSqlServerSinkOptions
{
    TableName = "Logs",
    AutoCreateSqlTable = true,
    BatchPostingLimit = 10
};

// 注册自定义增强器到DI容器
builder.Services.AddSingleton<ILogEventEnricher, HttpRequestEnricher>();

// 从DI中获取增强器实例
var enricher = builder.Services.BuildServiceProvider().GetRequiredService<ILogEventEnricher>();

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .Enrich.With(enricher) // 使用自定义增强器
    .WriteTo.MSSqlServer(
        connectionString: "xxx",
        columnOptions: new ColumnOptions(),
        sinkOptions: sinkOptions,
        restrictedToMinimumLevel: LogEventLevel.Warning
    )
    .CreateLogger();

builder.Services.AddLogging(lb =>
{
    lb.AddSerilog(Log.Logger, true);
});

4. 进程内模型的额外说明

若你使用进程内模型(需在host.json中配置"functionRuntime": "dotnet"),可通过构造函数注入HttpContextAccessor,但需注意:仅HTTP触发的函数执行期间HttpContext有效,非HTTP触发的函数中HttpContext本身就是null。

内容的提问来源于stack exchange,提问作者user3526149

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 00:40:08