Skip to content
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
7 changes: 7 additions & 0 deletions src/cloudflare/cloudflare-wizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ async function runCloudflareWizardWithTelemetry(
)} to track the performance of your application?`,
enabledHint: 'recommended',
},
{
id: 'logs',
prompt: `Do you want to enable ${chalk.bold(
'Logs',
)} to send your application logs to Sentry?`,
enabledHint: 'recommended',
},
] as const);

await traceStep('Create Sentry initialization', async () => {
Expand Down
1 change: 1 addition & 0 deletions src/cloudflare/sdk-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export async function createSentryInitFile(
dsn: string,
selectedFeatures: {
performance: boolean;
logs: boolean;
},
): Promise<void> {
const entryPointFromConfig = getEntryPointFromWranglerConfig();
Expand Down
10 changes: 9 additions & 1 deletion src/cloudflare/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export function getCloudflareWorkerTemplate(
dsn: string,
selectedFeatures: {
performance: boolean;
logs: boolean;
},
): string {
let performanceOptions = '';
Expand All @@ -11,11 +12,18 @@ export function getCloudflareWorkerTemplate(
tracesSampleRate: 1,`;
}

let logsOptions = '';
if (selectedFeatures.logs) {
logsOptions = `
// Enable logs to be sent to Sentry
enableLogs: true,`;
}

return `import * as Sentry from '@sentry/cloudflare';

export default Sentry.withSentry(
(env) => ({
dsn: '${dsn}',${performanceOptions}
dsn: '${dsn}',${performanceOptions}${logsOptions}
}),
{
async fetch(request, env, ctx): Promise<Response> {
Expand Down
15 changes: 15 additions & 0 deletions src/cloudflare/wrap-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export async function wrapWorkerWithSentry(
dsn: string,
selectedFeatures: {
performance: boolean;
logs: boolean;
},
): Promise<void> {
const workerAst = await loadFile(workerFilePath);
Expand Down Expand Up @@ -90,6 +91,7 @@ function createSentryConfigFunction(
dsn: string,
selectedFeatures: {
performance: boolean;
logs: boolean;
},
): t.ArrowFunctionExpression {
const configProperties: t.ObjectProperty[] = [
Expand All @@ -113,6 +115,19 @@ function createSentryConfigFunction(
configProperties.push(tracesSampleRateProperty);
}

if (selectedFeatures.logs) {
const enableLogsProperty = b.objectProperty(
b.identifier('enableLogs'),
b.booleanLiteral(true),
);

enableLogsProperty.comments = [
b.commentLine(' Enable logs to be sent to Sentry', true, false),
];

configProperties.push(enableLogsProperty);
}

const configObject = b.objectExpression(configProperties);

return b.arrowFunctionExpression([b.identifier('env')], configObject);
Expand Down
47 changes: 31 additions & 16 deletions test/cloudflare/__snapshots__/wrap-worker.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,6 @@ export default Sentry.withSentry(env => ({
});"
`;

exports[`wrapWorkerWithSentry > idempotency > does not wrap again if Sentry is already present 1`] = `
"import * as Sentry from '@sentry/cloudflare';

export default Sentry.withSentry(
(env) => ({
dsn: 'existing-dsn',
}),
{
async fetch(request, env, ctx): Promise<Response> {
return new Response('Already wrapped');
},
},
);
"
`;

exports[`wrapWorkerWithSentry > import handling > adds Sentry import at the beginning of the file 1`] = `
"import * as Sentry from "@sentry/cloudflare";
// Worker comment
Expand Down Expand Up @@ -108,6 +92,37 @@ export default Sentry.withSentry(env => ({
});"
`;

exports[`wrapWorkerWithSentry > logs > includes both tracesSampleRate and enableLogs when both are enabled 1`] = `
"import * as Sentry from "@sentry/cloudflare";
export default Sentry.withSentry(env => ({
dsn: "my-dsn",

// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
tracesSampleRate: 1,

// Enable logs to be sent to Sentry
enableLogs: true
}), {
async fetch(request, env, ctx): Promise<Response> {
return new Response('Hello');
}
});"
`;

exports[`wrapWorkerWithSentry > logs > includes enableLogs when logs is enabled 1`] = `
"import * as Sentry from "@sentry/cloudflare";
export default Sentry.withSentry(env => ({
dsn: "my-dsn",

// Enable logs to be sent to Sentry
enableLogs: true
}), {
async fetch(request, env, ctx): Promise<Response> {
return new Response('Hello');
}
});"
`;

