在附加的Polly策略中使用ILOGGER

发布于 2025-01-31 14:40:39 字数 1892 浏览 4 评论 0原文

我一直在尝试按照将ilogger传递给我的重试策略,以记录有关要重述错误的信息。

当我们使用Refit用于客户生成时,博客中的代码无法开箱即用。基于重新介绍docs 将属性添加到我的方法签名中,但无法将其添加到实际上工作。

即使我已将属性添加到我的方法签名中:

    Task<UserSubscriptions> GetUserSubscriptions(string userId, [Property("PollyExecutionContext")] Polly.Context context);

我已经在扩展方法中捕获了Logger管理:

    private static readonly string LoggerKey = "LoggerKey";

    public static Context WithLogger(this Context context, ILogger logger)
    {
        context[LoggerKey] = logger;
        return context;
    }

    public static ILogger GetLogger(this Context context)
    {
       if (context.TryGetValue(LoggerKey, out object logger))
       {
           return logger as ILogger;
       }
       return null;

    }

执行方法时创建一个新上下文:

    public Context GetPollyContext() => new Context().WithLogger(logger);

    public Task<UserSubscriptions> GetUserSubscriptions(UserId userId) {
        return restClient.GetUserSubscriptions(userId.UserIdString, GetPollyContext());
    }

并尝试作为重试操作的一部分访问记录器:

    return Policy
        .Handle<Exception>()
        .OrResult<HttpResponseMessage>(r => CodesToRetry.Contains(r.StatusCode))
        .WaitAndRetryAsync(3, retryCount => TimeSpan.FromSeconds(1), (result, timeSpan, retryCount, context) =>
        {
            var logger = context.GetLogger();
            if (logger == null) return;

            // do some logging
        }
    });

当我设置一个重试操作中的断点是我看到的上下文是一个新的空上下文,而不是我使用附件的记录器创建的上下文。

I've been trying to follow the directions from this blog post to pass an ILogger to my retry policy in order to log information about the errors being retried.

The code in the blog doesn't work out of the box as we're using Refit for client generation. Based on the refit docs it should just be a matter of adding a property to my method signatures, but haven't been able to get it to actually work.

Even though I've added the property to my method signature:

    Task<UserSubscriptions> GetUserSubscriptions(string userId, [Property("PollyExecutionContext")] Polly.Context context);

I've captured logger management in extension methods:

    private static readonly string LoggerKey = "LoggerKey";

    public static Context WithLogger(this Context context, ILogger logger)
    {
        context[LoggerKey] = logger;
        return context;
    }

    public static ILogger GetLogger(this Context context)
    {
       if (context.TryGetValue(LoggerKey, out object logger))
       {
           return logger as ILogger;
       }
       return null;

    }

I create a new context when executing the method:

    public Context GetPollyContext() => new Context().WithLogger(logger);

    public Task<UserSubscriptions> GetUserSubscriptions(UserId userId) {
        return restClient.GetUserSubscriptions(userId.UserIdString, GetPollyContext());
    }

And try to access the logger as part of the retry action:

    return Policy
        .Handle<Exception>()
        .OrResult<HttpResponseMessage>(r => CodesToRetry.Contains(r.StatusCode))
        .WaitAndRetryAsync(3, retryCount => TimeSpan.FromSeconds(1), (result, timeSpan, retryCount, context) =>
        {
            var logger = context.GetLogger();
            if (logger == null) return;

            // do some logging
        }
    });

When I set a break point in the retry action the context that I see is a new empty context and not the one I created with the attached logger.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情栀口红 2025-02-07 14:40:39

per github问题,有一个错字,属性是policy> policy> policy> policy>代码>,不是pollyexecutionContext

尽管鉴于我不需要每个请求生成唯一的上下文,但更好的模式是使用委托注入。

扩展方法

    private static readonly string LoggerKey = "LoggerKey";

    public static Context WithLogger(this Context context, ILogger logger)
    {
        context[LoggerKey] = logger;
        return context;
    }

    public static ILogger GetLogger(this Context context)
    {
       if (context.TryGetValue(LoggerKey, out object logger))
       {
           return logger as ILogger;
       }
       return null;

    }

委托定义

    public class PollyContextInjectingDelegatingHandler<T> : DelegatingHandler
    {
        private readonly ILogger<T> _logger;

        public PollyContextInjectingDelegatingHandler(ILogger<T> logger)
        {
            _logger = logger;
        }

        protected override async Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            var pollyContext = new Context().WithLogger(_logger);
            request.SetPolicyExecutionContext(pollyContext);

            return await base.SendAsync(request,    cancellationToken).ConfigureAwait(false);
        }
    }

,然后将代表添加到客户端定义

    services
        .AddTransient<ISubscriptionApi, SubscriptionApi>()
        .AddTransient<PollyContextInjectingDelegatingHandler<SubscriptionApi>>()
        .AddRefitClient<ISubscriptionApiRest>(EightClientFactory.GetRefitSettings())
        .ConfigureHttpClient((s, c) =>
        {
            ...
        })
       .AddHttpMessageHandler<PollyContextInjectingDelegatingHandler<SubscriptionApi>>()
       .ApplyTransientRetryPolicy(retryCount, timeout);

Per GitHub issues, there was a typo, the property is PolicyExecutionContext, not PollyExecutionContext.

Though given I don't need to generate a unique context per request, the better pattern is to use delegate injection.

Extension methods

    private static readonly string LoggerKey = "LoggerKey";

    public static Context WithLogger(this Context context, ILogger logger)
    {
        context[LoggerKey] = logger;
        return context;
    }

    public static ILogger GetLogger(this Context context)
    {
       if (context.TryGetValue(LoggerKey, out object logger))
       {
           return logger as ILogger;
       }
       return null;

    }

Delegate definition

    public class PollyContextInjectingDelegatingHandler<T> : DelegatingHandler
    {
        private readonly ILogger<T> _logger;

        public PollyContextInjectingDelegatingHandler(ILogger<T> logger)
        {
            _logger = logger;
        }

        protected override async Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            var pollyContext = new Context().WithLogger(_logger);
            request.SetPolicyExecutionContext(pollyContext);

            return await base.SendAsync(request,    cancellationToken).ConfigureAwait(false);
        }
    }

Then add the delegate to the client definition

    services
        .AddTransient<ISubscriptionApi, SubscriptionApi>()
        .AddTransient<PollyContextInjectingDelegatingHandler<SubscriptionApi>>()
        .AddRefitClient<ISubscriptionApiRest>(EightClientFactory.GetRefitSettings())
        .ConfigureHttpClient((s, c) =>
        {
            ...
        })
       .AddHttpMessageHandler<PollyContextInjectingDelegatingHandler<SubscriptionApi>>()
       .ApplyTransientRetryPolicy(retryCount, timeout);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文