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: Allow defining page.route #185

Closed
wants to merge 3 commits into from

Conversation

nordfjord
Copy link
Contributor

@nordfjord nordfjord commented Jul 1, 2024

Which problem is this PR solving?

When it comes to frontend it can be hard to know which "route" you're actually on. Currently the SDK will place window.location.pathname onto the page.route attribute. This is great for many cases, but in our application we have many routes such as /entity/:entity_id where it'd be nice to group them together.

Short description of the changes

  • Allow passing a getRoute function to the SDK which will be called to fill in http.route

How to verify that this has the expected result

  • View the test

Possibilities

It should be possible for users to use the getRoute function to interrogate their router for what route they're actually on, or in more complex cases apply some inference based on the pathname (e.g. replace segments matching uuids with a placeholder)

For someone using react-router they might use a function like this:

function createRouteGetter(router) {
  let route = window.location.pathname
  router.subscribe(state => {
    let newRoute  = ""
    // some shenanigans here since routes can be nested
    for (let i = state.matches.length - 1; i >= 0; --i) {
      const path = state.matches[i]?.route.path
      if (!path) continue
      if (!route.startsWith(path)) newRoute = path + (newRoute.startsWith("/") ? newRoute : "/" + newRoute)
    }
    route = newRoute
  });
  return () => route
}

new HoneycombSDK({
  // ...
  getRoute: createRouteGetter(router)
})

@nordfjord nordfjord requested review from a team as code owners July 1, 2024 14:03
@nordfjord nordfjord changed the title infer route from pathname Allow defining page.route Jul 2, 2024
@MustafaHaddara MustafaHaddara changed the title Allow defining page.route feat: Allow defining page.route Jul 3, 2024
@MustafaHaddara MustafaHaddara added type: enhancement New feature or request version: bump minor A PR that adds behavior, but is backwards-compatible. labels Jul 3, 2024
@wolfgangcodes wolfgangcodes self-assigned this Jul 9, 2024
/**
* A {@link SpanProcessor} that adds browser specific attributes to each span
* that might change over the course of a session.
* Static attributes (e.g. User Agent) are added to the Resource.
*/
export class BrowserAttributesSpanProcessor implements SpanProcessor {
constructor() {}
getRoute: () => string;
Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking about this a little bit and I feel like this in itself would make a great span processor that we can export from the distro, it would be consumed by passing this processor to the spanProcessor config option itself. This way we keep the surface area of the API more consistent and get this ready for reuse / contribute it upstream to OTel.

We should extend our spanProcessor option to be spanProcessors that can take multiple span processors but we can address that in a separate PR.

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 sounds very sensible to me, how would you like me to action in the context of this PR?

Copy link
Contributor

Choose a reason for hiding this comment

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

Would you be up for reworking this PR by creating a new span processor for this and showing an example of how to use it in the example app?

I will open up an issue to accept multiple span processors and open up a separate PR myself for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Happy to spend some time on that, one question: should I remove the page.route attribute from this processor?

/**
* A {@link SpanProcessor} that adds dynamic attributes to every span
*/
export class DynamicAttributesSpanProcessor implements SpanProcessor {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@pkanal, I started thinking that maybe a PageRouteSpanProcessor makes less sense than something more generic, so here is a DynamicAttributesSpanProcessor which can be exposed and the BrowserAttributesSpanProcessor can be implemented in terms of. This would avoid needing to introduce a separate processor for each little attribute that comes up over time.

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 this approach! I'm wondering whether this should be something we package with the SDK or whether this should be documented for users since everyone's use case will be slightly different? 🤔

Thoughts @wolfgangcodes / @MustafaHaddara ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm arriving at the same conclusion. I think adding dynamic attributes globally like this will be a common use case, but at the same time this is so exceedingly generic as to be almost worthless. I'm hoping that sometime soon the OTel client instrumentation SIG comes up with a proposal to allow dynamic resource attributes which might fit these use cases better. At that point the page.route thing is something you'd just set up in your render cycle with a trace.addResourceAttributes({ 'page.route': match.route }) and would also take care of things like changing the enduser.id or tenant.id when a user logs in during a session.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmmm yeah, I think that is what span processors are meant to do in general. So are we coming to the conclusion that the best thing to do here is make sure that this distro is able to support multiple span processors and that this should be expressed as a custom span processor in a consuming app?

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, agreed, I'll close this PR

@nordfjord nordfjord closed this Jul 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement New feature or request version: bump minor A PR that adds behavior, but is backwards-compatible.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants