Request/response body logging to app insights - Azure functions

Arun Kumar Mandya Prabhakar 1 Reputation point
2021-08-06T06:46:30.527+00:00

I am looking into logging request/response body to app insights from all of my azure function end point(around 200 plus). I have come up with a below solution(still a bit raw) however this would force me to call LogRequestResponseDetails(req, response) from every single function end point which is really annoying. Is there an efficient/cleaner way to achieve this? Please see the code snippet below. Appreciate if any of you experts have any thoughts. Unfortunately you cannot hook into the HTTP pipeline(middleware) in startup.cs in azure functions which would have made life so much easier.

protected async Task LogRequestResponseDetails(HttpRequest req, string responseJson)
{
try
{
var functionName = new StackTrace().GetFrames().Select(x => (x?.GetMethod()?.GetCustomAttribute(typeof(FunctionNameAttribute)) as FunctionNameAttribute)?.Name).FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));

            if ((AppOptions.IsLoggingEnabled ?? false)
                || (!string.IsNullOrWhiteSpace(functionName)
                    && AppOptions.RequestLoggingSettings != null
                    && AppOptions.RequestLoggingSettings.TryGetValue(functionName, out var loggingActive)
                    && loggingActive))
            {
                RequestLogInitializer.RequestBody = await req.GetRawBodyStringAsync();
                RequestLogInitializer.ResponseBody = responseJson;
                _telemetryInitializer.Initialize(new RequestTelemetry());
            }
        }
        catch (Exception)
        {

        }
    }

public class RequestLogInitializer : ITelemetryInitializer
{
private readonly IHttpContextAccessor _httpContextAccessor;
public static string RequestBody { get; set; }
public static string ResponseBody { get; set; }

    public RequestLogInitializer(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void Initialize(ITelemetry telemetry)
    {
        if (telemetry != null && telemetry is RequestTelemetry)
        {
            var requestTelemetry = telemetry as RequestTelemetry;
            var httpContext = _httpContextAccessor.HttpContext;

            if (httpContext != null)
            {
                try
                {
                    httpContext.Request.EnableBuffering();
                    requestTelemetry.Properties.Add("IdfNumber", httpContext.Request.GetTokenUserFromHeader().IdfNumber);
                    requestTelemetry.Properties.Add("DeviceId", httpContext.Request.GetDeviceId());
                    requestTelemetry.Properties.Add("DeviceVersion", httpContext.Request.GetDeviceVersion());

                    if (httpContext.Request.Method == HttpMethod.Post.ToString() || httpContext.Request.Method == HttpMethods.Put.ToString())
                    {
                        requestTelemetry.Properties.Add("RequestBody", RequestBody);
                    }
                    else if (httpContext.Request.Method == HttpMethod.Get.ToString())
                    {
                        var queryString = httpContext.Request.QueryString;

                        if(queryString.HasValue)
                        {
                            NameValueCollection parsedQueryString = System.Web.HttpUtility.ParseQueryString(queryString.ToUriComponent());
                            parsedQueryString.Remove("code");
                            requestTelemetry.Properties.Add("QueryString", Convert.ToString(parsedQueryString));

                        }
                    }

                    // Log Response
                    requestTelemetry.Properties.Add("ResponseBody", ResponseBody);

                }
                catch (Exception e)
                {
                    requestTelemetry.Properties.Add("TelemetryCatch", e.Message);

                }
            }

        }

    }
Azure Monitor
Azure Monitor
An Azure service that is used to collect, analyze, and act on telemetry data from Azure and on-premises environments.
3,661 questions
Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,933 questions
Developer technologies | ASP.NET | ASP.NET Core
{count} votes

1 answer

Sort by: Most helpful
  1. Monalla-MSFT 13,071 Reputation points Moderator
    2021-09-03T19:42:52.277+00:00

    Hi @Arun Kumar Mandya Prabhakar - Thanks for reaching out.

    As Tinywang has mentioned, you can integrate Azure Application Insights in codeless way for Azure functions.

    For a function app to send data to Application Insights, it needs to know the instrumentation key of an Application Insights resource. The key must be in an app setting named APPINSIGHTS_INSTRUMENTATIONKEY.

    When you create your function app in the Azure portal, from the command line by using Azure Functions Core Tools, or by using Visual Studio Code, Application Insights integration is enabled by default. The Application Insights resource has the same name as your function app, and it's created either in the same region or in the nearest region.

    • If its a New function app in the portal
      To review the Application Insights resource being created, select it to expand the Application Insights window. You can change the New resource name or choose a different Location in an Azure geography where you want to store your data.
      129243-image.png
    • Add to an existing function app
      If an Application Insights resource wasn't created with your function app, use the following steps to create the resource. You can then add the instrumentation key
      from that resource as an application setting in your function app.
    • In the Azure portal, search for and select function app, and then choose your function app.
    • Select the Application Insights is not configured banner at the top of the window. If you don't see this banner, then your app might already have Application Insights
      enabled.
      129271-image.png
    • Expand Change your resource and create an Application Insights resource by using the settings specified in the following table.
      129235-image.png
      • Select Apply.

    The Application Insights resource is created in the same resource group and subscription as your function app. After the resource is created, close the Application Insights window.

    • In your function app, select Configuration under Settings, and then select Application settings. If you see a setting named APPINSIGHTS_INSTRUMENTATIONKEY, Application Insights integration is enabled for your function app running in Azure. If for some reason this setting doesn't exist, add it using your Application Insights instrumentation key as the value.

    Hope this helps.

    If it helps, Please feel free to "accept as answer" so it can beneficial to the community.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.