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