UNPKG

3.15 kBJavaScriptView Raw
1/*
2 * Copyright (c) 2012 Dmitri Melikyan
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to permit
9 * persons to whom the Software is furnished to do so, subject to the
10 * following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
18 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24
25var os = require('os');
26
27
28var nt;
29var metrics = {};
30
31
32exports.init = function() {
33 nt = global.nodetime;
34
35 setInterval(function() {
36 try {
37 aggregate();
38 }
39 catch(e) {
40 nt.error(e);
41 }
42 }, 60000);
43
44 //send any initial values
45 setTimeout(function() {
46 try {
47 initial();
48 }
49 catch(e) {
50 nt.error(e);
51 }
52 }, 1000);
53};
54
55
56exports.add = function(scope, name, value, unit, op) {
57 if(!scope || !name || typeof(value) !== 'number')
58 throw new Error('parameter(s) missing');
59
60 process.nextTick(function() {
61 var key = scope + ':' + name;
62
63 // create
64 if(!metrics[key]) {
65 metrics[key] = {
66 scope: scope,
67 name: name,
68 value: 0,
69 _count: 0,
70 unit: unit,
71 op: op,
72 history: nt.history
73 };
74
75 if(op === 'hist')
76 metrics[key].value = {};
77 }
78
79
80 // update
81 var obj = metrics[key];
82
83 if(!op || op === 'val') {
84 obj.value = value;
85 }
86 else if(op === 'hist') {
87 var bin = Math.pow(10, Math.floor(Math.log(value) / Math.LN10) + 1);
88 if(obj.value[bin]) {
89 obj.value[bin]++;
90 }
91 else {
92 obj.value[bin] = 1;
93 }
94 }
95 else { // sum, avg
96 obj.value += value;
97 obj._count++;
98 }
99
100 if(!nt.history) {
101 obj.history = false;
102 }
103 });
104};
105
106
107var emit = function(obj) {
108 try {
109 delete obj._count;
110 obj.source = os.hostname() + '[' + process.pid + ']';
111 obj._id = nt.nextId++;
112 obj._ns = 'metrics';
113 obj._ts = nt.millis();
114
115 nt.emit('metric', obj);
116 }
117 catch(err) {
118 nt.error(err);
119 }
120};
121
122var initial = function() {
123 for (var key in metrics) {
124 var obj = metrics[key];
125
126 if(!obj.op || obj.op === 'val') {
127 emit(obj);
128
129 delete metrics[key];
130 }
131 }
132};
133
134
135var aggregate = function() {
136 for (var key in metrics) {
137 var obj = metrics[key];
138
139 if(obj.op === 'avg') {
140 obj.value = Math.round(obj.value / obj._count);
141 }
142
143 emit(obj);
144 }
145
146 metrics = {};
147};
148