1
votes

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.

4
it's a .NET framework webapi? not .NET core?Ivan Yang
@IvanYang It is .NET frameworkPavel
If the answer works, could you please accept it as answer? Thanks. It would be helpful for others.Ivan Yang
I had to switch to an urgent task. I'll update question when return to Application Insights integrationPavel

4 Answers

1
votes

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)

0
votes

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.

0
votes

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.

0
votes

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