Iain Brown
Iain Brown

Reputation: 1171

When can I get an Application Insights operation id?

I have a AspNetCore web app that writes to EventHub and a webjob that reads from it. I'd like the telemetry from both parts of this transaction to have the same operation id in Application Insights.

So, when I'm about to send the data to EventHub I try to pull the operation id out of the TelemetryClient, e.g.

var myOperationId = MyTelemetryClient.Context.Operation.Id;

But this always gives me null. I found this article and tried using

var request.HttpContext.Items["Microsoft.ApplicationInsights.RequestTelemetry"] as RequestTelemetry;

But again null. Any pointers on a way I can extract this value when I need it?

My code looks like this:

public class Startup
{
    public void ConfigureServices( IServiceCollection IServices )
    {
        var builder = TelemetryConfiguration.Active.TelemetryProcessorChainBuilder;
        builder.Use((next) => new MyTelemetryProcessor(next));
        builder.Build();

        var aiOptions = new Microsoft.ApplicationInsights.AspNetCore.Extensions.ApplicationInsightsServiceOptions();
        aiOptions.EnableQuickPulseMetricStream = true;

        IServices.AddApplicationInsightsTelemetry( Configuration, aiOptions);
        IServices.AddMvc();
        IServices.AddOptions();

        TelemetryClient AppTelemetry = new TelemetryClient();
        AppTelemetry.InstrumentationKey = InsightsInstrumentationKey;
        IServices.AddSingleton(typeof(TelemetryClient), AppTelemetry);
    }
    public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory )
    {
        app.UseApplicationInsightsRequestTelemetry();
        app.UseApplicationInsightsExceptionTelemetry();

        app.UseMvc();

        var configuration = app.ApplicationServices.GetService<TelemetryConfiguration>();
        configuration.TelemetryInitializers.Add(new MyTelemetryInitializer());
    }
}

[Route("[controller]")]
public class MyController
{
    private readonly TelemetryClient mTelemetryClient;

    public MyController(
        TelemetryClient TelemetryClientArg)
    {
        mTelemetryClient = TelemetryClientArg;
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromBody]MyPostDataClass MyPostData)
    {
        string telemetryId = mTelemetryClient.Context.Operation.Id; // this is null

        return Ok();
    }
}

Upvotes: 15

Views: 19106

Answers (4)

Gopal Krishnan
Gopal Krishnan

Reputation: 1126

I did not have OperationIdTelemetryInitializer in my TelemetryConfiguration .Active.TelemetryInitializers.

But this provides me with the current operation id:

System.Diagnostics.Activity.Current.RootId

https://github.com/Microsoft/ApplicationInsights-aspnetcore/issues/504

Upvotes: 21

Russell Seamer
Russell Seamer

Reputation: 146

Think I finally cracked this without creating unwanted telemetry. The following is for AspNetCore, but should translate as long as the operation id initializer is available:

var operationId = default(string);
try
{
    var telemetry = new RequestTelemetry();

    TelemetryConfiguration
        .Active
        .TelemetryInitializers
        .OfType<OperationIdTelemetryInitializer>()
        .Single()
        .Initialize(telemetry);

    operationId = telemetry.Context.Operation.Id;

}
catch { }

Upvotes: 11

Iain Brown
Iain Brown

Reputation: 1171

You can get this value by sending a piece of telemetry and then reading back the operation id from the telemetry object. Not elegant, but it works.

[HttpPost]
public async Task<IActionResult> Post([FromBody]MyPostDataClass MyPostData)
{
   var dummyTrace = new TraceTelemetry("hello", SeverityLevel.Verbose);
   mTelemetryClient.TrackTrace(dummyTrace);
   string opId = dummyTrace.Context.Operation.Id;

   return Ok();
}

Upvotes: 0

John Gardner
John Gardner

Reputation: 25126

Asp.Net core package has an OperationIdTelemetryInitializer (see github) which tries to set this from a request. Hypothetically if you have request tracking and this telemetry initializer turned on, everything that happens in that request should have an Operation.Id set.

if that isn't working for you, you could create your own custom TelemetryInitializer to set it however you need, or, in the place where you do find it to be null, you could just set it there, and all things in that context should then have that id.

Upvotes: 1

Related Questions