Search code examples
.netazureloggingazure-application-insights.net-core-logging

How to correlate related custom logs using ILogger and application insights?


I have a service, that performs some REST API calls and I do custom logging before and after the api call:

_logger.LogTrace("Invoked API {ApiName}", new { ApiName = apiName, Data = json });

var httpResponse = await _httpClient.PostAsync(url, new StringContent(json));
httpResponse.EnsureSuccessStatusCode();
var responseDto = await JsonSerializer.DeserializeAsync<ResponseDto>(httpResponse.Content.ReadAsStream())!;

if (!responseData.Success)
{
    _logger.LogWarning("Failed API {ApiName}", new { ApiName = apiName, Data = await httpResponse.Content.ReadAsStringAsync() });
}

The HttpClient also produces logs.

What is the recommended approach for correlating the logs, so that I can easily find related logs in application insights portal?

I would like all logs produced by HttpClient or possibly ADO.NET etc to be related to my custom log.

EDIT: I know ASP.NET Core MVC or Pages automatically correlate logs using an OperationTelemetry per request. I need the same for other scenarios: console app, rich client, blazor server (uses websockets instead requests)


Solution

  • So, telemetry is only automatically linked when it is part of an operation. An operation is created when a controller receives a request for example. That is done by the runtime.

    In cases you don't have a pending operation you will need to manually add context so you can relate telemetry or you can create your own operation to associate telemetry to that specific operation. You can do so like this:

    using (var op = _telemetryClient.StartOperation<DependencyTelemetry>($"Invoke API {ApiName}"))
    {
        _logger.LogTrace("Invoked API {ApiName}", new { ApiName = apiName, Data = json });
    
        var httpResponse = await _httpClient.PostAsync(url, new StringContent(json));
        httpResponse.EnsureSuccessStatusCode();
        var responseDto = await JsonSerializer.DeserializeAsync<ResponseDto>(httpResponse.Content.ReadAsStream())!;
    
        if (!responseData.Success)
        {
            op.Telemetry.Success = false;
            _logger.LogWarning("Failed API {ApiName}", new { ApiName = apiName, Data = await httpResponse.Content.ReadAsStringAsync() });
        }
    }
    

    Now all telemetry will be correlated inside the scope of the operation.