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: Add HTTP breadcrumbs. #508

Merged

Conversation

kinyoklion
Copy link
Member

Prototype implementation.

@@ -12,6 +12,15 @@ export default class ErrorCollector implements Collector {
},
true,
);
window.addEventListener(
Copy link
Member Author

Choose a reason for hiding this comment

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

I was not handling unhandled promise rejections. Treating it the same as an error when possible.

@kinyoklion kinyoklion changed the title feat: Scaffold browser telemetry project. feat: Add HTTP breadcrumbs. Jul 10, 2024
Base automatically changed from rlamb/sc-249562-click-message to feat/proto-client-telemetry July 11, 2024 16:29
@@ -0,0 +1,84 @@
import toSelector, { elementToString, getClassName } from '../../../src/collectors/dom/toSelector';
Copy link
Member Author

Choose a reason for hiding this comment

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

Moved this file, but it should not have changes.

* @param callback Function which handles a breadcrumb.
*/
export default function decorateFetch(callback: (breadcrumb: HttpBreadcrumb) => void) {
// TODO: Check if already wrapped?
Copy link
Member Author

Choose a reason for hiding this comment

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

There are a number of TODO items in this PR that will remain.

@kinyoklion kinyoklion marked this pull request as ready for review July 11, 2024 22:01
@kinyoklion kinyoklion requested a review from a team as a code owner July 11, 2024 22:01
@kinyoklion kinyoklion requested review from tanderson-ld and keelerm84 and removed request for a team July 11, 2024 22:01
* Customize URL filtering. This will be applied in addition to some baseline filtering included
* which redacts components of LaunchDarkly URLs.
*/
customUrlFilter?: UrlFilter;
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 include a base filter, and then a customer an supply this additional filter. We may need more advanced filtering. For instance excluding entire requests, for a production version.

try {
// Use defineProperties to prevent these values from being enumerable.
// The properties default to non-enumerable.
Object.defineProperties(window.XMLHttpRequest, {
Copy link
Member Author

Choose a reason for hiding this comment

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

Not doing anything with these yet, but will probably check for their presence in a future version. For cases where people instantiate multiple SDKs and telemetry.

const streamingREgex = /\/eval\/[^/]*\/(?<context>[a-zA-Z0-9=]*)\??.*?/;

/**
* Filter which removes context information for browser JavaScript endpoints.
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a sufficient implementation for a prototype. It isn't format agnostic, which means it could break easily.

We may want to filter to something more generic for production. For instance if the header includes one of the LD specified headers, then replace the URL with something like <LaunchDarkly-Polling> or other generic identifiers.

Copy link
Contributor

Choose a reason for hiding this comment

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

Could just lopping off everything after the domain be sufficient for our customers? Then the filter could look for our domains, find end, truncate.

Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed more in another channel.

@@ -85,7 +110,7 @@ export default class BrowserTelemetryImpl implements BrowserTelemetry {
this.pendingEvents.shift();
}
}
this.client?.track(`$ld:telemetry:${type}`, event);
Copy link
Member Author

Choose a reason for hiding this comment

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

Bug from earlier refactoring.

}

unregister(): void {
this.destination = undefined;
Copy link
Contributor

@tanderson-ld tanderson-ld Jul 12, 2024

Choose a reason for hiding this comment

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

this.destination being undefined after unregister is different than its original state before register was called. I know private destination: BrowserTelemetry | undefined is possible, but I'm unsure of the pros and cons. Perhaps there is no appreciable difference.

Copy link
Contributor

Choose a reason for hiding this comment

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

Now I see elsewhere there is init?: RequestInit | undefined

Copy link
Member Author

Choose a reason for hiding this comment

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

A field before registration is undefined and after unregistration is undefined.
private destination?: BrowserTelemetry;
is the same as
private destination: BrowserTelemetry | undefined

As the field is not defined in the constructor it will be undefined, so it is conditionally accessed.

It isn't assigned in the constructor because I want to be able to make collectors immediately and then attach them.

The second thing is just because it was defined that way in the lib.dom.ts and I copied the definition.

Copy link
Member Author

Choose a reason for hiding this comment

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

Generally speaking optional elements cannot follow non-optional elements, so there is another case where it is a parameter is non-optional, but can be undefined. Which just means you have to pass something.

* which is completed.
*/
export default class XhrCollector implements Collector {
private destination?: BrowserTelemetry;
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question here wrt to undefined-ness

const streamingREgex = /\/eval\/[^/]*\/(?<context>[a-zA-Z0-9=]*)\??.*?/;

/**
* Filter which removes context information for browser JavaScript endpoints.
Copy link
Contributor

Choose a reason for hiding this comment

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

Could just lopping off everything after the domain be sufficient for our customers? Then the filter could look for our domains, find end, truncate.

const streamingREgex = /\/eval\/[^/]*\/(?<context>[a-zA-Z0-9=]*)\??.*?/;

/**
* Filter which removes context information for browser JavaScript endpoints.
Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed more in another channel.

@kinyoklion kinyoklion merged commit 7625d4b into feat/proto-client-telemetry Jul 12, 2024
20 checks passed
@kinyoklion kinyoklion deleted the rlamb/sc-249563/http-breadcrumbs branch July 12, 2024 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants