index.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. var util = require('../core').util;
  2. var dgram = require('dgram');
  3. var stringToBuffer = util.buffer.toBuffer;
  4. var MAX_MESSAGE_SIZE = 1024 * 8; // 8 KB
  5. /**
  6. * Publishes metrics via udp.
  7. * @param {object} options Paramters for Publisher constructor
  8. * @param {number} [options.port = 31000] Port number
  9. * @param {string} [options.clientId = ''] Client Identifier
  10. * @param {boolean} [options.enabled = false] enable sending metrics datagram
  11. * @api private
  12. */
  13. function Publisher(options) {
  14. // handle configuration
  15. options = options || {};
  16. this.enabled = options.enabled || false;
  17. this.port = options.port || 31000;
  18. this.clientId = options.clientId || '';
  19. this.address = options.host || '127.0.0.1';
  20. if (this.clientId.length > 255) {
  21. // ClientId has a max length of 255
  22. this.clientId = this.clientId.substr(0, 255);
  23. }
  24. this.messagesInFlight = 0;
  25. }
  26. Publisher.prototype.fieldsToTrim = {
  27. UserAgent: 256,
  28. SdkException: 128,
  29. SdkExceptionMessage: 512,
  30. AwsException: 128,
  31. AwsExceptionMessage: 512,
  32. FinalSdkException: 128,
  33. FinalSdkExceptionMessage: 512,
  34. FinalAwsException: 128,
  35. FinalAwsExceptionMessage: 512
  36. };
  37. /**
  38. * Trims fields that have a specified max length.
  39. * @param {object} event ApiCall or ApiCallAttempt event.
  40. * @returns {object}
  41. * @api private
  42. */
  43. Publisher.prototype.trimFields = function(event) {
  44. var trimmableFields = Object.keys(this.fieldsToTrim);
  45. for (var i = 0, iLen = trimmableFields.length; i < iLen; i++) {
  46. var field = trimmableFields[i];
  47. if (event.hasOwnProperty(field)) {
  48. var maxLength = this.fieldsToTrim[field];
  49. var value = event[field];
  50. if (value && value.length > maxLength) {
  51. event[field] = value.substr(0, maxLength);
  52. }
  53. }
  54. }
  55. return event;
  56. };
  57. /**
  58. * Handles ApiCall and ApiCallAttempt events.
  59. * @param {Object} event apiCall or apiCallAttempt event.
  60. * @api private
  61. */
  62. Publisher.prototype.eventHandler = function(event) {
  63. // set the clientId
  64. event.ClientId = this.clientId;
  65. this.trimFields(event);
  66. var message = stringToBuffer(JSON.stringify(event));
  67. if (!this.enabled || message.length > MAX_MESSAGE_SIZE) {
  68. // drop the message if publisher not enabled or it is too large
  69. return;
  70. }
  71. this.publishDatagram(message);
  72. };
  73. /**
  74. * Publishes message to an agent.
  75. * @param {Buffer} message JSON message to send to agent.
  76. * @api private
  77. */
  78. Publisher.prototype.publishDatagram = function(message) {
  79. var self = this;
  80. var client = this.getClient();
  81. this.messagesInFlight++;
  82. this.client.send(message, 0, message.length, this.port, this.address, function(err, bytes) {
  83. if (--self.messagesInFlight <= 0) {
  84. // destroy existing client so the event loop isn't kept open
  85. self.destroyClient();
  86. }
  87. });
  88. };
  89. /**
  90. * Returns an existing udp socket, or creates one if it doesn't already exist.
  91. * @api private
  92. */
  93. Publisher.prototype.getClient = function() {
  94. if (!this.client) {
  95. this.client = dgram.createSocket('udp4');
  96. }
  97. return this.client;
  98. };
  99. /**
  100. * Destroys the udp socket.
  101. * @api private
  102. */
  103. Publisher.prototype.destroyClient = function() {
  104. if (this.client) {
  105. this.client.close();
  106. this.client = void 0;
  107. }
  108. };
  109. module.exports = {
  110. Publisher: Publisher
  111. };