Skip to content

Commit

Permalink
STASH
Browse files Browse the repository at this point in the history
  • Loading branch information
lobsterkatie committed Sep 7, 2022
1 parent 11b1fbd commit a806f00
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 9 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: 'Build & Test'
on:
push:
branches:
- master
- release/**
# branches:
# - master
# - release/**
pull_request:
workflow_dispatch:
inputs:
Expand Down
9 changes: 9 additions & 0 deletions packages/nextjs/src/config/wrappers/wrapperUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ function setTransactionOnRequest(transaction: Transaction, req: IncomingMessage)
req._sentryTransaction = transaction;
}

// function getRequestFromTransaction(transaction: Transaction): IncomingMessage | undefined {
// return req._sentryTransaction;
// }
//
// function setTransactionOnRequest(transaction: Transaction, req: IncomingMessage): void {
// req._sentryTransaction = transaction;
// }

// TODO: Make this work with flushing in serverless functions
function autoEndTransactionOnResponseEnd(transaction: Transaction, res: ServerResponse): void {
fill(res, 'end', (originalEnd: ServerResponse['end']) => {
return function (this: unknown, ...endArguments: Parameters<ServerResponse['end']>) {
Expand Down
176 changes: 176 additions & 0 deletions packages/nextjs/src/index.server copy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import type { Carrier, Scope } from '@sentry/hub';
import { getHubFromCarrier, getMainCarrier } from '@sentry/hub';
import { RewriteFrames } from '@sentry/integrations';
import { addRequestDataToEvent, configureScope, getCurrentHub, init as nodeInit, Integrations } from '@sentry/node';
import { hasTracingEnabled } from '@sentry/tracing';
import type { EventProcessor } from '@sentry/types';
import type { CrossPlatformRequest } from '@sentry/utils';
import { escapeStringForRegex, logger } from '@sentry/utils';
import * as domainModule from 'domain';
import * as path from 'path';

import { isBuild } from './utils/isBuild';
import { buildMetadata } from './utils/metadata';
import type { NextjsOptions } from './utils/nextjsOptions';
import { addOrUpdateIntegration } from './utils/userIntegrations';

export * from '@sentry/node';
export { captureUnderscoreErrorException } from './utils/_error';

// Here we want to make sure to only include what doesn't have browser specifics
// because or SSR of next.js we can only use this.
export { ErrorBoundary, showReportDialog, withErrorBoundary } from '@sentry/react';

type GlobalWithDistDir = typeof global & { __rewriteFramesDistDir__: string };
const domain = domainModule as typeof domainModule & { active: (domainModule.Domain & Carrier) | null };

const isVercel = !!process.env.VERCEL;

/** Inits the Sentry NextJS SDK on node. */
export function init(options: NextjsOptions): void {
let eventProcessors: EventProcessor[] = [];

if (__DEBUG_BUILD__ && options.debug) {
logger.enable();
}

__DEBUG_BUILD__ && logger.log('Initializing SDK...');

if (sdkAlreadyInitialized()) {
__DEBUG_BUILD__ && logger.log('SDK already initialized');
return;
}

buildMetadata(options, ['nextjs', 'node']);
options.environment = options.environment || process.env.NODE_ENV;
addServerIntegrations(options);
// Right now we only capture frontend sessions for Next.js
options.autoSessionTracking = false;

// In an ideal world, this init function would be called before any requests are handled. That way, every domain we
// use to wrap a request would inherit its scope and client from the global hub. In practice, however, handling the
// first request is what causes us to initialize the SDK, as the init code is injected into `_app` and all API route
// handlers, and those are only accessed in the course of handling a request. As a result, we're already in a domain
// when `init` is called. In order to compensate for this and mimic the ideal world scenario, we stash the active
// domain, run `init` as normal, and then restore the domain afterwards, copying over data from the main hub as if we
// really were inheriting.
const activeDomain = domain.active;
domain.active = null;

nodeInit(options);

configureScope(scope => {
scope.setTag('runtime', 'node');
if (isVercel) {
scope.setTag('vercel', true);
}

eventProcessors = addEventProcessors(scope);
});

if (activeDomain) {
const globalHub = getHubFromCarrier(getMainCarrier());
const domainHub = getHubFromCarrier(activeDomain);

// apply the changes made by `nodeInit` to the domain's hub also
domainHub.bindClient(globalHub.getClient());
domainHub.getScope()?.update(globalHub.getScope());
// `scope.update()` doesn't copy over event processors, so we have to add them manually
eventProcessors.forEach(processor => {
domainHub.getScope()?.addEventProcessor(processor);
});

// restore the domain hub as the current one
domain.active = activeDomain;
}

__DEBUG_BUILD__ && logger.log('SDK successfully initialized');
}

function sdkAlreadyInitialized(): boolean {
const hub = getCurrentHub();
return !!hub.getClient();
}

