Tiago Matos
Tiago Matos

Reputation: 45

Error when trying to log metric Azure Function

I have a problem with my Logger, whenever I try to log the metric, an error occurs. Below, I leave the part of my code that the error occurs.

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);
    }

I've tried several things, but it didn't work. The only solution would be to switch from log.LogMetric() to log.LogInformation(), however that way I would lose all metric, and it would become harder to track insight from my application

I also leave a stack trace that generated, but even warning null parameter, I checked and none of the parameters passed is null or incorrect.

    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

Thanks to everyone who can propose solutions or alternatives for this error, thank you very much.

Upvotes: 1

Views: 989

Answers (3)

Chiza
Chiza

Reputation: 39

How are you initializing you logger? I had a similar issue when I initialized logger like so:

class MyClass {
    private readonly ILogger _logger;
    
    public MyClass(ILogger logger) {
        _logger = logger;
    }
}

I was able to resolve the issue by passing a type of MyClass to ILogger in the variable definition in the constructor. The following code fixes the issue.

class MyClass {
    private readonly ILogger _logger;
    
    public MyClass(ILogger<MyClass> logger) {
        _logger = logger;
    }
}

Upvotes: 0

Joe Dyndale
Joe Dyndale

Reputation: 1071

I had the exact same issue. It worked fine in a v3 Azure Function when the ILogger was injected into the function. However, it no longer works after updating to .NET 6 and running the function out-of-process. The documentation says we have to inject FunctionContext context and within the function do context.GetLogger<MyType>(); The logger that's returned should seemingly be fully initialized, but with this I got the same exception as OP. Simply injecting an ILogger into the class constructor results in the same exception. Injecting ILogger into the function Run method directly does not result in an exception, but then the metric is not logged, simply ignored.

I got it to work by rewriting so that I use the ApplicationInsights logging more directly, mainly the same as the first answer suggested, but here's a more detailed example:

Start by making sure the Program.cs file includes the following:

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

Assuming you're using DI, make sure you create the telemetry client as follows:

private readonly TelemetryClient _telemetryClient;

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

Then, in your function, you can log your custom metrics like this:

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);

Upvotes: 0

SaiKarri-MT
SaiKarri-MT

Reputation: 1301

To handle this error we need to check the logger whether it is initialized with any other logger functions like ConsoleLogger

Also check the SO answer from saftimufti. If the log metrics are custom, then check custommetrics.

Sample code to track the metric:

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

Upvotes: 1

Related Questions