Miroslav Holec
Premium

Jak vrátit RequestID v HTTP Response hlavičce RESTových API pro App Insights

Miroslav Holec   12. prosince 2019

Tento článek byl napsán v roce 2019. Vývojářské technologie se neustále inovují a článek již nemusí popisovat aktuální stav technologie, ideální řešení a můj současný pohled na dané téma.

Mám RESTové API a v rámci něj zapojenou službu Application Insights. Každý request, který přijde na API má své specifické Request ID a já bych chtěl toto ID vyrolovat ven v HTTP Response hlavičce. Když API konzument dostane chybovou hlášku, může se podívat do této hlavičky a poslat mi dané Request ID pro snazší troubleshooting.

Celé řešení předpokládá, že máte zapojené Application Insights ve vaší aplikaci. Application Insights umí generovat pro každou operaci tzv. OperationID a RequestID. RequestID je globálně jedinečné, zatímco OperationID si musíte z RequestID eventuelně vytáhnout (je to ta část před tečkou).

Middleware pro zápis hlavičky

Pro přidání požadované response hlavičky si stačí vytvořit middleware (nebo teoreticky se dá použít MVC Filtr). Ten může nastavit response hlavičku již na začátku HTTP middleware pipeline, protože v té době už Request ID existuje. Zároveň samozřejmě existuje riziko, že nějaký middleware přemaže celou response včetně této hlavičky. Jaký middleware kdy hlavičku vykouzlí tedy nechám na vás a vaší request pipeline.

Celá magie spočívá v tom, že v middleware použiju tzv. HttpContext Features:

public class AppInsightsRequestIdMiddleware
{
    private readonly RequestDelegate next;

    public AppInsightsRequestIdMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext httpContext, TelemetryClient telemetryClient)
    {
        RequestTelemetry requestTelemetry = httpContext.Features.Get<RequestTelemetry>();
        httpContext.Response.Headers.Add("AI-RequestId", requestTelemetry.Id);
    }
}

Pomocí HttpContext Features jsem si nechal vrátit aktuální request telemetrii, ze které jsem si vytáhl potřebné Id. Pokud bych do telemetrie chtěl něco zapsat, ještě bych musel telemetrii vrátit přes TrackRequest(), aby došlo k zpropagování změny.

RequestTelemetry requestTelemetry = httpContext.Features.Get<RequestTelemetry>();
httpContext.Response.Headers.Add("AI-RequestId", requestTelemetry.Id);
requestTelemetry.Properties.Add("PropertyName", "Value");
telemetryClient.TrackRequest(requestTelemetry);

Celé je to neskutečně jednoduché a užitečné. Velmi podobnou funkci používám i u webových aplikací v případě chyby 500, kdy uživateli vrátím na chybové stránce možnost urgovat chybu mailem, kterým se mi posílá i Application Insights Request ID.

Error 500 s AppInsights Request ID