123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- import { _optionalChain } from '@sentry/utils';
- import { hasTracingEnabled, continueTrace, startTransaction, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, getCurrentScope, setHttpStatus, getClient, flush, runWithAsyncContext, withScope, getActiveSpan, captureException } from '@sentry/core';
- import { isString, extractPathForTransaction, extractRequestData, addRequestDataToTransaction, logger, normalize, isThenable, dropUndefinedKeys } from '@sentry/utils';
- import { DEBUG_BUILD } from './debug-build.js';
- import { isAutoSessionTrackingEnabled } from './sdk.js';
- export { extractRequestData, parseRequest } from './requestDataDeprecated.js';
- function tracingHandler()
- {
- return function sentryTracingMiddleware(
- req,
- res,
- next,
- ) {
- const options = _optionalChain([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 && isString(req.headers['sentry-trace']) ? req.headers['sentry-trace'] : undefined;
- const baggage = _optionalChain([req, 'access', _10 => _10.headers, 'optionalAccess', _11 => _11.baggage]);
- if (!hasTracingEnabled(options)) {
- return next();
- }
- const [name, source] = extractPathForTransaction(req, { path: true, method: true });
- const transaction = continueTrace({ sentryTrace, baggage }, ctx =>
-
-
- startTransaction(
- {
- name,
- op: 'http.server',
- origin: 'auto.http.node.tracingHandler',
- ...ctx,
- data: {
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
- },
- metadata: {
-
- ...ctx.metadata,
-
-
-
-
- request: req,
- },
- },
-
- { request: extractRequestData(req) },
- ),
- );
-
-
- getCurrentScope().setSpan(transaction);
-
-
-
- (res ).__sentry_transaction = transaction;
- res.once('finish', () => {
-
-
- setImmediate(() => {
- addRequestDataToTransaction(transaction, req);
- setHttpStatus(transaction, res.statusCode);
- transaction.end();
- });
- });
- next();
- };
- }
- function convertReqHandlerOptsToAddReqDataOpts(
- reqHandlerOptions = {},
- ) {
- let addRequestDataOptions;
- if ('include' in reqHandlerOptions) {
- addRequestDataOptions = { include: reqHandlerOptions.include };
- } else {
-
- const { ip, request, transaction, user } = reqHandlerOptions ;
- if (ip || request || transaction || user) {
- addRequestDataOptions = { include: dropUndefinedKeys({ ip, request, transaction, user }) };
- }
- }
- return addRequestDataOptions;
- }
- function requestHandler(
- options,
- ) {
-
- const requestDataOptions = convertReqHandlerOptsToAddReqDataOpts(options);
- const client = getClient();
-
-
- if (client && isAutoSessionTrackingEnabled(client)) {
- client.initSessionFlusher();
-
- const scope = getCurrentScope();
- if (scope.getSession()) {
- scope.setSession();
- }
- }
- return function sentryRequestMiddleware(
- req,
- res,
- next,
- ) {
- if (options && options.flushTimeout && options.flushTimeout > 0) {
-
- const _end = res.end;
- res.end = function (chunk, encoding, cb) {
- void flush(options.flushTimeout)
- .then(() => {
- _end.call(this, chunk, encoding, cb);
- })
- .then(null, e => {
- DEBUG_BUILD && logger.error(e);
- _end.call(this, chunk, encoding, cb);
- });
- };
- }
- runWithAsyncContext(() => {
- const scope = getCurrentScope();
- scope.setSDKProcessingMetadata({
- request: req,
-
- requestDataOptionsFromExpressHandler: requestDataOptions,
- });
- const client = getClient();
- if (isAutoSessionTrackingEnabled(client)) {
-
- scope.setRequestSession({ status: 'ok' });
- }
- res.once('finish', () => {
- const client = getClient();
- if (isAutoSessionTrackingEnabled(client)) {
- setImmediate(() => {
-
- if (client && (client )._captureRequestSession) {
-
-
-
- (client )._captureRequestSession();
- }
- });
- }
- });
- next();
- });
- };
- }
- function getStatusCodeFromResponse(error) {
- const statusCode = error.status || error.statusCode || error.status_code || (error.output && error.output.statusCode);
- return statusCode ? parseInt(statusCode , 10) : 500;
- }
- function defaultShouldHandleError(error) {
- const status = getStatusCodeFromResponse(error);
- return status >= 500;
- }
- function errorHandler(options
- )
- {
- return function sentryErrorMiddleware(
- error,
- _req,
- res,
- next,
- ) {
- const shouldHandleError = (options && options.shouldHandleError) || defaultShouldHandleError;
- if (shouldHandleError(error)) {
- withScope(_scope => {
-
-
-
- _scope.setSDKProcessingMetadata({ request: _req });
-
-
- const transaction = (res ).__sentry_transaction ;
- if (transaction && !getActiveSpan()) {
-
- _scope.setSpan(transaction);
- }
- const client = getClient();
- if (client && isAutoSessionTrackingEnabled(client)) {
-
-
-
-
-
- const isSessionAggregatesMode = (client )._sessionFlusher !== undefined;
- if (isSessionAggregatesMode) {
- const requestSession = _scope.getRequestSession();
-
-
-
- if (requestSession && requestSession.status !== undefined) {
- requestSession.status = 'crashed';
- }
- }
- }
- const eventId = captureException(error, { mechanism: { type: 'middleware', handled: false } });
-
- (res ).sentry = eventId;
- next(error);
- });
- return;
- }
- next(error);
- };
- }
- function trpcMiddleware(options = {}) {
- return function ({ path, type, next, rawInput }) {
- const clientOptions = _optionalChain([getClient, 'call', _12 => _12(), 'optionalAccess', _13 => _13.getOptions, 'call', _14 => _14()]);
-
- const sentryTransaction = getCurrentScope().getTransaction();
- if (sentryTransaction) {
- sentryTransaction.updateName(`trpc/${path}`);
- sentryTransaction.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route');
- sentryTransaction.op = 'rpc.server';
- const trpcContext = {
- procedure_type: type,
- };
- if (options.attachRpcInput !== undefined ? options.attachRpcInput : _optionalChain([clientOptions, 'optionalAccess', _15 => _15.sendDefaultPii])) {
- trpcContext.input = normalize(rawInput);
- }
-
-
- sentryTransaction.setContext('trpc', trpcContext);
- }
- function captureIfError(nextResult) {
- if (!nextResult.ok) {
- captureException(nextResult.error, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } });
- }
- }
- let maybePromiseResult;
- try {
- maybePromiseResult = next();
- } catch (e) {
- captureException(e, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } });
- throw e;
- }
- if (isThenable(maybePromiseResult)) {
-
- Promise.resolve(maybePromiseResult).then(
- nextResult => {
- captureIfError(nextResult );
- },
- e => {
- captureException(e, { mechanism: { handled: false, data: { function: 'trpcMiddleware' } } });
- },
- );
- } else {
- captureIfError(maybePromiseResult );
- }
-
- return maybePromiseResult;
- };
- }
- export { errorHandler, requestHandler, tracingHandler, trpcMiddleware };
|