function addServerIntegrations(options: NextjsOptions): void {
// This value is injected at build time, based on the output directory specified in the build config. Though a default
// is set there, we set it here as well, just in case something has gone wrong with the injection.
const distDirName = (global as GlobalWithDistDir).__rewriteFramesDistDir__ || '.next';
// nextjs always puts the build directory at the project root level, which is also where you run `next start` from, so
// we can read in the project directory from the currently running process
const distDirAbsPath = path.resolve(process.cwd(), distDirName);
const SOURCEMAP_FILENAME_REGEX = new RegExp(escapeStringForRegex(distDirAbsPath));

const defaultRewriteFramesIntegration = new RewriteFrames({
iteratee: frame => {
frame.filename = frame.filename?.replace(SOURCEMAP_FILENAME_REGEX, 'app:///_next');
return frame;
},
});

if (options.integrations) {
options.integrations = addOrUpdateIntegration(defaultRewriteFramesIntegration, options.integrations);
} else {
options.integrations = [defaultRewriteFramesIntegration];
}

if (hasTracingEnabled(options)) {
const defaultHttpTracingIntegration = new Integrations.Http({ tracing: true });
options.integrations = addOrUpdateIntegration(defaultHttpTracingIntegration, options.integrations, {
Http: { keyPath: '_tracing', value: true },
});
}
}

function addEventProcessors(scope: Scope): EventProcessor[] {
// Note: If you add an event processor here, you have to add it to the array that's returned also
const filterTransactions: EventProcessor = event => {
return event.type === 'transaction' && event.transaction === '/404' ? null : event;
};

const addRequestData: EventProcessor = event => {
const req = event.sdkProcessingMetadata?.req as CrossPlatformRequest;

addRequestDataToEvent(event, req, { include: 'get options from user' });

return event;
};

// Assign an `id` property to each event processor so that our logger and error messages can refer to it by name
filterTransactions.id = 'FilterTransactions';
addRequestData.id = 'AddRequestData';

scope.addEventProcessor(filterTransactions);
scope.addEventProcessor(addRequestData);

return [filterTransactions, addRequestData];
}

export type { SentryWebpackPluginOptions } from './config/types';
export { withSentryConfig } from './config';
export { isBuild } from './utils/isBuild';
export {
withSentryGetServerSideProps,
withSentryGetStaticProps,
withSentryServerSideGetInitialProps,
withSentryServerSideAppGetInitialProps,
withSentryServerSideDocumentGetInitialProps,
withSentryServerSideErrorGetInitialProps,
} from './config/wrappers';
export { withSentry } from './utils/withSentry';

// Wrap various server methods to enable error monitoring and tracing. (Note: This only happens for non-Vercel
// deployments, because the current method of doing the wrapping a) crashes Next 12 apps deployed to Vercel and
// b) doesn't work on those apps anyway. We also don't do it during build, because there's no server running in that
// phase.)
if (!isVercel && !isBuild()) {
// Dynamically require the file because even importing from it causes Next 12 to crash on Vercel.
// In environments where the JS file doesn't exist, such as testing, import the TS file.
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { instrumentServer } = require('./utils/instrumentServer.js');
instrumentServer();
} catch (err) {
__DEBUG_BUILD__ && logger.warn(`Error: Unable to instrument server for tracing. Got ${err}.`);
}
}
4 changes: 2 additions & 2 deletions packages/nextjs/src/index.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ if (!isVercel && !isBuild()) {
// In environments where the JS file doesn't exist, such as testing, import the TS file.
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { instrumentServer } = require('./utils/instrumentServer.js');
instrumentServer();
// const { instrumentServer } = require('./utils/instrumentServer.js');
// instrumentServer();
} catch (err) {
__DEBUG_BUILD__ && logger.warn(`Error: Unable to instrument server for tracing. Got ${err}.`);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/nextjs/src/utils/instrumentServer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable max-lines */
import {
addRequestDataToEvent,
// addRequestDataToEvent,
captureException,
configureScope,
deepReadDirSync,
Expand Down Expand Up @@ -244,7 +244,7 @@ function makeWrappedReqHandler(origReqHandler: ReqHandler): WrappedReqHandler {
const currentScope = getCurrentHub().getScope();

if (currentScope) {
currentScope.addEventProcessor(event => addRequestDataToEvent(event, nextReq));
// currentScope.addEventProcessor(event => addRequestDataToEvent(event, nextReq));

// We only want to record page and API requests
if (hasTracingEnabled() && shouldTraceRequest(nextReq.url, publicDirFiles)) {
Expand Down
5 changes: 3 additions & 2 deletions packages/nextjs/src/utils/withSentry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { addRequestDataToEvent, captureException, flush, getCurrentHub, startTransaction } from '@sentry/node';
import { captureException, flush, getCurrentHub, startTransaction } from '@sentry/node';
// import { addRequestDataToEvent, captureException, flush, getCurrentHub, startTransaction } from '@sentry/node';
import { extractTraceparentData, hasTracingEnabled } from '@sentry/tracing';
import { Transaction } from '@sentry/types';
import {
Expand Down Expand Up @@ -41,7 +42,7 @@ export const withSentry = (origHandler: NextApiHandler): WrappedNextApiHandler =
const currentScope = getCurrentHub().getScope();

if (currentScope) {
currentScope.addEventProcessor(event => addRequestDataToEvent(event, req));
// currentScope.addEventProcessor(event => addRequestDataToEvent(event, req));

if (hasTracingEnabled()) {
// If there is a trace header set, extract the data from it (parentSpanId, traceId, and sampling decision)
Expand Down

0 comments on commit a806f00

Please sign in to comment.