0
votes

I'm trying to log API request payload and response data to Azure Application Insight. Using trace I can able to log. but I want to know what is the best way to log request and response data to application insight. Because data is huge, no.of API calls will be more. I can't just trace hundreds of thousands of request and response data using tracing. I tried some of the blogs like using ITelemetryInitializer/ httpcontext.feature,get, but no luck.

I want to log from c# .Net framework, Web API, not .NET Core.

Sample code which I tried.

public class AzureRequestResponseInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;
        
        if (requestTelemetry != null && (HttpContext.Current.Request.HttpMethod == HttpMethod.Post.ToString() || HttpContext.Current.Request.HttpMethod == HttpMethod.Get.ToString()))
        {
            using (var reader = new StreamReader(HttpContext.Current.Request.InputStream))
            {
                string requestBody = reader.ReadToEnd();
                requestTelemetry.Properties.Add("body", requestBody);
            }
        } 
2
you can refer to this article. And please let me know if you have any updates.Ivan Yang
Do mind that this may cause high costs due to the large amount of data being logged. Are you sure you want to log this for each and every request? You might as well store the body in azure blob storage using a generated id and store that id as custom property so you can relate telemetry to the blob holding the request & response bodyPeter Bons

2 Answers

0
votes

You can achieve it by implementing IHttpModule that using Application Insight's TelemtryClient, see the following code:

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Contoso.Services.Logging.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Contoso.Services.Logging.Modules
{
    public class CaptureTrafficModule : IHttpModule
    {
        public TelemetryClient Telemetry { get; set; }
        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
            context.EndRequest += new EventHandler(context_EndRequest);

            Telemetry = new TelemetryClient();
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;

            HttpResponse response = HttpContext.Current.Response;
            OutputFilterStream filter = new OutputFilterStream(response.Filter);
            response.Filter = filter;
            app.Context.Items["Filter"] = filter;


            StringBuilder request = new StringBuilder();
            // Write All The Headers too :
            //foreach (string key in app.Request.Headers.Keys)
            //{
            //    request.Append(key);
            //    request.Append(": ");
            //    request.Append(app.Request.Headers[key]);
            //    request.Append("\n");
            //}
            //request.Append("\n");

            byte[] bytes = app.Request.BinaryRead(app.Request.ContentLength);
            if (bytes.Count() > 0)
                request.Append(Encoding.ASCII.GetString(bytes));
            app.Request.InputStream.Position = 0;

            string operationName = $"{app.Request.HttpMethod} {app.Request.FilePath}";
            string activityId = System.Diagnostics.Activity.Current.RootId;
            app.Context.Items["OperationName"] = operationName;
            app.Context.Items["ActivityId"] = activityId;
            using (var logRequest = Telemetry.StartOperation<RequestTelemetry>(operationName, System.Diagnostics.Activity.Current.RootId, System.Diagnostics.Activity.Current.RootId))
            {
                try
                {
                    //logRequest.Telemetry.Id = $"10-{activityId}";
                    logRequest.Telemetry.Url = app.Request.Url;
                    logRequest.Telemetry.Properties["RequestBody"] = request.ToString();
                }
                catch (Exception ex)
                {
                    logRequest.Telemetry.Success = false;

                    Telemetry.TrackException(ex);
                    //throw;
                }
            }
        }

        void context_EndRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            OutputFilterStream filter = null;
            string operationName = "", activityId = Guid.Empty.ToString(), responseStr = "NONE";

            if (app.Context.Items.Contains("OperationName"))
                operationName = app.Context.Items["OperationName"].ToString();

            if (app.Context.Items.Contains("ActivityId"))
                activityId = app.Context.Items["ActivityId"].ToString();

            if (app.Context.Items.Contains("Filter"))
            {
                filter = (OutputFilterStream)app.Context.Items["Filter"];
                responseStr = filter.ReadStream();
            }

            using (var logResponse = Telemetry.StartOperation<RequestTelemetry>(operationName, activityId, activityId))
            {
                try
                {
                    //logResponse.Telemetry.Id = $"20-{activityId}";
                    logResponse.Telemetry.Url = app.Request.Url;
                    logResponse.Telemetry.Properties["ResponseBody"] = responseStr.ToString();
                }
                catch (Exception ex)
                {
                    logResponse.Telemetry.Success = false;

                    Telemetry.TrackException(ex);
                    //throw;
                }
            }
        }



        public void Dispose()
        {
            //Does nothing
        }
    }

}