採用情報

お問い合わせ

BLOG

Zabbix テック・ラウンジ

2019 年 03 月 28 日

Zabbix 3.2以降の新機能解説(Zabbix 4.0を見据えて) その21 - 保存前処理、依存アイテムの設定と処理、ソースコード解説

こんにちは、MIRACLE ZBX サポートを担当している花島タケシです。今回は、保存前処理と依存アイテムの可能な設定と実際の処理についての紹介と、ソースコード解説を行います。

保存前処理 (preprocessing) と依存アイテムで遊ぶ

保存前処理の実際

かなり前に保存前処理と依存アイテムの大まかな実装については紹介していましたが、可能な設定と実際の処理については紹介していませんでした。

そこで、今回はこれらについてソースコード解説を含めて行います。

保存前処理については下記の設定ができます。

  • 差分、1 秒あたりの差分
  • 乗数、数値変換
  • トリム ( 文字列削除 )
  • 正規表現
  • XML Xpath
  • JSON Path

実際の Web フロントエンドでのプルダウンと異なりますが、説明上上記のような分類としました。

実際の設定は下記を参照してください。
https://www.zabbix.com/documentation/3.4/manual/config/items/item#item_value_preprocessing

差分、1 秒あたりの差分

これについては特に説明の必要もないでしょう。従来のものと変わりません。

他の設定の説明の都合もあるのでソースコード解説をしていきます。

src/zabbix_server/preprocessor/item_preproc.c

1022 int zbx_item_preproc(unsigned char value_type, zbx_variant_t *value, const zbx_timespec_t * ts,
1023 const zbx_preproc_op_t *op, zbx_item_history_value_t *history_value, char **errmsg)
1024 {
1025 switch (op->type)
1026 {
1027 case ZBX_PREPROC_MULTIPLIER:
1028 return item_preproc_multiplier(value_type, value, op->params, errmsg);
1029 case ZBX_PREPROC_RTRIM:
1030 return item_preproc_rtrim(value, op->params, errmsg);
1031 case ZBX_PREPROC_LTRIM:
1032 return item_preproc_ltrim(value, op->params, errmsg);
1033 case ZBX_PREPROC_TRIM:
1034 return item_preproc_lrtrim(value, op->params, errmsg);
1035 case ZBX_PREPROC_REGSUB:
1036 return item_preproc_regsub(value, op->params, errmsg);
1037 case ZBX_PREPROC_BOOL2DEC:
1038 return item_preproc_bool2dec(value, errmsg);
1039 case ZBX_PREPROC_OCT2DEC:
1040 return item_preproc_oct2dec(value, errmsg);
1041 case ZBX_PREPROC_HEX2DEC:
1042 return item_preproc_hex2dec(value, errmsg);
1043 case ZBX_PREPROC_DELTA_VALUE:
1044 return item_preproc_delta_value(value_type, value, ts, history_value, errmsg);
1045 case ZBX_PREPROC_DELTA_SPEED:
1046 return item_preproc_delta_speed(value_type, value, ts, history_value, errmsg);
1047 case ZBX_PREPROC_XPATH:
1048 return item_preproc_xpath(value, op->params, errmsg);
1049 case ZBX_PREPROC_JSONPATH:
1050 return item_preproc_jsonpath(value, op->params, errmsg);
1051 }
1052
1053 *errmsg = zbx_dsprintf(*errmsg, "unknown preprocessing operation");
1054
1055 return FAIL;
1056 }

src/zabbix_server/preprocessor/preproc_worker.c : worker_preprocess_value() から、保存前処理のステップごとに zbx_item_preproc() が呼び出されます。呼び出し前に以前のデータが必要なステップに対しては事前にヒストリーデータを参照します。

zbx_item_preproc() では、フィルターごとに用意された関数を呼び出します。「差分、1 秒あたりの差分」に関しては、item_preproc_delta_value(), item_preproc_delta_speed() となります。( 後者は命名が変だとは思いますが ) 内容は特に解説の必要もないでしょう。

乗数、数値変換

これに関しても解説は特に必要ないと思います。「乗数」は得られた値に対して指定した値を掛けるだけとなります。
「数値変換」は得られた値を文字列に変換し、値の正しさを検証 ( 例えば、16 進数に 'g' 等が入っていない ) した後に、10 進数に変換します。

