Implement metrics
This commit is contained in:
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"sqltools.connections": [
|
||||
{
|
||||
"previewLimit": 50,
|
||||
"driver": "SQLite",
|
||||
"name": "1",
|
||||
"database": "E:\\tmp\\output.db"
|
||||
}
|
||||
]
|
||||
}
|
22
client.js
22
client.js
@@ -5,6 +5,7 @@ const NanoTimer = require("nanotimer");
|
||||
const { createBaseLogger, createSessionLogger } = require("./logger");
|
||||
const { verifyDefaults, verifyExists } = require("./utils");
|
||||
const { clientOptions } = require("./cliOptions");
|
||||
const { MetricManager } = require("./metrics/metricManager");
|
||||
|
||||
const logger = createBaseLogger();
|
||||
const options = commandLineArgs(clientOptions);
|
||||
@@ -78,6 +79,17 @@ function startInterval(session, sessionLogger) {
|
||||
);
|
||||
}
|
||||
|
||||
const metricManager = new MetricManager();
|
||||
// async function main() {
|
||||
// const test1 = metricManager.AddMetrics("test");
|
||||
// for (let i = 0; i < 1e5; i++) {
|
||||
// test1.AddEvent();
|
||||
// test1.UpdateBar();
|
||||
// await setTimeout(() => {}, 200);
|
||||
// }
|
||||
// }
|
||||
// main();
|
||||
|
||||
for (let i = 0; i < options.sessions; i++) {
|
||||
const sessionLogger = createSessionLogger(i);
|
||||
sessionLogger.info(`Connecting to ${options.host}:${options.port}...`);
|
||||
@@ -101,12 +113,20 @@ for (let i = 0; i < options.sessions; i++) {
|
||||
sessionLogger.info(
|
||||
`Successfully bound, sending ${options.messagecount} messages '${options.source}'->'${options.destination}' ('${options.message}')`
|
||||
);
|
||||
const rxMetrics = metricManager.AddMetrics(`Session-${i}-RX`);
|
||||
const txMetrics = metricManager.AddMetrics(`Session-${i}-TX`);
|
||||
startInterval(session, sessionLogger);
|
||||
// TODO: Add error message for invalid systemid and password
|
||||
|
||||
session.on("deliver_sm", function (pdu) {
|
||||
sessionLogger.info("Got deliver_sm, replying...");
|
||||
rxMetrics.AddEvent();
|
||||
// sessionLogger.info("Got deliver_sm, replying...");
|
||||
setTimeout(() => {
|
||||
session.send(pdu.response());
|
||||
txMetrics.AddEvent();
|
||||
}, 2000);
|
||||
// session.send(pdu.response());
|
||||
// txMetrics.AddEvent();
|
||||
});
|
||||
session.on("enquire_link", function (pdu) {
|
||||
session.send(pdu.response());
|
||||
|
30
metrics/circularBuffer.js
Normal file
30
metrics/circularBuffer.js
Normal file
@@ -0,0 +1,30 @@
|
||||
class CircularBuffer {
|
||||
constructor(size) {
|
||||
this.buffer = new Array(size);
|
||||
this.size = size;
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
}
|
||||
|
||||
push(item) {
|
||||
this.buffer[this.head] = item;
|
||||
this.head = (this.head + 1) % this.size;
|
||||
if (this.head === this.tail) {
|
||||
this.tail = (this.tail + 1) % this.size;
|
||||
}
|
||||
}
|
||||
|
||||
toArray() {
|
||||
const result = [];
|
||||
let current = this.tail;
|
||||
for (let i = 0; i < this.size; i++) {
|
||||
if (this.buffer[current] !== undefined) {
|
||||
result.push(this.buffer[current]);
|
||||
}
|
||||
current = (current + 1) % this.size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { CircularBuffer };
|
24
metrics/metricManager.js
Normal file
24
metrics/metricManager.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const cliProgress = require("cli-progress");
|
||||
const { Metric } = require("./metrics");
|
||||
|
||||
class MetricManager {
|
||||
constructor() {
|
||||
this.metricBufferSize = 1000;
|
||||
this.multibar = new cliProgress.MultiBar(
|
||||
{
|
||||
clearOnComplete: false,
|
||||
barCompleteChar: "\u2588",
|
||||
barIncompleteChar: "\u2591",
|
||||
format: " {bar} | {name} | {value}/{total}",
|
||||
},
|
||||
cliProgress.Presets.shades_grey
|
||||
);
|
||||
}
|
||||
|
||||
AddMetrics(name) {
|
||||
const metric = new Metric(name, this.multibar, this.metricBufferSize);
|
||||
return metric;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { MetricManager };
|
39
metrics/metrics.js
Normal file
39
metrics/metrics.js
Normal file
@@ -0,0 +1,39 @@
|
||||
const { CircularBuffer } = require("./circularBuffer");
|
||||
|
||||
class Metric {
|
||||
constructor(barName, multibar, bufferSize) {
|
||||
this.multibar = multibar;
|
||||
this.pbar = multibar.create(0, 0);
|
||||
this.pbar.update(0, { name: barName });
|
||||
this.buffer = new CircularBuffer(bufferSize);
|
||||
this.maxRate = 0;
|
||||
setInterval(this.UpdateBar.bind(this), 100);
|
||||
}
|
||||
|
||||
AddEvent() {
|
||||
const timestamp = Date.now();
|
||||
this.buffer.push({ timestamp, count: 1 });
|
||||
}
|
||||
|
||||
GetRate() {
|
||||
const entries = this.buffer.toArray();
|
||||
const currentTime = Date.now();
|
||||
|
||||
const interval = entries.length > 1 ? currentTime - entries[0].timestamp : 1;
|
||||
|
||||
const totalRX = entries.reduce((sum, entry) => sum + entry.count, 0);
|
||||
return Math.round((totalRX / interval) * 100000) / 100;
|
||||
}
|
||||
|
||||
UpdateBar() {
|
||||
const eps = this.GetRate();
|
||||
if (eps > this.maxRate) {
|
||||
this.pbar.total = eps;
|
||||
this.maxRate = eps;
|
||||
}
|
||||
this.pbar.update(eps);
|
||||
this.multibar.update();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Metric };
|
@@ -14,6 +14,7 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cli-progress": "^3.12.0",
|
||||
"command-line-args": "^5.2.1",
|
||||
"command-line-usage": "^7.0.1",
|
||||
"nanotimer": "^0.3.15",
|
||||
|
30
pnpm-lock.yaml
generated
30
pnpm-lock.yaml
generated
@@ -5,6 +5,9 @@ settings:
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
cli-progress:
|
||||
specifier: ^3.12.0
|
||||
version: 3.12.0
|
||||
command-line-args:
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1
|
||||
@@ -166,7 +169,6 @@ packages:
|
||||
/ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/ansi-styles@4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
@@ -222,6 +224,13 @@ packages:
|
||||
ansi-styles: 4.3.0
|
||||
supports-color: 7.2.0
|
||||
|
||||
/cli-progress@3.12.0:
|
||||
resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
dev: false
|
||||
|
||||
/color-convert@1.9.3:
|
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||
dependencies:
|
||||
@@ -318,6 +327,10 @@ packages:
|
||||
esutils: 2.0.3
|
||||
dev: true
|
||||
|
||||
/emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
dev: false
|
||||
|
||||
/enabled@2.0.0:
|
||||
resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==}
|
||||
dev: false
|
||||
@@ -569,6 +582,11 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/is-fullwidth-code-point@3.0.0:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/is-glob@4.0.3:
|
||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -839,6 +857,15 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
dev: false
|
||||
|
||||
/string_decoder@1.3.0:
|
||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
||||
dependencies:
|
||||
@@ -850,7 +877,6 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
dev: true
|
||||
|
||||
/strip-json-comments@3.1.1:
|
||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||
|
Reference in New Issue
Block a user