5 JavaScript 预处理

概述

本节提供 JavaScript 预处理的详细信息。

JavaScript预处理

JavaScript预处理通过调用带有单个参数’value’和用户提供的函数体的JavaScript函数来完成。预处理步骤的结果是该函数返回的值。例如,要执行华氏温度到摄氏温度的转换,请输入以下内容:

  1. return (value - 32) * 5 / 9

服务器将这些JavaScript预处理参数封装成JavaScript函数:

  1. function (value)
  2. {
  3. return (value - 32) * 5 / 9;
  4. }

输入参数’value’始终作为字符串传递。返回值通过ToString()方法自动转换为字符串(如果失败,则返回错误作为字符串值),但有几个例外情况:

  • 返回未定义的值会导致错误;
  • 返回空值(null)会导致输入值被丢弃,类似于“自定义失败处理”动作中的“丢弃值”预处理。

错误可以通过抛出值/对象来返回(通常是字符串或Error对象)。

例如:

  1. if (value == 0)
  2. throw "Zero input value";
  3. return 1 / value;

每个脚本有10秒的执行超时(取决于脚本,超时时间可能更长)。超过超时时间将返回错误。有一个512兆字节的堆限制。

当应用下一次步骤时,JavaScript预处理步骤的字节码会被缓存和重用。项目预处理步骤的任何更改都会导致缓存的脚本被重置和重新编译。

连续的运行时失败(3次连续失败)将导致引擎重新初始化,以减少一个脚本破坏下一个脚本执行环境的可能性(此操作在DebugLevel 4及更高级别中记录)。

JavaScript预处理是使用Duktape JavaScript引擎实现的。

另请参阅:附加的JavaScript对象和全局函数

在脚本中使用宏

可以在JavaScript代码中使用用户宏。如果脚本包含用户宏,这些宏将在执行特定预处理步骤之前由服务器/代理解析。请注意,在前端测试预处理步骤时,宏值不会被提取,需要手动输入。

替换宏值时会忽略上下文。宏值会直接插入代码中,无法在将值放入JavaScript代码之前添加额外的转义字符。请注意,这在某些情况下可能会导致JavaScript错误。

在下面的示例中,如果接收到的值超过了{$THRESHOLD}宏值,则会返回阈值(如果存在):

  1. var threshold = '{$THRESHOLD}';
  2. return (!isNaN(threshold) && value > threshold) ? threshold : value;

示例

以下示例说明了如何使用JavaScript预处理。

每个示例包含一个简要描述、JavaScript预处理参数的函数体以及预处理步骤的结果 - 函数返回的值。

示例 1:将数字(科学计数法转换为整数)

将数字 “2.62128e+07” 从科学计数法转换为整数。

  1. return (Number(value))

函数返回的值:26212800。

示例2:将数字转换为十进制(二进制转十进制)

将二进制数”11010010”转换为十进制数。

  1. return(parseInt(value,2))

函数返回的值:210。

示例3:四舍五入

将数字”18.2345”四舍五入为2位小数。

  1. return(Math.round(value* 100) / 100)

函数返回的值:18.23。

示例4:计算字符串中的字母数

计算字符串”Zabbix”中的字母数。

  1. return (value.length)

函数返回的值:6。

示例5:获取剩余时间

获取距离证书到期日期(Feb 12 12:33:56 2022 GMT)的剩余时间(以秒为单位)。

  1. var split = value.split(' '),
  2. MONTHS_LIST = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  3. month_index = ('0' + (MONTHS_LIST.indexOf(split[0]) + 1)).slice(-2),
  4. ISOdate = split[3] + '-' + month_index + '-' + split[1] + 'T' + split[2],
  5. now = Date.now();
  6. return parseInt((Date.parse(ISOdate) - now) / 1000);

函数返回的值:44380233。

示例6:移除JSON属性

通过删除具有键为"data_size""index_size"的属性来修改JSON数据结构。

  1. var obj=JSON.parse(value);
  2. for (i = 0; i < Object.keys(obj).length; i++) {
  3. delete obj[i]["data_size"];
  4. delete obj[i]["index_size"];
  5. }
  6. return JSON.stringify(obj)

函数接受的值:

  1. [
  2. {
  3. "table_name":"history",
  4. "data_size":"326.05",
  5. "index_size":"174.34"
  6. },
  7. {
  8. "table_name":"history_log",
  9. "data_size":"6.02",
  10. "index_size":"3.45"
  11. }
  12. ]

函数返回的值:

  1. [
  2. {
  3. "table_name":"history"
  4. },
  5. {
  6. "table_name":"history_log"
  7. }
  8. ]
示例7:将Apache状态转换为JSON

