Skip to content
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

feat: plugin user interaction for web #658

Merged
merged 22 commits into from
Feb 5, 2020

Conversation

obecny
Copy link
Member

@obecny obecny commented Jan 2, 2020

Which problem is this PR solving?

Short description of the changes

  • It adds auto instrumentation for user click events. Together with plugin for xhr it will give user better overview and tracking for such actions

@obecny
Copy link
Member Author

obecny commented Jan 2, 2020

^^ @draffensperger

@codecov-io
Copy link

codecov-io commented Jan 2, 2020

Codecov Report

❗ No coverage uploaded for pull request base (master@b079de4). Click here to learn what that means.
The diff coverage is 0%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #658   +/-   ##
=========================================
  Coverage          ?   89.79%           
=========================================
  Files             ?      217           
  Lines             ?    10322           
  Branches          ?      990           
=========================================
  Hits              ?     9269           
  Misses            ?     1053           
  Partials          ?        0
Impacted Files Coverage Δ
.../opentelemetry-plugin-pg-pool/test/pg-pool.test.ts 34.92% <0%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b079de4...a392585. Read the comment docs.

shimmer.wrap(
HTMLElement.prototype,
'addEventListener',
this._patchElement()
Copy link
Member

Choose a reason for hiding this comment

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

Does this patch get used only on elements which use addEventListener (textbox, etc)? Would inlines like onclick="some fn" use this as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

inline onclick is not supported

Copy link
Contributor

Choose a reason for hiding this comment

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

That is correct, see this Stack Overflow answer that says the same thing.

A potential future work item could be to iterate over the DOM and see if there are any onclick event handlers set and then substitute them out for a wrapped version that would run them in the root zone.

That said, for the first version of this, I think we should just document it as a limitation and create a follow up issue to consider doing at some point in the future.

I expect that many people will use web frameworks like React, Vue, Angular, all of which I'm pretty sure use addEventListener rather than setting the onclick property.

Copy link
Member

Choose a reason for hiding this comment

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

That's an unfortunate limitation but seems like we can't really do much about it for now. Iterating over the DOM is potentially expensive and I would want it to be configurable at least.

Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if there would be a way to do it with a query selector, worth looking into anyway. But seems like a follow-up / future work item. We could also just see how often people actually request it, particularly since onclick is consider bad practice.

if (!element.getAttribute) {
return undefined;
}
if (element.hasAttribute('disabled')) {
Copy link
Member

Choose a reason for hiding this comment

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

Do you think it would be useful to include an additional element attribute that this plugin will look for to ignore tracking?

Copy link
Member Author

@obecny obecny Jan 3, 2020

Choose a reason for hiding this comment

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

Hmm don't have really opinion on that. Is there already anything like "common practice" or some standard how certain element is being excluded from auto instrumentation ?. Do you think it should be configurable in config ?

Copy link
Contributor

Choose a reason for hiding this comment

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

I like the idea of having a default attribute to opt-out of instrumentation for clicks but I think having it configurable is also good.

I think ideally (not for initial PR), we would also have some more intelligence on what types of interactions actually become spans. For example, a fair number of clicks might not result in any network calls, but maybe just change UI state (e.g. open a sidebar, etc.). Those aren't so meaningful to track whereas something like a "Save" button interaction that has multiple network calls and UI rendering would be valuable. A proxy for that could be that an interaction takes a certain amount of time or that it results in a network call. Seems like a potential area of future work but I don't think it's necessary for the first pass on this.

Copy link
Contributor

@draffensperger draffensperger left a comment

Choose a reason for hiding this comment

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

Great work @obecny this is awesome! I did a first pass with a number of comments, but this is generally good and moves the library forward in a really cool way.

if (!element.getAttribute) {
return undefined;
}
if (element.hasAttribute('disabled')) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the idea of having a default attribute to opt-out of instrumentation for clicks but I think having it configurable is also good.

I think ideally (not for initial PR), we would also have some more intelligence on what types of interactions actually become spans. For example, a fair number of clicks might not result in any network calls, but maybe just change UI state (e.g. open a sidebar, etc.). Those aren't so meaningful to track whereas something like a "Save" button interaction that has multiple network calls and UI rendering would be valuable. A proxy for that could be that an interaction takes a certain amount of time or that it results in a network call. Seems like a potential area of future work but I don't think it's necessary for the first pass on this.

packages/opentelemetry-web/src/utils.ts Show resolved Hide resolved
packages/opentelemetry-web/src/utils.ts Show resolved Hide resolved
@dyladan dyladan added the enhancement New feature or request label Jan 3, 2020
);

// this is needed as window is treated as scope and karma is adding
// context which is then detected as spanContext
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that context is a fairly generic thing, would it make sense for the scope manager to use something like _ot_context or similar to not collide with any production application that might be using context on the window for something application specific?

Copy link
Member Author

Choose a reason for hiding this comment

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

We might fix this differently by removing window from scope managers when active span doesn't exist I think this might be probably a proper fix, I need to check it but the fix will come in different PR anyway, for now I would say it will stay as it is

packages/opentelemetry-web/src/utils.ts Show resolved Hide resolved
packages/opentelemetry-web/src/utils.ts Outdated Show resolved Hide resolved
packages/opentelemetry-web/src/utils.ts Show resolved Hide resolved
task: AsyncTask
) {
const currentZone = Zone.current;
const currentSpan: types.Span = currentZone.get(ZONE_SCOPE_KEY);
Copy link
Member

Choose a reason for hiding this comment

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

types.Span is optional, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

what you mean ?

Copy link
Member

Choose a reason for hiding this comment

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

I think he is asking if currentZone.get always returns a Span or can it also return null or undefined?

Copy link
Contributor

@draffensperger draffensperger left a comment

Choose a reason for hiding this comment

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

Left a couple more comments, mostly stylistic / type system stuff and requesting that we don't test private methods. We can also iterate in the future on detecting span ends without Zone.js and on what exact events to trace.

But I think this is getting in a generally good overall shape. Great work @obecny . I'm going to give my approval though I gave a few more suggested changes.

shimmer.wrap(
HTMLElement.prototype,
'addEventListener',
this._patchElement()
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if there would be a way to do it with a query selector, worth looking into anyway. But seems like a follow-up / future work item. We could also just see how often people actually request it, particularly since onclick is consider bad practice.

let sandbox: sinon.SinonSandbox;
let webTracer: WebTracer;
let dummySpanExporter: DummySpanExporter;
let exportSpy: any;
Copy link
Contributor

Choose a reason for hiding this comment

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

@obecny friendly ping on this - is it possible to use the jasmine.Spy type here?

let webTracer: WebTracer;
let dummySpanExporter: DummySpanExporter;
let exportSpy: any;
let requests: any[] = [];
Copy link
Contributor

Choose a reason for hiding this comment

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

@obecny friendly ping here, is there any more specific type we can use?

packages/opentelemetry-web/src/utils.ts Show resolved Hide resolved
Copy link
Contributor

@draffensperger draffensperger left a comment

Choose a reason for hiding this comment

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

Nice, thanks for these changes!

@obecny
Copy link
Member Author

obecny commented Jan 13, 2020

lint is failing due to david-dm.org, fix is here #660

@obecny obecny self-assigned this Jan 16, 2020
@mayurkale22
Copy link
Member

@open-telemetry/javascript-approvers We need more reviews for this one!

Copy link
Member

@mayurkale22 mayurkale22 left a comment

Choose a reason for hiding this comment

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

Overall lgtm

Copy link
Member

@dyladan dyladan left a comment

Choose a reason for hiding this comment

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

Overall this LGTM. Just have the one question about the attribute name.

packages/opentelemetry-web/src/utils.ts Show resolved Hide resolved
packages/opentelemetry-web/src/utils.ts Show resolved Hide resolved
[AttributeNames.EVENT_TYPE]: eventName,
[AttributeNames.TARGET_ELEMENT]: element.tagName,
[AttributeNames.TARGET_XPATH]: xpath,
[AttributeNames.HTTP_URL]: window.location.href,
Copy link
Member

Choose a reason for hiding this comment

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

Is this meant to be the page you're currently viewing when you perform an interaction? If yes, I think we should use a different attribute name. http is a wire protocol and may not accurately represent the intended purpose. In addition, http.url already has a meaning in the spec and I don't want to confuse people. Can we change this to be something like view.url or page.url or similar?

@mayurkale22 @open-telemetry/javascript-approvers WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

One of the complexities here is that the user did in fact use the HTTP protocol to request the page initially. In that sense, it's sort of tied back to the original request. It also may be what people are most familiar with searching for if they were to think of it.

That said, it is true that view.url or page.url is more accurate. If we were to do with that, we should also update the Document load plugin to reference it in its root spans (see

)

Copy link
Member

Choose a reason for hiding this comment

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

@obecny @mayurkale22 what are your thoughts here?

Copy link
Member Author

@obecny obecny Feb 4, 2020

Choose a reason for hiding this comment

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

I don't have any strong opinion on that, for me all 3 options are fine but having the same name for url if this is either web or node makes more sense for me so that's why I added here the same name as in other plugins. But this is really a minor thing and can be changed at anytime now or later.

@mayurkale22 mayurkale22 merged commit e13dd57 into open-telemetry:master Feb 5, 2020
@obecny obecny deleted the plugin_user_interaction branch July 8, 2020 12:11
pichlermarc pushed a commit to dynatrace-oss-contrib/opentelemetry-js that referenced this pull request Dec 15, 2023
* chore: bumped aws components to 1.0

* chore: fixed link in docs to be consistent

Release-As: 1.0.0

* chore: cleaned up idgenerator readme

Release-As: 1.0.0

* chore: cleaned up propagator readme

Release-As: 1.0.0

* chore: updated sdk to 1.0.0

* updated readme for trace id generator

Co-authored-by: Rauno Viskus <[email protected]>
Co-authored-by: Bartlomiej Obecny <[email protected]>
martinkuba pushed a commit to martinkuba/opentelemetry-js that referenced this pull request Mar 13, 2024
* chore: bumped aws components to 1.0

* chore: fixed link in docs to be consistent

Release-As: 1.0.0

* chore: cleaned up idgenerator readme

Release-As: 1.0.0

* chore: cleaned up propagator readme

Release-As: 1.0.0

* chore: updated sdk to 1.0.0

* updated readme for trace id generator

Co-authored-by: Rauno Viskus <[email protected]>
Co-authored-by: Bartlomiej Obecny <[email protected]>
martinkuba pushed a commit to martinkuba/opentelemetry-js that referenced this pull request Mar 16, 2024
* chore: bumped aws components to 1.0

* chore: fixed link in docs to be consistent

Release-As: 1.0.0

* chore: cleaned up idgenerator readme

Release-As: 1.0.0

* chore: cleaned up propagator readme

Release-As: 1.0.0

* chore: updated sdk to 1.0.0

* updated readme for trace id generator

Co-authored-by: Rauno Viskus <[email protected]>
Co-authored-by: Bartlomiej Obecny <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Automatic tracing of user interactions in the browser (e.g. clicks)
6 participants