@sentry/node
Advanced tools
Comparing version 5.8.0-beta.1 to 5.8.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'; | ||
@@ -10,0 +5,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"); | ||
@@ -11,32 +12,2 @@ 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 */ | ||
@@ -242,12 +213,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 = core_1.Span.fromTraceparent(req.headers['sentry-trace']); | ||
if (_req.headers && utils_1.isString(_req.headers['sentry-trace'])) { | ||
var span = hub_1.Span.fromTraceparent(_req.headers['sentry-trace']); | ||
scope.setSpan(span); | ||
} | ||
var eventId = core_1.captureException(error); | ||
res.sentry = eventId; | ||
_res.sentry = eventId; | ||
next(error); | ||
@@ -254,0 +225,0 @@ }); |
export { Breadcrumb, Request, SdkInfo, Event, Exception, Response, Severity, StackFrame, Stacktrace, Status, Thread, User, } from '@sentry/types'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getHubFromCarrier, getCurrentHub, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, startSpan, Span, withScope, } from '@sentry/core'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getCurrentHub, getHubFromCarrier, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, 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.getCurrentHub = core_1.getCurrentHub; | ||
exports.getHubFromCarrier = core_1.getHubFromCarrier; | ||
exports.getCurrentHub = core_1.getCurrentHub; | ||
exports.Hub = core_1.Hub; | ||
@@ -24,3 +24,2 @@ exports.Scope = core_1.Scope; | ||
exports.setUser = core_1.setUser; | ||
exports.startSpan = core_1.startSpan; | ||
exports.Span = core_1.Span; | ||
@@ -27,0 +26,0 @@ exports.withScope = core_1.withScope; |
@@ -19,17 +19,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
Console.prototype.setupOnce = function () { | ||
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; } | ||
} | ||
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'); | ||
}; | ||
@@ -44,38 +33,62 @@ /** | ||
/** | ||
* 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 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; | ||
function consoleWrapper(originalModule) { | ||
return function (level) { | ||
if (!(level in originalModule)) { | ||
return; | ||
} | ||
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, | ||
}); | ||
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; | ||
} | ||
originalConsoleMethod.apply(this, arguments); | ||
}; | ||
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); | ||
}; | ||
}); | ||
}; | ||
} | ||
//# sourceMappingURL=console.js.map |
@@ -15,19 +15,4 @@ 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 NODE_VERSION = utils_1.parseSemver(process.versions.node); | ||
var util = require("util"); | ||
var lastResponse; | ||
/** http module integration */ | ||
var Http = /** @class */ (function () { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
function Http(options) { | ||
if (options === void 0) { options = {}; } | ||
function Http() { | ||
/** | ||
@@ -16,4 +13,2 @@ * @inheritDoc | ||
this.name = Http.id; | ||
this._breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs; | ||
this._tracing = typeof options.tracing === 'undefined' ? false : options.tracing; | ||
} | ||
@@ -24,18 +19,10 @@ /** | ||
Http.prototype.setupOnce = function () { | ||
// 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); | ||
} | ||
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'); | ||
}; | ||
@@ -50,64 +37,2 @@ /** | ||
/** | ||
* 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. | ||
@@ -118,3 +43,6 @@ * | ||
*/ | ||
function extractUrl(options) { | ||
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 | ||
if (typeof options === 'string') { | ||
@@ -131,16 +59,87 @@ return options; | ||
/** | ||
* Checks whether given url points to Sentry server | ||
* @param url url to verify | ||
* Wrapper function for internal _load calls within `require` | ||
*/ | ||
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; | ||
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; | ||
}; | ||
}; | ||
} | ||
/** | ||
* 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 |
@@ -31,2 +31,4 @@ /// <reference types="node" /> | ||
protected readonly _buffer: PromiseBuffer<Response>; | ||
/** Locks transport after receiving 429 response */ | ||
private _disabledUntil; | ||
/** Create instance and set this.dsn */ | ||
@@ -33,0 +35,0 @@ constructor(options: TransportOptions); |
@@ -15,2 +15,4 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
this._buffer = new utils_1.PromiseBuffer(30); | ||
/** Locks transport after receiving 429 response */ | ||
this._disabledUntil = new Date(Date.now()); | ||
this._api = new core_1.API(options.dsn); | ||
@@ -41,2 +43,5 @@ } | ||
return tslib_1.__generator(this, function (_a) { | ||
if (new Date(Date.now()) < this._disabledUntil) { | ||
return [2 /*return*/, Promise.reject(new utils_1.SentryError("Transport locked till " + this._disabledUntil + " due to too many requests."))]; | ||
} | ||
if (!this._buffer.isReady()) { | ||
@@ -47,18 +52,23 @@ return [2 /*return*/, Promise.reject(new utils_1.SentryError('Not adding Promise due to buffer limit reached.'))]; | ||
var req = httpModule.request(_this._getRequestOptions(), function (res) { | ||
var statusCode = res.statusCode || 500; | ||
var status = types_1.Status.fromHttpCode(statusCode); | ||
res.setEncoding('utf8'); | ||
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { | ||
resolve({ | ||
status: types_1.Status.fromHttpCode(res.statusCode), | ||
}); | ||
if (status === types_1.Status.Success) { | ||
resolve({ status: status }); | ||
} | ||
else { | ||
if (status === types_1.Status.RateLimit) { | ||
var now = Date.now(); | ||
var header = res.headers ? res.headers['Retry-After'] : ''; | ||
header = Array.isArray(header) ? header[0] : header; | ||
_this._disabledUntil = new Date(now + utils_1.parseRetryAfterHeader(now, header)); | ||
utils_1.logger.warn("Too many requests, backing off till: " + _this._disabledUntil); | ||
} | ||
var rejectionMessage = "HTTP Error (" + statusCode + ")"; | ||
if (res.headers && res.headers['x-sentry-error']) { | ||
var reason = res.headers['x-sentry-error']; | ||
reject(new utils_1.SentryError("HTTP Error (" + res.statusCode + "): " + reason)); | ||
rejectionMessage += ": " + res.headers['x-sentry-error']; | ||
} | ||
else { | ||
reject(new utils_1.SentryError("HTTP Error (" + res.statusCode + ")")); | ||
} | ||
reject(new utils_1.SentryError(rejectionMessage)); | ||
} | ||
// force the socket to drain | ||
// Force the socket to drain | ||
res.on('data', function () { | ||
@@ -65,0 +75,0 @@ // Drain |
export declare const SDK_NAME = "sentry.javascript.node"; | ||
export declare const SDK_VERSION = "5.8.0-beta.1"; | ||
export declare const SDK_VERSION = "5.8.0"; | ||
//# sourceMappingURL=version.d.ts.map |
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SDK_NAME = 'sentry.javascript.node'; | ||
exports.SDK_VERSION = '5.8.0-beta.1'; | ||
exports.SDK_VERSION = '5.8.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'; | ||
@@ -10,0 +5,0 @@ /** |
import * as tslib_1 from "tslib"; | ||
import { captureException, getCurrentHub, Span, withScope } from '@sentry/core'; | ||
import { captureException, getCurrentHub, withScope } from '@sentry/core'; | ||
import { Span } from '@sentry/hub'; | ||
import { forget, isString, logger, normalize } from '@sentry/utils'; | ||
@@ -10,31 +11,2 @@ 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 */ | ||
@@ -238,12 +210,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); | ||
@@ -250,0 +222,0 @@ }); |
export { Breadcrumb, Request, SdkInfo, Event, Exception, Response, Severity, StackFrame, Stacktrace, Status, Thread, User, } from '@sentry/types'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getHubFromCarrier, getCurrentHub, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, startSpan, Span, withScope, } from '@sentry/core'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getCurrentHub, getHubFromCarrier, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, 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, getHubFromCarrier, getCurrentHub, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, startSpan, Span, withScope, } from '@sentry/core'; | ||
export { addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, configureScope, getCurrentHub, getHubFromCarrier, Hub, Scope, setContext, setExtra, setExtras, setTag, setTags, setUser, Span, withScope, } from '@sentry/core'; | ||
export { NodeClient } from './client'; | ||
@@ -5,0 +5,0 @@ export { defaultIntegrations, init, lastEventId, flush, close } from './sdk'; |
@@ -18,17 +18,6 @@ import * as tslib_1 from "tslib"; | ||
Console.prototype.setupOnce = function () { | ||
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; } | ||
} | ||
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'); | ||
}; | ||
@@ -43,38 +32,62 @@ /** | ||
/** | ||
* 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 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; | ||
function consoleWrapper(originalModule) { | ||
return function (level) { | ||
if (!(level in originalModule)) { | ||
return; | ||
} | ||
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, | ||
}); | ||
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; | ||
} | ||
originalConsoleMethod.apply(this, arguments); | ||
}; | ||
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); | ||
}; | ||
}); | ||
}; | ||
} | ||
//# sourceMappingURL=console.js.map |
@@ -15,19 +15,4 @@ 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, parseSemver } from '@sentry/utils'; | ||
var NODE_VERSION = parseSemver(process.versions.node); | ||
import { fill } from '@sentry/utils'; | ||
import * as util from 'util'; | ||
var lastResponse; | ||
/** http module integration */ | ||
var Http = /** @class */ (function () { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
function Http(options) { | ||
if (options === void 0) { options = {}; } | ||
function Http() { | ||
/** | ||
@@ -15,4 +12,2 @@ * @inheritDoc | ||
this.name = Http.id; | ||
this._breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs; | ||
this._tracing = typeof options.tracing === 'undefined' ? false : options.tracing; | ||
} | ||
@@ -23,18 +18,10 @@ /** | ||
Http.prototype.setupOnce = function () { | ||
// 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); | ||
} | ||
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'); | ||
}; | ||
@@ -49,64 +36,2 @@ /** | ||
/** | ||
* 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. | ||
@@ -117,3 +42,6 @@ * | ||
*/ | ||
function extractUrl(options) { | ||
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 | ||
if (typeof options === 'string') { | ||
@@ -130,16 +58,87 @@ return options; | ||
/** | ||
* Checks whether given url points to Sentry server | ||
* @param url url to verify | ||
* Wrapper function for internal _load calls within `require` | ||
*/ | ||
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; | ||
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; | ||
}; | ||
}; | ||
} | ||
/** | ||
* 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 |
@@ -31,2 +31,4 @@ /// <reference types="node" /> | ||
protected readonly _buffer: PromiseBuffer<Response>; | ||
/** Locks transport after receiving 429 response */ | ||
private _disabledUntil; | ||
/** Create instance and set this.dsn */ | ||
@@ -33,0 +35,0 @@ constructor(options: TransportOptions); |
import * as tslib_1 from "tslib"; | ||
import { API } from '@sentry/core'; | ||
import { Status } from '@sentry/types'; | ||
import { PromiseBuffer, SentryError } from '@sentry/utils'; | ||
import { logger, parseRetryAfterHeader, PromiseBuffer, SentryError } from '@sentry/utils'; | ||
import * as fs from 'fs'; | ||
@@ -14,2 +14,4 @@ import { SDK_NAME, SDK_VERSION } from '../version'; | ||
this._buffer = new PromiseBuffer(30); | ||
/** Locks transport after receiving 429 response */ | ||
this._disabledUntil = new Date(Date.now()); | ||
this._api = new API(options.dsn); | ||
@@ -40,2 +42,5 @@ } | ||
return tslib_1.__generator(this, function (_a) { | ||
if (new Date(Date.now()) < this._disabledUntil) { | ||
return [2 /*return*/, Promise.reject(new SentryError("Transport locked till " + this._disabledUntil + " due to too many requests."))]; | ||
} | ||
if (!this._buffer.isReady()) { | ||
@@ -46,18 +51,23 @@ return [2 /*return*/, Promise.reject(new SentryError('Not adding Promise due to buffer limit reached.'))]; | ||
var req = httpModule.request(_this._getRequestOptions(), function (res) { | ||
var statusCode = res.statusCode || 500; | ||
var status = Status.fromHttpCode(statusCode); | ||
res.setEncoding('utf8'); | ||
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { | ||
resolve({ | ||
status: Status.fromHttpCode(res.statusCode), | ||
}); | ||
if (status === Status.Success) { | ||
resolve({ status: status }); | ||
} | ||
else { | ||
if (status === Status.RateLimit) { | ||
var now = Date.now(); | ||
var header = res.headers ? res.headers['Retry-After'] : ''; | ||
header = Array.isArray(header) ? header[0] : header; | ||
_this._disabledUntil = new Date(now + parseRetryAfterHeader(now, header)); | ||
logger.warn("Too many requests, backing off till: " + _this._disabledUntil); | ||
} | ||
var rejectionMessage = "HTTP Error (" + statusCode + ")"; | ||
if (res.headers && res.headers['x-sentry-error']) { | ||
var reason = res.headers['x-sentry-error']; | ||
reject(new SentryError("HTTP Error (" + res.statusCode + "): " + reason)); | ||
rejectionMessage += ": " + res.headers['x-sentry-error']; | ||
} | ||
else { | ||
reject(new SentryError("HTTP Error (" + res.statusCode + ")")); | ||
} | ||
reject(new SentryError(rejectionMessage)); | ||
} | ||
// force the socket to drain | ||
// Force the socket to drain | ||
res.on('data', function () { | ||
@@ -64,0 +74,0 @@ // Drain |
export declare const SDK_NAME = "sentry.javascript.node"; | ||
export declare const SDK_VERSION = "5.8.0-beta.1"; | ||
export declare const SDK_VERSION = "5.8.0"; | ||
//# sourceMappingURL=version.d.ts.map |
export var SDK_NAME = 'sentry.javascript.node'; | ||
export var SDK_VERSION = '5.8.0-beta.1'; | ||
export var SDK_VERSION = '5.8.0'; | ||
//# sourceMappingURL=version.js.map |
{ | ||
"name": "@sentry/node", | ||
"version": "5.8.0-beta.1", | ||
"version": "5.8.0", | ||
"description": "Offical Sentry SDK for Node.js", | ||
@@ -19,13 +19,13 @@ "repository": "git://github.com/getsentry/sentry-javascript.git", | ||
"dependencies": { | ||
"@sentry/core": "5.8.0-beta.1", | ||
"@sentry/hub": "5.8.0-beta.1", | ||
"@sentry/types": "5.8.0-beta.1", | ||
"@sentry/utils": "5.8.0-beta.1", | ||
"cookie": "0.3.1", | ||
"https-proxy-agent": "2.2.1", | ||
"lru_map": "0.3.3", | ||
"@sentry/core": "5.8.0", | ||
"@sentry/hub": "5.8.0", | ||
"@sentry/types": "5.7.1", | ||
"@sentry/utils": "5.8.0", | ||
"cookie": "^0.3.1", | ||
"https-proxy-agent": "^3.0.0", | ||
"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
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
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
393026
0
10
4233
29
+ Added@sentry/core@5.8.0(transitive)
+ Added@sentry/hub@5.8.0(transitive)
+ Added@sentry/minimal@5.8.0(transitive)
+ Added@sentry/types@5.7.1(transitive)
+ Added@sentry/utils@5.8.0(transitive)
+ Addedhttps-proxy-agent@3.0.1(transitive)
- Removed@sentry/core@5.8.0-beta.1(transitive)
- Removed@sentry/hub@5.8.0-beta.1(transitive)
- Removed@sentry/minimal@5.8.0-beta.1(transitive)
- Removed@sentry/types@5.8.0-beta.1(transitive)
- Removed@sentry/utils@5.8.0-beta.1(transitive)
- Removedhttps-proxy-agent@2.2.1(transitive)
Updated@sentry/core@5.8.0
Updated@sentry/hub@5.8.0
Updated@sentry/types@5.7.1
Updated@sentry/utils@5.8.0
Updatedcookie@^0.3.1
Updatedhttps-proxy-agent@^3.0.0
Updatedlru_map@^0.3.3