簡體   English   中英

如何在Azure上的Application Insights中將異常鏈接到請求?

[英]How to link exceptions to requests in Application Insights on Azure?

我們在Azure上使用Owin來提供REST服務,並且必須直接向Application Insights報告。 我們想記錄異常和請求。 現在我們有這個:

using AppFunc = Func<IDictionary<string, object>, Task>;
public class InsightsReportMiddleware
{

    readonly AppFunc next;
    readonly TelemetryClient telemetryClient;

    public InsightsReportMiddleware(AppFunc next, TelemetryClient telemetryClient)
    {
        if (next == null)
        {
            throw new ArgumentNullException("next");
        }

        this.telemetryClient = telemetryClient;
        this.next = next;
    }

    public async Task Invoke(IDictionary<string, object> environment)
    {
        var sw = new Stopwatch();
        sw.Start();

        await next(environment);
        sw.Stop();

        var ctx = new OwinContext(environment);
        var rt = new RequestTelemetry(
            name: ctx.Request.Path.ToString(),
            timestamp: DateTimeOffset.Now,
            duration: sw.Elapsed,
            responseCode: ctx.Response.StatusCode.ToString(),
            success: 200 == ctx.Response.StatusCode
            );

        rt.Url = ctx.Request.Uri;
        rt.HttpMethod = ctx.Request.Method;
        telemetryClient.TrackRequest(rt);
    }
}


public class InsightsExceptionLogger : ExceptionLogger
{
    readonly TelemetryClient telemetryClient;

    public InsightsExceptionLogger(TelemetryClient telemetryClient)
    {
        this.telemetryClient = telemetryClient;            
    }

    public override Task LogAsync(ExceptionLoggerContext context, System.Threading.CancellationToken cancellationToken)
    {
        telemetryClient.TrackException(context.Exception);
        return Task.FromResult<object>(null);
    }

    public override void Log(ExceptionLoggerContext context)
    {
        telemetryClient.TrackException(context.Exception);
    }
}

它們在我們的應用程序中注冊如下:

static void ConfigureInsights(IAppBuilder app, HttpConfiguration config)
{
    var rtClient = new TelemetryClient();
    app.Use<InsightsReportMiddleware>(rtClient);
    config.Services.Add(typeof (IExceptionLogger), new InsightsExceptionLogger(rtClient));
}

這有效,但異常和請求未連接。 兩者都被記錄,但是當點擊失敗的請求時,它會顯示“未找到相關的例外”。 相反,在打開異常屬性時,我們可以讀取“受此異常影響的請求:0”。 這樣做的正確方法是什么?

Application Insights通過比較ExceptionTelemetry.Context.Operation.IdRequestTelemetry.Id鏈接異常和請求。

我沒有OWIN的代碼示例,但Application Insights SDK的ASP.NET 5包具有類似的中間件組件,用於跟蹤異常和請求。 我希望您可以使用此信息為OWIN構建解決方案。

我們創建一個RequestTelemetry實例,並在調用執行實際請求處理的下一個中間件組件之前將其存儲在請求處理環境中。 在ASP.NET 5中,我們將RequestTelemetry注冊為請求范圍的服務。 有了OWIN,我想你的中間件組件會創建它並將它存儲在environment字典中。

我們還有一個名為OperationIdTelemetryInitializerITelemetryInitializerITelemetry.Context.Operation.Id使用從環境中提取的RequestTelemetry.Id設置ITelemetry.Context.Operation.Id 這初始化需要被添加到TelemetryConfiguration用於創建TelemetryClient在你的應用程序實例。 默認情況下使用TelemetryConfiguration.Active

我最終做了什么:

using AppFunc = Func<IDictionary<string, object>, Task>;
public class InsightsReportMiddleware
{
    readonly AppFunc next;
    readonly TelemetryClient telemetryClient;

    public InsightsReportMiddleware(AppFunc next, TelemetryClient telemetryClient)
    {
        if (next == null)
        {
            throw new ArgumentNullException("next");
        }

        this.telemetryClient = telemetryClient;
        this.next = next;
    }

    public async Task Invoke(IDictionary<string, object> environment)
    {
        var ctx = new OwinContext(environment);
        var rt = new RequestTelemetry()
        {
            Url = ctx.Request.Uri,
            HttpMethod = ctx.Request.Method,
            Name = ctx.Request.Path.ToString(),
            Timestamp = DateTimeOffset.Now
        };
        environment.Add("requestTelemetry", rt);

        var sw = new Stopwatch();
        sw.Start();
        await next(environment);
        sw.Stop();

        rt.ResponseCode = ctx.Response.StatusCode.ToString();
        rt.Success = ctx.Response.StatusCode < 400;
        rt.Duration = sw.Elapsed;
        telemetryClient.TrackRequest(rt);
    }
}

public class InsightsExceptionLogger : ExceptionLogger
{
    readonly TelemetryClient telemetryClient;

    public InsightsExceptionLogger(TelemetryClient telemetryClient)
    {
        this.telemetryClient = telemetryClient;            
    }

    public override Task LogAsync(ExceptionLoggerContext context, System.Threading.CancellationToken cancellationToken)
    {
        var owinContext = context.Request.GetOwinEnvironment();
        ExceptionTelemetry exceptionTelemetry = null;
        if (owinContext != null)
        {
            object obj;
            if (owinContext.TryGetValue("requestTelemetry", out obj))
            {
                var requestTelemetry = obj as RequestTelemetry;
                exceptionTelemetry = new ExceptionTelemetry(context.Exception)
                {
                    Timestamp = DateTimeOffset.Now
                };
                exceptionTelemetry.Context.Operation.Id = requestTelemetry.Id;
            }
        }

        if (exceptionTelemetry != null)
        {
            telemetryClient.TrackException(exceptionTelemetry);
        }
        else
        {
            telemetryClient.TrackException(context.Exception);                
        }

        return Task.FromResult<object>(null);
    }

    public override void Log(ExceptionLoggerContext context)
    {
        telemetryClient.TrackException(context.Exception);
    }
}

對於我現在的客戶,我們還沒有OWIN-ed。

我在WebAPI上注冊了DelegatingHandler ,它通過CallContext.LogicalSetData將當前請求粘貼到線程的SynchronizationContext ,並在請求完成后將其刪除。

在我現有的日志記錄系統中,它必須使用Application Insights的東西進行改編,然后我通過CallContext.LogicalSetData從線程中獲取請求並設置關於獲取由框架放入請求屬性的HttpContext ,然后從在HttpContext.Items ,我得到了RequestTelemetry實例。

最終,這一切都是必需的,因為我無法訪問IoC容器中的請求或操作或任何新的服務。

最終我們可能改寫一些這允許改善創造和流動OperationContextInstrumentationContext風格的對象下移堆棧,擺脫處理器和CallContext滑稽的生意。

TelemetryClient.TrackException方法存在重載,它接受屬性字典。 它專門用於分類和搜索異常。 這允許生成錯誤ID,並將錯誤鏈接到AppInsights。

錯誤處理的一個例子:

var errorId = GenerateErrorId();

var trackProperties = new Dictionary<string, string>();
trackProperties.Add("ErrorId", errorId);

var ai = new TelemetryClient();
ai.TrackException(exception, trackProperties);

JObject resp = new JObject();
resp["message"] = exception.Message + " - " + errorId;

await context.Response.WriteAsync(resp.ToString());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM