@jambonz/time-series 0.1.7 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +109 -5
- package/package.json +1 -1
- package/test/unit-tests.js +31 -2
package/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const AlertType = {
|
|
|
5
5
|
WEBHOOK_CONNECTION_FAILURE: 'webhook-connection-failure',
|
|
6
6
|
WEBHOOK_URL_NOTFOUND: 'webhook-url-notfound',
|
|
7
7
|
WEBHOOK_AUTH_FAILURE: 'webhook-auth-failure',
|
|
8
|
+
INVALID_APP_PAYLOAD: 'invalid-app-payload',
|
|
8
9
|
TTS_NOT_PROVISIONED: 'no-tts',
|
|
9
10
|
STT_NOT_PROVISIONED: 'no-stt',
|
|
10
11
|
TTS_FAILURE: 'tts-failure',
|
|
@@ -49,6 +50,15 @@ const schemas = {
|
|
|
49
50
|
'account_sid',
|
|
50
51
|
'alert_type'
|
|
51
52
|
]
|
|
53
|
+
},
|
|
54
|
+
call_counts: {
|
|
55
|
+
measurement: 'call_counts',
|
|
56
|
+
fields: {
|
|
57
|
+
calls_in_progress: Influx.FieldType.INTEGER,
|
|
58
|
+
},
|
|
59
|
+
tags: [
|
|
60
|
+
'account_sid'
|
|
61
|
+
]
|
|
52
62
|
}
|
|
53
63
|
};
|
|
54
64
|
|
|
@@ -70,9 +80,33 @@ const writeData = async(client) => {
|
|
|
70
80
|
}
|
|
71
81
|
};
|
|
72
82
|
|
|
83
|
+
const createCallCountsQuery = ({account_sid, page, page_size, days, start, end}) => {
|
|
84
|
+
let sql = `SELECT * from call_counts WHERE account_sid = '${account_sid}'`;
|
|
85
|
+
if (days) sql += `AND time > now() - ${days}d `;
|
|
86
|
+
else {
|
|
87
|
+
if (start) sql += `AND time >= '${start}' `;
|
|
88
|
+
if (end) sql += `AND time <= '${end}' `;
|
|
89
|
+
}
|
|
90
|
+
sql += ' ORDER BY time DESC';
|
|
91
|
+
if (page_size) sql += ` LIMIT ${page_size}`;
|
|
92
|
+
if (page) sql += ` OFFSET ${(page - 1) * page_size}`;
|
|
93
|
+
//console.log(sql);
|
|
94
|
+
return sql;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const createCallCountsCountQuery = ({account_sid, days, start, end}) => {
|
|
98
|
+
let sql = `SELECT COUNT(calls_in_progress) from call_counts WHERE account_sid = '${account_sid}' `;
|
|
99
|
+
if (days) sql += `AND time > now() - ${days}d `;
|
|
100
|
+
else {
|
|
101
|
+
if (start) sql += `AND time >= '${start}' `;
|
|
102
|
+
if (end) sql += `AND time <= '${end}' `;
|
|
103
|
+
}
|
|
104
|
+
//console.log(sql);
|
|
105
|
+
return sql;
|
|
106
|
+
};
|
|
73
107
|
|
|
74
108
|
const createCdrQuery = ({account_sid, page, page_size, trunk, direction, answered, days, start, end}) => {
|
|
75
|
-
let sql = `SELECT * from cdrs WHERE account_sid = '${account_sid}'
|
|
109
|
+
let sql = `SELECT * from cdrs WHERE account_sid = '${account_sid}'`;
|
|
76
110
|
if (trunk) sql += `AND trunk = '${trunk}' `;
|
|
77
111
|
if (direction) sql += `AND direction = '${direction}' `;
|
|
78
112
|
if (['true', 'false'].includes(answered)) sql += `AND answered = '${answered}' `;
|
|
@@ -101,8 +135,9 @@ const createCdrCountQuery = ({account_sid, trunk, direction, answered, days, sta
|
|
|
101
135
|
return sql;
|
|
102
136
|
};
|
|
103
137
|
|
|
104
|
-
const createAlertsQuery = ({account_sid, alert_type, page, page_size, days, start, end}) => {
|
|
138
|
+
const createAlertsQuery = ({account_sid, target_sid, alert_type, page, page_size, days, start, end}) => {
|
|
105
139
|
let sql = `SELECT * FROM alerts WHERE account_sid = '${account_sid}' `;
|
|
140
|
+
if (target_sid) sql += `AND target_sid = '${target_sid}' `;
|
|
106
141
|
if (alert_type) sql += `AND alert_type = '${alert_type}' `;
|
|
107
142
|
if (days) sql += `AND time > now() - ${days}d `;
|
|
108
143
|
else {
|
|
@@ -116,8 +151,9 @@ const createAlertsQuery = ({account_sid, alert_type, page, page_size, days, star
|
|
|
116
151
|
return sql;
|
|
117
152
|
};
|
|
118
153
|
|
|
119
|
-
const createAlertsCountQuery = ({account_sid, alert_type, days, start, end}) => {
|
|
154
|
+
const createAlertsCountQuery = ({account_sid, target_sid, alert_type, days, start, end}) => {
|
|
120
155
|
let sql = `SELECT COUNT(message) FROM alerts WHERE account_sid = '${account_sid}' `;
|
|
156
|
+
if (target_sid) sql += `AND target_sid = '${target_sid}' `;
|
|
121
157
|
if (alert_type) sql += `AND alert_type = '${alert_type}' `;
|
|
122
158
|
if (days) sql += `AND time > now() - ${days}d `;
|
|
123
159
|
else {
|
|
@@ -136,6 +172,57 @@ const initDatabase = async(client, dbName) => {
|
|
|
136
172
|
client.locals.initialized = true;
|
|
137
173
|
};
|
|
138
174
|
|
|
175
|
+
const writeCallCount = async(client, count) => {
|
|
176
|
+
if (!client.locals.initialized) await initDatabase(client, 'call_counts');
|
|
177
|
+
const {account_sid, ...fields} = count;
|
|
178
|
+
const data = {
|
|
179
|
+
measurement: 'call_counts',
|
|
180
|
+
fields,
|
|
181
|
+
tags: {
|
|
182
|
+
account_sid
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
client.locals.data = [...client.locals.data, ...[data]];
|
|
186
|
+
if (client.locals.data.length >= client.locals.commitSize) {
|
|
187
|
+
await writeData(client);
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const queryCallCounts = async(client, opts) => {
|
|
193
|
+
if (!client.locals.initialized) await initDatabase(client, 'call_counts');
|
|
194
|
+
const response = {
|
|
195
|
+
total: 0,
|
|
196
|
+
page_size: opts.page_size,
|
|
197
|
+
page: opts.page,
|
|
198
|
+
data: []
|
|
199
|
+
};
|
|
200
|
+
const sqlTotal = createCallCountsCountQuery(opts);
|
|
201
|
+
const obj = await client.queryRaw(sqlTotal);
|
|
202
|
+
//console.log(`sqlTotal: ${sqlTotal}, results: ${JSON.stringify(obj)}`);
|
|
203
|
+
if (!obj.results || !obj.results[0].series) return response;
|
|
204
|
+
response.total = obj.results[0].series[0].values[0][1];
|
|
205
|
+
|
|
206
|
+
const sql = createCallCountsQuery(opts);
|
|
207
|
+
const res = await client.queryRaw(sql);
|
|
208
|
+
//console.log(`sql: ${sqlTotal}, results: ${JSON.stringify(res)}`);
|
|
209
|
+
if (res.results[0].series && res.results[0].series.length) {
|
|
210
|
+
const {columns, values} = res.results[0].series[0];
|
|
211
|
+
const data = values.map((v) => {
|
|
212
|
+
const obj = {};
|
|
213
|
+
v.forEach((val, idx) => {
|
|
214
|
+
v.forEach((val, idx) => {
|
|
215
|
+
const key = columns[idx];
|
|
216
|
+
obj[key] = val;
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
return obj;
|
|
220
|
+
});
|
|
221
|
+
response.data = data;
|
|
222
|
+
}
|
|
223
|
+
return response;
|
|
224
|
+
};
|
|
225
|
+
|
|
139
226
|
const writeCdrs = async(client, cdrs) => {
|
|
140
227
|
if (!client.locals.initialized) await initDatabase(client, 'cdrs');
|
|
141
228
|
cdrs = (Array.isArray(cdrs) ? cdrs : [cdrs])
|
|
@@ -200,7 +287,7 @@ const writeAlerts = async(client, alerts) => {
|
|
|
200
287
|
if (!client.locals.initialized) await initDatabase(client, 'alerts');
|
|
201
288
|
alerts = (Array.isArray(alerts) ? alerts : [alerts])
|
|
202
289
|
.map((alert) => {
|
|
203
|
-
const {alert_type, account_sid, url, status, vendor, count, detail, timestamp} = alert;
|
|
290
|
+
const {alert_type, account_sid, target_sid, url, status, vendor, count, detail, timestamp} = alert;
|
|
204
291
|
let message = alert.message;
|
|
205
292
|
if (!message) {
|
|
206
293
|
switch (alert_type) {
|
|
@@ -216,6 +303,9 @@ const writeAlerts = async(client, alerts) => {
|
|
|
216
303
|
case AlertType.WEBHOOK_URL_NOTFOUND:
|
|
217
304
|
message = `webhook url not found: ${url}`;
|
|
218
305
|
break;
|
|
306
|
+
case AlertType.INVALID_APP_PAYLOAD:
|
|
307
|
+
message = `${url} return invalid app payload`;
|
|
308
|
+
break;
|
|
219
309
|
case AlertType.TTS_NOT_PROVISIONED:
|
|
220
310
|
message = `text to speech credentials for ${vendor} have not been provisioned`;
|
|
221
311
|
break;
|
|
@@ -245,7 +335,9 @@ const writeAlerts = async(client, alerts) => {
|
|
|
245
335
|
break;
|
|
246
336
|
}
|
|
247
337
|
}
|
|
248
|
-
|
|
338
|
+
let fields = { message };
|
|
339
|
+
if (target_sid) fields = Object.assign(fields, {target_sid});
|
|
340
|
+
const obj = {measurement: 'alerts', fields: fields, tags: { alert_type, account_sid }};
|
|
249
341
|
if (timestamp) obj.timestamp = timestamp;
|
|
250
342
|
if (detail) obj.fields.detail = detail;
|
|
251
343
|
return obj;
|
|
@@ -295,6 +387,7 @@ module.exports = (logger, opts) => {
|
|
|
295
387
|
|
|
296
388
|
const cdrClient = new Influx.InfluxDB({database: 'cdrs', schemas: schemas.cdr, ...opts});
|
|
297
389
|
const alertClient = new Influx.InfluxDB({database: 'alerts', schemas: schemas.alerts, ...opts});
|
|
390
|
+
const callCountClient = new Influx.InfluxDB({database: 'call_counts', schemas: schemas.call_counts, ...opts});
|
|
298
391
|
|
|
299
392
|
cdrClient.locals = {
|
|
300
393
|
db: 'cdrs',
|
|
@@ -312,13 +405,24 @@ module.exports = (logger, opts) => {
|
|
|
312
405
|
commitInterval: opts.commitInterval || 10,
|
|
313
406
|
data: []
|
|
314
407
|
};
|
|
408
|
+
callCountClient.locals = {
|
|
409
|
+
db: 'call_counts',
|
|
410
|
+
initialized: false,
|
|
411
|
+
writing: false,
|
|
412
|
+
commitSize: opts.commitSize || 1,
|
|
413
|
+
commitInterval: opts.commitInterval || 10,
|
|
414
|
+
data: []
|
|
415
|
+
};
|
|
315
416
|
|
|
316
417
|
if (opts.commitSize > 1 && opts.commitInterval && opts.commitInterval > 2) {
|
|
418
|
+
setInterval(writeData.bind(null, callCountClient), opts.commitInterval * 1000);
|
|
317
419
|
setInterval(writeData.bind(null, cdrClient), opts.commitInterval * 1000);
|
|
318
420
|
setInterval(writeData.bind(null, alertClient), opts.commitInterval * 1000);
|
|
319
421
|
}
|
|
320
422
|
|
|
321
423
|
return {
|
|
424
|
+
writeCallCount: writeCallCount.bind(null, callCountClient),
|
|
425
|
+
queryCallCounts: queryCallCounts.bind(null, callCountClient),
|
|
322
426
|
writeCdrs: writeCdrs.bind(null, cdrClient),
|
|
323
427
|
queryCdrs: queryCdrs.bind(null, cdrClient),
|
|
324
428
|
writeAlerts: writeAlerts.bind(null, alertClient),
|
package/package.json
CHANGED
package/test/unit-tests.js
CHANGED
|
@@ -3,6 +3,8 @@ const Influx = require('influx');
|
|
|
3
3
|
const consoleLogger = {error: console.error, info: console.log, debug: console.log};
|
|
4
4
|
|
|
5
5
|
const {
|
|
6
|
+
writeCallCount,
|
|
7
|
+
queryCallCounts,
|
|
6
8
|
writeCdrs,
|
|
7
9
|
queryCdrs,
|
|
8
10
|
writeAlerts,
|
|
@@ -10,7 +12,7 @@ const {
|
|
|
10
12
|
AlertType
|
|
11
13
|
} = require('..')(consoleLogger, '127.0.0.1', {commitSize: 1});
|
|
12
14
|
|
|
13
|
-
test('write
|
|
15
|
+
test('write timeseries data', async(t) => {
|
|
14
16
|
let result = await writeCdrs([{
|
|
15
17
|
from: 'me',
|
|
16
18
|
to: 'you',
|
|
@@ -71,6 +73,12 @@ test('write cdr data', async(t) => {
|
|
|
71
73
|
account_sid: 'yyyy',
|
|
72
74
|
url: 'http://foo.bar'
|
|
73
75
|
},
|
|
76
|
+
{
|
|
77
|
+
alert_type: AlertType.INVALID_APP_PAYLOAD,
|
|
78
|
+
account_sid: 'yyyy',
|
|
79
|
+
target_sid: 'zzzz',
|
|
80
|
+
message: 'invalid app payload'
|
|
81
|
+
},
|
|
74
82
|
{
|
|
75
83
|
alert_type: AlertType.TTS_NOT_PROVISIONED,
|
|
76
84
|
account_sid: 'yyyy',
|
|
@@ -115,6 +123,27 @@ test('write cdr data', async(t) => {
|
|
|
115
123
|
|
|
116
124
|
result = await queryAlerts({account_sid: 'yyyy', page: 1, page_size: 25, days: 7});
|
|
117
125
|
//console.log(JSON.stringify(result));
|
|
118
|
-
t.ok(result.data.length ===
|
|
126
|
+
t.ok(result.data.length === 12, 'queried alerts');
|
|
127
|
+
t.ok(result.data[0].target_sid === null)
|
|
128
|
+
|
|
129
|
+
result = await queryAlerts({account_sid: 'yyyy', target_sid: 'zzzz', page: 1, page_size: 25, days: 7});
|
|
130
|
+
t.ok(result.data.length === 1, 'queried alerts by target_sid');
|
|
131
|
+
t.ok(result.data[0].target_sid === 'zzzz')
|
|
132
|
+
|
|
133
|
+
result = await writeCallCount(
|
|
134
|
+
{
|
|
135
|
+
calls_in_progress: 49,
|
|
136
|
+
account_sid: 'yyyy'
|
|
137
|
+
});
|
|
138
|
+
result = await writeCallCount(
|
|
139
|
+
{
|
|
140
|
+
calls_in_progress: 50,
|
|
141
|
+
account_sid: 'yyyy'
|
|
142
|
+
});
|
|
143
|
+
t.pass('wrote call counts');
|
|
144
|
+
|
|
145
|
+
result = await queryCallCounts({account_sid: 'yyyy', page: 1, page_size: 25, days: 7});
|
|
146
|
+
//console.log(JSON.stringify(result));
|
|
147
|
+
t.ok(result.data.length === 2, 'queried call counts');
|
|
119
148
|
|
|
120
149
|
});
|