Skip to content
This repository was archived by the owner on Jul 5, 2020. It is now read-only.

Populate DependencyTelemetry with Operation Data for Initializers#897

Merged
TimothyMothra merged 16 commits intomicrosoft:developfrom
michaelwstark:develop
Jun 5, 2018
Merged

Populate DependencyTelemetry with Operation Data for Initializers#897
TimothyMothra merged 16 commits intomicrosoft:developfrom
michaelwstark:develop

Conversation

@michaelwstark
Copy link
Contributor

@michaelwstark michaelwstark commented Apr 26, 2018

Fix Issue # .
[Consolidated]
#900

[Original]
#820
#747
#587

Populate DependencyTelemetry with operation data for initializers.

  • I ran Unit Tests locally.

For significant contributions please make sure you have completed the following items:

@michaelwstark
Copy link
Contributor Author

I assume there is a change to the core SDK nuget package required, but as that hasn't been built yet, I just worked with the update locally. If there is a better processor for changes which modify both, please point me in the right direction -- appreciated.

Copy link

@lmolkova lmolkova left a comment

Choose a reason for hiding this comment

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

Thanks for the PR and all the tests, overall looks great!

I have a concern here regarding duplication in the OperationDetails dictionary.

  1. http response and headers should be mutually exclusive: in most of the cases reponse is available. the case where only headers are available is corener case and an ugly workaround.

  2. It seems Sql connection is avaialble through the command.

