kord
kord

Reputation: 1039

How to extend Dependency tracking for outgoing http requests in Application Insights

I have a .NET core API that performs HTTP connections to other API. I am able to visualize the outgoing HTTP request in Application Insights, under Dependency Event Types, but it has only basic information. I'm looking on how to add more information about the outgoing HTTP call (like the HTTP headers for instance).

I've looked into https://learn.microsoft.com/en-us/azure/azure-monitor/app/api-custom-events-metrics#trackdependency but I didn't find any concrete way of doing this.

Upvotes: 4

Views: 4274

Answers (3)

keithl8041
keithl8041

Reputation: 2403

The other solution given doesn't actually work the way you think it should, since it's attaching the header from the incoming HTTP request to the outgoing dependency request, which is misleading. If you want to attach dependency data to dependency logs then you need to wrap the dependency in a custom dependency wrapper, eg here I'm logging the outgoing payload of the dependency so I can see what's being sent by my system:

Activity activity = null;
IOperationHolder<DependencyTelemetry> requestOperation = null;
if ((request.Method == HttpMethod.Post || request.Method == HttpMethod.Put) && _httpContextAccessor?.HttpContext != null)
{
    var bodyContent = await request.Content?.ReadAsStringAsync();
    if (!string.IsNullOrEmpty(bodyContent))
    {
        activity = new Activity("Wrapped POST/PUT operation");
        activity.SetTag("RequestBody", bodyContent);
        requestOperation = _telemetryClient.StartOperation<DependencyTelemetry>(activity);
    }
}

// perform dependency function
httpResponseMessage = await base.SendAsync(request, cancellationToken);

if (activity != null && requestOperation != null)
{
    _telemetryClient.StopOperation(requestOperation);
}

Upvotes: 1

Javier Pazos
Javier Pazos

Reputation: 169

As it has been said, the solution proposed by IvanYang is using the recived request instead of the dependency request. I've built this ITelemetryInstance for that:

public void Initialize(ITelemetry telemetry)
{
    var dependecyTelemetry = telemetry as DependencyTelemetry;
    if (dependecyTelemetry == null) return;

    if (dependecyTelemetry.TryGetOperationDetail("HttpRequest", out object request)
        && request is HttpRequestMessage httpRequest)
    {
        foreach (var item in httpRequest.Headers)
        {
            if (!dependecyTelemetry.Properties.ContainsKey(item.Key))
                dependecyTelemetry.Properties.Add(item.Key, string.Join(Environment.NewLine, item.Value));
        }
    }
    if (dependecyTelemetry.TryGetOperationDetail("HttpResponse", out object response)
        && response is HttpResponseMessage httpResponse)
    {
        var responseBody = httpResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult();
        if (!string.IsNullOrEmpty(responseBody))
            dependecyTelemetry.Properties.Add("ResponseBody", responseBody);
    }
}

This will record all the headers sent to the dependency and also the response received

Upvotes: 3

Ivan Glasenberg
Ivan Glasenberg

Reputation: 29985

I think what you're looking for is ITelemetryInitializer, which can add custom property for dependency telemetry.

And for .net core web project, you can refer to this link.

I write a demo as below:

1.Create a custom ITelemetryInitializer class to collect any dependency data:

    public class MyTelemetryInitializer: ITelemetryInitializer
    {
        IHttpContextAccessor httpContextAccessor;

        public MyTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
        {
            this.httpContextAccessor = httpContextAccessor;
        }

        public void Initialize(ITelemetry telemetry)
        {
            //only add custom property to dependency type, otherwise just return.
            var dependencyTelemetry = telemetry as DependencyTelemetry;
            if (dependencyTelemetry == null) return;

            if (!dependencyTelemetry.Context.Properties.ContainsKey("custom_dependency_headers_1"))
            {
                //the comment out code use to check the fields in Headers if you don't know
                //var s = httpContextAccessor.HttpContext.Request.Headers;
                //foreach (var s2 in s)
                //{
                //   var a1 = s2.Key;
                //    var a2 = s2.Value;
                //}

                dependencyTelemetry.Context.Properties["custom_dependency_headers_1"] = httpContextAccessor.HttpContext.Request.Headers["Connection"].ToString();
            }
        }

    }

2.Then in the Startup.cs -> ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
//other code

//add this line of code here
services.AddSingleton<ITelemetryInitializer, MyTelemetryInitializer>();
}

3.Test result, check if the custom property is added to azure portal -> Custom Properties:

enter image description here

Upvotes: 0

Related Questions