instrumentation.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. define([
  2. "./tracer",
  3. "../has",
  4. "../_base/lang",
  5. "../_base/array"
  6. ], function(tracer, has, lang, arrayUtil){
  7. has.add("config-useDeferredInstrumentation", "report-unhandled-rejections");
  8. function logError(error, rejection, deferred){
  9. var stack = "";
  10. if(error && error.stack){
  11. stack += error.stack;
  12. }
  13. if(rejection && rejection.stack){
  14. stack += "\n ----------------------------------------\n rejected" + rejection.stack.split("\n").slice(1).join("\n").replace(/^\s+/, " ");
  15. }
  16. if(deferred && deferred.stack){
  17. stack += "\n ----------------------------------------\n" + deferred.stack;
  18. }
  19. console.error(error, stack);
  20. }
  21. function reportRejections(error, handled, rejection, deferred){
  22. if(!handled){
  23. logError(error, rejection, deferred);
  24. }
  25. }
  26. var errors = [];
  27. var activeTimeout = false;
  28. var unhandledWait = 1000;
  29. function trackUnhandledRejections(error, handled, rejection, deferred){
  30. // try to find the existing tracking object
  31. if(!arrayUtil.some(errors, function(obj){
  32. if(obj.error === error){
  33. // found the tracking object for this error
  34. if(handled){
  35. // if handled, update the state
  36. obj.handled = true;
  37. }
  38. return true;
  39. }
  40. })){
  41. // no tracking object has been setup, create one
  42. errors.push({
  43. error: error,
  44. rejection: rejection,
  45. handled: handled,
  46. deferred: deferred,
  47. timestamp: new Date().getTime()
  48. });
  49. }
  50. if(!activeTimeout){
  51. activeTimeout = setTimeout(logRejected, unhandledWait);
  52. }
  53. }
  54. function logRejected(){
  55. var now = new Date().getTime();
  56. var reportBefore = now - unhandledWait;
  57. errors = arrayUtil.filter(errors, function(obj){
  58. // only report the error if we have waited long enough and
  59. // it hasn't been handled
  60. if(obj.timestamp < reportBefore){
  61. if(!obj.handled){
  62. logError(obj.error, obj.rejection, obj.deferred);
  63. }
  64. return false;
  65. }
  66. return true;
  67. });
  68. if(errors.length){
  69. activeTimeout = setTimeout(logRejected, errors[0].timestamp + unhandledWait - now);
  70. }else{
  71. activeTimeout = false;
  72. }
  73. }
  74. return function(Deferred){
  75. // summary:
  76. // Initialize instrumentation for the Deferred class.
  77. // description:
  78. // Initialize instrumentation for the Deferred class.
  79. // Done automatically by `dojo/Deferred` if the
  80. // `deferredInstrumentation` and `useDeferredInstrumentation`
  81. // config options are set.
  82. //
  83. // Sets up `dojo/promise/tracer` to log to the console.
  84. //
  85. // Sets up instrumentation of rejected deferreds so unhandled
  86. // errors are logged to the console.
  87. var usage = has("config-useDeferredInstrumentation");
  88. if(usage){
  89. tracer.on("resolved", lang.hitch(console, "log", "resolved"));
  90. tracer.on("rejected", lang.hitch(console, "log", "rejected"));
  91. tracer.on("progress", lang.hitch(console, "log", "progress"));
  92. var args = [];
  93. if(typeof usage === "string"){
  94. args = usage.split(",");
  95. usage = args.shift();
  96. }
  97. if(usage === "report-rejections"){
  98. Deferred.instrumentRejected = reportRejections;
  99. }else if(usage === "report-unhandled-rejections" || usage === true || usage === 1){
  100. Deferred.instrumentRejected = trackUnhandledRejections;
  101. unhandledWait = parseInt(args[0], 10) || unhandledWait;
  102. }else{
  103. throw new Error("Unsupported instrumentation usage <" + usage + ">");
  104. }
  105. }
  106. };
  107. });