トリム ( 文字列削除 )

これは、「前後文字列削除」「末尾文字列削除」「先頭文字列削除」が該当します。
注意点としては、パラメータに設定した文字列を削除するのではなく、「何れかが該当しなくなるまで再帰的に削除する」ということです。
つまり、パラメータの 'hoge' を指定したとします。直接的な取得結果が 'MLhoge' の場合、'ML' が監視結果となります。同様に 'MLegoh' の場合も 'ML' となります。
パラメータはマルチバイト文字にも対応しています。

463 static int item_preproc_trim(zbx_variant_t *value, unsigned char op_type, const char *param s, char **errmsg)
464 {
465 char params_raw[ITEM_PREPROC_PARAMS_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1];
466
467 if (FAIL == item_preproc_convert_value(value, ZBX_VARIANT_STR, errmsg))
468 return FAIL;
469
470 unescape_trim_params(params, params_raw);
471
472 if (ZBX_PREPROC_LTRIM == op_type || ZBX_PREPROC_TRIM == op_type)
473 zbx_ltrim(value->data.str, params_raw);
474
475 if (ZBX_PREPROC_RTRIM == op_type || ZBX_PREPROC_TRIM == op_type)
476 zbx_rtrim(value->data.str, params_raw);
477
478 return SUCCEED;
479 }
どの文字列削除も item_preproc_trim() に辿りつきます。最初にパラメータからエスケープ文字の削除を行い、前後のトリムを実行します。

正規表現

これについては、log[] キー等の正規表現と出力パラメータの関係と同じとなります。

下記 URL の log[] キー項を参考にします。
https://www.zabbix.com/documentation/4.0/manual/config/items/itemtypes/zabbix_agent#supported_item_keys

正規表現が、"task run [0-9.]+ sec, processed ([0-9]+) records, [0-9]+ errors" で、出力が "\1" であるとします。直接的な監視結果が、"2015-11-13 10:08:26 task run 6.08 sec, processed 6080 records, 0 errors" ならば、最終的な監視結果は、6080 となります。もし、出力に "\0" と指定した場合は、"task...errors" が最終的な監視結果となります。\0 や \1 がどこに該当するかは ? は、使用している正規表現の regexec() 関数の結果に依存します。regmatch_t pmatch[] 配列からの参照となります。もし、文字列の部分も切り出したいのならば () で囲う必要があります。(processed) のような具合です。

XML Xpath

これに関しては解説が長くなります。

最初に、直接的な監視結果 (xpathCtx) からパラメータ (params) パスに指定したノードを libxml2 関数 xmlXPathEvalExpression() を用いて取得します。この関数については、下記を参照してください。
http://xmlsoft.org/html/libxml-xpath.html#xmlXPathEvalExpression

パラメータで指定するロケーションパスは絶対パスで指定する必要があるようです。( 実際には xmlXPathEvalExpression() にそのまま渡しているため、これが許容する書式となります。)
ロケーションパスについては下記を参照してください。
https://msdn.microsoft.com/en-us/library/ms256039(v=vs.110).aspx

libxml2 のヘッダーファイルを見ると、node-set, boolean, string, number が使用できるようですが、テストしたところ node-set, boolean は想定したとおりの動作とはなりませんでした。マニュアルにあるように node-set の取得にはロケーションパスだけを指定すれば良いです。

