-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathindex.js
158 lines (137 loc) · 3.72 KB
/
index.js
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
'use strict';
var _ = require('lodash');
var request = require('request');
var logger = console;
function Insights(config){
this.config = _.assign({
accountId: null,
enabled: true,
insertKey: '',
queryKey: '',
timerInterval: 10000,
maxPending: 100,
defaultEventType: 'data',
baseURL: null,
url: null
}, config);
if(_.isEmpty(this.config.accountId)){
throw new Error('Missing account ID');
}
this.data = [];
this.timerId = null;
this.timerCallback = _.bind(this.send, this);
this.urlPathPrefix = '/v1/accounts/' + this.config.accountId + '/';
}
Insights.collectorBaseURL = "https://insights-collector.newrelic.com";
Insights.queryBaseURL = "https://insights-api.newrelic.com";
//start the timer that will send insights after some interval of time
//this is called implicitly when data is added via the add method
Insights.prototype.start = function(){
if (!this.timerId){
this.timerId = setInterval(this.timerCallback, this.config.timerInterval);
}
};
//stop the timer that will send insights after some interval of time
//this is called implicitly when the amount of data exceeds maxPending and the queue is sent
Insights.prototype.stop = function(){
if (this.timerId){
clearInterval(this.timerId);
this.timerId = null;
}
};
//Send accumulated insights data to new relic (if enabled)
Insights.prototype.send = function(){
var that = this;
if (that.config.enabled && that.data.length > 0){
var bodyData = that.data;
that.data = [];
try {
request({
method: 'POST',
json: true,
headers: {
"X-Insert-Key": this.config.insertKey
},
url: (Insights.collectorBaseURL + that.urlPathPrefix + "events"),
body: bodyData
}, function(err, res, body){
if (err){
logger.error('Error sending to insights', err);
}
else if (res){
logger.log('Insights response', res.statusCode, body);
}
});
}
catch(x){
logger.error(x);
}
}
};
function reducer(prefix){
return function(insight, value, key){
if (_.isString(value) || _.isNumber(value)){
insight[prefix + key] = value;
}
else if (_.isPlainObject(value) || _.isArray(value)){
_.reduce(value, reducer(key + '.'), insight);
}
else if (_.isBoolean(value) || _.isDate(value)){
insight[prefix + key] = value.toString();
}
else {
//ignore functions, nulls, undefineds
logger.warn('not reducing', prefix, key, value);
}
return insight;
};
}
//Add insights data to the queue.
//It is sent when the queue reaches a max size or a period of time has elapsed
Insights.prototype.add = function(data, eventType){
if (_.isEmpty(this.config.insertKey)){
throw new Error('Missing insert key');
}
var that = this;
try {
var insight = _.reduce(data, reducer(""), {
"eventType": eventType || that.config.defaultEventType
});
logger.log('Insights data', insight);
that.data.push(insight);
if (that.data.length >= that.config.maxPending){
that.stop();
that.send();
}
else {
that.start();
}
}
catch(x){
logger.error('Insights Add Exception:', x);
that.data.length = 0;
}
};
Insights.prototype.query = function(query, done) {
if (_.isEmpty(this.config.queryKey)){
throw new Error('Missing query key');
}
try {
decodeURIComponent(query);
}
catch(ex) {
query = encodeURI(query);
}
var url = Insights.queryBaseURL + this.urlPathPrefix + "query?nrql=" + query;
request({
method: 'GET',
json: true,
headers: {
"X-Query-Key": this.config.queryKey
},
url: url,
}, function(err, res, body){
done(err, body);
});
};
module.exports = Insights;