Application Insights - ILogger 参数呈现为自定义维度中的对象名称
Posted
技术标签:
【中文标题】Application Insights - ILogger 参数呈现为自定义维度中的对象名称【英文标题】:Application Insights - ILogger arguments rendered as name of the object in custom dimensions 【发布时间】:2020-06-20 07:14:45 【问题描述】:当作为参数传递给 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);
【问题讨论】:
【参考方案1】:不支持
引用https://github.com/microsoft/ApplicationInsights-dotnet/issues/1722
我认为您对记录器的期望过高。它不知道 JSON 格式,它只是在属性上调用 Convert.ToString
Convert.ToString 通常调用 ToString() 并且新类的默认 ToString 实现只是返回类型名称
你能做什么
对记录到 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)
结果
【讨论】:
【参考方案2】:从您的自定义维度中,我可以看到它没有将健康 obj 参数视为额外数据
_logger.LogInformation("Hlep me pls health", health);
尝试在字符串本身中使用 jsonConverter。
_logger.LogInformation($"Hlep me pls JsonConvert.SerializeObject(health)");
【讨论】:
是的,将其转换为 json 字符串是可行的,但我不想对每个日志都这样做,我在问题中提到了这一点。可以在中间件中执行此操作,但那里的值已经不正确 我认为记录的值是 *.Api.Models.Health ... 等是您的对象的 .ToString() 的值 尝试在您的类中覆盖 .ToString() 并检查。 我不建议按照此处的建议预先组合字符串,因为无法查询参数本身的值。需要解析日志消息,这可能并不容易。最好按照问题中的建议将该值作为单独的参数传递给 ILogger 方法。以上是关于Application Insights - ILogger 参数呈现为自定义维度中的对象名称的主要内容,如果未能解决你的问题,请参考以下文章
ILogger 到 Application Insights