Application Insights - ILogger 参数呈现为自定义维度中的对象名称

Application Insights - ILogger arguments rendered as name of the object in custom dimensions

当对象作为参数传递给 ilogger 时,对象在 Application Insights 自定义维度中呈现为字符串(对象的名称)。未显示实际值。

注册 Application Insights

services.AddApplicationInsightsTelemetry();

新日志

public class HealthController : ControllerBase
{
    private readonly ILogger<HealthController> _logger;

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

    [HttpGet]
    public IActionResult Get()
    {
        var health = new HealthViewModel()
        {
             ok = false
        };

        _logger.LogInformation("Hlep me pls {health}", health);

        return Ok(health);
    }
}

结果

我不想对每个日志都这样:

var health = new HealthViewModel()
{
     ok = false
};

_logger.LogInformation("Hlep me pls {health}", JsonConvert.SerializeObject(health));

我尝试为应用程序洞察创建一个中间件,但值仍然是对象的名称..

为什么参数没有呈现为 json?

编辑

好像是

var health = new
{
     ok = false
};

_logger.LogInformation("HEJ2 {health}", health);

有效但无效

var health = new HealthViewModel
{
     ok = false
};

_logger.LogInformation("HEJ2 {health}", health);

从您的自定义维度我可以看出它没有将健康对象参数视为额外数据

_logger.LogInformation("Hlep me pls {health}", health);

尝试在字符串本身中使用 jsonConverter。

_logger.LogInformation($"Hlep me pls {JsonConvert.SerializeObject(health)}");

不支持

引自https://github.com/microsoft/ApplicationInsights-dotnet/issues/1722

I think you're expecting too much of the logger. It doesn't know about JSON format, it just calls Convert.ToString on properties

Convert.ToString typically calls ToString() and the default ToString implementation for new classes is simply to return the type name

你能做什么

对记录到 ILogger 的对象使用 ToJson() 并为应用程序洞察创建中间件并修改日志名称和自定义维度。

中间件

public class ProcessApiTraceFilter : ITelemetryProcessor
{
    private ITelemetryProcessor Next { get; set; }
    private readonly IIdentity _identity;
    private readonly IHostEnvironment _hostEnvironment;

    public ProcessApiTraceFilter(ITelemetryProcessor next, IHostEnvironment hostEnvironment, IIdentity identity)
    {
        Next = next;
        _identity = identity;
        _hostEnvironment = hostEnvironment;
    }

    public void Process(ITelemetry item)
    {
        item.Process(_hostEnvironment, _identity);

        Next.Process(item);
    }
}

实施

public static class ApplicationInsightsExtensions
{
    public static void Process(this ITelemetry item, IHostEnvironment hostEnvironment, IIdentity identity)
    {
        if (item is TraceTelemetry)
        {
            var traceTelemetry = item as TraceTelemetry;
            var originalMessage = traceTelemetry.Properties.FirstOrDefault(x => x.Key == "{OriginalFormat}");

            if (!string.IsNullOrEmpty(originalMessage.Key))
            {
                var reg = new Regex("{([A-z]*)*}", RegexOptions.Compiled);
                var match = reg.Matches(originalMessage.Value);
                var formattedMessage = originalMessage.Value;
                foreach (Match arg in match)
                {
                    var parameterName = arg.Value.Replace("{", "").Replace("}", "");
                    var parameterValue = traceTelemetry.Properties.FirstOrDefault(x => x.Key == parameterName);
                    formattedMessage = formattedMessage.Replace(arg.Value, "");
                }

                traceTelemetry.Message = formattedMessage.Trim();
            }

            if (identity != null)
            {
                var isAuthenticated = identity.IsAuthenticated();
                const string customerKey = "customer";

                if (isAuthenticated && !traceTelemetry.Properties.ContainsKey(customerKey))
                {
                    var customer = identity.Customer();

                    if (customer != null)
                    {
                        traceTelemetry.Properties.Add(customerKey, customer.ToJson());
                    }
                }

                var request = identity.Request();
                const string requestKey = "request";

                if (request != null && !traceTelemetry.Properties.ContainsKey(requestKey))
                {
                    traceTelemetry.Properties.Add(requestKey, request.ToJson());
                }
            }

            var applicationNameKey = "applicationName";

            if (hostEnvironment != null && !string.IsNullOrEmpty(hostEnvironment.ApplicationName) && !traceTelemetry.Properties.ContainsKey(applicationNameKey))
            {
                traceTelemetry.Properties.Add(applicationNameKey, hostEnvironment.ApplicationName);
            }
        }
    }
}

在启动时注册应用洞察和中间件

services.AddApplicationInsightsTelemetry();
services.AddApplicationInsightsTelemetryProcessor<ProcessApiTraceFilter>();

ToJson

public static class ObjectExtensions
{
    private static readonly string Null = "null";
    private static readonly string Exception = "Could not serialize object to json";

    public static string ToJson(this object value, Formatting formatting = Formatting.None)
    {
        if (value == null) return Null;

        try
        {
            string json = JsonConvert.SerializeObject(value, formatting);

            return json;
        }
        catch (Exception ex)
        {
            return $"{Exception} - {ex?.Message}";
        }
    }
}

日志

//Log object? _smtpAppSettings.ToJson()

_logger.LogInformation("Email sent {to} {from} {subject}", to, _smtpAppSettings.From, subject)

结果