Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Extensible payload handler #111

Merged
merged 11 commits into from
Aug 30, 2017

Conversation

jafletch
Copy link
Contributor

We use Tracelogging extensively in our system and we often log nested EventData objects via Write. The current implementation doesn't work for this scenario since it just calls ToString() on each value in the Payload collection. This change allows for implementing your own handler for converting EventWrittenEventArgs to TraceTelemetry.

@msftclas
Copy link

@jafletch,
Thanks for your contribution.
To ensure that the project team has proper rights to use your work, please complete the Contribution License Agreement at https://cla.microsoft.com.

It will cover your contributions to all Microsoft-managed open source projects.
Thanks,
Microsoft Pull Request Bot

@msftclas
Copy link

@jafletch, thanks for signing the contribution license agreement. We will now validate the agreement and then the pull request.

Thanks, Microsoft Pull Request Bot

@Dmitry-Matveev
Copy link
Member

@jafletch, it looks similar to the existing concept of Telemetry Initializers that allow one to modify/enrich telemetry item context before it gets sent. Is there another scenario or requirement this change might address?

@jafletch
Copy link
Contributor Author

@Dmitry-Matveev I am pretty new to AI in general and I just glanced through the docs in initializers and processors and it isn't obvious that would solve my problem, but perhaps I am just not familiar enough. The issue that I have is that I need to get access to the underlying ETW EventData object before that gets encoded into the properties of the TraceTelemetry object. The current implementation very simply passes over that EventData calling ToString() on the various parts of the payload and puts those in as properties of TraceTelemetry. I like most of what the current implementation does, but I want to be able to override that one behavior. I am open to any option that lets me do that.

@karolz-ms
Copy link
Contributor

@jafletch how about we give you an event off of the module, where you would get the EventData object and the TraceTelemetry object produced out of it and you could massage the TraceTelemetry object the way you see fit before it is passed down the pipeline?

@jafletch
Copy link
Contributor Author

jafletch commented Aug 24, 2017

@karolz-ms Sure, that sounds like basically what my change enables. For reference, here is my OnEventWrittenHandler currently looks like:

        public static void Track(EventWrittenEventArgs eventData, TelemetryClient client)
        {
            var telemetry = eventData.ToTraceTelementry(includePayload: false);

            eventData.ExtractPayloadData(telemetry);

            client.Track(telemetry);
        }

where the ToTraceTelementry extension method is just a slightly altered version of the Track EventData extension method that previously existed in the code and the ExtratPayloadData method is my own custom code. So I am able to reuse all of the functionality of setting up the TraceTelemetry object that this code was previously doing and just opt out of the payload handling part.

If you passed me the TraceTelemetry object with the payload fields already in there per the current ToString() mechanism, that doesn't seem useful so I would want to make sure that I get full control over handling the payload.

@karolz-ms
Copy link
Contributor

@jafletch Two questions then

  1. How generic is your handler that deals with nested EventData objects? Would that be something that is universally useful? If so, we should just incorporate this into the module.

if the answer is "no"

  1. I would like you to modify your proposal so that there is no includePayload bool parameter on for the ToTraceTelemetry method. Please refactor the code so that it has the building blocks you need (methods on EventDataExtensions, e.g. CreateTelemetry, AddStandardProperties, AddPayloadProperties) and make the ToTraceTelemetry and your custom EventData --> TraceTelemetry converter use these methods.

The latter is to ensure (to the foreseeable extent) that if someone else comes along and wants to create TraceTelemetry in yet another slightly different way, we do not have to change anything in the module code anymore.

@jafletch
Copy link
Contributor Author

@karolz-ms No, I wouldn't consider my solution sufficient for all cases. We are lucky in that we have a pretty narrow set of things that come through payload and my implementation is enough to handle those, but it isn't something I would be comfortable shipping much more broadly. I think this is going to be a pretty hard problem for a general solution which is why I think this particular extensibility point will be essential.

Agreed on point (2). I'll make some changes there and push them up.

Thanks! We already have people waiting on AI support so this is pretty cool for us.

@SergeyKanzhelev
Copy link
Contributor

I wonder why do we need an extensibility on telemetry module when it may be more natural to implement a custom eventsource listener? The benefit of custom listener is that you get a full control over it's behavior and granularity of configuring it only for the event sources you are interested in.

@karolz-ms
Copy link
Contributor

karolz-ms commented Aug 24, 2017

@SergeyKanzhelev the granularity part is also present with our EventSourceTelemetryModule (through the Sources property, specifically). And if your goal is to send data to AI, a custom listener does not help you in any way...

@jafletch
Copy link
Contributor Author

Ok I believe the current code reflects the requested changes

@SergeyKanzhelev
Copy link
Contributor

@karolz-ms my question was what benefit telemetry module gives comparing to the custom event listener. It feel like close to zero code reuse unless I missing something important.

James Fletcher added 2 commits August 25, 2017 10:42
…ights-dotnet-logging into extensible-payload-handler

# Conflicts:
#	src/Adapters/EventSource.Netstandard13/EventSourceTelemetryModule.cs
@SergeyKanzhelev
Copy link
Contributor

To give some context here - exposing a callback to allow one to extract more data is a very common scenario. Same way you need access to EventData object - one may need access to HttpClient to properly initializer the dependency telemetry object.

So long term we need a new layer in the SDK layering model that will enable such scenario in a more generic way.

We discussed it with @karolz-ms offline at Friday and floated ideas like TelemttryFactory<EventData> object and things of this nature. But there are more considerations at play. So we do not have a clear solution right away.

I think we need to get this change and later refactor it into the generic approach. I'd also like to know what would be your experience with the callback approach and ideas around it.

Copy link
Contributor

@SergeyKanzhelev SergeyKanzhelev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try{}catch is important there. You do not want to crash the process that writes something to EventSource because of the bad callback implementation

@@ -106,7 +120,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData)
// and not that useful for production tracing. However, TPL EventSource must be enabled to get hierarchical activity IDs.
if (this.initialized && !TplActivities.TplEventSourceGuid.Equals(eventData.EventSource.Guid))
{
eventData.Track(this.client);
this.onEventWrittenHandler(eventData, this.client);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put try catch around it as it is an external code you are calling

@@ -15,7 +15,7 @@ namespace Microsoft.ApplicationInsights.EventSourceListener.Implementation
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.TraceEvent.Shared.Utilities;

internal static class EventDataExtensions
public static class EventDataExtensions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why making it public? Do you want to re-use certain methods from here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the PopulateStandardProperties method is very useful for outside creators who want to write their own payload readers but make still use of the rest of the properties.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the callback may be called after telemetry got initialized then? My worry is that if you use this method you probably relying on the implementation too much. It feel you want a callback to "add" information, not to replace. Is it correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps I am not the standard consumer here but it works exactly as I would expect it to work and it handles the job of that I would just end up implementing myself if it wasn't there. For my scenario, I call:

var telemetry = eventData.ToTraceTelementry()
                                          .PopulateStandardProperties(eventData);

// My custom Payload handler 
eventData.ExtractPayloadData(telemetry);

This gives me a TraceTelemetry with all of the "boilerplate" fields populated from the EventWrittenEventArgs and then I add my own payload onto that. Of course you need not call any of these methods if you don't want to, but I find them convenient.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you! I appreciate you taking time to submit this PR and have this conversation. It definitely helps to form the opinion on how analogous generic API should look like.

@jafletch
Copy link
Contributor Author

Ok I believe all the feedback is addressed now

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants