记录器在 Azure Durable Function 中变为空

Logger becomes null in Azure Durable Function

A similar question 被询问,但 OP 的解决方案对我不起作用。

我正在尝试在 actvity 函数中创建一个 Bar 实例,它应该在其中注入一个记录器。这是简化的代码。

Func1.cs:

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace DurableFunctionTest
{
    public class Function1
    {
        private readonly IBarFactory _barFactory;

        public Function1(IBarFactory barFactory)
        {
            _barFactory = barFactory;
        }

        [FunctionName("Function1")]
        public static async Task RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            var bar = await context.CallActivityAsync<Bar>(nameof(CreateBarInstance), context);
            bar.DoSomething();
        }

        [FunctionName(nameof(CreateBarInstance))]
        public async Task<Bar> CreateBarInstance([ActivityTrigger] IDurableActivityContext context)
        {
            var result = await _barFactory.CreateBarAsync();
            return result;
        }

        [FunctionName("Function1_HttpStart")]
        public static async Task<HttpResponseMessage> HttpStart(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
            [DurableClient] IDurableOrchestrationClient starter,
            ILogger log)
        {
            // Function input comes from the request content.
            string instanceId = await starter.StartNewAsync("Function1", null);

            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

            return starter.CreateCheckStatusResponse(req, instanceId);
        }
    }

    public interface IBarFactory
    {
       public Task<Bar> CreateBarAsync();
    }

    public class BarFactory : IBarFactory
    {
        private readonly ILoggerFactory _loggerFactory;
        private readonly ILogger<BarFactory> _logger;

        public BarFactory(ILoggerFactory loggerFactory)
        {
            _loggerFactory = loggerFactory;
            _logger = loggerFactory.CreateLogger<BarFactory>();
        }
        public async Task<Bar> CreateBarAsync()
        {
            _logger.LogInformation("Business logic here in reality to determine what derived class of Bar to create.");
            var bar = new Bar(_loggerFactory.CreateLogger<Bar>());
            await bar.InitializeAsync();
            return bar;
        }
    }


    public class Bar
    {
        private readonly ILogger<Bar> _logger;

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

        public void DoSomething()
        {
            _logger.LogInformation("Doing something");
        }

        public async Task InitializeAsync()
        {
            _logger.LogInformation("Run some initialization logic");
            await Task.Delay(500);
        }
    }
}

Startup.cs DI:

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

[assembly: FunctionsStartup(typeof(DurableFunctionTest.Startup))]
namespace DurableFunctionTest
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<IBarFactory, BarFactory>(p => new BarFactory(p.GetRequiredService<ILoggerFactory>()));
        }
    }
}

我可以验证 Bar 的记录器是否已正确填充到 activity 函数中。但是当它返回到编排器时,Bar 的记录器变为空。因此在 Bar.DoSomething 方法中抛出错误。

附带说明一下,在我的真实代码中,不仅仅是记录器有问题。 EF 对象也不能在函数之间传递。我怀疑这可能是由于相同的根本原因造成的。

这是意料之中的。 activity 函数运行并填充柱 class 的记录器项,然后就可以使用它了。但是,当 activity 函数 returns 时,Bar 对象不会直接传递给协调器,而是放入天蓝色的 table(您应该能够查看它)。为了存储,序列化到JSON。 Logger 对象无法序列化并被忽略。当 orchestrator 重新运行反序列化时,将从 table 执行反序列化。因此记录器将为空。

通常 return 来自活动的值只是关于执行的数据或信息,它们不可能 return 更复杂的东西。要么将 logger 传递给 orchestrator,然后作为参数传递给 Bar.DoSomething,或者注册一个具有处理 bar 数据逻辑的单例 BarService。