zabbix-utils
Version:
TypeScript port of zabbix-utils - Python library for working with Zabbix API, Sender, and Getter protocols
311 lines • 9.82 kB
JavaScript
"use strict";
// zabbix_utils
//
// Copyright (C) 2001-2023 Zabbix SIA (Original Python library)
// Copyright (C) 2024-2025 Han Yong Lim <hanyong.lim@gmail.com> (TypeScript adaptation)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify,
// merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgentResponse = exports.Cluster = exports.Node = exports.ItemValue = exports.TrapperResponse = exports.APIVersion = void 0;
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
const exceptions_1 = require("./exceptions");
const version_1 = require("./version");
class APIVersion {
constructor(apiver) {
this.__raw = apiver;
const [first, second, third] = this.__parseVersion(this.__raw);
this.__first = first;
this.__second = second;
this.__third = third;
}
/**
* Get a symbol from the raw version string by index
* For compatibility with using Zabbix version as a string
*/
[Symbol.iterator]() {
return this.__raw[Symbol.iterator]();
}
charAt(index) {
return this.__raw.charAt(index);
}
/**
* Check if the current version is LTS.
*
* @returns true if the current version is LTS.
*/
isLts() {
return this.__second === 0;
}
/**
* Get major version number.
*
* @returns A major version number.
*/
get major() {
return parseFloat(`${this.__first}.${this.__second}`);
}
/**
* Get minor version number.
*
* @returns A minor version number.
*/
get minor() {
return this.__third;
}
__parseVersion(ver) {
// Parse the version string into a list of integers.
const match = ver.match(/^(\d+)\.(\d+)\.(\d+)$/);
if (!match) {
throw new Error(`Unable to parse version of Zabbix API: ${ver}. ` +
`Default '${version_1.__max_supported__}.0' format is expected.`);
}
return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])];
}
toString() {
return this.__raw;
}
valueOf() {
return this.__raw;
}
equals(other) {
if (typeof other === 'number') {
return this.major === other;
}
if (typeof other === 'string') {
const [first, second, third] = this.__parseVersion(other);
return this.__first === first && this.__second === second && this.__third === third;
}
throw new TypeError(`'equals' not supported between instances of '${this.constructor.name}' and ` +
`'${typeof other}', only 'number' or 'string' is expected`);
}
greaterThan(other) {
if (typeof other === 'number') {
return this.major > other;
}
if (typeof other === 'string') {
const [first, second, third] = this.__parseVersion(other);
return [this.__first, this.__second, this.__third] > [first, second, third];
}
throw new TypeError(`'>' not supported between instances of '${this.constructor.name}' and ` +
`'${typeof other}', only 'number' or 'string' is expected`);
}
lessThan(other) {
if (typeof other === 'number') {
return this.major < other;
}
if (typeof other === 'string') {
const [first, second, third] = this.__parseVersion(other);
return [this.__first, this.__second, this.__third] < [first, second, third];
}
throw new TypeError(`'<' not supported between instances of '${this.constructor.name}' and ` +
`'${typeof other}', only 'number' or 'string' is expected`);
}
notEquals(other) {
return !this.equals(other);
}
greaterThanOrEqual(other) {
return !this.lessThan(other);
}
lessThanOrEqual(other) {
return !this.greaterThan(other);
}
}
exports.APIVersion = APIVersion;
class TrapperResponse {
constructor(chunk = 1) {
/**
* Contains response from Zabbix server/proxy.
*
* @param chunk - Current chunk number. Defaults to 1.
*/
this.__processed = 0;
this.__failed = 0;
this.__total = 0;
this.__time = 0;
this.details = null;
this.__chunk = chunk;
}
toString() {
const result = {};
for (const [key, value] of Object.entries(this)) {
if (key === 'details') {
continue;
}
const cleanKey = key.replace(/^_+TrapperResponse_+/, '').replace(/^_+/, '');
result[cleanKey] = typeof value === 'number' ? value.toString() : value;
}
return JSON.stringify(result);
}
/**
* Parse response from Zabbix.
*
* @param response - Raw response from Zabbix.
* @throws ProcessingError if unexpected response received
*/
parse(response) {
const fields = {
"processed": ['[Pp]rocessed', '\\d+'],
"failed": ['[Ff]ailed', '\\d+'],
"total": ['[Tt]otal', '\\d+'],
"time": ['[Ss]econds spent', '\\d+\\.\\d+']
};
const patternParts = Object.entries(fields).map(([k, [r0, r1]]) => `${r0}:\\s+?(?<${k}>${r1})`);
const pattern = new RegExp(patternParts.join(';\\s+?'));
const info = response.info;
if (!info) {
throw new exceptions_1.ProcessingError(`Received unexpected response: ${JSON.stringify(response)}`);
}
const match = pattern.exec(info);
if (!match || !match.groups) {
throw new exceptions_1.ProcessingError(`Failed to parse response: ${info}`);
}
return match.groups;
}
/**
* Add and merge response data from Zabbix.
*
* @param response - Raw response from Zabbix.
* @param chunk - Chunk number. Defaults to null.
*/
add(response, chunk) {
const resp = this.parse(response);
this.__processed += parseInt(resp.processed);
this.__failed += parseInt(resp.failed);
this.__total += parseInt(resp.total);
this.__time += parseFloat(resp.time);
if (chunk !== undefined) {
this.__chunk = chunk;
}
this.details = response;
}
/**
* Get processed count
*/
get processed() {
return this.__processed;
}
/**
* Get failed count
*/
get failed() {
return this.__failed;
}
/**
* Get total count
*/
get total() {
return this.__total;
}
/**
* Get time spent
*/
get time() {
return this.__time;
}
/**
* Get chunk number
*/
get chunk() {
return this.__chunk;
}
}
exports.TrapperResponse = TrapperResponse;
class ItemValue {
constructor(host, key, value, clock, ns) {
this.host = host;
this.key = key;
this.value = value;
this.clock = clock || Math.floor(Date.now() / 1000);
this.ns = ns;
}
toString() {
return JSON.stringify(this.toJson());
}
valueOf() {
return this.toString();
}
toJson() {
const result = {
host: this.host,
key: this.key,
value: this.value,
clock: this.clock
};
if (this.ns !== undefined) {
result.ns = this.ns;
}
return result;
}
}
exports.ItemValue = ItemValue;
class Node {
constructor(addr, port) {
this.addr = addr;
this.port = typeof port === 'string' ? parseInt(port) : port;
}
toString() {
return `${this.addr}:${this.port}`;
}
valueOf() {
return this.toString();
}
}
exports.Node = Node;
class Cluster {
constructor(addr) {
this.nodes = this.__parseHaNode(addr);
}
__parseHaNode(nodeList) {
const nodes = [];
for (const node of nodeList) {
const [addr, port] = node.split(':');
nodes.push(new Node(addr, port || '10051'));
}
return nodes;
}
toString() {
return this.nodes.map(node => node.toString()).join(',');
}
valueOf() {
return this.toString();
}
}
exports.Cluster = Cluster;
class AgentResponse {
constructor(response) {
this.raw = response;
if (response.startsWith('ZBXD')) {
// Handle binary protocol response
this.value = response.slice(13); // Skip header
}
else if (response.startsWith('ZBX_NOTSUPPORTED')) {
this.error = response.slice(17); // Remove "ZBX_NOTSUPPORTED\0"
}
else {
this.value = response;
}
}
toString() {
return this.raw;
}
valueOf() {
return this.toString();
}
}
exports.AgentResponse = AgentResponse;
//# sourceMappingURL=types.js.map