rittenhop-dev/versions/5.94.2/node_modules/@sentry/node/cjs/handlers.js
2024-09-23 19:40:12 -04:00

300 lines
11 KiB
JavaScript

var {
_optionalChain
} = require('@sentry/utils');
Object.defineProperty(exports, '__esModule', { value: true });
const core = require('@sentry/core');
const utils = require('@sentry/utils');
const debugBuild = require('./debug-build.js');
const sdk = require('./sdk.js');
const trpc = require('./trpc.js');
const requestDataDeprecated = require('./requestDataDeprecated.js');
/**
* Express-compatible tracing handler.
* @see Exposed as `Handlers.tracingHandler`
*/
function tracingHandler()
{
return function sentryTracingMiddleware(
req,
res,
next,
) {
const options = _optionalChain([core.getClient, 'call', _ => _(), 'optionalAccess', _2 => _2.getOptions, 'call', _3 => _3()]);
if (
!options ||
options.instrumenter !== 'sentry' ||
_optionalChain([req, 'access', _4 => _4.method, 'optionalAccess', _5 => _5.toUpperCase, 'call', _6 => _6()]) === 'OPTIONS' ||
_optionalChain([req, 'access', _7 => _7.method, 'optionalAccess', _8 => _8.toUpperCase, 'call', _9 => _9()]) === 'HEAD'
) {
return next();
}
const sentryTrace = req.headers && utils.isString(req.headers['sentry-trace']) ? req.headers['sentry-trace'] : undefined;
const baggage = _optionalChain([req, 'access', _10 => _10.headers, 'optionalAccess', _11 => _11.baggage]);
if (!core.hasTracingEnabled(options)) {
return next();
}
const [name, source] = utils.extractPathForTransaction(req, { path: true, method: true });
const transaction = core.continueTrace({ sentryTrace, baggage }, ctx =>
// TODO: Refactor this to use `startSpan()`
// eslint-disable-next-line deprecation/deprecation
core.startTransaction(
{
name,
op: 'http.server',
origin: 'auto.http.node.tracingHandler',
...ctx,
data: {
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
},
metadata: {
// eslint-disable-next-line deprecation/deprecation
...ctx.metadata,
// The request should already have been stored in `scope.sdkProcessingMetadata` (which will become
// `event.sdkProcessingMetadata` the same way the metadata here will) by `sentryRequestMiddleware`, but on the
// off chance someone is using `sentryTracingMiddleware` without `sentryRequestMiddleware`, it doesn't hurt to
// be sure
request: req,
},
},
// extra context passed to the tracesSampler
{ request: utils.extractRequestData(req) },
),
);
// We put the transaction on the scope so users can attach children to it
// eslint-disable-next-line deprecation/deprecation
core.getCurrentScope().setSpan(transaction);
// We also set __sentry_transaction on the response so people can grab the transaction there to add
// spans to it later.
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(res ).__sentry_transaction = transaction;
res.once('finish', () => {
// Push `transaction.finish` to the next event loop so open spans have a chance to finish before the transaction
// closes
setImmediate(() => {
// eslint-disable-next-line deprecation/deprecation
utils.addRequestDataToTransaction(transaction, req);
core.setHttpStatus(transaction, res.statusCode);
transaction.end();
});
});
next();
};
}
/**
* Backwards compatibility shim which can be removed in v8. Forces the given options to follow the
* `AddRequestDataToEventOptions` interface.
*
* TODO (v8): Get rid of this, and stop passing `requestDataOptionsFromExpressHandler` to `setSDKProcessingMetadata`.
*/
function convertReqHandlerOptsToAddReqDataOpts(
reqHandlerOptions = {},
) {
let addRequestDataOptions;
if ('include' in reqHandlerOptions) {
addRequestDataOptions = { include: reqHandlerOptions.include };
} else {
// eslint-disable-next-line deprecation/deprecation
const { ip, request, transaction, user } = reqHandlerOptions ;
if (ip || request || transaction || user) {
addRequestDataOptions = { include: utils.dropUndefinedKeys({ ip, request, transaction, user }) };
}
}
return addRequestDataOptions;
}
/**
* Express compatible request handler.
* @see Exposed as `Handlers.requestHandler`
*/
function requestHandler(
options,
) {
// TODO (v8): Get rid of this
const requestDataOptions = convertReqHandlerOptsToAddReqDataOpts(options);
const client = core.getClient();
// Initialise an instance of SessionFlusher on the client when `autoSessionTracking` is enabled and the
// `requestHandler` middleware is used indicating that we are running in SessionAggregates mode
if (client && sdk.isAutoSessionTrackingEnabled(client)) {
client.initSessionFlusher();
// If Scope contains a Single mode Session, it is removed in favor of using Session Aggregates mode
const scope = core.getCurrentScope();
if (scope.getSession()) {
scope.setSession();
}
}
return function sentryRequestMiddleware(
req,
res,
next,
) {
if (options && options.flushTimeout && options.flushTimeout > 0) {
// eslint-disable-next-line @typescript-eslint/unbound-method
const _end = res.end;
res.end = function (chunk, encoding, cb) {
void core.flush(options.flushTimeout)
.then(() => {
_end.call(this, chunk, encoding, cb);
})
.then(null, e => {
debugBuild.DEBUG_BUILD && utils.logger.error(e);
_end.call(this, chunk, encoding, cb);
});
};
}
core.runWithAsyncContext(() => {
const scope = core.getCurrentScope();
scope.setSDKProcessingMetadata({
request: req,
// TODO (v8): Stop passing this
requestDataOptionsFromExpressHandler: requestDataOptions,
});
const client = core.getClient();
if (sdk.isAutoSessionTrackingEnabled(client)) {
// Set `status` of `RequestSession` to Ok, at the beginning of the request
scope.setRequestSession({ status: 'ok' });
}
res.once('finish', () => {
const client = core.getClient();
if (sdk.isAutoSessionTrackingEnabled(client)) {
setImmediate(() => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (client && (client )._captureRequestSession) {
// Calling _captureRequestSession to capture request session at the end of the request by incrementing
// the correct SessionAggregates bucket i.e. crashed, errored or exited
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(client )._captureRequestSession();
}
});
}
});
next();
});
};
}
/** JSDoc */
/** JSDoc */
function getStatusCodeFromResponse(error) {
const statusCode = error.status || error.statusCode || error.status_code || (error.output && error.output.statusCode);
return statusCode ? parseInt(statusCode , 10) : 500;
}
/** Returns true if response code is internal server error */
function defaultShouldHandleError(error) {
const status = getStatusCodeFromResponse(error);
return status >= 500;
}
/**
* Express compatible error handler.
* @see Exposed as `Handlers.errorHandler`
*/
function errorHandler(options
)
{
return function sentryErrorMiddleware(
error,
_req,
res,
next,
) {
const shouldHandleError = (options && options.shouldHandleError) || defaultShouldHandleError;
if (shouldHandleError(error)) {
core.withScope(_scope => {
// The request should already have been stored in `scope.sdkProcessingMetadata` by `sentryRequestMiddleware`,
// but on the off chance someone is using `sentryErrorMiddleware` without `sentryRequestMiddleware`, it doesn't
// hurt to be sure
_scope.setSDKProcessingMetadata({ request: _req });
// For some reason we need to set the transaction on the scope again
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const transaction = (res ).__sentry_transaction ;
if (transaction && !core.getActiveSpan()) {
// eslint-disable-next-line deprecation/deprecation
_scope.setSpan(transaction);
}
const client = core.getClient();
if (client && sdk.isAutoSessionTrackingEnabled(client)) {
// Check if the `SessionFlusher` is instantiated on the client to go into this branch that marks the
// `requestSession.status` as `Crashed`, and this check is necessary because the `SessionFlusher` is only
// instantiated when the the`requestHandler` middleware is initialised, which indicates that we should be
// running in SessionAggregates mode
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const isSessionAggregatesMode = (client )._sessionFlusher !== undefined;
if (isSessionAggregatesMode) {
const requestSession = _scope.getRequestSession();
// If an error bubbles to the `errorHandler`, then this is an unhandled error, and should be reported as a
// Crashed session. The `_requestSession.status` is checked to ensure that this error is happening within
// the bounds of a request, and if so the status is updated
if (requestSession && requestSession.status !== undefined) {
requestSession.status = 'crashed';
}
}
}
const eventId = core.captureException(error, { mechanism: { type: 'middleware', handled: false } });
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(res ).sentry = eventId;
next(error);
});
return;
}
next(error);
};
}
/**
* Sentry tRPC middleware that names the handling transaction after the called procedure.
*
* Use the Sentry tRPC middleware in combination with the Sentry server integration,
* e.g. Express Request Handlers or Next.js SDK.
*
* @deprecated Please use the top level export instead:
* ```
* // OLD
* import * as Sentry from '@sentry/node';
* Sentry.Handlers.trpcMiddleware();
*
* // NEW
* import * as Sentry from '@sentry/node';
* Sentry.trpcMiddleware();
* ```
*/
// eslint-disable-next-line deprecation/deprecation
const trpcMiddleware = trpc.trpcMiddleware;
exports.extractRequestData = requestDataDeprecated.extractRequestData;
exports.parseRequest = requestDataDeprecated.parseRequest;
exports.errorHandler = errorHandler;
exports.requestHandler = requestHandler;
exports.tracingHandler = tracingHandler;
exports.trpcMiddleware = trpcMiddleware;
//# sourceMappingURL=handlers.js.map