将从 web.page.get Zabbix agent 项接收到的值(例如,web.page.get[http://127.0.0.1:80/server-status?auto\])转换为 JSON 对象。

  1. // 将Apache状态转换为JSON
  2. // 将值拆分为子字符串并将这些子字符串放入数组中
  3. var lines = value.split('\n');
  4. // 创建一个空对象 "output"
  5. var output = {};
  6. // 使用预定义属性创建一个对象 "workers"
  7. var workers = {
  8. '_': 0, 'S': 0, 'R': 0, 'W': 0,
  9. 'K': 0, 'D': 0, 'C': 0, 'L': 0,
  10. 'G': 0, 'I': 0, '.': 0
  11. };
  12. // 将来自 "lines" 数组的子字符串作为属性(键值对)添加到 "output" 对象中
  13. for (var i = 0; i < lines.length; i++) {
  14. var line = lines[i].match(/([A-z0-9 ]+): (.*)/);
  15. if (line !== null) {
  16. output[line[1]] = isNaN(line[2]) ? line[2] : Number(line[2]);
  17. }
  18. }
  19. // 多版本指标
  20. output.ServerUptimeSeconds = output.ServerUptimeSeconds || output.Uptime;
  21. output.ServerVersion = output.ServerVersion || output.Server;
  22. // 解析 "Scoreboard" 属性以获取工作进程数
  23. if (typeof output.Scoreboard === 'string') {
  24. for (var i = 0; i < output.Scoreboard.length; i++) {
  25. var char = output.Scoreboard[i];
  26. workers[char]++;
  27. }
  28. }
  29. // 将工作进程数据添加到 "output" 对象中
  30. output.Workers = {
  31. waiting: workers['_'], starting: workers['S'], reading: workers['R'],
  32. sending: workers['W'], keepalive: workers['K'], dnslookup: workers['D'],
  33. closing: workers['C'], logging: workers['L'], finishing: workers['G'],
  34. cleanup: workers['I'], slot: workers['.']
  35. };
  36. // 返回JSON字符串
  37. return JSON.stringify(output);

函数接受的值:

  1. HTTP/1.1 200 OK
  2. Date: Mon, 27 Mar 2023 11:08:39 GMT
  3. Server: Apache/2.4.52 (Ubuntu)
  4. Vary: Accept-Encoding
  5. Content-Encoding: gzip
  6. Content-Length: 405
  7. Content-Type: text/plain; charset=ISO-8859-1
  8. 127.0.0.1
  9. ServerVersion: Apache/2.4.52 (Ubuntu)
  10. ServerMPM: prefork
  11. Server Built: 2023-03-08T17:32:01
  12. CurrentTime: Monday, 27-Mar-2023 14:08:39 EEST
  13. RestartTime: Monday, 27-Mar-2023 12:19:59 EEST
  14. ParentServerConfigGeneration: 1
  15. ParentServerMPMGeneration: 0
  16. ServerUptimeSeconds: 6520
  17. ServerUptime: 1 hour 48 minutes 40 seconds
  18. Load1: 0.56
  19. Load5: 0.33
  20. Load15: 0.28
  21. Total Accesses: 2476
  22. Total kBytes: 8370
  23. Total Duration: 52718
  24. CPUUser: 8.16
  25. CPUSystem: 3.44
  26. CPUChildrenUser: 0
  27. CPUChildrenSystem: 0
  28. CPULoad: .177914
  29. Uptime: 6520
  30. ReqPerSec: .379755
  31. BytesPerSec: 3461.58
  32. BytesPerReq: 3461.58
  33. DurationPerReq: 21.2916
  34. BusyWorkers: 2
  35. IdleWorkers: 6
  36. Scoreboard: ____KW__..............................................................................................................................................

函数返回的值:

  1. {
  2. "Date": "Mon, 27 Mar 2023 11:08:39 GMT",
  3. "Server": "Apache/2.4.52 (Ubuntu)",
  4. "Vary": "Accept-Encoding",
  5. "Encoding": "gzip",
  6. "Length": 405,
  7. "Type": "text/plain; charset=ISO-8859-1",
  8. "ServerVersion": "Apache/2.4.52 (Ubuntu)",
  9. "ServerMPM": "prefork",
  10. "Server Built": "2023-03-08T17:32:01",
  11. "CurrentTime": "Monday, 27-Mar-2023 14:08:39 EEST",
  12. "RestartTime": "Monday, 27-Mar-2023 12:19:59 EEST",
  13. "ParentServerConfigGeneration": 1,
  14. "ParentServerMPMGeneration": 0,
  15. "ServerUptimeSeconds": 6520,
  16. "ServerUptime": "1 hour 48 minutes 40 seconds",
  17. "Load1": 0.56,
  18. "Load5": 0.33,
  19. "Load15": 0.28,
  20. "Total Accesses": 2476,
  21. "Total kBytes": 8370,
  22. "Total Duration": 52718,
  23. "CPUUser": 8.16,
  24. "CPUSystem": 3.44,
  25. "CPUChildrenUser": 0,
  26. "CPUChildrenSystem": 0,
  27. "CPULoad
  28. ": 0.177914,
  29. "Uptime": 6520,
  30. "ReqPerSec": 0.379755,
  31. "BytesPerSec": 1314.55,
  32. "BytesPerReq": 3461.58,
  33. "DurationPerReq": 21.2916,
  34. "BusyWorkers": 2,
  35. "IdleWorkers": 6,
  36. "Scoreboard": "____KW__..............................................................................................................................................",
  37. "Workers": {
  38. "waiting": 6,
  39. "starting": 0,
  40. "reading": 0,
  41. "sending": 1,
  42. "keepalive": 1,
  43. "dnslookup": 0,
  44. "closing": 0,
  45. "logging": 0,
  46. "finishing": 0,
  47. "cleanup": 0,
  48. "slot": 142
  49. }
  50. }