1

I'm trying to get some additional information about the message we received (basically its application-level outcome) into the Application Insights RequestTelemetry object for a WCF service.

Application Insights is logging request telemetry already. I created an ITelemetryInitializer that is being run, but at the time it runs I have no way that I can find to access information about the request, much less application-specific data from the request's context.

Is there somewhere I can put data that will be accessible by the ITelemetryInitializer at the time it runs?

    public class WcfServiceTelemetryInitializer : ITelemetryInitializer
    {
        public void Initialize(ITelemetry telemetry)
        {
            if (telemetry is RequestTelemetry rTelemetry)
            {
                // HttpContext.Current is populated at this point, but doesn't seem to be available within my application code.
                // So is System.ServiceModel.OperationContext.Current
            }
        }
    }
Mike
  • 827
  • 7
  • 21
  • what are the data that you want to add to telemetry? Please provide an example. – Ivan Glasenberg May 21 '20 at 05:59
  • For example, I have basic authentication. From the username in the authorization header I look up a user record in our system. I'd like to store the user's ID in the telemetry. Also this service is one where if there's an application error it returns a 200 and the error description is in the response text, and I'd like to put the error code in the telemetry if possible. I was trying something like: `HttpContext.Current.Items["property"] = "value";` But `HttpContext.Current` is not available in the application code. – Mike May 21 '20 at 18:50
  • I also tried adding to `OperationContext.Current.IncomingRequestProperties` which is available from the application, but not from the `TelemetryInitializer` – Mike May 21 '20 at 18:52
  • I'm sad to say I've given up on this. My solution ended up being to migrate the service to WebAPI which, if I'm being honest, is probably for my long-term sanity anyway. – Mike Aug 05 '20 at 18:50

3 Answers3

1

I had to face similar issue as the author described. Tried by implementing ITelemetryInitializer/ITelemetryProcessor but did not work.

Ended up writing my own MessageTraceTelemetryModule class implementing IWcfTelemetryModule and IWcfMessageTrace.

In the OnTraceResponse method, I added my custom property to the request telemetry by extracting value from OperationContext (which is accessible here!):

internal class MessageTraceTelemetryModule : IWcfTelemetryModule, IWcfMessageTrace
{
    public void OnTraceResponse(IOperationContext operation, ref Message response)
    {
        if (OperationContext.Current.IncomingMessageProperties.TryGetValue("clientID", out object value))
        {
            operation.Request.Properties.Add("clientID", value.ToString());
        }
    }
}

New custom property visible in Application Insights telemetry - ClientID custom property Pic.
Note that the clientID property is being set in the OperationContext in Message Inspector:

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
    if(!OperationContext.Current.IncomingMessageProperties.ContainsKey("clientID"))
        OperationContext.Current.IncomingMessageProperties.Add("clientID", clientID);
}

Brief Context:
I implemented AAD Token based Authentication in a SOAP based WCF Service.
I needed to store the clientID from the token (which is validated in message inspector) and add the same as a custom property in the application insights request telemetry.

References:

  1. Message Inspectors Documentation
  2. Application Insights for WCF Documentation

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Abhishek Anand
  • 101
  • 1
  • 8
1

In case it helps anyone, Application Insights automatically adds custom dimensions from data you store in System.Diagnostics.Activity.Current.AddBaggage(), or at least it does in asp.net 5. That might be available at the right place for you in WCF land.

e.g.

var currentActivity = System.Diagnostics.Activity.Current;
if (currentActivity != null)
{
    currentActivity.AddBaggage("MyPropertyName", someData);
}
Rory
  • 40,559
  • 52
  • 175
  • 261
-1

To log custom property, you can try like this...

public class CustomTelemetry : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;
        if (requestTelemetry == null) return;
        requestTelemetry.Properties.Add("CustomProperty", "DummyValue");
    }
}

And register CustomTelemetry at start of the application

TelemetryConfiguration.Active.TelemetryInitializers.Add(new CustomTelemetry());

Here is the Original Answer

MS Doc - Application Insights API for custom events and metrics

Indar
  • 267
  • 2
  • 11
  • 1
    This does not answer the question. Looks like the OP knows how to add properties but needs a way to access details about the WCF operation to use as values for the custom properties – Peter Bons May 21 '20 at 12:06
  • Like Peter said, I know how to add the properties. If I just wanted to add a constant value to every request I'd be good, but I'm trying to get some information in there that's not just specific to the request, but specific to how my application handled the request. I was hoping to call `HttpContext.Current.Items` from my application code, but it's null. – Mike May 21 '20 at 19:04