You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We are currently trying to setup up client-side instrumentation for our application using OpenTelemetry. For context, Otel generalizes a notion of a span (think like the callstack span you might see in the JS debugger) and allows you to create custom spans that can contain other spans across services. So in the browser, for instance, it is common to wrap fetch in a function that creates a span and passes it along to the server, so you can see all the different things that fetch request triggered and handled.
Instrumenting fetch on the client is it's own can of worms that's being discussed in #9530 and #10009, and those would help a lot with allowing apps to do this kind of instrumentation. However, there is another issue we've been running into, specifically around the load hooks of pages and the preloading feature.
Ideally, we would create a span to wrap each load hook that is called. This way we can see the collection of load requests that went into every single page's render, and also gather metrics such as duration. We started building a solution to this based on onNavigate (which is not ideal because it's tied to a component lifecycle rather than being global, but that's a separate issue), but we found that our spans created in onNavigate were never being associated with the fetch requests that the load function was making. After some head scratching, we realized this was due to the preloading functionality SvelteKit exposes.
When the user hovers over a link, SvelteKit starts preloading the data for the route it is going to by default. This is great behavior for optimizing UX out of the box, but currently there doesn't seem to be a way to instrument this behavior and group it together logically into a single notion of a "page load". This means we can't accurately track the impact it has on users, whether or not prefetching is erroring, and what the overall performance of these preload calls is.
We considered disabling preloading altogether, but there doesn't appear to be a way to do this globally in an app at the moment. Moreover, the issue is not with the functionality itself, but with our inability to observe it.
Describe the proposed solution
I think this could be handled a few different ways:
Add handle to client side hooks, which would run for all client side load calls. This feels like it would be ideal from an API perspective if it would work, because then you are just conceptually mirroring the server functionality, but I could see this being tricky for a number of reasons on the client (different signatures, different notion of what an "event" is, etc).
Add client-side handleLoad and/or handlePreload hooks, or alternatively handleNavigate (though, like onNavigate, that would imply it only runs on actual user navigation). This would be a more targeted version of adding hooks, which means the API is less generalized and not as much of a commitment.
Add an onPreload function to the navigation module, which allows us to hook into the preload event much like a navigation event. This seems less ideal to me because preloading doesn't really seem to relate to a component as much, but it would solve the issue for us.
Alternatives considered
We've considered wrapping every single load hook with an instrumentLoad helper function, but this has a number of issues:
It makes type annotations a pain to write overall, a lot more boilerplate per module
Mistakes were very common, devs would forget to add the instrumentation all the time
It runs on the server as well, where we don't have this issue because we can wrap all events in a request in a span using the handle hook
Importance
i cannot use SvelteKit without it
Additional Information
Long term we really need this functionality, I'm exploring ways I could have our build-system add instrumentLoad helpers to each page load via a Vite plugin but ideally this would be pluggable within the framework.
Also, happy to implement this if it is accepted.
The text was updated successfully, but these errors were encountered:
Describe the problem
We are currently trying to setup up client-side instrumentation for our application using OpenTelemetry. For context, Otel generalizes a notion of a span (think like the callstack span you might see in the JS debugger) and allows you to create custom spans that can contain other spans across services. So in the browser, for instance, it is common to wrap
fetch
in a function that creates a span and passes it along to the server, so you can see all the different things thatfetch
request triggered and handled.Instrumenting
fetch
on the client is it's own can of worms that's being discussed in #9530 and #10009, and those would help a lot with allowing apps to do this kind of instrumentation. However, there is another issue we've been running into, specifically around theload
hooks of pages and the preloading feature.Ideally, we would create a span to wrap each load hook that is called. This way we can see the collection of load requests that went into every single page's render, and also gather metrics such as duration. We started building a solution to this based on
onNavigate
(which is not ideal because it's tied to a component lifecycle rather than being global, but that's a separate issue), but we found that our spans created inonNavigate
were never being associated with thefetch
requests that the load function was making. After some head scratching, we realized this was due to the preloading functionality SvelteKit exposes.When the user hovers over a link, SvelteKit starts preloading the data for the route it is going to by default. This is great behavior for optimizing UX out of the box, but currently there doesn't seem to be a way to instrument this behavior and group it together logically into a single notion of a "page load". This means we can't accurately track the impact it has on users, whether or not prefetching is erroring, and what the overall performance of these preload calls is.
We considered disabling preloading altogether, but there doesn't appear to be a way to do this globally in an app at the moment. Moreover, the issue is not with the functionality itself, but with our inability to observe it.
Describe the proposed solution
I think this could be handled a few different ways:
handle
to client side hooks, which would run for all client sideload
calls. This feels like it would be ideal from an API perspective if it would work, because then you are just conceptually mirroring the server functionality, but I could see this being tricky for a number of reasons on the client (different signatures, different notion of what an "event" is, etc).handleLoad
and/orhandlePreload
hooks, or alternativelyhandleNavigate
(though, likeonNavigate
, that would imply it only runs on actual user navigation). This would be a more targeted version of adding hooks, which means the API is less generalized and not as much of a commitment.onPreload
function to thenavigation
module, which allows us to hook into the preload event much like a navigation event. This seems less ideal to me because preloading doesn't really seem to relate to a component as much, but it would solve the issue for us.Alternatives considered
We've considered wrapping every single load hook with an
instrumentLoad
helper function, but this has a number of issues:handle
hookImportance
i cannot use SvelteKit without it
Additional Information
Long term we really need this functionality, I'm exploring ways I could have our build-system add
instrumentLoad
helpers to each page load via a Vite plugin but ideally this would be pluggable within the framework.Also, happy to implement this if it is accepted.
The text was updated successfully, but these errors were encountered: