4 JavaScript 预处理
概述
本节提供 JavaScript 预处理的详细信息。
JavaScript 预处理
JavaScript 预处理是通过调用具有单个参数“值”和用户提供的函数体的 JavaScript 函数来完成的。 预处理步骤的结果是从这个函数返回的值,例如,要执行华氏到摄氏度的转换,用户必须输入:
return (value - 32) * 5 / 9
在 JavaScript 预处理参数中,将被服务器包装成一个 JavaScript 函数:
function (value)
{
return (value - 32) * 5 / 9
}
输入参数“值”始终作为字符串传递。 返回值通过 ToString() 方法自动强制转换为字符串(如果失败,则错误作为字符串值返回),但有一些例外:
- 返回未定义的值将导致错误
- 返回空值将导致输入值被丢弃,很像“Custom on fail”操作中的“丢弃值”预处理。
可以通过抛出值/对象(通常是字符串或错误对象)来返回错误。
例子:
if (value == 0)
throw "Zero input value"
return 1/value
每个脚本都有 10 秒的执行超时(根据脚本的不同,触发超时可能需要更长的时间); 超过它会返回错误。 强制执行 64 兆字节的堆限制。
JavaScript 预处理步骤字节码被缓存并在下次应用该步骤时重用。 对监控项预处理步骤的任何更改都将导致缓存的脚本被重置并稍后重新编译。
连续运行时失败(连续 3 次)将导致引擎重新初始化,以减少一个脚本破坏下一个脚本的执行环境的可能性(此操作使用 DebugLevel 4 及更高级别记录)。
JavaScript 预处理是用 Duktape 实现的 (https://duktape.org/) JavaScript 引擎。
在脚本中使用宏
可以在 JavaScript 代码中使用用户宏。 如果脚本包含用户宏,则这些宏在执行特定预处理步骤之前由服务器/代理解析。 注意,在前端测试预处理步骤时,宏值不会被拉取,需要手动输入。
将宏替换为其值时将忽略上下文。宏值按原样插入代码中,在将值放入 JavaScript 代码之前无法添加额外的转义。请注意,这可能在某些情况下会导致 JavaScript 错误 。
在下面的示例中,如果接收到的值超过 {$THRESHOLD} 宏值,则将返回阈值(如果存在):
var threshold = '{$THRESHOLD}';
return (!isNaN(threshold) && value > threshold) ? threshold : value;
Examples
The following examples illustrate how you can use JavaScript preprocessing. Each example contains a brief description, a function body for JavaScript preprocessing parameters, and the preprocessing step result (value accepted by the function → value returned by the function).
Example 1: Convert number (scientific notation to integer)
Convert a number from scientific notation to an integer.
return (Number(value))
Result: 2.62128e+07 → 26212800
Example 2: Convert number (binary to decimal)
Convert a binary number to a decimal number.
return(parseInt(value,2))
Result: 11010010 → 210
Example 3: Round a number
Round a number to 2 digits.
return(Math.round(value* 100) / 100)
Result: 18.2345 → 18.23
Example 4: Count letters in a string
Count the number of letters in a string.
return (value.length)
Result: “zabbix” → 6
Example 5: Get time remaining
Get the remaining time (in seconds) until the expiration date of a certificate.
var split = value.split(' '),
MONTHS_LIST = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
month_index = ('0' + (MONTHS_LIST.indexOf(split[0]) + 1)).slice(-2),
ISOdate = split[3] + '-' + month_index + '-' + split[1] + 'T' + split[2],
now = Date.now();
return parseInt((Date.parse(ISOdate) - now) / 1000);
Result: Feb 12 12:33:56 2022 GMT → 44380233
Example 6: Modify JSON (remove properties)
Modify a JSON data structure by removing any properties with the key "data_size"
or "index_size"
.
var obj=JSON.parse(value);
for (i = 0; i < Object.keys(obj).length; i++) {
delete obj[i]["data_size"];
delete obj[i]["index_size"];
}
return JSON.stringify(obj)
Value accepted by the function:
[
{
"table_name":"history",
"data_size":"326.05",
"index_size":"174.34"
},
{
"table_name":"history_log",
"data_size":"6.02",
"index_size":"3.45"
}
]
Value returned by the function:
[
{
"table_name":"history"
},
{
"table_name":"history_log"
}
]
Example 7: Convert Apache status to JSON
Convert the value received from a web.page.get Zabbix agent item (e.g., web.page.get[http://127.0.0.1:80/server-status?auto\]) to a JSON object.
// Convert Apache status to JSON
// Split the value into substrings and put these substrings into an array
var lines = value.split('\n');
// Create an empty object "output"
var output = {};
// Create an object "workers" with predefined properties
var workers = {
'_': 0, 'S': 0, 'R': 0, 'W': 0,
'K': 0, 'D': 0, 'C': 0, 'L': 0,
'G': 0, 'I': 0, '.': 0
};
// Add the substrings from the "lines" array to the "output" object as properties (key-value pairs)
for (var i = 0; i < lines.length; i++) {
var line = lines[i].match(/([A-z0-9 ]+): (.*)/);
if (line !== null) {
output[line[1]] = isNaN(line[2]) ? line[2] : Number(line[2]);
}
}
// Multiversion metrics
output.ServerUptimeSeconds = output.ServerUptimeSeconds || output.Uptime;
output.ServerVersion = output.ServerVersion || output.Server;
// Parse "Scoreboard" property to get the worker count
if (typeof output.Scoreboard === 'string') {
for (var i = 0; i < output.Scoreboard.length; i++) {
var char = output.Scoreboard[i];
workers[char]++;
}
}
// Add worker data to the "output" object
output.Workers = {
waiting: workers['_'], starting: workers['S'], reading: workers['R'],
sending: workers['W'], keepalive: workers['K'], dnslookup: workers['D'],
closing: workers['C'], logging: workers['L'], finishing: workers['G'],
cleanup: workers['I'], slot: workers['.']
};
// Return JSON string
return JSON.stringify(output);
Value accepted by the function:
HTTP/1.1 200 OK
Date: Mon, 27 Mar 2023 11:08:39 GMT
Server: Apache/2.4.52 (Ubuntu)
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 405
Content-Type: text/plain; charset=ISO-8859-1
127.0.0.1
ServerVersion: Apache/2.4.52 (Ubuntu)
ServerMPM: prefork
Server Built: 2023-03-08T17:32:01
CurrentTime: Monday, 27-Mar-2023 14:08:39 EEST
RestartTime: Monday, 27-Mar-2023 12:19:59 EEST
ParentServerConfigGeneration: 1
ParentServerMPMGeneration: 0
ServerUptimeSeconds: 6520
ServerUptime: 1 hour 48 minutes 40 seconds
Load1: 0.56
Load5: 0.33
Load15: 0.28
Total Accesses: 2476
Total kBytes: 8370
Total Duration: 52718
CPUUser: 8.16
CPUSystem: 3.44
CPUChildrenUser: 0
CPUChildrenSystem: 0
CPULoad: .177914
Uptime: 6520
ReqPerSec: .379755
BytesPerSec: 3461.58
BytesPerReq: 3461.58
DurationPerReq: 21.2916
BusyWorkers: 2
IdleWorkers: 6
Scoreboard: ____KW__..............................................................................................................................................
Value returned by the function:
{
"Date": "Mon, 27 Mar 2023 11:08:39 GMT",
"Server": "Apache/2.4.52 (Ubuntu)",
"Vary": "Accept-Encoding",
"Encoding": "gzip",
"Length": 405,
"Type": "text/plain; charset=ISO-8859-1",
"ServerVersion": "Apache/2.4.52 (Ubuntu)",
"ServerMPM": "prefork",
"Server Built": "2023-03-08T17:32:01",
"CurrentTime": "Monday, 27-Mar-2023 14:08:39 EEST",
"RestartTime": "Monday, 27-Mar-2023 12:19:59 EEST",
"ParentServerConfigGeneration": 1,
"ParentServerMPMGeneration": 0,
"ServerUptimeSeconds": 6520,
"ServerUptime": "1 hour 48 minutes 40 seconds",
"Load1": 0.56,
"Load5": 0.33,
"Load15": 0.28,
"Total Accesses": 2476,
"Total kBytes": 8370,
"Total Duration": 52718,
"CPUUser": 8.16,
"CPUSystem": 3.44,
"CPUChildrenUser": 0,
"CPUChildrenSystem": 0,
"CPULoad": 0.177914,
"Uptime": 6520,
"ReqPerSec": 0.379755,
"BytesPerSec": 1314.55,
"BytesPerReq": 3461.58,
"DurationPerReq": 21.2916,
"BusyWorkers": 2,
"IdleWorkers": 6,
"Scoreboard": "____KW__..............................................................................................................................................",
"Workers": {
"waiting": 6,
"starting": 0,
"reading": 0,
"sending": 1,
"keepalive": 1,
"dnslookup": 0,
"closing": 0,
"logging": 0,
"finishing": 0,
"cleanup": 0,
"slot": 142
}
}