5 JavaScriptの保存前処理

概要

このセクションでは、JavaScriptによる保存前処理について詳しく説明します。

JavaScriptの保存前処理

JavaScriptの保存前処理は、JavaScriptの関数を'value'という1つのパラメーターとユーザー提供の関数本体で呼び出すことで行われます。保存前処理のステップの結果は、この関数から返される値です。例えば、華氏から摂氏への変換を行う場合、次のように入力します。

return (value - 32) * 5 / 9

JavaScriptの保存前処理パラメーターは、サーバーによってJavaScript関数にラップされます。

function (value) {  return (value - 32) * 5 / 9 }

入力パラメーター'value'は常に文字列として渡されます。戻り値はいくつかの例外とともに自動的にtoString()メソッドで文字列に変換されます(失敗した場合は、エラーが文字列として返されます)。

  • 未定義の値を返すとエラーになります。
  • null値を返すと、入力値が破棄されます。これは'失敗時のカスタマイズ'の'値を破棄'と似た動作になります。

エラーは、値/オブジェクト(通常は文字列かエラーオブジェクト)をスローすることによって返されます。

例:

if (value == 0)  throw "Zero input value" return 1/value

各スクリプトには10秒の実行タイムアウトがあり、超えるとエラーが返されます(スクリプトによって、タイムアウトがトリガーするのに時間がかかる場合があります)。512メガバイトのヒープ制限が施行されています。

JavaScriptの保存前処理のステップのバイトコードはキャッシュされ、次回ステップが適用されたときに再利用されます。アイテムの保存前処理ステップに変更を加えると、キャッシュされたスクリプトがリセットされ、後で再コンパイルされます。

連続したランタイムエラー(3回連続)が発生すると、1つのスクリプトによって次のスクリプトの実行環境が破壊される可能性を軽減するために、エンジンが再初期化されます(このアクションは、デバッグレベル4以上でログに記録されます)。

JavaScriptの保存前処理は、Duktape JavaScriptエンジンを使用して実装されています。

参照: 追加のJavaScriptオブジェクトとグローバル関数

スクリプトでマクロの使用

JavaScriptのコードでユーザーマクロを使用することができます。 スクリプトにユーザーマクロが含まれている場合、これらのマクロは特定の保存前処理のステップを実行する前に、サーバー/プロキシによって解決されます。 フロントエンドで保存前処理ステップのテストするとき、マクロの値は引き出されないので手動で入力する必要があることに注意してください。

マクロがその値で置き換えられるとき、コンテキストは無視されます。 マクロの値はそのままコードに挿入されるため、JavaScriptコードにマクロの値を挿入する前にエスケープを追加することはできません。 このため、場合によってはJavaScriptのエラーを引き起こす可能性があります。

以下の例では、受信した値が{$THRESHOLD}マクロの値を超えた場合、代わりに閾値(存在する場合)が返されます。

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

次の例は、JavaScriptの保存前処理の使用方法を示しています。 各例には、簡単な説明、JavaScript保存前処理パラメーターの関数本体、および保存前処理のステップの結果(関数によって返される値)が含まれています。

例1: 数値の変換 (科学的記数法から整数へ)

数値"2.62128e+07"を科学的記数法から整数に変換します。

return (Number(value))

関数によって返される値: 26212800

例2: 数値の変換 (2進数から10進数へ)

2 進数"11010010"を10進数に変換します。

return(parseInt(value,2))

関数によって返される値: 210

例3: 数値を丸める

数値"18.2345"を2桁に丸めます。

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

関数によって返される値: 18.23

例4: 文字列内の文字数を数える

文字列 "Zabbix"内の文字数を数えます。

return (value.length)

関数によって返される値: 6

例5: 残り時間を取得する

証明書の有効期限(Feb 12 12:33:56 2022 GMT)までの残り時間(秒単位)を取得します。

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);

関数によって返される値: 44380233

例6: JSONプロパティの削除

キー"data_size"または"index_size"を持つプロパティを削除して、JSONデータ構造を変更します。

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)

関数によって受け入れられる値:

[  {  "table_name":"history",  "data_size":"326.05",  "index_size":"174.34"  },  {  "table_name":"history_log",  "data_size":"6.02",  "index_size":"3.45"  } ]

関数によって返される値:

[  {  "table_name":"history"  },  {  "table_name":"history_log"  } ]
例7: ApacheステータスをJSONに変換する

Zabbixエージェントアイテムweb.page.get(例: web.page.get[http://127.0.0.1:80/server-status?auto])から受信した値をJSONオブジェクトに変換します。

// 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);

関数によって受け入れられる値:

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__..............................................................................................................................................

関数によって返される値:

{  "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  } }