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

如何修改ServiceStack JsonApiClient的默认日志行为?

解决ServiceStack JsonApiClient将4xx状态码记录为错误日志的问题

要调整JsonApiClient对4xx状态码的日志级别,核心是拦截或覆盖其默认的日志判断逻辑,以下是几种可行方案:

方案1:自定义ILogger实现状态码感知的日志级别转换

通过包装默认的ILogger,在日志记录时根据状态码动态调整级别,将4xx请求转为警告级别,5xx及其他错误保留错误级别:

// 自定义Logger,根据状态码调整日志级别
public class StatusCodeAwareLogger : ILogger
{
    private readonly ILogger _innerLogger;

    public StatusCodeAwareLogger(ILogger innerLogger) => _innerLogger = innerLogger;

    public IDisposable BeginScope<TState>(TState state) => _innerLogger.BeginScope(state);
    public bool IsEnabled(LogLevel logLevel) => _innerLogger.IsEnabled(logLevel);

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        var logMessage = formatter(state, exception);
        // 检测日志内容中的4xx状态码
        bool isClientError = logMessage.Contains("400") || logMessage.Contains("401") || 
                             logMessage.Contains("403") || logMessage.Contains("404");
        
        if (logLevel == LogLevel.Error && isClientError)
        {
            // 将4xx错误日志转为警告级别
            _innerLogger.Log(LogLevel.Warning, eventId, state, exception, formatter);
        }
        else
        {
            // 其他情况保留原日志级别
            _innerLogger.Log(logLevel, eventId, state, exception, formatter);
        }
    }
}

// 自定义LoggerFactory包装器
public class StatusCodeAwareLoggerFactory : ILoggerFactory
{
    private readonly ILoggerFactory _innerFactory;

    public StatusCodeAwareLoggerFactory(ILoggerFactory innerFactory) => _innerFactory = innerFactory;

    public void AddProvider(ILoggerProvider provider) => _innerFactory.AddProvider(provider);
    public ILogger CreateLogger(string categoryName) => new StatusCodeAwareLogger(_innerFactory.CreateLogger(categoryName));
}

使用方式

创建JsonApiClient时传入自定义LoggerFactory:

var defaultFactory = LoggerFactory.Create(builder => builder.AddConsole());
var client = new JsonApiClient("http://localhost:8080")
{
    LoggerFactory = new StatusCodeAwareLoggerFactory(defaultFactory)
};

方案2:继承JsonApiClient重写SendAsync方法

通过继承JsonApiClient,重写核心请求方法,自定义异常和响应的日志逻辑:

public class CustomJsonApiClient : JsonApiClient
{
    public CustomJsonApiClient(string baseUri) : base(baseUri) {}

    protected override async Task<TResponse> SendAsync<TResponse>(HttpMethod httpMethod, string relativeOrAbsoluteUrl, object request, CancellationToken token = default)
    {
        try
        {
            var response = await base.SendAsync<TResponse>(httpMethod, relativeOrAbsoluteUrl, request, token);
            
            // 处理返回带状态码的响应(实现IHasStatusCode的情况)
            if (response is IHasStatusCode hasStatusCode && hasStatusCode.StatusCode >= 400 && hasStatusCode.StatusCode < 500)
            {
                Logger.LogWarning("SendAsync: {StatusCode} {StatusDescription}", 
                    hasStatusCode.StatusCode, 
                    HttpStatusCode.GetName((HttpStatusCode)hasStatusCode.StatusCode));
            }
            
            return response;
        }
        catch (WebServiceException ex)
        {
            // 处理请求抛出的异常
            if (ex.StatusCode >= 400 && ex.StatusCode < 500)
            {
                Logger.LogWarning("SendAsync: {Status} {StatusCode} - {Message}", 
                    ex.Status, ex.StatusCode, ex.Message);
            }
            else
            {
                Logger.LogError(ex, "SendAsync: {Status} {StatusCode}", ex.Status, ex.StatusCode);
            }
            throw;
        }
    }
}

使用方式

直接实例化自定义客户端:

var client = new CustomJsonApiClient("http://localhost:8080");

方案3:通过日志过滤规则屏蔽4xx错误日志(快速临时方案)

如果只是想临时屏蔽4xx的错误日志,可通过日志框架的过滤规则实现(以Microsoft.Extensions.Logging为例):

var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.AddConsole()
           .AddFilter("ServiceStack.JsonApiClient", (logLevel, _, state, __) =>
           {
               if (logLevel == LogLevel.Error)
               {
                   var message = state.ToString();
                   // 排除包含4xx状态码的错误日志
                   return !(message.Contains("400") || message.Contains("401") || 
                           message.Contains("403") || message.Contains("404"));
               }
               return true;
           });
});

var client = new JsonApiClient("http://localhost:8080")
{
    LoggerFactory = loggerFactory
};

注意:此方案会直接过滤掉4xx的错误日志,无法转为警告级别,适合临时场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:13:12