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(nuxt): Adding experimental_basicServerTracing option to Nuxt module #13643

Merged
merged 8 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
10 changes: 10 additions & 0 deletions packages/nuxt/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,14 @@ export type SentryNuxtModuleOptions = {
* Enabling this will give you, for example, logs about source maps.
*/
debug?: boolean;

/**
* Enabling simplified deployment can be used for environments where modifying the node option `--import` is not possible.
* If this flag is `true`, the Sentry SDK will import the server config at the top of the server entry file to load the SDK on the server.
*
* Note that enabling this option only supports limited tracing instrumentation. Only http traces will be collected.
*
* @default false
*/
simplifiedDeployment?: boolean;
Copy link
Member

Choose a reason for hiding this comment

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

🧵 name bikeshedding :D

Some ideas:

  • basicTracingOnlyDeployment
  • noImportFlagDeployment
  • noImportFlagEnvironment

Copy link
Member Author

Choose a reason for hiding this comment

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

What do you think about a workaround_ prefix?

  1. workaround_injectSentryConfigIntoServer
  2. workaround_basicTracingWithServerConfigInject

Copy link
Member

Choose a reason for hiding this comment

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

I have no strong feelings either way! IMHO the question is, do we want to describe what the flag does, or when you need it? Describing what it does is obviously technically correct, but maybe makes it harder to understand when you would/should actually use this. I'll happily defer to you and other folks on the team about the name for this! We can also start with something like experimental_XXXX - we can still promote it to a non-experimental name later, if needed/wanted!

};
21 changes: 13 additions & 8 deletions packages/nuxt/src/module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { addPlugin, addPluginTemplate, addServerPlugin, createResolver, defineNuxtModule } from '@nuxt/kit';
import type { SentryNuxtModuleOptions } from './common/types';
import { addServerConfigToBuild } from './vite/addServerConfig';
import { addSentryTopImport, addServerConfigToBuild } from './vite/addServerConfig';
import { setupSourceMaps } from './vite/sourceMaps';
import { findDefaultSdkInitFile } from './vite/utils';

Expand Down Expand Up @@ -62,15 +62,20 @@ export default defineNuxtModule<ModuleOptions>({
if (clientConfigFile || serverConfigFile) {
setupSourceMaps(moduleOptions, nuxt);
}
if (serverConfigFile && serverConfigFile.includes('.server.config')) {
if (moduleOptions.debug) {
// eslint-disable-next-line no-console
console.log(
`[Sentry] Using your \`${serverConfigFile}\` file for the server-side Sentry configuration. In case you have a \`public/instrument.server\` file, the \`public/instrument.server\` file will be ignored. Make sure the file path in your node \`--import\` option matches the Sentry server config file in your \`.output\` folder and has a \`.mjs\` extension.`,
);
}

if (serverConfigFile && serverConfigFile.includes('.server.config')) {
addServerConfigToBuild(moduleOptions, nuxt, serverConfigFile);

if (moduleOptions.simplifiedDeployment) {
addSentryTopImport(moduleOptions, nuxt);
} else {
if (moduleOptions.debug) {
// eslint-disable-next-line no-console
console.log(
`[Sentry] Using your \`${serverConfigFile}\` file for the server-side Sentry configuration. In case you have a \`public/instrument.server\` file, the \`public/instrument.server\` file will be ignored. Make sure the file path in your node \`--import\` option matches the Sentry server config file in your \`.output\` folder and has a \`.mjs\` extension.`,
);
}
}
}
},
});
41 changes: 38 additions & 3 deletions packages/nuxt/src/vite/addServerConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as fs from 'fs';
import * as path from 'path';
import { createResolver } from '@nuxt/kit';
import type { Nuxt } from '@nuxt/schema';
import type { SentryNuxtModuleOptions } from '../common/types';
Expand Down Expand Up @@ -30,8 +29,9 @@ export function addServerConfigToBuild(
* This is necessary because we need to reference this file path in the node --import option.
*/
nuxt.hook('close', async () => {
const source = path.resolve('.nuxt/dist/server/sentry.server.config.mjs');
const destination = path.resolve('.output/server/sentry.server.config.mjs');
const rootDirResolver = createResolver(nuxt.options.rootDir);
const source = rootDirResolver.resolve('.nuxt/dist/server/sentry.server.config.mjs');
const destination = rootDirResolver.resolve('.output/server/sentry.server.config.mjs');

try {
await fs.promises.access(source, fs.constants.F_OK);
Expand All @@ -55,3 +55,38 @@ export function addServerConfigToBuild(
});
});
}

/**
* Adds the Sentry server config import at the top of the server entry file to load the SDK on the server.
* This is necessary for environments where modifying the node option `--import` is not possible.
* However, only limited tracing instrumentation is supported when doing this.
*/
export function addSentryTopImport(moduleOptions: SentryNuxtModuleOptions, nuxt: Nuxt): void {
nuxt.hook('close', async () => {
const rootDirResolver = createResolver(nuxt.options.rootDir);
const entryFilePath = rootDirResolver.resolve('.output/server/index.mjs');

try {
fs.readFile(entryFilePath, 'utf8', (err, data) => {
const updatedContent = `import './sentry.server.config.mjs';\n${data}`;

fs.writeFile(entryFilePath, updatedContent, 'utf8', () => {
if (moduleOptions.debug) {
// eslint-disable-next-line no-console
console.log(
`[Sentry] Successfully added the Sentry import to the server entry file "\`${entryFilePath}\`"`,
);
}
});
});
} catch (err) {
if (moduleOptions.debug) {
// eslint-disable-next-line no-console
console.warn(
`[Sentry] An error occurred when trying to add the Sentry import to the server entry file "\`${entryFilePath}\`":`,
err,
);
}
}
});
}
Loading