-
Notifications
You must be signed in to change notification settings - Fork 285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add OperationDetails object bag to DependencyTelemtry for Initializers #788
Conversation
FWIW. I am not in love with the name of the property -- "Data" was already taken, and putting this on a "Data" field on OperationContext would have made this a much more significant change. Open to suggestions (obviously). |
Consider making the Dictionary instantiation lazy to minimize the allocation penalty for code that doesn't need/use it. Also, it should probably be a ConcurrentDictionary (which I'm reluctant to point out because it is an allocation hog) |
/// <summary> | ||
/// Gets the dependency operation details, if any. | ||
/// </summary> | ||
public IDictionary<string, object> OperationDetails |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned with two things here
- confusion - we have too many properties already. I imagine users would not understand what info should go here and is it sent to AI backend.
- abuse - users should not use this dict to pass something unrelated
One possible way to address at least first could be to
- Make operation details private field
- Add getter and setter functions
- mark setter function as not browsable (like TelemetryClient.Track)
- keep getter public and browsable and give a detailed documentation summary of what it is.
Another way
- keep
OperationDetails
public, but not browsable - Add extension method in the DependencyCollector package like
DependencyTelemtery.TryGetValue(string key)
Even more strict way could be make an enum with possible keys in the DependenycCollector package and allow to get by enum.
@@ -19,6 +22,7 @@ public sealed class DependencyTelemetry : OperationTelemetry, ITelemetry, ISuppo | |||
|
|||
internal readonly RemoteDependencyData InternalData; | |||
private readonly TelemetryContext context; | |||
private readonly Lazy<IDictionary<string, object>> operationDetails; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For compactness (fewer object allocations), I prefer not to use Lazy<T>
.
Instead, make the field non-readonly IDictionary<string, object>
and use System.Threading.LazyInitializer.EnsureInitialized
.
The pattern is this:
using static System.Threading.LazyInitializer;
private IDictionary<string, object> operationDetails;
public IDictionary<string, object> OperationDetails => EnsureInitialized(ref operationDetails, () => new ConcurrentDictionary<string, object>());
/// <returns>true if the key was found; otherwise, false.</returns> | ||
public bool TryGetOperationDetail(string key, out object detail) | ||
{ | ||
return this.OperationDetails.TryGetValue(key, out detail); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short-circuit if operationDetails (the backing field) has not been initialized (avoid creating an empty ConcurrentDictionary here).
CHANGELOG.md
Outdated
-[Fix: changed namespace SamplingPercentageEstimatorSettings](https://github.com/Microsoft/ApplicationInsights-dotnet/issues/727) | ||
|
||
- [Fix: changed namespace SamplingPercentageEstimatorSettings](https://github.com/Microsoft/ApplicationInsights-dotnet/issues/727) | ||
- [NEW: Added TryGetOperationDetail to DependencyTelemetry to facilitate advanced ITelemetryInitializer scenarios] (https://github.com/Microsoft/ApplicationInsights-dotnet-server/issues/587) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was meant for 2.6.0 stable or 2.7.0-beta1? @MS-TimothyMothra can help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be great to explicitly mention that these new fields are NOT meant to be serialized and sent to AI backend, they only exist for facilitate TelemetryInitializers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know if the release the note is under needs to change -- I just put it under the latest one assuming that all pending changes should be put there. If you'd rather not release something in a stable release that hasn't been in a beta release I understand. I'll update the release note and the comment on the set method to explicitly state that the data is not serialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this changes would go into 2.7.0-beta1.
We had already shipped the last beta of 2.6.0 so only critical bugs would be released into 2.6.0-stable. So this change should be in beta1 of the next release, which is 2.7.0-beta1
…elds are not automatically serialized to the backend.
/// Initializes a new instance of the <see cref="DependencyTelemetry"/> class with the given <paramref name="dependencyName"/>, <paramref name="data"/>, | ||
/// <paramref name="startTime"/>, <paramref name="duration"/> and <paramref name="success"/> property values. | ||
/// </summary> | ||
[Obsolete("Use other constructors which allows to define dependency call with all the properties.")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lost some indenting here (lines 43-47). Please fix.
See comment from the Web SDK here: microsoft/ApplicationInsights-dotnet-server#897 (comment) 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? 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. |
Seems reasonable. I'll have to add some additional work to the test verification in the other repo, but shouldn't be to hard to grab these items prior to them being cleared out. |
I expected my tests for the dependency collector package to start failing, and when they did not, I investigated and found TrackDependency() is never called -- Track() is called directly. Is there a reason TrackDependency is not being called? |
You are right, we don't actually call Ok so the alternative could be to clean OperationDetail in the Web SDK (in dependency collector) where we assign them after the track call... |
@lmolkova - I actually prefer the original suggestion (seems like less maintenance over time), and had already updated the web sdk repo to call TrackDependency(), I was just verifying that there was not a reason for this. I noticed that Track() itself is not browsable. |
Sure, calling TrackDependency instead of Track is fine |
Manually triggered CI build/tests - all good and ready to merge |
@MS-TimothyMothra - Please merge this when branch is open for 2.7.0-beta1 |
Is there any way to retrieve the request body for HTTP dependency calls using the OperationDetails? Following the links posted earlier, I find that I can retrieve the
But the stream on the request is closed at this point, so unable to be read. Alternatively, is there any other way to capture the request body such that it is attached to the dependency telemetry? |
@MikeLarah no, there is no way to read closed stream. |
Do not prevent correlation headers injection on localhost
Fix Issue # .
[Consolidated]
microsoft/ApplicationInsights-dotnet-server#900
[Original]
microsoft/ApplicationInsights-dotnet-server#820
microsoft/ApplicationInsights-dotnet-server#747
microsoft/ApplicationInsights-dotnet-server#587
For significant contributions please make sure you have completed the following items:
Support adding arbitrary HTTP response headers from dependencies ApplicationInsights-dotnet-server#587