exports[`wrapWorkerWithSentry > performance monitoring > includes tracesSampleRate when performance is enabled 1`] = `
"import * as Sentry from "@sentry/cloudflare";
export default Sentry.withSentry(env => ({
Expand Down
36 changes: 34 additions & 2 deletions test/cloudflare/sdk-setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ describe('createSentryInitFile', () => {
const testDsn = 'https://example@sentry.io/123';
const testFeatures = {
performance: true,
logs: false,
};

beforeEach(() => {
Expand Down Expand Up @@ -155,12 +156,43 @@ describe('createSentryInitFile', () => {
.spyOn(wrapWorker, 'wrapWorkerWithSentry')
.mockResolvedValue(undefined);

await createSentryInitFile(testDsn, { performance: false });
await createSentryInitFile(testDsn, {
performance: false,
logs: false,
});

expect(wrapWorkerWithSentrySpy).toHaveBeenCalledWith(
path.join(tmpDir, defaultEntryPoint),
testDsn,
{ performance: false },
{ performance: false, logs: false },
);
});

it('passes logs feature flag correctly', async () => {
const wrapWorkerWithSentrySpy = vi
.spyOn(wrapWorker, 'wrapWorkerWithSentry')
.mockResolvedValue(undefined);

await createSentryInitFile(testDsn, { performance: false, logs: true });

expect(wrapWorkerWithSentrySpy).toHaveBeenCalledWith(
path.join(tmpDir, defaultEntryPoint),
testDsn,
{ performance: false, logs: true },
);
});

it('passes both feature flags correctly', async () => {
const wrapWorkerWithSentrySpy = vi
.spyOn(wrapWorker, 'wrapWorkerWithSentry')
.mockResolvedValue(undefined);

await createSentryInitFile(testDsn, { performance: true, logs: true });

expect(wrapWorkerWithSentrySpy).toHaveBeenCalledWith(
path.join(tmpDir, defaultEntryPoint),
testDsn,
{ performance: true, logs: true },
);
});
});
Expand Down
58 changes: 58 additions & 0 deletions test/cloudflare/templates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ describe('Cloudflare code templates', () => {
it('generates worker template with performance monitoring enabled', () => {
const template = getCloudflareWorkerTemplate('my-dsn', {
performance: true,
logs: false,
});

expect(template).toMatchInlineSnapshot(`
Expand All @@ -31,6 +32,7 @@ describe('Cloudflare code templates', () => {
it('generates worker template with performance monitoring disabled', () => {
const template = getCloudflareWorkerTemplate('my-dsn', {
performance: false,
logs: false,
});

expect(template).toMatchInlineSnapshot(`
Expand All @@ -51,10 +53,65 @@ describe('Cloudflare code templates', () => {
`);
});

it('generates worker template with logs enabled', () => {
const template = getCloudflareWorkerTemplate('my-dsn', {
performance: false,
logs: true,
});

expect(template).toMatchInlineSnapshot(`
"import * as Sentry from '@sentry/cloudflare';

export default Sentry.withSentry(
(env) => ({
dsn: 'my-dsn',
// Enable logs to be sent to Sentry
enableLogs: true,
}),
{
async fetch(request, env, ctx): Promise<Response> {
// Your worker logic here
return new Response('Hello World!');
},
} satisfies ExportedHandler<Env>,
);
"
`);
});

it('generates worker template with both performance and logs enabled', () => {
const template = getCloudflareWorkerTemplate('my-dsn', {
performance: true,
logs: true,
});

expect(template).toMatchInlineSnapshot(`
"import * as Sentry from '@sentry/cloudflare';

export default Sentry.withSentry(
(env) => ({
dsn: 'my-dsn',
// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
tracesSampleRate: 1,
// Enable logs to be sent to Sentry
enableLogs: true,
}),
{
async fetch(request, env, ctx): Promise<Response> {
// Your worker logic here
return new Response('Hello World!');
},
} satisfies ExportedHandler<Env>,
);
"
`);
});

it('includes the correct DSN', () => {
const dsn = 'https://example@sentry.io/123';
const template = getCloudflareWorkerTemplate(dsn, {
performance: true,
logs: false,
});

expect(template).toContain(`dsn: '${dsn}'`);
Expand All @@ -63,6 +120,7 @@ describe('Cloudflare code templates', () => {
it('wraps handler with Sentry.withSentry', () => {
const template = getCloudflareWorkerTemplate('my-dsn', {
performance: false,
logs: false,
});

expect(template).toContain('Sentry.withSentry');
Expand Down
Loading
Loading