917 switch (xpathObj->type)
918 {
919 case XPATH_NODESET:
920 xmlBufferLocal = xmlBufferCreate();
921
922 if (0 == xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
923 {
924 nodeset = xpathObj->nodesetval;
925 for (i = 0; i < nodeset->nodeNr; i++)
926 xmlNodeDump(xmlBufferLocal, doc, nodeset->nodeTab[i], 0, 0);
927 }
928
929 zbx_variant_clear(value);
930 zbx_variant_set_str(value, zbx_strdup(NULL, (const char *)xmlBufferLocal->content));
931
932 xmlBufferFree(xmlBufferLocal);
933 ret = SUCCEED;
934 break;
935 case XPATH_STRING:
936 zbx_variant_clear(value);
937 zbx_variant_set_str(value, zbx_strdup(NULL, (const char *)xpathObj->stringval));
938 ret = SUCCEED;
939 break;
940 case XPATH_BOOLEAN:
941 zbx_variant_clear(value);
942 zbx_variant_set_str(value, zbx_dsprintf(NULL, "%d", xpathObj->boolval));
943 ret = SUCCEED;
944 break;
945 case XPATH_NUMBER:

のようになっているのですが。

ちなみに、HTML は XML のサブセットであるため、この XML Xpath で解釈できるはずです。

JSON Path

該当するコードは下記となります。

815 static int item_preproc_jsonpath_op(zbx_variant_t *value, const char *params, char **errms g)
816 {
...
824 if (FAIL == zbx_json_open(value->data.str, &jp) || FAIL == zbx_json_path_open(&jp, params , &jp_out))
825 {
826 *errmsg = zbx_strdup(*errmsg, zbx_json_strerror());
827 return FAIL;
828 }
829
830 zbx_json_value_dyn(&jp_out, &data, &data_alloc);
831 zbx_variant_clear(value);
832 zbx_variant_set_str(value, data);
833
834 return SUCCEED;
835 }

Zabbix では JSON の解釈を外部ライブラリを用いず、独自のパーザーを実装しています。
この zbx_json_path_open() は、PreProcessor からしか呼び出されません。Zabbix 独自のパス指定方法だと思われます。
マニュアルにあるように、パスの指定には . 区切りと [] 区切りを混在して使用できます。
zbx_json_path_open() からの処理はそのパーザーとなっています。文字列のごりごりとした処理であるため、説明は省きます。

複数のフィルター

一つのアイテムに複数のフィルターを設定した場合はどうなるのでしょう ?

src/zabbix_server/preprocessor/preproc_worker.c

45 static void worker_preprocess_value(zbx_ipc_socket_t *socket, zbx_ipc_message_t *message)
46 {
...
60 for (i = 0; i < steps_num; i++)
61 {
62 zbx_preproc_op_t *op = &steps[i];
63
64 if ((ZBX_PREPROC_DELTA_VALUE == op->type || ZBX_PREPROC_DELTA_SPEED == op->type) &&
65 NULL == history_value)
66 {
...
76 }
77
78 if (SUCCEED != zbx_item_preproc(value_type, &value, ts, op, history_value, &error))
79 {
80 char *errmsg_full;
81
82 errmsg_full = zbx_dsprintf(NULL, "Item preprocessing step #%d failed: %s", i + 1, erro r);
83 zbx_free(error);
84 error = errmsg_full;
85
86 break;
87 }
88
89 if (ZBX_VARIANT_NONE == value.type)
90 break;
91 }

l.78 で呼び出す value は、いままで見て来た関数 (e.g. item_preproc_jsonpath_op()) により置き換えられることがわかります。つまり、前のフィルターで処理を行った結果が次のフィルターに渡されることとなります。
したがって、設定した上位から順々に処理され変化していくこととなり、設定の順番が重要になってきます。

依存アイテムとの関係

複数のフィルターを設定しても、得られる結果は一つとなります。
XML や JSON の結果は複数の情報を含むことができ、これより複数の監視結果を得たいという要望もあるでしょう。その場合には、依存アイテムを作成することとなります。

依存アイテムで設定したマスターアイテムのフィルター前 ( 直接的な監視結果 ) と最終的な監視結果のどちらを使用するのか ? というと、最終的な監視結果となります。
これは以前解説したように、最終的な監視結果を作成した後に依存アイテムの処理を行う実装となっているため自明となります。

関連記事

Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 1
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 2
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 3
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 4
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 5
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 6
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 7
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 8
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 9
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 10
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 11
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 12
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 13
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 14
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 15
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 16
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 17
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 18
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 19
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 20
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 21

注意事項

  • 本ドキュメントの内容は、予告なしに変更される場合があります。
  • 本ドキュメントは、限られた評価環境における検証結果をもとに作成しており、全ての環境での動作を保証するものではありません。
  • 本ドキュメントの内容に基づき、導入、設定、運用を行なったことにより損害が生じた場合でも、当社はその損害についての責任を負いません。あくまでお客さまのご判断にてご使用ください。
CentOS 7 延長サポートサービス
デジタルトランスフォーメーションのための電子認証基盤 iTrust
SSL/TLS サーバー証明書 SureServer Prime