@@ -599,6 +599,27 @@ function setCustomItemKeys(item, custom) {
599
599
}
600
600
}
601
601
602
+ function addErrorContext ( item , errors ) {
603
+ var custom = item . data . custom || { } ;
604
+ var contextAdded = false ;
605
+
606
+ try {
607
+ for ( var i = 0 ; i < errors . length ; ++ i ) {
608
+ if ( errors [ i ] . hasOwnProperty ( 'rollbarContext' ) ) {
609
+ custom = merge ( custom , errors [ i ] . rollbarContext ) ;
610
+ contextAdded = true ;
611
+ }
612
+ }
613
+
614
+ // Avoid adding an empty object to the data.
615
+ if ( contextAdded ) {
616
+ item . data . custom = custom ;
617
+ }
618
+ } catch ( e ) {
619
+ item . diagnostic . error_context = 'Failed: ' + e . message ;
620
+ }
621
+ }
622
+
602
623
var TELEMETRY_TYPES = [ 'log' , 'network' , 'dom' , 'navigation' , 'error' , 'manual' ] ;
603
624
var TELEMETRY_LEVELS = [ 'critical' , 'error' , 'warning' , 'info' , 'debug' ] ;
604
625
@@ -695,8 +716,15 @@ function set(obj, path, value) {
695
716
}
696
717
}
697
718
698
- function scrub ( data , scrubFields ) {
719
+ function scrub ( data , scrubFields , scrubPaths ) {
699
720
scrubFields = scrubFields || [ ] ;
721
+
722
+ if ( scrubPaths ) {
723
+ for ( var i = 0 ; i < scrubPaths . length ; ++ i ) {
724
+ scrubPath ( data , scrubPaths [ i ] ) ;
725
+ }
726
+ }
727
+
700
728
var paramRes = _getScrubFieldRegexs ( scrubFields ) ;
701
729
var queryRes = _getScrubQueryParamRegexs ( scrubFields ) ;
702
730
@@ -740,6 +768,22 @@ function scrub(data, scrubFields) {
740
768
return traverse ( data , scrubber , [ ] ) ;
741
769
}
742
770
771
+ function scrubPath ( obj , path ) {
772
+ var keys = path . split ( '.' ) ;
773
+ var last = keys . length - 1 ;
774
+ try {
775
+ for ( var i = 0 ; i <= last ; ++ i ) {
776
+ if ( i < last ) {
777
+ obj = obj [ keys [ i ] ] ;
778
+ } else {
779
+ obj [ keys [ i ] ] = redact ( ) ;
780
+ }
781
+ }
782
+ } catch ( e ) {
783
+ // Missing key is OK;
784
+ }
785
+ }
786
+
743
787
function _getScrubFieldRegexs ( scrubFields ) {
744
788
var ret = [ ] ;
745
789
var pat ;
@@ -846,6 +890,7 @@ function handleOptions(current, input, payload) {
846
890
module . exports = {
847
891
addParamsAndAccessTokenToPath : addParamsAndAccessTokenToPath ,
848
892
createItem : createItem ,
893
+ addErrorContext : addErrorContext ,
849
894
createTelemetryEvent : createTelemetryEvent ,
850
895
filterIp : filterIp ,
851
896
formatArgsAsString : formatArgsAsString ,
@@ -1840,7 +1885,7 @@ function _gWindow() {
1840
1885
/* global __DEFAULT_ENDPOINT__:false */
1841
1886
1842
1887
var defaultOptions = {
1843
- version : "2.17 .0" ,
1888
+ version : "2.18 .0" ,
1844
1889
scrubFields : [ "pw" , "pass" , "passwd" , "password" , "secret" , "confirm_password" , "confirmPassword" , "password_confirmation" , "passwordConfirmation" , "access_token" , "accessToken" , "X-Rollbar-Access-Token" , "secret_key" , "secretKey" , "secretToken" , "cc-number" , "card number" , "cardnumber" , "cardnum" , "ccnum" , "ccnumber" , "cc num" , "creditcardnumber" , "credit card number" , "newcreditcardnumber" , "new credit card" , "creditcardno" , "credit card no" , "card#" , "card #" , "cc-csc" , "cvc" , "cvc2" , "cvv2" , "ccv2" , "security code" , "card verification" , "name on credit card" , "name on card" , "nameoncard" , "cardholder" , "card holder" , "name des karteninhabers" , "ccname" , "card type" , "cardtype" , "cc type" , "cctype" , "payment type" , "expiration date" , "expirationdate" , "expdate" , "cc-exp" , "ccmonth" , "ccyear" ] ,
1845
1890
logLevel : "debug" ,
1846
1891
reportLevel : "debug" ,
@@ -4408,6 +4453,10 @@ function handleItemWithError(item, options, callback) {
4408
4453
if ( item . err ) {
4409
4454
try {
4410
4455
item . stackInfo = item . err . _savedStackTrace || errorParser . parse ( item . err , item . skipFrames ) ;
4456
+
4457
+ if ( options . addErrorContext ) {
4458
+ addErrorContext ( item ) ;
4459
+ }
4411
4460
} catch ( e ) {
4412
4461
logger . error ( 'Error while parsing the error object.' , e ) ;
4413
4462
try {
@@ -4421,6 +4470,20 @@ function handleItemWithError(item, options, callback) {
4421
4470
callback ( null , item ) ;
4422
4471
}
4423
4472
4473
+ function addErrorContext ( item ) {
4474
+ var chain = [ ] ;
4475
+ var err = item . err ;
4476
+
4477
+ chain . push ( err ) ;
4478
+
4479
+ while ( err . nested ) {
4480
+ err = err . nested ;
4481
+ chain . push ( err ) ;
4482
+ }
4483
+
4484
+ _ . addErrorContext ( item , chain ) ;
4485
+ }
4486
+
4424
4487
function ensureItemHasSomethingToSay ( item , options , callback ) {
4425
4488
if ( ! item . message && ! item . stackInfo && ! item . custom ) {
4426
4489
callback ( new Error ( 'No message, stack info, or custom data' ) , null ) ;
@@ -4681,8 +4744,9 @@ function errorClass(stackInfo, guess, options) {
4681
4744
}
4682
4745
4683
4746
function scrubPayload ( item , options , callback ) {
4684
- var scrubFields = options . scrubFields ;
4685
- item . data = _ . scrub ( item . data , scrubFields ) ;
4747
+ var scrubFields = options . scrubFields || [ ] ;
4748
+ var scrubPaths = options . scrubPaths || [ ] ;
4749
+ item . data = _ . scrub ( item . data , scrubFields , scrubPaths ) ;
4686
4750
callback ( null , item ) ;
4687
4751
}
4688
4752
@@ -5777,8 +5841,9 @@ Instrumenter.prototype.instrumentNetwork = function() {
5777
5841
}
5778
5842
var body = null ;
5779
5843
if ( self . autoInstrument . networkResponseBody ) {
5780
- if ( typeof resp . text === 'function' ) { // Response.text() is not implemented on multiple platforms
5781
- body = resp . text ( ) ; //returns a Promise
5844
+ if ( typeof resp . text === 'function' ) { // Response.text() is not implemented on some platforms
5845
+ // The response must be cloned to prevent reading (and locking) the original stream.
5846
+ body = resp . clone ( ) . text ( ) ; //returns a Promise
5782
5847
}
5783
5848
}
5784
5849
if ( headers || body ) {
0 commit comments