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(next): add sentry to payments-next #17550

Merged
merged 1 commit into from
Sep 9, 2024
Merged
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,6 @@ tmp
# shared-cms
libs/shared/cms/src/__generated__/graphql.d.ts
libs/shared/cms/src/__generated__/graphql.js

# Sentry Config File
.env.sentry-build-plugin
13 changes: 13 additions & 0 deletions apps/payments/next/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,18 @@ STATS_D_CONFIG__PREFIX=
CSP__ACCOUNTS_STATIC_CDN=https://accounts-static.cdn.mozilla.net
CSP__PAYPAL_API='https://www.sandbox.paypal.com'

# Sentry Config
SENTRY__SERVER_NAME=fxa-payments-next-server
SENTRY__AUTH_TOKEN=

# Other
CONTENT_SERVER_URL=http://localhost:3030

# Nextjs Public Environment Variables

# Sentry Config
NEXT_PUBLIC_SENTRY_DSN=
NEXT_PUBLIC_SENTRY_ENV=local
NEXT_PUBLIC_SENTRY_CLIENT_NAME=fxa-payments-next-client
NEXT_PUBLIC_SENTRY_SAMPLE_RATE=1
NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE=1
13 changes: 13 additions & 0 deletions apps/payments/next/.env.production
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,18 @@ STATS_D_CONFIG__PREFIX=
CSP__ACCOUNTS_STATIC_CDN=https://accounts-static.cdn.mozilla.net
CSP__PAYPAL_API='https://www.paypal.com'

# Sentry Config
SENTRY__SERVER_NAME=fxa-payments-next-server
SENTRY__AUTH_TOKEN=

# Other
CONTENT_SERVER_URL=https://accounts.firefox.com

# Nextjs Public Environment Variables

# Sentry Config
NEXT_PUBLIC_SENTRY_DSN=
NEXT_PUBLIC_SENTRY_ENV=prod
NEXT_PUBLIC_SENTRY_CLIENT_NAME=fxa-payments-next-client
NEXT_PUBLIC_SENTRY_SAMPLE_RATE=1
NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE=1
31 changes: 31 additions & 0 deletions apps/payments/next/app/global-error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
StaberindeZA marked this conversation as resolved.
Show resolved Hide resolved
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

'use client';

import * as Sentry from '@sentry/nextjs';
import NextError from 'next/error';
import { useEffect } from 'react';

export default function GlobalError({
error,
}: {
error: Error & { digest?: string };
}) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);

