realm-object-server
Version:
73 lines • 2.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const dgram = require("dgram");
const events_1 = require("events");
const URI = require("urijs");
class StatsdReceiver extends events_1.EventEmitter {
constructor(config) {
super();
this.logger = config.logger;
}
start() {
return new Promise((resolve, reject) => {
const socket = dgram.createSocket("udp4", (msg, rinfo) => {
this.handleMessage(msg, rinfo);
});
socket.on("error", err => {
this.socket.close();
this.logger.error(`Datagram socket error: ${err.message}`);
return reject(err);
});
socket.bind(0, "127.0.0.1", () => resolve(socket));
});
}
handleMessage(msg, rinfo) {
const lines = msg.toString("ascii").split("\n");
for (const line of lines) {
const metric = this.parseMetricGracefully(line);
if (metric) {
this.emit("metric", metric);
}
}
}
parseMetricGracefully(line) {
if (line.length === 0) {
return null;
}
else {
try {
return this.parseMetric(line);
}
catch (err) {
this.logger.warn(`Failed processing a metric: ${err.message}`);
return null;
}
}
}
parseMetric(line) {
const [namespace, ...statParts] = line.split(":");
if (namespace.length > 0) {
const { name, labels } = this.parseNamespace(namespace);
const stats = statParts.map(statPart => this.parseStat(statPart));
return { name, labels, stats };
}
else {
throw new Error("Failed to determine the namespace");
}
}
parseNamespace(namespace) {
const [name, ...labelParts] = namespace.split(",");
const labels = {};
for (const labelPart of labelParts) {
const [key, value] = labelPart.split("=", 2);
labels[key] = URI.decode(value);
}
return { name, labels };
}
parseStat(stat) {
const [value, typeString] = stat.split("|", 2);
return { value, type: typeString };
}
}
exports.StatsdReceiver = StatsdReceiver;
//# sourceMappingURL=StatsdReceiver.js.map