![](/img/trans.png)
[英]Application Insights - ILogger arguments rendered as name of the object in custom dimensions
[英]Log custom object in Application Insights from Function App ILogger (C#)
我有一個 C# .NET Core Azure Function App,我正在使用 ILogger 將日志發送到 Application Insights。 到目前為止,這運行良好。
函數頭:
public static void Run([TimerTrigger("0 30 * * * *")] TimerInfo myTimer, ILogger log, ExecutionContext context)
ILogger 用法:
log.LogInformation($"MyFunction trigger function executed at: {DateTime.Now}");
在 App Insights 中,我看到日志包含默認信息,例如它來自哪個函數應用程序,以及包含上述字符串的message
。
但是,現在我想記錄自定義日志。 我有一個IEnumerable<IDictionary<string, string>>
並且我希望列表的每個字典元素都是一個單獨的日志。 理想情況下,我可以有一個日志,其中每個字段都是字典中的一個鍵,其值是相應的值。 或者,我可以在日志中使用某種 customDimensions 字段,該字段將是一個包含列表中 1 個字典中的所有鍵值對的對象。
目的是使日志易於在 Kusto 中查詢。 我想避免在 App Insights 中查詢它們時解析它們。
筆記:
我查看了許多其他類似的帖子,但似乎沒有一個得到完整的回答。
這是我以前使用過的模式:
public class LogService : ILogService
{
private readonly ILogger<LogService> _log;
private readonly Dictionary<string, object> _customProperties = new Dictionary<string, object>();
public LogService(ILogger<LogService> log)
{
_log = log;
}
public void SetCustomProperty(string key, object value)
{
_customProperties.Add(key, value);
}
public void LogInformation(string message, params object[] args)
{
Log(LogLevel.Information, message, args);
}
public void LogWarning(string message, params object[] args)
{
Log(LogLevel.Warning, message, args);
}
...etc
private void Log(LogLevel logLevel, string message, params object[] args)
{
using (_log.BeginScope(_customProperties))
{
_log.Log(logLevel, message, args);
}
}
}
重要的一點是最后一個方法Log(LogLevel logLevel, string message, params object[] args)
。 它將_log.Log()
包裝在using
並使用_log.BeginScope()
將自定義屬性添加到日志消息中,日志消息應該在 Application Insights“自定義屬性”部分中可見。
詳細說明@pinkfloydx33 的評論:您可以通過
_logger.BeginScope( < your state here > )
{
// All log methods here include state, regardless
// of which ILogger object is used.
}
或通過使用
System.Diagnostics.Activity.Current.AddBaggage()
這無需額外配置即可工作(例如,默認情況下 AI 已啟用范圍)。
例如,這是一個中間件類,用於記錄顯示兩種方法的租戶信息:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MyApp
{
public static class StoreTenantForLoggingMiddlewareExtensions
{
/// <summary>
/// Register StoreTenantForLoggingMiddleware as middleware.
/// Call this from Configure() in Startup, as:
/// app.UseStoreTenantForLogging()
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IApplicationBuilder UseStoreTenantForLogging(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<StoreTenantForLoggingMiddleware>();
}
}
/// <summary>
/// Middleware to log the Tenant's domain to Application
/// Insights as a customDimension
/// </summary>
public class StoreTenantForLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<StoreTenantForLoggingMiddleware> _logger;
public StoreTenantForLoggingMiddleware(RequestDelegate next,
ILogger<StoreTenantForLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
}
// Here TenantContext is my own class that gets the state
// I want to be logged. You'd replace with your own object
// or just call a method on httpContext.
public async Task InvokeAsync(HttpContext httpContext, TenantContext tenantContext)
{
// Example 1: Add data to current activity. AI will pick this
// up and add as a customDimension in traces logs.
var currentActivity = System.Diagnostics.Activity.Current;
if (currentActivity != null)
{
currentActivity.AddBaggage("TenantDomain1", tenantContext?.Domain);
}
// Example 2: Use a scope.
// If you go with option 1, remove this 'using' but still
// call await _next(httpContext);
using ( var scope = _logger.BeginScope(new Dictionary<string, object>()
{ { "TenantDomain2", tenantContext?.Domain } }))
{
await _next(httpContext);
}
}
}
}
我不確定哪個最好。 Activity
one 對我更有吸引力,而且我猜數據可能會在管道中保留一段時間。
如果您使用 nlog 並希望能夠在那里記錄屬性,則可以在上面的Invoke()
開頭添加此行,然后在nlog.config
文件中使用${mdlc:item=TenantDomain}
nlog.config
。
NLog.MappedDiagnosticsLogicalContext.Set("TenantDomain", tenantContext?.Domain);
您可能可以使用https://github.com/NLog/NLog.DiagnosticSource作為替代,但我還沒有嘗試過。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.