return (
<html>
<body>
{/* `NextError` is the default Next.js error page component. Its type
definition requires a `statusCode` prop. However, since the App Router
does not expose status codes for errors, we simply pass 0 to render a
generic error message. */}
<NextError statusCode={0} />
</body>
</html>
);
}
49 changes: 48 additions & 1 deletion apps/payments/next/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import 'reflect-metadata';
import 'server-only';
import { Type } from 'class-transformer';
import { IsString, ValidateNested, IsDefined, IsUrl } from 'class-validator';
import {
IsString,
ValidateNested,
IsDefined,
IsUrl,
IsNumber,
IsOptional,
} from 'class-validator';
import {
RootConfig as NestAppRootConfig,
validate,
Expand All @@ -20,6 +31,14 @@ class PaypalConfig {
clientId!: string;
}

class SentryServerConfig {
@IsString()
serverName!: string;

@IsString()
authToken!: string;
}

class AuthJSConfig {
@IsUrl({ require_tld: false })
issuerUrl!: string;
Expand Down Expand Up @@ -47,6 +66,11 @@ export class PaymentsNextConfig extends NestAppRootConfig {
@IsDefined()
csp!: CspConfig;

@Type(() => SentryServerConfig)
@ValidateNested()
@IsDefined()
sentry!: SentryServerConfig;

@IsString()
authSecret!: string;

Expand All @@ -55,6 +79,29 @@ export class PaymentsNextConfig extends NestAppRootConfig {

@IsUrl({ require_tld: false })
contentServerUrl!: string;

/**
* Nextjs Public Environment Variables
*/

/**
* Sentry Config
*/
@IsOptional()
@IsString()
nextPublicSentryDsn?: string;

@IsString()
nextPublicSentryEnv!: string;

@IsString()
nextPublicSentryClientName!: string;

@IsNumber()
nextPublicSentrySampleRate!: number;

@IsNumber()
nextPublicSentryTracesSampleRate!: number;
}

export const config = validate(process.env, PaymentsNextConfig);
5 changes: 5 additions & 0 deletions apps/payments/next/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./sentry.server.config');
const { getApp } = await import('@fxa/payments/ui/server');

await getApp().initialize();
Expand Down
48 changes: 48 additions & 0 deletions apps/payments/next/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

// eslint-disable-next-line @typescript-eslint/no-var-requires
const { composePlugins, withNx } = require('@nx/next');
const { withSentryConfig } = require('@sentry/nextjs');

/**
* @type {import('@nx/next/plugins/with-nx').WithNxOptions}
Expand All @@ -22,6 +23,8 @@ const nextConfig = {
'@nestjs/core',
'@nestjs/common',
'@nestjs/websockets',
'@nestjs/graphql',
'@nestjs/mapped-types',
'class-transformer',
'class-validator',
'hot-shots',
Expand Down Expand Up @@ -50,9 +53,54 @@ const nextConfig = {
},
};

/**
* @type {import('@sentry/nextjs').SentryBuildOptions}
**/
const sentryOptions = {
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options

org: "mozilla",
project: "fxa-payments-next",

// Enable source maps
authToken: process.env.SENTRY_AUTH_TOKEN,

// Only print logs for uploading source maps in CI
silent: !process.env.CI,

// For all available options, see:
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/

// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,

// Automatically annotate React components to show their full name in breadcrumbs and session replay
reactComponentAnnotation: {
enabled: true,
},

// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
// This can increase your server load as well as your hosting bill.
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
// side errors will fail.
tunnelRoute: "/monitoring",

// Hides source maps from generated client bundles
hideSourceMaps: true,

// Automatically tree-shake Sentry logger statements to reduce bundle size
disableLogger: true,
}

// Use withSentryConfig to wrap the next config
const sentryEnhancedConfig = (passedConfig) =>
withSentryConfig(passedConfig, sentryOptions);

const plugins = [
// Add more Next.js plugins to this list if needed.
withNx,
sentryEnhancedConfig,
];

module.exports = composePlugins(...plugins)(nextConfig);
2 changes: 1 addition & 1 deletion apps/payments/next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "payments-next",
"version": "0.0.1",
"version": "0.0.0",
"scripts": {
"start": "next start"
}
Expand Down
30 changes: 30 additions & 0 deletions apps/payments/next/sentry.client.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// This file configures the initialization of Sentry on the client.
// The config you add here will be used whenever a users loads a page in their browser.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
import { initSentryForNextjsClient } from '@fxa/shared/sentry/client';
import { version } from './package.json';

const DEFAULT_SAMPLE_RATE = '1';
const DEFAULT_TRACES_SAMPLE_RATE = '1';

const sentryConfig = {
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
env: process.env.NEXT_PUBLIC_SENTRY_ENV,
clientName: process.env.NEXT_PUBLIC_SENTRY_CLIENT_NAME,
sampleRate: parseInt(
process.env.NEXT_PUBLIC_SENTRY_SAMPLE_RATE || DEFAULT_SAMPLE_RATE
),
tracesSampleRate: parseInt(
process.env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE ||
DEFAULT_TRACES_SAMPLE_RATE
),
};

initSentryForNextjsClient({
release: version,
sentry: sentryConfig,
});
26 changes: 26 additions & 0 deletions apps/payments/next/sentry.server.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
import { initSentryForNextjsServer } from '@fxa/shared/sentry';
import { config } from './config';
import { version } from './package.json';

const sentryConfig = {
dsn: config.nextPublicSentryDsn,
env: config.nextPublicSentryEnv,
serverName: config.sentry.serverName,
sampleRate: config.nextPublicSentrySampleRate,
tracesSampleRate: config.nextPublicSentryTracesSampleRate,
};

initSentryForNextjsServer(
{
release: version,
sentry: sentryConfig,
},
console
);
4 changes: 4 additions & 0 deletions libs/payments/ui/src/lib/config.utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import set from 'set-value';
import { plainToInstance, ClassConstructor } from 'class-transformer';
import { validateSync } from 'class-validator';
Expand Down
5 changes: 5 additions & 0 deletions libs/shared/sentry/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

export * from './lib/next/client';
1 change: 1 addition & 0 deletions libs/shared/sentry/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from './lib/nest/sentry.constants';
export * from './lib/reporting';
export * from './lib/node';
export * from './lib/browser';
export * from './lib/next/server';
54 changes: 54 additions & 0 deletions libs/shared/sentry/src/lib/next/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// This file configures the initialization of Sentry on the client.
// The config you add here will be used whenever a users loads a page in their browser.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from '@sentry/nextjs';
import { SentryConfigOpts } from '../models/SentryConfigOpts';
import { buildSentryConfig } from '../config-builder';
import { Logger } from '../sentry.types';
import { beforeSend } from '../utils/beforeSend.client';

/**
* @@todo - To be worked on in FXA-10398
*/
const sentryEnabled = true;

export function initSentryForNextjsClient(
config: SentryConfigOpts,
log?: Logger
) {
if (!log) {
log = console;
}

if (!config?.sentry?.dsn) {
log.error('No Sentry dsn provided');
return;
}

// We want sentry to be disabled by default... This is because we only emit data
// for users that 'have opted in'. A subsequent call to 'enable' is needed to ensure
// that sentry events only flow under the proper circumstances.
//disable();

const opts = buildSentryConfig(config, log);
try {
Sentry.init({
...opts,
integrations: [
Sentry.browserTracingIntegration({
enableInp: true,
}),
],
beforeSend: function (event: Sentry.ErrorEvent) {
return beforeSend(sentryEnabled, opts, event);
},
});
} catch (e) {
log.error(e);
}
}
Loading