1
0

http.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. 'use strict';
  2. var util = require('util');
  3. var utils = require('../utils');
  4. module.exports = function(Raven, http, originals) {
  5. var OrigClientRequest = http.ClientRequest;
  6. var ClientRequest = function(options, cb) {
  7. // Note: this won't capture a breadcrumb if a response never comes
  8. // It would be useful to know if that was the case, though, so
  9. // todo: revisit to see if we can capture sth indicating response never came
  10. // possibility: capture one breadcrumb for "req sent" and one for "res recvd"
  11. // seems excessive but solves the problem and *is* strictly more information
  12. // could be useful for weird response sequencing bug scenarios
  13. OrigClientRequest.call(this, options, cb);
  14. // We could just always reconstruct this from this.agent, this._headers, this.path, etc
  15. // but certain other http-instrumenting libraries (like nock, which we use for tests) fail to
  16. // maintain the guarantee that after calling OrigClientRequest, those fields will be populated
  17. if (typeof options === 'string') {
  18. this.__ravenBreadcrumbUrl = options;
  19. } else {
  20. var protocol = options.protocol || '';
  21. var hostname = options.hostname || options.host || '';
  22. // Don't log standard :80 (http) and :443 (https) ports to reduce the noise
  23. var port =
  24. !options.port || options.port === 80 || options.port === 443
  25. ? ''
  26. : ':' + options.port;
  27. var path = options.path || '/';
  28. this.__ravenBreadcrumbUrl = protocol + '//' + hostname + port + path;
  29. }
  30. };
  31. util.inherits(ClientRequest, OrigClientRequest);
  32. utils.fill(ClientRequest.prototype, 'emit', function(origEmit) {
  33. return function(evt, maybeResp) {
  34. if (evt === 'response' && this.__ravenBreadcrumbUrl) {
  35. if (!Raven.dsn || this.__ravenBreadcrumbUrl.indexOf(Raven.dsn.host) === -1) {
  36. Raven.captureBreadcrumb({
  37. type: 'http',
  38. category: 'http',
  39. data: {
  40. method: this.method,
  41. url: this.__ravenBreadcrumbUrl,
  42. status_code: maybeResp.statusCode
  43. }
  44. });
  45. }
  46. }
  47. return origEmit.apply(this, arguments);
  48. };
  49. });
  50. utils.fill(
  51. http,
  52. 'ClientRequest',
  53. function() {
  54. return ClientRequest;
  55. },
  56. originals
  57. );
  58. // http.request orig refs module-internal ClientRequest, not exported one, so
  59. // it still points at orig ClientRequest after our monkeypatch; these reimpls
  60. // just get that reference updated to use our new ClientRequest
  61. utils.fill(
  62. http,
  63. 'request',
  64. function() {
  65. return function(options, cb) {
  66. return new http.ClientRequest(options, cb);
  67. };
  68. },
  69. originals
  70. );
  71. utils.fill(
  72. http,
  73. 'get',
  74. function() {
  75. return function(options, cb) {
  76. var req = http.request(options, cb);
  77. req.end();
  78. return req;
  79. };
  80. },
  81. originals
  82. );
  83. return http;
  84. };