Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-traces-render.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

fix: exclude relative imports from tracing interception
8 changes: 6 additions & 2 deletions documentation/docs/30-advanced/68-observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentation
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { register } from 'import-in-the-middle/register-hooks.mjs';

register();
register({ shouldInclude: (_url, specifier) => !specifier.startsWith('.') });

const sdk = new NodeSDK({
serviceName: 'test-sveltekit-tracing',
Expand All @@ -89,6 +89,10 @@ const sdk = new NodeSDK({
sdk.start();
```

The `shouldInclude` option limits interception to package imports. It is important to exclude relative
imports, because `import-in-the-middle` does not preserve live bindings when wrapping mutable ESM
exports, which can break bundled application and framework code.

Now, server-side requests will begin generating traces, which you can view in Jaeger's web console at [localhost:16686](http://localhost:16686).

> [!NOTE] `import-in-the-middle/register-hooks.mjs` registers the loader via [`module.registerHooks()`](https://nodejs.org/api/module.html#moduleregisterhooksoptions), which runs the hooks synchronously on the application thread. This avoids the inter-thread message channel that the older `module.register()`-based setup required.
Expand All @@ -106,7 +110,7 @@ Now, server-side requests will begin generating traces, which you can view in Ja
> import { register as registerAsync } from 'node:module';
>
> if (supportsSyncHooks()) {
> register();
> register({ shouldInclude: (_url, specifier) => !specifier.startsWith('.') });
> } else {
> const { registerOptions } = createAddHookMessageChannel();
> registerAsync('import-in-the-middle/hook.mjs', import.meta.url, registerOptions);
Expand Down
3 changes: 2 additions & 1 deletion packages/kit/test/apps/basics/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
"@opentelemetry/sdk-trace-node": "catalog:",
"@sveltejs/kit": "workspace:^",
"@sveltejs/vite-plugin-svelte": "catalog:",
"@typescript/native": "catalog:",
"@vitest/browser-playwright": "catalog:",
"import-in-the-middle": "3.3.3",
"svelte": "catalog:",
"svelte-check": "catalog:",
"test-redirect-importer": "workspace:*",
"typescript": "catalog:",
"@typescript/native": "catalog:",
"vite": "catalog:",
"vitest": "catalog:"
},
Expand Down
21 changes: 21 additions & 0 deletions packages/kit/test/apps/basics/src/instrumentation.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@
/** @import {SpanData} from '../../../types' */
import { NodeSDK } from '@opentelemetry/sdk-node';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
// @ts-expect-error import-in-the-middle does not declare this entry point
import { register, supportsSyncHooks } from 'import-in-the-middle/register-hooks.mjs';
import { createAddHookMessageChannel } from 'import-in-the-middle';
import { register as registerAsync } from 'node:module';
import fs from 'node:fs';

/**
* @param {string} _url
* @param {string} specifier
*/
function should_include(_url, specifier) {
return !specifier.startsWith('.');
}

if (process.env.SVELTE_ASYNC === 'true') {
if (supportsSyncHooks()) {
register({ shouldInclude: should_include });
} else {
const { registerOptions } = createAddHookMessageChannel();
registerAsync('import-in-the-middle/hook.mjs', import.meta.url, registerOptions);
}
}

/** @implements {SpanExporter} */
class FilesystemSpanExporter {
#path;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
import { onDestroy } from 'svelte';

onDestroy(() => {});
</script>

<h1>rendered</h1>
11 changes: 11 additions & 0 deletions packages/kit/test/apps/basics/test/tracing-async.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import process from 'node:process';
import { expect } from '@playwright/test';
import { test } from '../../../utils.js';

test('SSR works with import interception and experimental async', async ({ request }) => {
test.skip(!!process.env.DEV || process.env.SVELTE_ASYNC !== 'true');

const response = await request.get('/tracing/async-ssr');
expect(response.status()).toBe(200);
expect(await response.text()).toContain('<h1>rendered</h1>');
});
13 changes: 13 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading