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
This issue is a collection of things I think SvelteKit should eventually offer to allow for and augment server-side instrumentation of SvelteKit applications. With kit being more prominently used nowadays, I see instrumentation for Observability (e.g. OpenTelemetry) as an important requirement, especially for larger companies.
At Sentry, we spent significant time researching and proposing the best methods for how (meta) frameworks and libraries should cater towards Instrumentation. Much of what I'm proposing here, is based on Sentry's Observability Guide (credits to @s1gr1d)
Background
The problem: Today, most frameworks, including SvelteKit, emit ESM. Unfortunately, ESM code no longer allows for classic monkey patching, due to ESM-imported modules being immutable and - more importantly - ESM imports being resolved and loaded before the actual JS code is evaluated.
As a result, instrumentation libraries (OpenTelemetry, Sentry, etc) need to use Node's module customization hooks to register code that enables instrumentation and then return a customized version of the imported packages. For this to work, the hook needs to be loaded before any import file. This can be done in two ways:
Users specify the hook (or the code that registers the hook) via --import when running node
node --import instrument.mjs index.mjs
# or
NODE_ENV="--import instrument.mjs" node index.mjs
This is possible in environments where users control the run command -- or can set the NODE_ENV environment variable -- but some cloud hosting platforms (e.g. Vercel or Netlify) don't provide a good enough way to accomplish this.
Users dynamically import their code after registering the hook:
awaitimport'./instrumentation.mjs';awaitimport('./server.mjs');// new file which contains code from previous index.mjs file
For SvelteKit application this only works today if you completely control the server (e.g. via adapter-node when rolling your own server).
Describe the proposed solution
1. First Class Support for loading instrumentation
Today, users are basically forced to load instrumentation hooks via --import. I propose SvelteKit exposes a instrument.server.ts file to users (similarly to hooks.server.ts) in which they can register their module customization hooks (e.g. import-in-the-middle) and init their obsvervability SDK (e.g. OpenTelemetry).
In addition to SvelteKit supporting instrumentation, it can also emit more signals so that instrumentation writers can write proper instrumentation for Kit. For example, SvelteKit can emit diagnostics channel messages for
request start/end
load functions
form actions
SSR
Then, we can create e.g. an OpenTelemetry instrumentation that listens for these signals and extracts spans, metrics or logs from it.
3. Related: Client-side instrumentation
If we'd go with the instrument.server.ts approach, we could also offer instrument.client.ts to provide users a similar experience to set up their client-side monitoring. On a technical level, this file could be imported or bundled in, very similarly to hooks.client.ts. The good thing here is that we don't need to worry about any kind of pre-loading, like on the server. We should just make sure that it's loaded as early as possible (e.g. like client hooks or the init hook specifically).
Users can also just import the client instrumentation file in their hooks for starters.
Alternatives considered
As an alternative to adding the instrument.server.ts file support, some observability folks are currently working on AST-based instrumentation. The libary is called orchestrion-js and could eventually also be applied at build time. Meaning, we can loosen the requirement of having to load the module custimization hook first. However, all of this is still very much work in progress and experimental. To the best of my knowledge, no-one so far has tried out applying orchestrion at build time (e.g. via a Vite plugin).
However, there's the problem of adapters again. Many adapters make a second build to which users can't add plugins. So for example, we could not inject http instrumentation at build time in the Node adapter. This would require adapter support, which ideally can be toggled by users.
I don't really have an alternative to 2, other than what we're doing at Sentry: wrapping users' load functions at build time. This works 90% of the time but depending on build and application setup might fail terribly :)
Importance
This would significantly improve instrumentation support for sveltekit users who today have a really hard time setting up observability instrumentation like OpenTelemetry
Additional Information
I'd be more than happy to collaborate with the Svelte(kit) team in making this become a reality.
I'm also presenting these ideas at my talk at Svelte Summit in Barcelona.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Describe the problem
Hi 👋
This issue is a collection of things I think SvelteKit should eventually offer to allow for and augment server-side instrumentation of SvelteKit applications. With kit being more prominently used nowadays, I see instrumentation for Observability (e.g. OpenTelemetry) as an important requirement, especially for larger companies.
At Sentry, we spent significant time researching and proposing the best methods for how (meta) frameworks and libraries should cater towards Instrumentation. Much of what I'm proposing here, is based on Sentry's Observability Guide (credits to @s1gr1d)
Background
The problem: Today, most frameworks, including SvelteKit, emit ESM. Unfortunately, ESM code no longer allows for classic monkey patching, due to ESM-imported modules being immutable and - more importantly - ESM imports being resolved and loaded before the actual JS code is evaluated.
As a result, instrumentation libraries (OpenTelemetry, Sentry, etc) need to use Node's module customization hooks to register code that enables instrumentation and then return a customized version of the imported packages. For this to work, the hook needs to be loaded before any import file. This can be done in two ways:
Users specify the hook (or the code that registers the hook) via
--import
when running nodeThis is possible in environments where users control the run command -- or can set the
NODE_ENV
environment variable -- but some cloud hosting platforms (e.g. Vercel or Netlify) don't provide a good enough way to accomplish this.Users dynamically import their code after registering the hook:
For SvelteKit application this only works today if you completely control the server (e.g. via adapter-node when rolling your own server).
Describe the proposed solution
1. First Class Support for loading instrumentation
Today, users are basically forced to load instrumentation hooks via
--import
. I propose SvelteKit exposes ainstrument.server.ts
file to users (similarly tohooks.server.ts
) in which they can register their module customization hooks (e.g.import-in-the-middle
) and init their obsvervability SDK (e.g. OpenTelemetry).For example
Then, the individual adapters can first import the instrument file and then dynamically import the actual server-side code:
I already gave this a try in a PoC PR: #13776
2. Emit request and rendering lifecycle signals
In addition to SvelteKit supporting instrumentation, it can also emit more signals so that instrumentation writers can write proper instrumentation for Kit. For example, SvelteKit can emit diagnostics channel messages for
Then, we can create e.g. an OpenTelemetry instrumentation that listens for these signals and extracts spans, metrics or logs from it.
3. Related: Client-side instrumentation
If we'd go with the
instrument.server.ts
approach, we could also offerinstrument.client.ts
to provide users a similar experience to set up their client-side monitoring. On a technical level, this file could be imported or bundled in, very similarly tohooks.client.ts
. The good thing here is that we don't need to worry about any kind of pre-loading, like on the server. We should just make sure that it's loaded as early as possible (e.g. like client hooks or theinit
hook specifically).Users can also just import the client instrumentation file in their hooks for starters.
Alternatives considered
As an alternative to adding the
instrument.server.ts
file support, some observability folks are currently working on AST-based instrumentation. The libary is calledorchestrion-js
and could eventually also be applied at build time. Meaning, we can loosen the requirement of having to load the module custimization hook first. However, all of this is still very much work in progress and experimental. To the best of my knowledge, no-one so far has tried out applying orchestrion at build time (e.g. via a Vite plugin).However, there's the problem of adapters again. Many adapters make a second build to which users can't add plugins. So for example, we could not inject
http
instrumentation at build time in the Node adapter. This would require adapter support, which ideally can be toggled by users.I don't really have an alternative to 2, other than what we're doing at Sentry: wrapping users'
load
functions at build time. This works 90% of the time but depending on build and application setup might fail terribly :)Importance
This would significantly improve instrumentation support for sveltekit users who today have a really hard time setting up observability instrumentation like OpenTelemetry
Additional Information
I'd be more than happy to collaborate with the Svelte(kit) team in making this become a reality.
I'm also presenting these ideas at my talk at Svelte Summit in Barcelona.
Beta Was this translation helpful? Give feedback.
All reactions