1

I'm trying to access the HTTP Request in my custom AppInsights telemetry initializer.

Mainly, i want to extract the POST body.

My question relates to this other answer

But, the answer indicates to use HttpContext.Current.Request.InputStream.

I can't do this... as im in an OWIN environment.

Any ideas?

Thanks

RPM1984
  • 72,246
  • 58
  • 225
  • 350

2 Answers2

2

OWIN introduces the notion of middlewares (which has been extended by asp.net core later) that requires you to build your application in layers.
One of the main reasons for that it to improve maintainability, performances as well as keep a high level of separation of concerns.
In the process they removed most of the static context variables (like httpContext.Current) the equivalent information will be passed to your middleware by the OWIN infrastructure as the OwinContext.
That being said you don't have to write your middleware from scratch if you're using Application Insights, an excellent nuget package exists to help you get there faster. Lastly, the body of a request can only be consumed once (at least safely) because of the way it's implemented see related github issue

baywet
  • 4,377
  • 4
  • 20
  • 49
  • I am using OWIN and Application Insights but I cannot install the nuget package because of incompatibility with my .NET framework. At the moment I cannot update the .NET framework version. How can I read the request stream? – Simone Nov 26 '17 at 19:02
  • 1
    This is probably a target framework setup issue and I suggest you post a separate question about that. Don't hesitate to link it here. – baywet Nov 26 '17 at 20:29
  • yes, I think so.. I have framework 4.5.1... I have read that a lot of new framework/plugin (not only this one) support framework 4.5.2+.. At the moment I'm trying this one https://stackoverflow.com/a/35953383/968759 + this one https://stackoverflow.com/a/37363258/968759 I will see what happen... otherwise I post a new question... Thank you! – Simone Nov 26 '17 at 20:40
  • 1
    Currently the package is targeting .net 4.6.1 as we can see here https://github.com/marcinbudny/applicationinsights-owinextensions/blob/develop/src/ApplicationInsights.OwinExtensions/ApplicationInsights.OwinExtensions.csproj#L12 – baywet Nov 26 '17 at 20:45
  • Ohh wow... thank you... I must learn to see also the source code... not only the documentation... I had not found the target framework in documentation! Thank you... However... that solution "I" have implemented has worked! Thank you! – Simone Nov 26 '17 at 20:48
0

I just want to extend baywet's answer.

If you can, I suggest to use the existing nuget package to extend Application Insights with OWIN. In that case you need at least .NET Framework 4.6.1.

Otherwise you can use "my" solution. I have just mixed theese two answers:

What I needed was logging exceptions and requests. This is what I have done.. (Here I write the essential things to let you to write a working solution).

I have created two different objects trackers: TrackerException and a TrackerRequest. Both implement the Proxy Pattern. In this way I do not have to apparently care what I have decided to track. I just let you see a simpler implementation of one tracker:

public class TrackerException : ITracker
{
    private readonly TelemetryClient _telemetryClient;
    public TrackerException(TelemetryClient telemetryClient)
    {
        this._telemetryClient = telemetryClient;
    }

    public void Track(ITelemetryObject telemetry)
    {
        if (telemetry is TelemetryExceptionObject)
        {
            Exception ex = ((TelemetryExceptionObject)telemetry).Exception;
            this._telemetryClient.TrackException(ex);
        }
    }
}

I use the trackers inside my custom Owin middleware:

public class ApplicationInsightsMiddleware : OwinMiddleware
{
    private TrackingOptions _trackingOptions;

    public ApplicationInsightsMiddleware(OwinMiddleware next) 
        : base(next)
    { }

    public ApplicationInsightsMiddleware(OwinMiddleware next, TrackingOptions trackingOptions) 
        : base(next)
    {
        this._trackingOptions = trackingOptions;
    }

    public override async Task Invoke(IOwinContext context)
    {
        var client = new TelemetryClient();
        this._trackingOptions.TelemetryClient = client;

        // Start Time Tracking
        var sw = new Stopwatch();
        var startTime = DateTimeOffset.Now;
        sw.Start();

        this._trackingOptions.TrackRequest.ReadRequestBody(context.Request);

        try
        {
            await Next.Invoke(context); 
        }
        catch (Exception ex)
        {
            ITelemetryObject exception = new TelemetryExceptionObject(ex);
            this._trackingOptions.TrackException.Track(exception);

            throw ex;
        }

        RequestTelemetry requestTelemetry = this._trackingOptions.TrackRequest.CreateTelemetryRequest(context.Request, context.Response, startTime, sw.Elapsed);
        ITelemetryObject request = new TelemetryRequestObject(requestTelemetry);
        this._trackingOptions.TrackRequest.Track(request);

        sw.Stop();
    }
}

TrackingOptions is a class that just enable or not a tracker... Here its implementation:

public class TrackingOptions
{
    //Here I initialize all my trackers

    private ProxyTrackerException _trackException;
    internal ProxyTrackerException TrackException { get { return _trackException; } }

    private TelemetryClient _telemetryClient;
    internal TelemetryClient TelemetryClient
    {
        get { return _telemetryClient; }
        set { _telemetryClient = value; }
    }

    public TrackingOptions(bool enableTrackingRequest, bool enableTrackingException)
    {
        this.InitializeExceptionTracker(enableTrackingException);
        //...
    }

    private void InitializeExceptionTracker(bool enableTrackingException)
    {
        this._trackException = new ProxyTrackerException(enableTrackingException, this._telemetryClient);
    }
}

In the end I have written an extension method for Owin

public static void UseApplicationInsights(this IAppBuilder app, TrackingOptions options)
{
    app.Use(typeof(ApplicationInsightsMiddleware), options);
}

In the startup of my project I add my new middleware:

app.UseApplicationInsights(
    new TrackingOptions(enableTrackingRequest: true, enableTrackingException: true)
);

However, this is a temporary solution for me... As soon as possible I will update my framework and install the existing nuget package.

Simone
  • 2,304
  • 6
  • 30
  • 79