1

Is it possible to tell Application Insights to use a different InstrumentationKey depending on the request URL?

Our application works with different clients and we want to separate the logs for them in different instances of Application Insights.

Url format: https://webapi.com/v1/{client_name}/bla/bla

It would be great to setup configuration to select InstrumentationKey by client_name from request.

Pavel
  • 1,015
  • 3
  • 13
  • 27

4 Answers4

1

If the goal is to send different telemetry items to different instrumentation key, the correct way to achieve that is by modifying the individual item with a TelemetryInitializer to have the correct ikey.

An initializer like the following:

item.Context.InstrumentationKey = ikey.

This initializer should access HttpContext and decide the ikey dynamically from request route/other params.

Modifying TC.Active is not recommended for this purpose as its a global shared setting.

(This is not a very common use case - but there are teams inside Microsoft who does this for PROD scale apps)

cijothomas
  • 2,818
  • 1
  • 13
  • 25
0

You can do that. If you have a logger, have the ApplicationInsightsKey parameter-ized and pass the Key for the client on every call, or inject it on load if your application is tenant based.

Checkout the Docs here: Separating telemetry from Development, Test, and Production

Microsoft.ApplicationInsights.Extensibility.
TelemetryConfiguration.Active.InstrumentationKey = <App-Insights-Key-for-the-client>

Just change the Application Insights key before logging and it will do the job.

Sunny Sharma
  • 4,688
  • 5
  • 35
  • 73
  • Changing .Active ikey affects other parallel requests. If there is a single request at any point, then this works. But most apps have parallel requests and this wont work there. – cijothomas Apr 24 '20 at 02:57
  • that's right, exactly what I've mentioned - "pass the Key for the client on every call, or inject it on load if your application is tenant based." – Sunny Sharma Apr 24 '20 at 04:09
0

It would be great to setup configuration to select InstrumentationKey by client_name from request.

You can dynamically select the ikey as per the client_name from the request. First, you need to get the request url, then check the client_name.

To do that, you can add the following code to the Global.asax file:

    void Application_BeginRequest(Object source, EventArgs e)
    {
        var app = (HttpApplication)source;
        //get the request url
        var uriObject = app.Context.Request.Url.ToString();

        if (uriObject.Contains("/client_name_1"))
        {
            Microsoft.ApplicationInsights.Extensibility.
                      TelemetryConfiguration.Active.InstrumentationKey = "ikey_1";
        }
        else if (uriObject.Contains("/client_name_2"))
        {
            Microsoft.ApplicationInsights.Extensibility.
                      TelemetryConfiguration.Active.InstrumentationKey = "ikey_2";
        }
        else
        {
            Microsoft.ApplicationInsights.Extensibility.
                      TelemetryConfiguration.Active.InstrumentationKey = "ikey_3";
        }
    }

The test result:

enter image description here

But I want to say we rarely use 1 more ikeys in one environment. If your goal is to make the data not being cluttered, I suggest you can use only 1 ikey, and then use Kusto query for your purpose.

Ivan Glasenberg
  • 29,865
  • 2
  • 44
  • 60
0

Thanks to the answers from @cijothomas and @danpop (link) I was able to understand the whole picture.

Step 1: Create custom ITelemetryInitializer (Microsoft Documentation):

public class MyTelemetryInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        var appKey = CallContext.LogicalGetData("ApplicationKey")?.ToString();

        switch (appKey)
        {
            case "App1":
                telemetry.Context.InstrumentationKey = "d223527b-f34e-4c47-8aa8-1f21eb0fc349";
                return;
            default:
                telemetry.Context.InstrumentationKey = "f8ceb6cf-4357-4776-a2b6-5bbed8d2561c";
                return;
        }
    }
}

Step 2: Register custom initializer:

<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
   <TelemetryInitializers>
     <Add Type="Application.WebAPI.MyTelemetryInitializer, Application.WebAPI"/>
   </TelemetryInitializers>
   <!--<InstrumentationKey>f8ceb6cf-4357-4776-a2b6-5bbed8d2561c</InstrumentationKey>-->
</ApplicationInsights>

OR

protected void Application_Start()
{
    // ...
    TelemetryConfiguration.Active.TelemetryInitializers.Add(new MyTelemetryInitializer());
}

Step 3: Make some adjustments to the logger (source code taken from @danpop answer Logger target configuration):

var config = new LoggingConfiguration();
ConfigurationItemFactory.Default.Targets.RegisterDefinition("ai", typeof());
ApplicationInsightsTarget aiTarget = new ApplicationInsightsTarget();
aiTarget.InstrumentationKey = "your_key";
aiTarget.Name = "ai";
config.AddTarget("ai", aiTarget);
LogManager.Configuration = config;

ILogger configuration exmples: Log4Net, NLog, System.Diagnostics

Pavel
  • 1,015
  • 3
  • 13
  • 27