【问题标题】:Error when trying to log metric Azure Function尝试记录指标 Azure 函数时出错
【发布时间】:2022-01-10 18:15:58
【问题描述】:

我的 Logger 出现问题,每当我尝试记录指标时,都会发生错误。下面,我留下了发生错误的代码部分。

private void LogBlobExecutionMetric(ILogger log,
                                        BlobMigrationStrategyIdentifier blobMigrationStrategyIdentifier,
                                        ControlMetadataEntity controlMetadataEntity,
                                        BlobMetadataEntity blobMetadataEntity,
                                        long elapsedMilliseconds,
                                        long? fileSizeInBytes)
    {
        // Create the properties for all metrics that will be logged.
        Dictionary<string, object> properties = new Dictionary<string, object>()
        {
            { "BlobMigrationStrategyIdentifier", blobMigrationStrategyIdentifier.ToString() },
            { "ExecutionId", controlMetadataEntity.RowKey },
            { "BlobMetadataId", blobMetadataEntity.RowKey },
            { "BlobState", blobMetadataEntity.State }
        };

        //The error occurs here 
        log.LogMetric("BlobExecutionElapsedMilliseconds", elapsedMilliseconds, properties);
    }

我尝试了几件事,但没有成功。唯一的解决方案是从 log.LogMetric() 切换到 log.LogInformation(),但是那样我会丢失所有指标,并且很难从我的应用程序中跟踪洞察力

我还留下了一个生成的堆栈跟踪,但即使警告 null 参数,我检查并没有传递的参数为 null 或不正确。

    Result: Failure
Exception: System.AggregateException: One or more errors occurred. (An error occurred while writing to logger(s). (Value cannot be null. (Parameter 'value')))
 ---> System.AggregateException: An error occurred while writing to logger(s). (Value cannot be null. (Parameter 'value'))
 ---> System.ArgumentNullException: Value cannot be null. (Parameter 'value')
   at Google.Protobuf.ProtoPreconditions.CheckNotNull[T](T value, String name)
   at Microsoft.Azure.Functions.Worker.Logging.GrpcFunctionsHostLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter) in D:\a\1\s\src\DotNetWorker.Grpc\GrpcFunctionsHostLogger.cs:line 44
   at Microsoft.Extensions.Logging.Logger.<Log>g__LoggerLog|12_0[TState](LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func`3 formatter, List`1& exceptions, TState& state)
   --- End of inner exception stack trace ---
   at Microsoft.Extensions.Logging.Logger.ThrowLoggingError(List`1 exceptions)
   at Microsoft.Extensions.Logging.Logger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
   at Microsoft.Extensions.Logging.LoggerExtensions.LogMetric(ILogger logger, String name, Double value, IDictionary`2 properties) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Loggers\Logger\LoggerExtensions.cs:line 33
   at ThomsonReuters.DocMi.BlobMigration.Execution.AzureFunctions.Functions.BlobMigration.RunBlobMigration.LogBlobExecutionMetric(ILogger log, BlobMigrationStrategyIdentifier blobMigrationStrategyIdentifier, ControlMetadataEntity controlMetadataEntity, BlobMetadataEntity blobMetadataEntity, Int64 elapsedMilliseconds, Nullable`1 fileSizeInBytes) in /home/runner/work/DocMi_Functions/DocMi_Functions/src/BlobMigration/ExecutionServices/ThomsonReuters.DocMi.BlobMigration.Execution.AzureFunctions/Functions/BlobMigration/RunBlobMigration.cs:line 195
   at ThomsonReuters.DocMi.BlobMigration.Execution.AzureFunctions.Functions.BlobMigration.RunBlobMigration.RunAsync(String messageBrokerMessageString, FunctionContext context) in /home/runner/work/DocMi_Functions/DocMi_Functions/src/BlobMigration/ExecutionServices/ThomsonReuters.DocMi.BlobMigration.Execution.AzureFunctions/Functions/BlobMigration/RunBlobMigration.cs:line 164
   at Microsoft.Azure.Functions.Worker.Invocation.VoidTaskMethodInvoker`2.InvokeAsync(TReflected instance, Object[] arguments) in D:\a\1\s\src\DotNetWorker.Core\Invocation\VoidTaskMethodInvoker.cs:line 24
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker`2.<>c.<InvokeAsync>b__6_0(Task`1 t) in D:\a\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionInvoker.cs:line 32
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   --- End of stack trace from previous location ---
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   --- End of stack trace from previous location ---
   at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.ExecuteAsync(FunctionContext context) in D:\a\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 45
   at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 16
   at Microsoft.Azure.Functions.Worker.GrpcWorker.InvocationRequestHandlerAsync(InvocationRequest request, IFunctionsApplication application, IInvocationFeaturesFactory invocationFeaturesFactory, ObjectSerializer serializer, IOutputBindingsInfoProvider outputBindingsInfoProvider) in D:\a\1\s\src\DotNetWorker.Grpc\GrpcWorker.cs:line 167