{
this.ParseResponse(response, telemetry);
telemetry.OperationDetails[RemoteDependencyConstants.HttpResponseOperationDetailName] = response;
telemetry.OperationDetails[RemoteDependencyConstants.HttpResponseHeadersOperationDetailName] = response.Headers;

Choose a reason for hiding this comment

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

why do we need to populate response AND headers? I'd prefer them to be mutually exclusive.
In case of .NET Core there is no case when a response is missing, but headers are present

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was actually how I originally had it (until I hit the corner case where the response was not present). My rationale for always including them was to make development of a initializer easier -- if the developer is only interested in headers, headers is always populated. This is not a stance of principal or conviction -- you are much more familiar with what the developer experience of the initializers should be, so I will defer to you. Please ack that you would prefer to only have the headers when the response is not available and I will make the change after I finish an update on the SDK pull request.

Choose a reason for hiding this comment

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

I hear your concern. I consider the scenario as very advanced and rare. And within this scenario case when a response is not available is rare itself. Making it convenient for a very small subset of users should come with a lowest possible performance impact even if it makes usage a bit less convenient.

So yes, I would prefer to have headers only when a response is not available.

telemetry.OperationDetails[RemoteDependencyConstants.SqlCommandOperationDetailName] = command;
if (connection != null)
{
telemetry.OperationDetails[RemoteDependencyConstants.SqlConnectionOperationDetailName] = connection;

Choose a reason for hiding this comment

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

The connection is available through the command, why do we need to explicitly add it to the dictionary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similar rationale as the response\headers comment above. I was not sure that the command would always be populated based on the failure cases, and I wanted to make it easier to develop the initializer if someone was only interested in properties on the connection. I will wait for confirmation on the comment above, and align the two to be consistent.

@lmolkova
Copy link

@anpete
Could you please help us review these SQL dependency collection changes?

Our goal is to enable scenario when users add arbitrary dynamic properties to their dependency telemetry. In HTTP case it could be adding request or response header value to the telemetry.

Could you please help us understand whether it is relevant for SQL and what kind of information could be useful/not useful.

Basically, we proxy DiagnostiSource payload to users through telemetry instance (but this info is not serialized and is never sent to the backend as it). It's up to users to access these objects and modify telemetry based on them.

This is a very advanced scenario we don't expect the absolute majority of users to implement.

Copy link
Contributor

@cijothomas cijothomas left a comment

Choose a reason for hiding this comment

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

Would like to have a 'flag' to turn this feature on/off if customer desires so, since some people may find the additional memory consumption not worth..
something like https://github.com/Microsoft/ApplicationInsights-dotnet-server/blob/develop/Src/DependencyCollector/Shared/DependencyTrackingTelemetryModule.cs#L57.

I have added couple other comments as well.

Target = string.Join(" | ", connection.DataSource, connection.Database),
Data = operation,
Success = true
Success = true,
Copy link
Contributor

Choose a reason for hiding this comment

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

intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not intentional, but it is a coding style from my projects. I'll remove the trailing comma when we hear back regarding the feature flag.



// Populate the operation details for intializers
telemetry.SetOperationDetail(RemoteDependencyConstants.SqlCommandOperationDetailName, command);
Copy link
Contributor

Choose a reason for hiding this comment

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

need similar change here as well:
https://github.com/Microsoft/ApplicationInsights-dotnet-server/blob/develop/Src/DependencyCollector/Shared/Implementation/ProfilerSqlProcessingBase.cs
This contains SQL dependency collection logic with Profiler installed.

CHANGELOG.md Outdated

## Version 2.7.0-beta1
- [Added support to collect Perf Counters for .NET Core Apps if running inside Azure WebApps] (https://github.com/Microsoft/ApplicationInsights-dotnet-server/issues/889)
- [Add operation details for HTTP and SQL operation to the dependency telemetry.](https://github.com/Microsoft/ApplicationInsights-dotnet-server/issues/587)
Copy link
Contributor

Choose a reason for hiding this comment

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

If possible create a new issue in gh, which contain detail about the specific fix. The original issue is quite long discussion, and it'll be hard to figure out which part from that is being implemented here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also helpful if an example TelemetryInitializer can be provided which utilizes this new feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cijothomas - Did you want the sample to be checked in somewhere and included in this PR, or inline in the new issue you were requesting on GitHub?

Copy link
Contributor

@cijothomas cijothomas Apr 30, 2018

Choose a reason for hiding this comment

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

Either is fine. Inline in a GH issue is easier to find as it's linked from release notes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

K. I'll code up a sample as I was intending to use this feature and include it in a new GH issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here is a consolidated issue with a code sample for intended use:
#900

@cijothomas
Copy link
Contributor

@SergeyKanzhelev and @Dmitry-Matveev - Please share your thoughts on making this under a feature flag, and having them OFF by default. I'd assume that this is only useful if customer has their own telemetry initializer which makes use of this. Those customers can turn this feature ON, so regular users dont see increased memory usage from AI SDK.

@michaelwstark
Copy link
Contributor Author

@cijothomas - While we are waiting for @SergeyKanzhelev and @Dmitry-Matveev to respond to whether this needs to be placed under a feature flag, can you point me to a current example? I presume it would be something similar to ExcludeComponentCorrelationHttpHeadersOnDomains or IncludeDiagnosticSourceActivities on the current dependency collection module, but am not completely sure.

@cijothomas
Copy link
Contributor

@michaelwstark Yes you are pretty close. More relevant example is DisableDiagnosticSourceInstrumentation flag on DependencyTrackingTelemetryModule which turns on/off DiagnosticSource based dependency tracking.
https://github.com/Microsoft/ApplicationInsights-dotnet-server/blob/develop/Src/DependencyCollector/Shared/DependencyTrackingTelemetryModule.cs#L57

@michaelwstark
Copy link
Contributor Author

Thanks for the pointer. I will create a branch off of my current working code with this change in anticipation of @SergeyKanzhelev or @Dmitry-Matveev indicating that we should include a flag for this behavior.

@lmolkova
Copy link

lmolkova commented May 1, 2018

@cijothomas
I believe the reason you are proposing the feature flag is making sure it does not break users not interested in this or it's easy to disable if it is broken.

However, this feature does not look risky: DependencyTelemetry has a new property that is just assigned to something we have validated. It will be safely ignored by existing users.
Users would need to write code to use the feature, they do not gain anything by default, i.e. it is de-facto disabled by default.

I could not see what can go wrong here and why we'd wan't to disable this feature.

@lmolkova
Copy link

lmolkova commented May 1, 2018

Those customers can turn this feature ON, so regular users dont see increased memory usage from AI SDK.

There should be no increase in memory usage. The new properties DependencyTelemetry gets already present in the memory and are cleaned up after dependency call is finished.

E.g. in case of HTTP we add Http request and Http response - there are no new allocations, except for dictionary with 2 items.

@lmolkova
Copy link

lmolkova commented May 1, 2018

@michaelwstark

we discussed it with @cijothomas offline.
The concern is that the feature would postpone GC for the requests/responses since reference would be kept in dependency telemetry until it is sent to the backend (that happens asynchronously).

I wonder, can we clean up the OperationDetails in TrackDependency call after initialize is called to address this concern?

Here

        public void TrackDependency(DependencyTelemetry telemetry)
        {
            if (telemetry == null)
            {
                telemetry = new DependencyTelemetry();
            }

            this.Track(telemetry);

!!!         telemetry.OperationDetails.Clear();
        }

It totally makes sense to me, as Track happens syncronously with dependency call and request/response should not be accessed after that.

@Dmitry-Matveev
Copy link
Member

@michaelwstark, I'm with Cijo on this one - due to increased memory usage for default scenario, I'd suggest to make this feature opt-in rather than on by default. Performant apps (let's say 500+ RPS) may all of a sudden become less performant if we store all request/responses/headers for 30 seconds (15000 * 3 objects). Super-performant apps (1000+ RPS) may struggle even if we come up with some optimization to release object sooner - it will still exist more than ASP.NET intended it to.
Making this opt-in will require a switch or flag that you are discussing with Cijo already.

@michaelwstark
Copy link
Contributor Author

michaelwstark commented May 2, 2018

@Dmitry-Matveev - Just wanting to confirm -- so the ask is to clear the captured objects on Track() as well as add a feature opt-in?

@lmolkova
Copy link

lmolkova commented May 2, 2018

@Dmitry-Matveev @michaelwstark
I do think having both: clean up AND feature flag is an overkill. If no additional references exist after dependency is tracked, there is nothing to protect from by feature flag.

@lmolkova
Copy link

lmolkova commented May 2, 2018

Chatted with @Dmitry-Matveev offline (he had to run for a meeting so cannot reply right now).
He is fine with the approach when we clean up details immediately after tracking telemetry (sync with response events). He agrees that in this case feature flag is not needed.

@Dmitry-Matveev
Copy link
Member

Thanks, @lmolkova! @michaelwstark, in case we do not copy nor keep response/request objects after the request is over - we are good without the feature flag.

@michaelwstark
Copy link
Contributor Author

@Dmitry-Matveev Thanks! @lmolkova - I think that all of the outstanding feedback has been resolved, please let me know what else needs to be done prior to merging these PRs into their respective repos. I noticed there are some VSTS checks which never provide any feedback -- anything I need to do there?

@cijothomas
Copy link
Contributor

@michaelwstark thanks for addressing the suggestions!
The VSTS checks are for CI Builds, which are not auto-triggered for forked repo pull requests. I'll manually trigger them for you and if all tests pass, we are good.
The changes in base SDK need to be first merged and published before the changes in this repo can be merged. I will start in base sdk build trigger first.

@cijothomas
Copy link
Contributor

@MS-TimothyMothra to ensure this is merged AFTER base 2.7.0-beta1 is published to myget.

@TimothyMothra TimothyMothra added this to the 2.7-Beta2 milestone May 8, 2018
updated changelog to reflect that this is expected to go in 2.7 Beta2
@TimothyMothra TimothyMothra modified the milestones: 2.7-Beta2, 2.7-Beta1 May 8, 2018
@TimothyMothra
Copy link

Sorry, I misunderstood and prep-ed this for Beta2.
Reverted my change.

@michaelwstark
Copy link
Contributor Author

@MS-TimothyMothra has the Beta1 of the core SDK been published to myget? When do we expect this PR to merge? Thanks in advance.

@TimothyMothra
Copy link

Sorry @michaelwstark, the 2.7 Beta1 got delayed to June 1st because we're working on hotfixes for 2.6 Stable.
Feel free to contact me directly if you need more information

@TimothyMothra
Copy link

@michaelwstark It looks like some of your new tests are failing.

  • TestZeroAndNonZeroContentResponseDiagnosticSource
  • TestBasicDependencyCollectionDiagnosticSourceLegacyHeaders

Will you have time to look at these today?

@michaelwstark
Copy link
Contributor Author

@MS-TimothyMothra. Yup. I'll be able to take a look today.

@lmolkova
Copy link

lmolkova commented Jun 5, 2018

I've added these two recently:

TestZeroAndNonZeroContentResponseDiagnosticSource
TestBasicDependencyCollectionDiagnosticSourceLegacyHeaders

Probably failures are result of auto-merge and new tests are missing something.

@michaelwstark
Copy link
Contributor Author

One test is a negative case for response, and the validate call requires hint not to validate response data. The other leveraged a new Boolean value in the validate pipeline which was not named which conflicted with the one I added. Re-running unit tests after the update and will push shortly if they pass.

@michaelwstark
Copy link
Contributor Author

@MS-TimothyMothra you should be good to proceed now. Let me know if you hit any more issues.

@TimothyMothra
Copy link

Thanks @michaelwstark ! Queuing your build 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