在外部库中使用 TraceWriter 进行 Azure 函数日志记录

Azure Function logging using TraceWriter in external library

如何重用 Azure 函数中可用的 TraceWriter 对象来记录外部引用库中的信息?我尝试使用构造函数传入对象并引用 TraceWriter class (web.http.tracing)。我运气不好,因为 classes 看起来不一样。

短版 使用 this nuget package 中可用的 Microsoft.Azure.WebJobs.Host.TraceWriter。

或者,将您的函数构建为 Web 项目,然后您可以在本地进行调试。 You can find a sample here.

长版

您的问题是您使用了错误的 TraceWriter。

我在 Azure 函数中使用了 Azure 函数记录器来输出记录器的类型。

log.Info(log.GetType().ToString());

给出了以下内容:

Microsoft.Azure.WebJobs.Script.InterceptingTraceWriter

我也期待 Web/Http TraceWriter 并且很惊讶还有另一个实现要处理。微软真的可以创建一个标准方法,或者至少为我们提供一个漂亮干净的错误、警告、信息、详细等界面。也许是 .Net Standard 的东西……拜托。

我将创建自己的界面并包装我的应用记录器和 Azure 记录器,这样我就可以注入我需要的任何一个,而不会在我的代码中进一步引起麻烦。这也将提供一些保护,免受未来重大变化造成的潜在痛苦。

无论如何,我跑题了,然后我跟踪 Microsoft.Azure.WebJobs.Script.InterceptingTraceWriterAzure Functions / Webjobs scripting GitHub repo 然后到 Nuget 包。我已经对此进行了测试,将 Azure Function 记录器传递到您的外部程序集并继续从那里登录到 Azure Function 环境时工作正常。

这是一个例子:

using Microsoft.Azure.WebJobs.Host;

public static void TryLog(TraceWriter azureFunctionsLogger)
{
    azureFunctionsLogger.Info("************** IT WORKED **************");
}

我喜欢 Azure 函数的潜力,但它仍然有点不成熟且过于复杂。

希望对您有所帮助。

添加了一个非常简单的单个 class 记录器来说明。

它写入 Azure Functions Logger 或标准 Systems.Diagnostics.Trace。您需要将其粘贴到标准 C# 控制台应用程序的 Program.cs 的内容上。您还需要包含 Nuget 包 Microsoft.Azure.WebJobs

namespace LoggingTestConsole
{
    using System;

    /// <summary>
    /// Generic logging interface for portability 
    /// </summary>
    public interface ILogger
    {
        void Error(string message);
        void Information(string message);
        void Warning(string message);
    }


    /// <summary>
    /// Azure Functions logger
    /// </summary>
    public class AzureFunctionLogger : ILogger
    {
        private static Microsoft.Azure.WebJobs.Host.TraceWriter _logger;

        public AzureFunctionLogger(Microsoft.Azure.WebJobs.Host.TraceWriter logger)
        {
            _logger = logger;
        }

        public void Error(string message)
        {
            _logger.Error(message);
        }

        public void Information(string message)
        {
            _logger.Info(message);
        }

        public void Warning(string message)
        {
            _logger.Warning(message);
        }
    }


    /// <summary>
    /// Windows Trace logger
    /// </summary>
    public class TraceLogger : ILogger
    {
        public TraceLogger()
        {
            System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out));
        }

        public void Error(string message)
        {
            System.Diagnostics.Trace.TraceError(message);
        }


        public void Information(string message)
        {
            System.Diagnostics.Trace.TraceInformation(message);
        }

        public void Warning(string message)
        {
            System.Diagnostics.Trace.TraceWarning(message);
        }

        public void Warning(string format, params object[] args)
        {
            System.Diagnostics.Trace.TraceWarning(format, args);
        }
    }

    /// <summary>
    /// You would put this in a separate project and just share the ILogger interface.
    /// Pass the relevant logger in from Azure Functions or a standard windows Trace logger.
    /// </summary>
    public class DoStuff
    {
        public DoStuff(ILogger logger)
        {
            logger.Information("We are logging to logger you passed in!");
        }
    }

    public class Program
    {

        /// <summary>
        /// Sample usage
        /// </summary>
        static void Main(string[] args)
        {
            // var loggerEnvironment = "AzureFunctions";
            var loggerEnvironment = "ConsoleApp";

            ILogger logger = null;

            if (loggerEnvironment == "AzureFunctions")
            {
                Microsoft.Azure.WebJobs.Host.TraceWriter azureFunctionLogger = null;
                logger = new AzureFunctionLogger(azureFunctionLogger);
            }
            else if (loggerEnvironment == "ConsoleApp")
            {
                logger = new TraceLogger();
            }

            var doStuff = new DoStuff(logger);
            Console.ReadKey();
        }
    }
}

作为一项更新,Azure Functions 现在支持使用 ILogger 而不是 TraceWriter,因此您可以使用任何实现 ILogger 的日志记录框架。

参见GitHub issue and the subsequent wiki documentation

如果我是正确的,那么使 ILogger 与 Azure 函数一起工作的必要版本将是 Microsoft.Azure.WebJobs 2.1.0-beta1。但是,我似乎无法使用 ILogger 而不是 TraceWriter 获得 Azure 函数 运行。

关于使用 ILogger 开发 Azure Functions 的信息和文档也很少。有没有人有更多信息或技巧来使它正常工作?

我的 C# 代码片段:

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.ServiceBus;
using System;
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;

namespace Experimental.Functions
{
    public static class ListenToEventFunction
    {
        [FunctionName("ListenToEventFunction")]
        public static void Run([EventHubTrigger("events", Connection = "EventHubConnectionString")]string myEventHubMessage, ILogger log)
        {
            log.LogInformation($"C# Event Hub trigger function processed a message: {myEventHubMessage}");
        }
    }
}

使用适用于 VS2017 的 Azure 函数工具调试我的 Azure 函数时出现以下错误:

A ScriptHost error has occurred
Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.EnrichTelemetryLocation'. 
Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'log' to type ILogger. 
Make sure the parameter Type is supported by the binding. 
If you're using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. config.UseServiceBus(), config.UseTimers(), etc.).