Stack:   
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker`2.<>c.<InvokeAsync>b__6_0(Task`1 t) in D:\a\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionInvoker.cs:line 32
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   --- End of stack trace from previous location ---
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   --- End of stack trace from previous location ---
   at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.ExecuteAsync(FunctionContext context) in D:\a\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 45
   at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 16
   at Microsoft.Azure.Functions.Worker.GrpcWorker.InvocationRequestHandlerAsync(InvocationRequest request, IFunctionsApplication application, IInvocationFeaturesFactory invocationFeaturesFactory, ObjectSerializer serializer, IOutputBindingsInfoProvider outputBindingsInfoProvider) in D:\a\1\s\src\DotNetWorker.Grpc\GrpcWorker.cs:line 167

感谢所有可以为此错误提出解决方案或替代方案的人,非常感谢。

【问题讨论】:

  • 您能否提供一些关于运行时值的见解?很抱歉成为队长,但它抱怨空值。
  • 但我再说一遍,没有值是空的。作为参数传递给 Logger 的值都不是 null。
  • 恕我直言,没关系,人们想亲眼看看。有什么理由抱怨这个“Google.Protobuf”命名空间?这和你的项目有什么关系?你知道吗?此外,您传递给该方法的其他对象,它们来自哪些包?
  • 您正在记录一些属性,例如 blobMigrationStrategyIdentifier.ToString()controlMetadataEntity.RowKey。检查这些参数是否为空。
  • 关于属性,它们不为空。查了好几遍,都是正确的。

标签: .net logging azure-functions azure-application-insights


【解决方案1】:

要处理这个错误,我们需要检查记录器是否使用任何其他记录器函数(如 ConsoleLogger)进行初始化

同时检查来自 saftimufti 的SO 答案。 如果日志指标是自定义的,请检查 custommetrics。

跟踪指标的示例代码:

TelemetryConfiguration.Active.InstrumentationKey = "your key";
TelemetryClient client = new TelemetryClient(); 
client.TrackMetric("my metric", 60);
client.GetMetric("my metric").TrackValue(89);
client.Flush();

【讨论】:

    【解决方案2】:

    我遇到了完全相同的问题。当 ILogger 被注入到函数中时,它在 v3 Azure 函数中运行良好。但是,在更新到 .NET 6 并在进程外运行该函数后,它不再起作用。文档说我们必须注入 FunctionContext context 并在函数中执行 context.GetLogger&lt;MyType&gt;(); 返回的记录器似乎应该完全初始化,但是我得到了与 OP 相同的异常。简单地将 ILogger 注入类构造函数会导致相同的异常。将 ILogger 直接注入函数 Run 方法确实不会导致异常,但随后该指标不会被记录,只是被忽略。

    我通过重写使其工作,以便更直接地使用 ApplicationInsights 日志记录,主要与建议的第一个答案相同,但这里有一个更详细的示例:

    首先确保 Program.cs 文件包含以下内容:

    static async Task Main(string[] args)
    {
        var host = new HostBuilder()
            .ConfigureServices(s =>
            {
                s.AddLogging();
                s.AddApplicationInsightsTelemetryWorkerService();
            }
    }
    

    假设您使用的是 DI,请确保按如下方式创建遥测客户端:

    private readonly TelemetryClient _telemetryClient;
    
    public MyClass(TelemetryConfiguration telemetryConfiguration)
    {
        _telemetryClient = new TelemetryClient(telemetryConfiguration);
    }
    

    然后,在您的函数中,您可以像这样记录您的自定义指标:

    var myMetric = new MetricTelemetry
    {
        Name = "MyMetricName",
        Sum = 123
    };
    myMetric.Properties.Add("MyCustomProperty1", "My custom property value 1.");
    myMetric.Properties.Add("MyCustomProperty2", "My custom property value 2.");
    
    _telemetryClient.TrackMetric(myMetric);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-09
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      相关资源
      最近更新 更多