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

如何为Serilog Http Sink配置Bearer认证实现Logtail日志上报

问题分析与解决方案

你的代码无法正常上报日志到Logtail,核心问题及修复方案如下:

核心问题

  1. 认证头未生效:自定义CustomHttpClient中的Configure方法不会被Serilog Http Sink自动调用,导致Bearer认证头从未被添加到请求中。
  2. 程序退出过快:控制台程序执行完Main后直接退出,Serilog异步批量发送的日志还未完成上报就被终止。
  3. 日志格式与发送配置不匹配:未明确指定JSON格式化器,可能导致日志格式不符合Logtail要求。

修改后的完整代码

using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Formatting.Json;
using Serilog.Sinks.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

internal class Program
{
    // 改为异步Main方法,确保日志发送完成后再退出
    private static async Task Main(string[] args)
    {
        var appName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
        
        // 开启Serilog内部日志,方便调试
        Serilog.Debugging.SelfLog.Enable(msg => Console.WriteLine(msg));

        using var logger = new LoggerConfiguration()
            .MinimumLevel.Information()
            .Enrich.WithProperty("ApplicationName", appName) // 添加应用标识,便于Logtail筛选
            .WriteTo.Http(
                requestUri: "https://in.logtail.com/",
                queueLimitBytes: null,
                batchPostingLimit: 1, // 测试阶段设为1,每条日志立即发送;生产环境可调整为更大值
                period: TimeSpan.FromSeconds(1),
                httpClient: new CustomHttpClient("your-bearer-token-here"), // 直接传入有效Token
                formatter: new JsonFormatter() // 强制输出标准JSON格式日志
            )
            .CreateLogger();
        
        logger.Information("log message in json format");
        
        // 等待所有日志发送任务完成
        await logger.DisposeAsync();
    }
}

public class CustomHttpClient : IHttpClient
{
    private readonly HttpClient httpClient;

    // 直接在构造函数中设置认证头,跳过未被调用的Configure方法
    public CustomHttpClient(string bearerToken)
    {
        httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
    }

    // 空实现Configure方法,满足接口要求
    public void Configure(IConfiguration configuration) { }

    public async Task<HttpResponseMessage> PostAsync(string requestUri, Stream contentStream)
    {
        using var content = new StreamContent(contentStream);
        content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); // 规范设置Content-Type

        var response = await httpClient.PostAsync(requestUri, content).ConfigureAwait(false);
        
        // 调试时可取消注释,查看失败请求的响应内容
        // if (!response.IsSuccessStatusCode)
        // {
        //     var responseContent = await response.Content.ReadAsStringAsync();
        //     Serilog.Debugging.SelfLog.WriteLine("Logtail请求失败: {0}, 响应内容: {1}", response.StatusCode, responseContent);
        // }

        return response;
    }

    public void Dispose() => httpClient?.Dispose();
    
    // 实现异步Dispose,配合Serilog的DisposeAsync方法
    public ValueTask DisposeAsync()
    {
        ((IDisposable)httpClient).Dispose();
        return ValueTask.CompletedTask;
    }
}

关键修改说明

  • 认证头设置:直接在CustomHttpClient构造函数中传入Bearer Token并配置认证头,确保请求携带有效权限信息。
  • 异步程序生命周期:将Main改为异步方法,调用logger.DisposeAsync()等待所有日志发送完成后再退出。
  • JSON格式化:显式指定JsonFormatter,保证日志以Logtail可解析的标准JSON格式发送。
  • 调试辅助:开启Serilog内部日志,可快速定位发送失败的原因;注释部分可查看请求失败时的响应详情。

内容的提问来源于stack exchange,提问作者toan nguyen khanh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 04:15:48