@sentry/node
Advanced tools
Comparing version 5.7.1 to 5.8.0-beta.0
/// <reference types="node" /> | ||
import { Event } from '@sentry/types'; | ||
import * as http from 'http'; | ||
/** | ||
* Express compatible tracing handler. | ||
* @see Exposed as `Handlers.tracingHandler` | ||
*/ | ||
export declare function tracingHandler(): (req: http.IncomingMessage, res: http.ServerResponse, next: (error?: any) => void) => void; | ||
declare type TransactionTypes = 'path' | 'methodPath' | 'handler'; | ||
@@ -5,0 +10,0 @@ /** |
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tslib_1 = require("tslib"); | ||
var core_1 = require("@sentry/core"); | ||
var hub_1 = require("@sentry/hub"); | ||
var utils_1 = require("@sentry/utils"); | ||
@@ -12,2 +11,32 @@ var cookie = require("cookie"); | ||
var DEFAULT_SHUTDOWN_TIMEOUT = 2000; | ||
/** | ||
* Express compatible tracing handler. | ||
* @see Exposed as `Handlers.tracingHandler` | ||
*/ | ||
function tracingHandler() { | ||
return function sentryTracingMiddleware(req, res, next) { | ||
// TODO: At this point req.route.path we use in `extractTransaction` is not available | ||
// but `req.path` or `req.url` should do the job as well. We could unify this here. | ||
var reqMethod = (req.method || '').toUpperCase(); | ||
var reqUrl = req.url; | ||
var hub = core_1.getCurrentHub(); | ||
var transaction = hub.startSpan({ | ||
transaction: reqMethod + "|" + reqUrl, | ||
}); | ||
hub.configureScope(function (scope) { | ||
scope.setSpan(transaction); | ||
}); | ||
res.once('finish', function () { | ||
if (res.statusCode >= 500) { | ||
transaction.setFailure(); | ||
} | ||
else { | ||
transaction.setSuccess(); | ||
} | ||
transaction.finish(); | ||
}); | ||
next(); | ||
}; | ||
} | ||
exports.tracingHandler = tracingHandler; | ||
/** JSDoc */ | ||
@@ -213,12 +242,12 @@ function extractTransaction(req, type) { | ||
function errorHandler(options) { | ||
return function sentryErrorMiddleware(error, _req, _res, next) { | ||
return function sentryErrorMiddleware(error, req, res, next) { | ||
var shouldHandleError = (options && options.shouldHandleError) || defaultShouldHandleError; | ||
if (shouldHandleError(error)) { | ||
core_1.withScope(function (scope) { | ||
if (_req.headers && utils_1.isString(_req.headers['sentry-trace'])) { | ||
var span = hub_1.Span.fromTraceparent(_req.headers['sentry-trace']); | ||
if (req.headers && utils_1.isString(req.headers['sentry-trace'])) { | ||
var span = core_1.Span.fromTraceparent(req.headers['sentry-trace']); | ||
scope.setSpan(span); | ||
} | ||
var eventId = core_1.captureException(error); | ||
_res.sentry = eventId; | ||
res.sentry = eventId; | ||
next(error); | ||
@@ -225,0 +254,0 @@ }); |
export { Breadcrumb, Request, SdkInfo, Event, Exception, Response, Severity, StackFrame, Stacktrace, Status, Thread, User, } from '@sentry/types'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getCurrentHub, getHubFromCarrier, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, Span, withScope, } from '@sentry/core'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getHubFromCarrier, getCurrentHub, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, startSpan, Span, withScope, } from '@sentry/core'; | ||
export { NodeOptions } from './backend'; | ||
@@ -4,0 +4,0 @@ export { NodeClient } from './client'; |
@@ -13,4 +13,4 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.configureScope = core_1.configureScope; | ||
exports.getHubFromCarrier = core_1.getHubFromCarrier; | ||
exports.getCurrentHub = core_1.getCurrentHub; | ||
exports.getHubFromCarrier = core_1.getHubFromCarrier; | ||
exports.Hub = core_1.Hub; | ||
@@ -24,2 +24,3 @@ exports.Scope = core_1.Scope; | ||
exports.setUser = core_1.setUser; | ||
exports.startSpan = core_1.startSpan; | ||
exports.Span = core_1.Span; | ||
@@ -26,0 +27,0 @@ exports.withScope = core_1.withScope; |
@@ -19,6 +19,17 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
Console.prototype.setupOnce = function () { | ||
var nativeModule = require('module'); | ||
utils_1.fill(nativeModule, '_load', loadWrapper(nativeModule)); | ||
// special case: since console is built-in and app-level code won't require() it, do that here | ||
require('console'); | ||
var e_1, _a; | ||
var consoleModule = require('console'); | ||
try { | ||
for (var _b = tslib_1.__values(['debug', 'info', 'warn', 'error', 'log']), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var level = _c.value; | ||
utils_1.fill(consoleModule, level, createConsoleWrapper(level)); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
}; | ||
@@ -33,62 +44,38 @@ /** | ||
/** | ||
* Wrapper function for internal _load calls within `require` | ||
*/ | ||
function loadWrapper(nativeModule) { | ||
// We need to use some functional-style currying to pass values around | ||
// as we cannot rely on `bind`, because this has to preserve correct | ||
// context for native calls | ||
return function (originalLoad) { | ||
return function (moduleId) { | ||
var originalModule = originalLoad.apply(nativeModule, arguments); | ||
if (moduleId !== 'console' || originalModule.__sentry__) { | ||
return originalModule; | ||
} | ||
['debug', 'info', 'warn', 'error', 'log'].forEach(consoleWrapper(originalModule)); | ||
originalModule.__sentry__ = true; | ||
return originalModule; | ||
}; | ||
}; | ||
} | ||
/** | ||
* Wrapper function that'll be used for every console level | ||
*/ | ||
function consoleWrapper(originalModule) { | ||
return function (level) { | ||
if (!(level in originalModule)) { | ||
return; | ||
function createConsoleWrapper(level) { | ||
return function consoleWrapper(originalConsoleMethod) { | ||
var sentryLevel; | ||
switch (level) { | ||
case 'debug': | ||
sentryLevel = types_1.Severity.Debug; | ||
break; | ||
case 'error': | ||
sentryLevel = types_1.Severity.Error; | ||
break; | ||
case 'info': | ||
sentryLevel = types_1.Severity.Info; | ||
break; | ||
case 'warn': | ||
sentryLevel = types_1.Severity.Warning; | ||
break; | ||
default: | ||
sentryLevel = types_1.Severity.Log; | ||
} | ||
utils_1.fill(originalModule, level, function (originalConsoleLevel) { | ||
var sentryLevel; | ||
switch (level) { | ||
case 'debug': | ||
sentryLevel = types_1.Severity.Debug; | ||
break; | ||
case 'error': | ||
sentryLevel = types_1.Severity.Error; | ||
break; | ||
case 'info': | ||
sentryLevel = types_1.Severity.Info; | ||
break; | ||
case 'warn': | ||
sentryLevel = types_1.Severity.Warning; | ||
break; | ||
default: | ||
sentryLevel = types_1.Severity.Log; | ||
return function () { | ||
if (core_1.getCurrentHub().getIntegration(Console)) { | ||
core_1.getCurrentHub().addBreadcrumb({ | ||
category: 'console', | ||
level: sentryLevel, | ||
message: util.format.apply(undefined, arguments), | ||
}, { | ||
input: tslib_1.__spread(arguments), | ||
level: level, | ||
}); | ||
} | ||
return function () { | ||
if (core_1.getCurrentHub().getIntegration(Console)) { | ||
core_1.getCurrentHub().addBreadcrumb({ | ||
category: 'console', | ||
level: sentryLevel, | ||
message: util.format.apply(undefined, arguments), | ||
}, { | ||
input: tslib_1.__spread(arguments), | ||
level: level, | ||
}); | ||
} | ||
originalConsoleLevel.apply(originalModule, arguments); | ||
}; | ||
}); | ||
originalConsoleMethod.apply(this, arguments); | ||
}; | ||
}; | ||
} | ||
//# sourceMappingURL=console.js.map |
@@ -15,4 +15,19 @@ import { Integration } from '@sentry/types'; | ||
*/ | ||
private readonly _breadcrumbs; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
private readonly _tracing; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
constructor(options?: { | ||
breadcrumbs?: boolean; | ||
tracing?: boolean; | ||
}); | ||
/** | ||
* @inheritDoc | ||
*/ | ||
setupOnce(): void; | ||
} | ||
//# sourceMappingURL=http.d.ts.map |
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var core_1 = require("@sentry/core"); | ||
var utils_1 = require("@sentry/utils"); | ||
var util = require("util"); | ||
var lastResponse; | ||
var NODE_VERSION = utils_1.parseSemver(process.versions.node); | ||
/** http module integration */ | ||
var Http = /** @class */ (function () { | ||
function Http() { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
function Http(options) { | ||
if (options === void 0) { options = {}; } | ||
/** | ||
@@ -13,2 +16,4 @@ * @inheritDoc | ||
this.name = Http.id; | ||
this._breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs; | ||
this._tracing = typeof options.tracing === 'undefined' ? false : options.tracing; | ||
} | ||
@@ -19,10 +24,18 @@ /** | ||
Http.prototype.setupOnce = function () { | ||
var nativeModule = require('module'); | ||
utils_1.fill(nativeModule, '_load', loadWrapper(nativeModule)); | ||
// observation: when the https module does its own require('http'), it *does not* hit our hooked require to instrument http on the fly | ||
// but if we've previously instrumented http, https *does* get our already-instrumented version | ||
// this is because raven's transports are required before this instrumentation takes place, which loads https (and http) | ||
// so module cache will have uninstrumented http; proactively loading it here ensures instrumented version is in module cache | ||
// alternatively we could refactor to load our transports later, but this is easier and doesn't have much drawback | ||
require('http'); | ||
// No need to instrument if we don't want to track anything | ||
if (!this._breadcrumbs && !this._tracing) { | ||
return; | ||
} | ||
var handlerWrapper = createHandlerWrapper(this._breadcrumbs, this._tracing); | ||
var httpModule = require('http'); | ||
utils_1.fill(httpModule, 'get', handlerWrapper); | ||
utils_1.fill(httpModule, 'request', handlerWrapper); | ||
// NOTE: Prior to Node 9, `https` used internals of `http` module, thus we don't patch it. | ||
// If we do, we'd get double breadcrumbs and double spans for `https` calls. | ||
// It has been changed in Node 9, so for all versions equal and above, we patch `https` separately. | ||
if (NODE_VERSION.major && NODE_VERSION.major > 8) { | ||
var httpsModule = require('https'); | ||
utils_1.fill(httpsModule, 'get', handlerWrapper); | ||
utils_1.fill(httpsModule, 'request', handlerWrapper); | ||
} | ||
}; | ||
@@ -37,2 +50,64 @@ /** | ||
/** | ||
* Wrapper function for internal `request` and `get` calls within `http` and `https` modules | ||
*/ | ||
function createHandlerWrapper(breadcrumbsEnabled, tracingEnabled) { | ||
return function handlerWrapper(originalHandler) { | ||
return function (options) { | ||
var requestUrl = extractUrl(options); | ||
if (isSentryRequest(requestUrl)) { | ||
return originalHandler.apply(this, arguments); | ||
} | ||
var span; | ||
if (tracingEnabled) { | ||
span = core_1.getCurrentHub().startSpan({ | ||
description: (typeof options === 'string' || !options.method ? 'GET' : options.method) + "|" + requestUrl, | ||
op: 'request', | ||
}); | ||
} | ||
return originalHandler | ||
.apply(this, arguments) | ||
.once('response', function (res) { | ||
if (breadcrumbsEnabled) { | ||
addRequestBreadcrumb('response', requestUrl, this, res); | ||
} | ||
// TODO: Mark >= 500 as failed as well? | ||
if (tracingEnabled) { | ||
span.setSuccess(); | ||
span.finish(); | ||
} | ||
}) | ||
.once('error', function () { | ||
if (breadcrumbsEnabled) { | ||
addRequestBreadcrumb('error', requestUrl, this); | ||
} | ||
if (tracingEnabled) { | ||
span.setFailure(); | ||
span.finish(); | ||
} | ||
}); | ||
}; | ||
}; | ||
} | ||
/** | ||
* Captures Breadcrumb based on provided request/response pair | ||
*/ | ||
function addRequestBreadcrumb(event, url, req, res) { | ||
if (!core_1.getCurrentHub().getIntegration(Http)) { | ||
return; | ||
} | ||
core_1.getCurrentHub().addBreadcrumb({ | ||
category: 'http', | ||
data: { | ||
method: req.method, | ||
status_code: res && res.statusCode, | ||
url: url, | ||
}, | ||
type: 'http', | ||
}, { | ||
event: event, | ||
request: req, | ||
response: res, | ||
}); | ||
} | ||
/** | ||
* Function that can combine together a url that'll be used for our breadcrumbs. | ||
@@ -43,6 +118,3 @@ * | ||
*/ | ||
function createBreadcrumbUrl(options) { | ||
// We could just always reconstruct this from this.agent, this._headers, this.path, etc | ||
// but certain other http-instrumenting libraries (like nock, which we use for tests) fail to | ||
// maintain the guarantee that after calling origClientRequest, those fields will be populated | ||
function extractUrl(options) { | ||
if (typeof options === 'string') { | ||
@@ -59,87 +131,16 @@ return options; | ||
/** | ||
* Wrapper function for internal _load calls within `require` | ||
* Checks whether given url points to Sentry server | ||
* @param url url to verify | ||
*/ | ||
function loadWrapper(nativeModule) { | ||
// We need to use some functional-style currying to pass values around | ||
// as we cannot rely on `bind`, because this has to preserve correct | ||
// context for native calls | ||
return function (originalLoad) { | ||
return function (moduleId) { | ||
var originalModule = originalLoad.apply(nativeModule, arguments); | ||
if (moduleId !== 'http' || originalModule.__sentry__) { | ||
return originalModule; | ||
} | ||
var origClientRequest = originalModule.ClientRequest; | ||
var clientRequest = function (options, callback) { | ||
// Note: this won't capture a breadcrumb if a response never comes | ||
// It would be useful to know if that was the case, though, so | ||
// TODO: revisit to see if we can capture sth indicating response never came | ||
// possibility: capture one breadcrumb for "req sent" and one for "res recvd" | ||
// seems excessive but solves the problem and *is* strictly more information | ||
// could be useful for weird response sequencing bug scenarios | ||
origClientRequest.call(this, options, callback); | ||
this.__ravenBreadcrumbUrl = createBreadcrumbUrl(options); | ||
}; | ||
util.inherits(clientRequest, origClientRequest); | ||
utils_1.fill(clientRequest.prototype, 'emit', emitWrapper); | ||
utils_1.fill(originalModule, 'ClientRequest', function () { | ||
return clientRequest; | ||
}); | ||
// http.request orig refs module-internal ClientRequest, not exported one, so | ||
// it still points at orig ClientRequest after our monkeypatch; these reimpls | ||
// just get that reference updated to use our new ClientRequest | ||
utils_1.fill(originalModule, 'request', function () { | ||
return function (options, callback) { | ||
return new originalModule.ClientRequest(options, callback); | ||
}; | ||
}); | ||
utils_1.fill(originalModule, 'get', function () { | ||
return function (options, callback) { | ||
var req = originalModule.request(options, callback); | ||
req.end(); | ||
return req; | ||
}; | ||
}); | ||
originalModule.__sentry__ = true; | ||
return originalModule; | ||
}; | ||
}; | ||
function isSentryRequest(url) { | ||
var client = core_1.getCurrentHub().getClient(); | ||
if (!url || !client) { | ||
return false; | ||
} | ||
var dsn = client.getDsn(); | ||
if (!dsn) { | ||
return false; | ||
} | ||
return url.indexOf(dsn.host) !== -1; | ||
} | ||
/** | ||
* Wrapper function for request's `emit` calls | ||
*/ | ||
function emitWrapper(origEmit) { | ||
return function (event, response) { | ||
// I'm not sure why but Node.js (at least in v8.X) | ||
// is emitting all events twice :| | ||
if (lastResponse === undefined || lastResponse !== response) { | ||
lastResponse = response; | ||
} | ||
else { | ||
return origEmit.apply(this, arguments); | ||
} | ||
var client = core_1.getCurrentHub().getClient(); | ||
if (client) { | ||
var dsn = client.getDsn(); | ||
var isInterestingEvent = event === 'response' || event === 'error'; | ||
var isNotSentryRequest = dsn && this.__ravenBreadcrumbUrl && this.__ravenBreadcrumbUrl.indexOf(dsn.host) === -1; | ||
if (isInterestingEvent && isNotSentryRequest && core_1.getCurrentHub().getIntegration(Http)) { | ||
core_1.getCurrentHub().addBreadcrumb({ | ||
category: 'http', | ||
data: { | ||
method: this.method, | ||
status_code: response.statusCode, | ||
url: this.__ravenBreadcrumbUrl, | ||
}, | ||
type: 'http', | ||
}, { | ||
event: event, | ||
request: this, | ||
response: response, | ||
}); | ||
} | ||
} | ||
return origEmit.apply(this, arguments); | ||
}; | ||
} | ||
//# sourceMappingURL=http.js.map |
export declare const SDK_NAME = "sentry.javascript.node"; | ||
export declare const SDK_VERSION = "5.7.1"; | ||
export declare const SDK_VERSION = "5.8.0-beta.0"; | ||
//# sourceMappingURL=version.d.ts.map |
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SDK_NAME = 'sentry.javascript.node'; | ||
exports.SDK_VERSION = '5.7.1'; | ||
exports.SDK_VERSION = '5.8.0-beta.0'; | ||
//# sourceMappingURL=version.js.map |
/// <reference types="node" /> | ||
import { Event } from '@sentry/types'; | ||
import * as http from 'http'; | ||
/** | ||
* Express compatible tracing handler. | ||
* @see Exposed as `Handlers.tracingHandler` | ||
*/ | ||
export declare function tracingHandler(): (req: http.IncomingMessage, res: http.ServerResponse, next: (error?: any) => void) => void; | ||
declare type TransactionTypes = 'path' | 'methodPath' | 'handler'; | ||
@@ -5,0 +10,0 @@ /** |
import * as tslib_1 from "tslib"; | ||
import { captureException, getCurrentHub, withScope } from '@sentry/core'; | ||
import { Span } from '@sentry/hub'; | ||
import { captureException, getCurrentHub, Span, withScope } from '@sentry/core'; | ||
import { forget, isString, logger, normalize } from '@sentry/utils'; | ||
@@ -11,2 +10,31 @@ import * as cookie from 'cookie'; | ||
var DEFAULT_SHUTDOWN_TIMEOUT = 2000; | ||
/** | ||
* Express compatible tracing handler. | ||
* @see Exposed as `Handlers.tracingHandler` | ||
*/ | ||
export function tracingHandler() { | ||
return function sentryTracingMiddleware(req, res, next) { | ||
// TODO: At this point req.route.path we use in `extractTransaction` is not available | ||
// but `req.path` or `req.url` should do the job as well. We could unify this here. | ||
var reqMethod = (req.method || '').toUpperCase(); | ||
var reqUrl = req.url; | ||
var hub = getCurrentHub(); | ||
var transaction = hub.startSpan({ | ||
transaction: reqMethod + "|" + reqUrl, | ||
}); | ||
hub.configureScope(function (scope) { | ||
scope.setSpan(transaction); | ||
}); | ||
res.once('finish', function () { | ||
if (res.statusCode >= 500) { | ||
transaction.setFailure(); | ||
} | ||
else { | ||
transaction.setSuccess(); | ||
} | ||
transaction.finish(); | ||
}); | ||
next(); | ||
}; | ||
} | ||
/** JSDoc */ | ||
@@ -210,12 +238,12 @@ function extractTransaction(req, type) { | ||
export function errorHandler(options) { | ||
return function sentryErrorMiddleware(error, _req, _res, next) { | ||
return function sentryErrorMiddleware(error, req, res, next) { | ||
var shouldHandleError = (options && options.shouldHandleError) || defaultShouldHandleError; | ||
if (shouldHandleError(error)) { | ||
withScope(function (scope) { | ||
if (_req.headers && isString(_req.headers['sentry-trace'])) { | ||
var span = Span.fromTraceparent(_req.headers['sentry-trace']); | ||
if (req.headers && isString(req.headers['sentry-trace'])) { | ||
var span = Span.fromTraceparent(req.headers['sentry-trace']); | ||
scope.setSpan(span); | ||
} | ||
var eventId = captureException(error); | ||
_res.sentry = eventId; | ||
res.sentry = eventId; | ||
next(error); | ||
@@ -222,0 +250,0 @@ }); |
export { Breadcrumb, Request, SdkInfo, Event, Exception, Response, Severity, StackFrame, Stacktrace, Status, Thread, User, } from '@sentry/types'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getCurrentHub, getHubFromCarrier, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, Span, withScope, } from '@sentry/core'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getHubFromCarrier, getCurrentHub, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, startSpan, Span, withScope, } from '@sentry/core'; | ||
export { NodeOptions } from './backend'; | ||
@@ -4,0 +4,0 @@ export { NodeClient } from './client'; |
import * as tslib_1 from "tslib"; | ||
export { Severity, Status, } from '@sentry/types'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getCurrentHub, getHubFromCarrier, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, Span, withScope, } from '@sentry/core'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getHubFromCarrier, getCurrentHub, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, startSpan, Span, withScope, } from '@sentry/core'; | ||
export { NodeClient } from './client'; | ||
@@ -5,0 +5,0 @@ export { defaultIntegrations, init, lastEventId, flush, close } from './sdk'; |
@@ -18,6 +18,17 @@ import * as tslib_1 from "tslib"; | ||
Console.prototype.setupOnce = function () { | ||
var nativeModule = require('module'); | ||
fill(nativeModule, '_load', loadWrapper(nativeModule)); | ||
// special case: since console is built-in and app-level code won't require() it, do that here | ||
require('console'); | ||
var e_1, _a; | ||
var consoleModule = require('console'); | ||
try { | ||
for (var _b = tslib_1.__values(['debug', 'info', 'warn', 'error', 'log']), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var level = _c.value; | ||
fill(consoleModule, level, createConsoleWrapper(level)); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
}; | ||
@@ -32,62 +43,38 @@ /** | ||
/** | ||
* Wrapper function for internal _load calls within `require` | ||
*/ | ||
function loadWrapper(nativeModule) { | ||
// We need to use some functional-style currying to pass values around | ||
// as we cannot rely on `bind`, because this has to preserve correct | ||
// context for native calls | ||
return function (originalLoad) { | ||
return function (moduleId) { | ||
var originalModule = originalLoad.apply(nativeModule, arguments); | ||
if (moduleId !== 'console' || originalModule.__sentry__) { | ||
return originalModule; | ||
} | ||
['debug', 'info', 'warn', 'error', 'log'].forEach(consoleWrapper(originalModule)); | ||
originalModule.__sentry__ = true; | ||
return originalModule; | ||
}; | ||
}; | ||
} | ||
/** | ||
* Wrapper function that'll be used for every console level | ||
*/ | ||
function consoleWrapper(originalModule) { | ||
return function (level) { | ||
if (!(level in originalModule)) { | ||
return; | ||
function createConsoleWrapper(level) { | ||
return function consoleWrapper(originalConsoleMethod) { | ||
var sentryLevel; | ||
switch (level) { | ||
case 'debug': | ||
sentryLevel = Severity.Debug; | ||
break; | ||
case 'error': | ||
sentryLevel = Severity.Error; | ||
break; | ||
case 'info': | ||
sentryLevel = Severity.Info; | ||
break; | ||
case 'warn': | ||
sentryLevel = Severity.Warning; | ||
break; | ||
default: | ||
sentryLevel = Severity.Log; | ||
} | ||
fill(originalModule, level, function (originalConsoleLevel) { | ||
var sentryLevel; | ||
switch (level) { | ||
case 'debug': | ||
sentryLevel = Severity.Debug; | ||
break; | ||
case 'error': | ||
sentryLevel = Severity.Error; | ||
break; | ||
case 'info': | ||
sentryLevel = Severity.Info; | ||
break; | ||
case 'warn': | ||
sentryLevel = Severity.Warning; | ||
break; | ||
default: | ||
sentryLevel = Severity.Log; | ||
return function () { | ||
if (getCurrentHub().getIntegration(Console)) { | ||
getCurrentHub().addBreadcrumb({ | ||
category: 'console', | ||
level: sentryLevel, | ||
message: util.format.apply(undefined, arguments), | ||
}, { | ||
input: tslib_1.__spread(arguments), | ||
level: level, | ||
}); | ||
} | ||
return function () { | ||
if (getCurrentHub().getIntegration(Console)) { | ||
getCurrentHub().addBreadcrumb({ | ||
category: 'console', | ||
level: sentryLevel, | ||
message: util.format.apply(undefined, arguments), | ||
}, { | ||
input: tslib_1.__spread(arguments), | ||
level: level, | ||
}); | ||
} | ||
originalConsoleLevel.apply(originalModule, arguments); | ||
}; | ||
}); | ||
originalConsoleMethod.apply(this, arguments); | ||
}; | ||
}; | ||
} | ||
//# sourceMappingURL=console.js.map |
@@ -15,4 +15,19 @@ import { Integration } from '@sentry/types'; | ||
*/ | ||
private readonly _breadcrumbs; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
private readonly _tracing; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
constructor(options?: { | ||
breadcrumbs?: boolean; | ||
tracing?: boolean; | ||
}); | ||
/** | ||
* @inheritDoc | ||
*/ | ||
setupOnce(): void; | ||
} | ||
//# sourceMappingURL=http.d.ts.map |
import { getCurrentHub } from '@sentry/core'; | ||
import { fill } from '@sentry/utils'; | ||
import * as util from 'util'; | ||
var lastResponse; | ||
import { fill, parseSemver } from '@sentry/utils'; | ||
var NODE_VERSION = parseSemver(process.versions.node); | ||
/** http module integration */ | ||
var Http = /** @class */ (function () { | ||
function Http() { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
function Http(options) { | ||
if (options === void 0) { options = {}; } | ||
/** | ||
@@ -12,2 +15,4 @@ * @inheritDoc | ||
this.name = Http.id; | ||
this._breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs; | ||
this._tracing = typeof options.tracing === 'undefined' ? false : options.tracing; | ||
} | ||
@@ -18,10 +23,18 @@ /** | ||
Http.prototype.setupOnce = function () { | ||
var nativeModule = require('module'); | ||
fill(nativeModule, '_load', loadWrapper(nativeModule)); | ||
// observation: when the https module does its own require('http'), it *does not* hit our hooked require to instrument http on the fly | ||
// but if we've previously instrumented http, https *does* get our already-instrumented version | ||
// this is because raven's transports are required before this instrumentation takes place, which loads https (and http) | ||
// so module cache will have uninstrumented http; proactively loading it here ensures instrumented version is in module cache | ||
// alternatively we could refactor to load our transports later, but this is easier and doesn't have much drawback | ||
require('http'); | ||
// No need to instrument if we don't want to track anything | ||
if (!this._breadcrumbs && !this._tracing) { | ||
return; | ||
} | ||
var handlerWrapper = createHandlerWrapper(this._breadcrumbs, this._tracing); | ||
var httpModule = require('http'); | ||
fill(httpModule, 'get', handlerWrapper); | ||
fill(httpModule, 'request', handlerWrapper); | ||
// NOTE: Prior to Node 9, `https` used internals of `http` module, thus we don't patch it. | ||
// If we do, we'd get double breadcrumbs and double spans for `https` calls. | ||
// It has been changed in Node 9, so for all versions equal and above, we patch `https` separately. | ||
if (NODE_VERSION.major && NODE_VERSION.major > 8) { | ||
var httpsModule = require('https'); | ||
fill(httpsModule, 'get', handlerWrapper); | ||
fill(httpsModule, 'request', handlerWrapper); | ||
} | ||
}; | ||
@@ -36,2 +49,64 @@ /** | ||
/** | ||
* Wrapper function for internal `request` and `get` calls within `http` and `https` modules | ||
*/ | ||
function createHandlerWrapper(breadcrumbsEnabled, tracingEnabled) { | ||
return function handlerWrapper(originalHandler) { | ||
return function (options) { | ||
var requestUrl = extractUrl(options); | ||
if (isSentryRequest(requestUrl)) { | ||
return originalHandler.apply(this, arguments); | ||
} | ||
var span; | ||
if (tracingEnabled) { | ||
span = getCurrentHub().startSpan({ | ||
description: (typeof options === 'string' || !options.method ? 'GET' : options.method) + "|" + requestUrl, | ||
op: 'request', | ||
}); | ||
} | ||
return originalHandler | ||
.apply(this, arguments) | ||
.once('response', function (res) { | ||
if (breadcrumbsEnabled) { | ||
addRequestBreadcrumb('response', requestUrl, this, res); | ||
} | ||
// TODO: Mark >= 500 as failed as well? | ||
if (tracingEnabled) { | ||
span.setSuccess(); | ||
span.finish(); | ||
} | ||
}) | ||
.once('error', function () { | ||
if (breadcrumbsEnabled) { | ||
addRequestBreadcrumb('error', requestUrl, this); | ||
} | ||
if (tracingEnabled) { | ||
span.setFailure(); | ||
span.finish(); | ||
} | ||
}); | ||
}; | ||
}; | ||
} | ||
/** | ||
* Captures Breadcrumb based on provided request/response pair | ||
*/ | ||
function addRequestBreadcrumb(event, url, req, res) { | ||
if (!getCurrentHub().getIntegration(Http)) { | ||
return; | ||
} | ||
getCurrentHub().addBreadcrumb({ | ||
category: 'http', | ||
data: { | ||
method: req.method, | ||
status_code: res && res.statusCode, | ||
url: url, | ||
}, | ||
type: 'http', | ||
}, { | ||
event: event, | ||
request: req, | ||
response: res, | ||
}); | ||
} | ||
/** | ||
* Function that can combine together a url that'll be used for our breadcrumbs. | ||
@@ -42,6 +117,3 @@ * | ||
*/ | ||
function createBreadcrumbUrl(options) { | ||
// We could just always reconstruct this from this.agent, this._headers, this.path, etc | ||
// but certain other http-instrumenting libraries (like nock, which we use for tests) fail to | ||
// maintain the guarantee that after calling origClientRequest, those fields will be populated | ||
function extractUrl(options) { | ||
if (typeof options === 'string') { | ||
@@ -58,87 +130,16 @@ return options; | ||
/** | ||
* Wrapper function for internal _load calls within `require` | ||
* Checks whether given url points to Sentry server | ||
* @param url url to verify | ||
*/ | ||
function loadWrapper(nativeModule) { | ||
// We need to use some functional-style currying to pass values around | ||
// as we cannot rely on `bind`, because this has to preserve correct | ||
// context for native calls | ||
return function (originalLoad) { | ||
return function (moduleId) { | ||
var originalModule = originalLoad.apply(nativeModule, arguments); | ||
if (moduleId !== 'http' || originalModule.__sentry__) { | ||
return originalModule; | ||
} | ||
var origClientRequest = originalModule.ClientRequest; | ||
var clientRequest = function (options, callback) { | ||
// Note: this won't capture a breadcrumb if a response never comes | ||
// It would be useful to know if that was the case, though, so | ||
// TODO: revisit to see if we can capture sth indicating response never came | ||
// possibility: capture one breadcrumb for "req sent" and one for "res recvd" | ||
// seems excessive but solves the problem and *is* strictly more information | ||
// could be useful for weird response sequencing bug scenarios | ||
origClientRequest.call(this, options, callback); | ||
this.__ravenBreadcrumbUrl = createBreadcrumbUrl(options); | ||
}; | ||
util.inherits(clientRequest, origClientRequest); | ||
fill(clientRequest.prototype, 'emit', emitWrapper); | ||
fill(originalModule, 'ClientRequest', function () { | ||
return clientRequest; | ||
}); | ||
// http.request orig refs module-internal ClientRequest, not exported one, so | ||
// it still points at orig ClientRequest after our monkeypatch; these reimpls | ||
// just get that reference updated to use our new ClientRequest | ||
fill(originalModule, 'request', function () { | ||
return function (options, callback) { | ||
return new originalModule.ClientRequest(options, callback); | ||
}; | ||
}); | ||
fill(originalModule, 'get', function () { | ||
return function (options, callback) { | ||
var req = originalModule.request(options, callback); | ||
req.end(); | ||
return req; | ||
}; | ||
}); | ||
originalModule.__sentry__ = true; | ||
return originalModule; | ||
}; | ||
}; | ||
function isSentryRequest(url) { | ||
var client = getCurrentHub().getClient(); | ||
if (!url || !client) { | ||
return false; | ||
} | ||
var dsn = client.getDsn(); | ||
if (!dsn) { | ||
return false; | ||
} | ||
return url.indexOf(dsn.host) !== -1; | ||
} | ||
/** | ||
* Wrapper function for request's `emit` calls | ||
*/ | ||
function emitWrapper(origEmit) { | ||
return function (event, response) { | ||
// I'm not sure why but Node.js (at least in v8.X) | ||
// is emitting all events twice :| | ||
if (lastResponse === undefined || lastResponse !== response) { | ||
lastResponse = response; | ||
} | ||
else { | ||
return origEmit.apply(this, arguments); | ||
} | ||
var client = getCurrentHub().getClient(); | ||
if (client) { | ||
var dsn = client.getDsn(); | ||
var isInterestingEvent = event === 'response' || event === 'error'; | ||
var isNotSentryRequest = dsn && this.__ravenBreadcrumbUrl && this.__ravenBreadcrumbUrl.indexOf(dsn.host) === -1; | ||
if (isInterestingEvent && isNotSentryRequest && getCurrentHub().getIntegration(Http)) { | ||
getCurrentHub().addBreadcrumb({ | ||
category: 'http', | ||
data: { | ||
method: this.method, | ||
status_code: response.statusCode, | ||
url: this.__ravenBreadcrumbUrl, | ||
}, | ||
type: 'http', | ||
}, { | ||
event: event, | ||
request: this, | ||
response: response, | ||
}); | ||
} | ||
} | ||
return origEmit.apply(this, arguments); | ||
}; | ||
} | ||
//# sourceMappingURL=http.js.map |
export declare const SDK_NAME = "sentry.javascript.node"; | ||
export declare const SDK_VERSION = "5.7.1"; | ||
export declare const SDK_VERSION = "5.8.0-beta.0"; | ||
//# sourceMappingURL=version.d.ts.map |
export var SDK_NAME = 'sentry.javascript.node'; | ||
export var SDK_VERSION = '5.7.1'; | ||
export var SDK_VERSION = '5.8.0-beta.0'; | ||
//# sourceMappingURL=version.js.map |
{ | ||
"name": "@sentry/node", | ||
"version": "5.7.1", | ||
"version": "5.8.0-beta.0", | ||
"description": "Offical Sentry SDK for Node.js", | ||
@@ -19,13 +19,13 @@ "repository": "git://github.com/getsentry/sentry-javascript.git", | ||
"dependencies": { | ||
"@sentry/core": "5.7.1", | ||
"@sentry/hub": "5.7.1", | ||
"@sentry/types": "5.7.1", | ||
"@sentry/utils": "5.7.1", | ||
"cookie": "^0.3.1", | ||
"https-proxy-agent": "^3.0.0", | ||
"lru_map": "^0.3.3", | ||
"@sentry/core": "5.8.0-beta.0", | ||
"@sentry/hub": "5.8.0-beta.0", | ||
"@sentry/types": "5.8.0-beta.0", | ||
"@sentry/utils": "5.8.0-beta.0", | ||
"cookie": "0.3.1", | ||
"https-proxy-agent": "2.2.1", | ||
"lru_map": "0.3.3", | ||
"tslib": "^1.9.3" | ||
}, | ||
"devDependencies": { | ||
"@types/cookie": "^0.3.2", | ||
"@types/cookie": "0.3.2", | ||
"@types/lru-cache": "^5.1.0", | ||
@@ -32,0 +32,0 @@ "@types/node": "^11.13.7", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
4283
25
386611
1
12
+ Added@sentry/core@5.8.0-beta.0(transitive)
+ Added@sentry/hub@5.8.0-beta.0(transitive)
+ Added@sentry/minimal@5.8.0-beta.0(transitive)
+ Added@sentry/types@5.8.0-beta.0(transitive)
+ Added@sentry/utils@5.8.0-beta.0(transitive)
+ Addedhttps-proxy-agent@2.2.1(transitive)
- Removed@sentry/core@5.7.1(transitive)
- Removed@sentry/hub@5.7.1(transitive)
- Removed@sentry/minimal@5.7.1(transitive)
- Removed@sentry/types@5.7.1(transitive)
- Removed@sentry/utils@5.7.1(transitive)
- Removedhttps-proxy-agent@3.0.1(transitive)
Updated@sentry/core@5.8.0-beta.0
Updated@sentry/hub@5.8.0-beta.0
Updated@sentry/types@5.8.0-beta.0
Updated@sentry/utils@5.8.0-beta.0
Updatedcookie@0.3.1
Updatedhttps-proxy-agent@2.2.1
Updatedlru_map@0.3.3