Collection/Reflection設定例

CollectionとReflectionは、データ収集、選別、加工、転送の一連の流れを提供するため、通常は組み合わせて使用します。ここではCollectionパターン、Collectionフック、Collection、Reflectionを組み合わせた使用例を紹介します。尚、この簡単なアプリケーションの環境は、以下の構成を例題としています。


Step1. Collectionパターンを作成する

本サンプルアプリケーションにおけるCollectionパターンの仕様は、CSR1000vに対して1分間隔でsysUpTImeをSNMP-GETで取得、5分単位でtcpActiveOpens、tcpPassiveOpens、ifHCInOctets、ifHCOutOctetsをSNMP-BULKで一括収集、また1分間隔でCSR1000vが稼働しているVMのパワー状態をREST-APIで収集、VMに対してpingを1回送信して遅延を収集することとします。
また機器毎に可変となることが想定されるパラメータについてはテンプレート変数として定義し、後に作成するCollectionのcorrelation_infoでレンダリングして動的に解決することとします。

- name: csr1000v
  collections:
    - interval: 1
      method:
        credential:
          community: '{snmp_community}'
          version: v2c
        oid: 1.3.6.1.2.1.1.3.0
        port: 161
        protocol: SNMP
    - interval: 5
      method:
        credential:
          community: '{snmp_community}'
          version: v2c
        nonRepeaters: 2
        oids:
          - 1.3.6.1.2.1.6.5
          - 1.3.6.1.2.1.6.6
          - '1.3.6.1.2.1.31.1.1.1.6.{Gi1}'
          - '1.3.6.1.2.1.31.1.1.1.6.{Gi2}'
          - '1.3.6.1.2.1.31.1.1.1.6.{Gi3}'
          - '1.3.6.1.2.1.31.1.1.1.10.{Gi1}'
          - '1.3.6.1.2.1.31.1.1.1.10.{Gi2}'
          - '1.3.6.1.2.1.31.1.1.1.10.{Gi3}'
        port: 161
        protocol: SNMP
    - interval: 1
      method:
        authentication:
          auth_mode: basic
          password: '{vmware_password}'
          username: '{vmware_username}'
        endpoint: '{vmware_endpoint}'
        path: '/api/vms/{vmid}/power'
        protocol: HTTP
    - interval: 1
      method:
        name: ping
        script: |-
          p = await asyncio.create_subprocess_shell("ping -c 1 {}".format(address), stdout=asyncio.subprocess.PIPE)
          r = await p.communicate()
          collection = r[0].decode("utf-8").splitlines()[-1]


Step2. Collectionフックを作成する

収集したデータは、後に定義するReflectionでメトリック値に変換してZabbixに転送することとします。従って収集対象(Collection)を作成したタイミングでZabbix側にも管理ホストを認識させておく必要があります。Collection登録時にCollectionフックでZabbixに管理ホストや管理アイテムを作成するカスタムスクリプトを定義しておきましょう。

- name: createHost
  script: |-
    global collection

    async def jsonrpc(token, method, **params):
        payload = MU(dict(jsonrpc="2.0", method=method, params=params, id=1, auth=token))
        r = await callout(url=collection["correlation_info"]["zabbix_url"],
                          method=POST,
                          headers={"Content-Type": "application/json-rpc"},
                          body=payload.dictionary)
        if r.error:
            raise Error(r.code, reason="Communication failure occurred")
        result = MU(json.loads(r.body))
        return result

    # Zabbix認証トークン取得
    r = await jsonrpc(None, "user.login", user=collection["correlation_info"]["zabbix_username"],
                                          password=collection["correlation_info"]["zabbix_password"])
    if r.error:
        raise Error(500, reason="Unable to get token", body=r.error.dictionary)
    token = r.result
    qprint("Zabbix Token: %r" % token)

    # ホストグループ登録
    r = await jsonrpc(token, "hostgroup.create", name=collection["correlation_info"]["zabbix_hostgroup"])
    # 重複登録の場合以外は例外発出
    if r.error and r.error.code != -32602:
        raise Error(500, reason="Unable to create host group", body=r.error.dictionary)

    # ホストグループID取得
    r = await jsonrpc(token, "hostgroup.get", output="extend", filter={"name": [collection["correlation_info"]["zabbix_hostgroup"]]})
    if r.error:
        raise Error(500, reason="Unable to retrieve host group", body=r.error.dictionary)

    groupid = r.result[0].groupid
    qprint("Host Group ID: %r" % groupid)

    # ホスト登録
    r = await jsonrpc(token, "host.create", host=collection["hostname"],
                                            interfaces=[{"type": 1, "main": 1,"useip": 1, "ip": collection["address"], "dns": "", "port": "10050"}],
                                            groups=[{"groupid": groupid}])
    # 重複登録の場合以外は例外発出
    if r.error and r.error.code != -32602:
        raise Error(500, reason="Unable to create host", body=r.error.dictionary)

    # ホストID取得
    r = await jsonrpc(token, "host.get", filter={"name": [collection["hostname"]]})
    if r.error:
        raise Error(500, reason="Unable to get host", body=r.error.dictionary)
    hostid = r.result[0].hostid
    qprint("Host ID: %r" % hostid)

    # 監視アイテム登録
    r = await jsonrpc(token, "item.create", name="tcpActiveOpens",
                                            key_="tcpActiveOpens",
                                            hostid=hostid,
                                            type=2,
                                            value_type=3)
    if r.error:
        raise Error(500, reason="Unable to create tcpActiveOpens item", body=r.error.dictionary)

    r = await jsonrpc(token, "item.create", name="tcpPassiveOpens",
                                            key_="tcpPassiveOpens",
                                            hostid=hostid,
                                            type=2,
                                            value_type=3)
    if r.error:
        raise Error(500, reason="Unable to create tcpPassiveOpens item", body=r.error.dictionary)

    for i in ["Gi1", "Gi2", "Gi3"]:
        r = await jsonrpc(token, "item.create", name="{}.traffic.in.bps".format(i),
                                                key_="{}.traffic.in.bps".format(i),
                                                hostid=hostid,
                                                type=2,
                                                value_type=0)
        if r.error:
            raise Error(500, reason="Unable to create {}.traffic.in.bps item".format(i), body=r.error.dictionary)

    r = await jsonrpc(token, "item.create", name="vmStatus",
                                            key_="vmStatus",
                                            hostid=hostid,
                                            type=2,
                                            value_type=3)
    if r.error:
        raise Error(500, reason="Unable to create vmStatus item", body=r.error.dictionary)

    r = await jsonrpc(token, "item.create", name="pingDelay",
                                            key_="pingDelay",
                                            hostid=hostid,
                                            type=2,
                                            value_type=0)
    if r.error:
        raise Error(500, reason="Unable to create vmStatus item", body=r.error.dictionary)

    collection["correlation_info"]["zabbix_hostgroupid"] = groupid
    collection["correlation_info"]["zabbix_hostid"] = hostid
    qprint(MU(collection).yaml_format)


Step3. Collectionを作成する

Collectionは、データ収集対象となる機器を定義します。データ収集アイテムにはテンプレート変数を定義しているため、correlation_infoにレンダリング変数を定義しています。

- hostname: CSR1000v
  address: 192.168.2.200
  collections:
    - csr1000v
  correlation_info:
    snmp_community: public
    vmid: 75CE72DHP742RGQCMLI1MCRFK8I1KRNS
    vmware_endpoint: 'http://localhost:8697'
    vmware_password: Qmonus!2021
    vmware_username: qmonus
    zabbix_host: localhost
    zabbix_hostgroup: qmonus-example
    zabbix_password: zabbix
    zabbix_port: 10051
    zabbix_url: 'http://localhost:80/api_jsonrpc.php'
    zabbix_username: Admin
  enable: true


Step4. データ収集が適切に行えることを確認する

Collection組込みオブジェクトを利用してデータ収集が適切に行えることを確認します。runメソッドの返り値は、list型です。収集したデータは、MU型で格納されています。ただし、SNMP-BULKで収集したデータはMU型のlistで格納されていることに注意が必要です。

>>> c = await Collection.load("CSR1000v")↵
... r = await c.run()↵
... for i in r:↵
...     if type(i)==list:↵
...         for j in i:↵
...             print(j.yaml_format)↵
...     else:↵
...         print(i.yaml_format)↵
... ↵
↵
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.1.3.0
stamp: 1612757123
type: TimeTicks
value: 1510076
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.6.5.0
stamp: 1612757123
type: Counter32
value: 0
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.6.6.0
stamp: 1612757123
type: Counter32
value: 0
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.31.1.1.1.6.1
stamp: 1612757123
type: Counter64
value: 1346506
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.31.1.1.1.6.2
stamp: 1612757123
type: Counter64
value: 324334
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.31.1.1.1.6.3
stamp: 1612757123
type: Counter64
value: 321901
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.31.1.1.1.10.1
stamp: 1612757123
type: Counter64
value: 1108534
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.31.1.1.1.10.2
stamp: 1612757123
type: Counter64
value: 0
address: 192.168.2.200
datetime: '2021-02-08T04:05:23+00:00'
host: CSR1000v
oid: 1.3.6.1.2.1.31.1.1.1.10.3
stamp: 1612757123
type: Counter64
value: 2309
address: 192.168.2.200
body:
  power_state: poweredOn
code: 200
endpoint: http://localhost:8697
headers:
  Cache-Control: no-cache
  Content-Length: '32'
  Content-Type: application/vnd.vmware.vmw.rest-v1+json
  Date: Mon, 08 Feb 2021 04:05:25 GMT
  X-Http-Reason: OK
host: CSR1000v
method: GET
path: /api/vms/75CE72DHP742RGQCMLI1MCRFK8I1KRNS/power
stamp: 1612757125
url: null
address: 192.168.2.200
host: CSR1000v
name: ping
response: round-trip min/avg/max/stddev = 24.747/24.747/24.747/0.000 ms
stamp: 1612757123
>>>


Step5. CollectionフックでZabbixへの管理ホスト登録が適切に行えることを確認する

Collection Hookのテストは、Collection組込みオブジェクトを利用します。カスタムスクリプトにqprintを埋め込みREPLのdebug機能で出力確認すると効率的です。以下のように実行したら、Zabbixの管理UIでホストグループやホストが適切に表示されるか確認しておきましょう。

>>> debug()↵
Disconnected the currently subscribed channel and connected to the debug channel ['xaas.southbound.channel']
debug channel connected
>>> c = await Collection.load("CSR1000v")↵
... await c.hook("createHost")↵
... ↵
Zabbix Token: 'ed921d79aa5dcc3f1b4297bb2dc205c4'
Host Group ID: '22'
Host ID: '10326'
↵
__FILE__: axis/handson/collections/CSR1000v.yml
__WORKSPACE__: axis-edge/hands-on_plugins
address: 192.168.2.200
collections:
- csr1000v
correlation_info:
  snmp_community: public
  vmid: 75CE72DHP742RGQCMLI1MCRFK8I1KRNS
  vmware_endpoint: http://localhost:8697
  vmware_password: Qmonus!2021
  vmware_username: qmonus
  zabbix_host: localhost
  zabbix_hostgroup: qmonus-example
  zabbix_hostgroupid: '22'
  zabbix_hostid: '10326'
  zabbix_password: zabbix
  zabbix_port: 10051
  zabbix_url: http://localhost:80/api_jsonrpc.php
  zabbix_username: Admin
enable: true
hostname: CSR1000v
target_id: e22ea82a612311eb92f7acde48001122
update: '2021-02-08T10:22:17.167850+09:00'
version: 9
>>> debug(False)↵
debug channel disconnected
>>>


Step6. Reflectionを作成する

Collectionでは、sysUpTimetcpActiveOpenstcpPassiveOpensifHCInOctetsifHCOutOctetsVM電源状態ping遅延を取得していますが、ここではifHCInOctetsVM電源状態ping遅延のみを作成します。同様の環境が用意できる方は他のメトリックについても作成してみてください。

ifHCInOctetsをメトリック化するReflection

ifHCInOctetsは、64bitカウンタのため、前回取得値との差分をメトリックとして算出しています。

- name: ifHCInOctets
  action_script: |-
    if len(cache)==0:
        return

    if collection.value is None:
        return

    ifIndex = collection.oid.split(".")[-1]

    rifmap = {v: k for k, v in ifmap.items()}

    meterName = "{}.traffic.in.bps".format(rifmap[ifIndex].replace("/", ""))

    difference = 0
    if collection.value < cache[-1]["value"]:
        difference = (2**64-1)-cache[-1]["value"]+collection.value
    else:
        difference = collection.value-cache[-1]["value"]
        if difference < 0:
            difference*=-1

    v = difference*8/(collection.stamp-cache[-1]["stamp"])
    await push_metrics(endpoint="%s:%s" % (correlation_info.zabbix_host, correlation_info.zabbix_port),
                       host=collection.host,
                       key=meterName,
                       value=round(v, 4),
                       stamp=collection.stamp)
  apply_condition:
    data_type: mib
    oid: '1.3.6.1.2.1.31.1.1.1.6.{ifIndex}'
  cache_size: 1
  cache_ttl: 3600
  cache_unit: oid
  enable: true


vmStatusをメトリック化するReflection

vmStatusは、VMwareのREST-APIで電源状態を取得します。電源状態は、poweredOn,poweredOff,paused,suspendedの4値のいづれかですが、ここではpoweredOn1、それ以外は0というメトリック値を送信します。

- name: vmStatus
  apply_condition:
    data_type: http
    path: '/api/vms/{vmid}/power'
  action_script: |-
    if collection.code==200:
        await push_metrics(endpoint="%s:%s" % (correlation_info.zabbix_host, correlation_info.zabbix_port),
                           host=collection.host,
                           key="vmStatus",
                           value=1 if collection.body.power_state=="poweredOn" else 0,
                           stamp=collection.stamp)
  cache_size: 0
  cache_ttl: 3600
  cache_unit: name
  enable: true


ping遅延をメトリック化するReflection

ping遅延は、スクリプトでpingを1回発行して遅延値をメトリックとして送信します。

- name: pingDelay
  enable: true
  apply_condition:
    data_type: script
    name: ping
  action_script: |-
    if collection.response:
        if collection.response.startswith("round-trip"):
            await push_metrics(endpoint="%s:%s" % (correlation_info.zabbix_host, correlation_info.zabbix_port),
                               host=collection.host,
                               key="pingDelay",
                               value=float(collection.response.split("=")[-1].strip().split("/")[0]),
                               stamp=collection.stamp)
  cache_size: 0
  cache_ttl: 3600
  cache_unit: name


Step7. Reflectionが適切に動作することを確認する

Reflectionのテストは、Collection組込みオブジェクトを利用します。Collection.runは、reflect=Trueのようにキーワード引数でReflectionまで実行するかを指定できます。デフォルトはFalseです。以下のようにreflectを有効にして実行するとマッチするReflectionがヒットするとreflectionキー配下にReflection情報が格納されます。Reflectionのaction_scriptで例外が発生した場合は、errorキーにスタックとレース情報が格納されます。

>>> c = await Collection.load("CSR1000v")↵
... r = await c.run(reflect=True)↵
... for i in r:↵
...     print(i.yaml_format)↵
... ↵
↵
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.1.3.0
  stamp: 1612759692
  type: TimeTicks
  value: 1766945
error: null
reflection:
  __FILE__: axis/handson/reflections/sysUpTime.yml
  __WORKSPACE__: axis-edge/hands-on_plugins
  action_script: print(collection.yaml_format)
  apply_condition:
    data_type: mib
    oid: 1.3.6.1.2.1.1.3.0
  cache_size: 1
  cache_ttl: 3600
  cache_unit: oid
  enable: true
  name: sysUpTime
  reflection_id: 639f14ac61c511eb9fc2acde48001122
  update: '2021-02-08T10:17:15.500018+09:00'
  version: 3
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.6.5.0
  stamp: 1612759692
  type: Counter32
  value: 0
error: null
reflection:
  __FILE__: axis/handson/reflections/tcpActiveOpens.yml
  __WORKSPACE__: axis-edge/hands-on_plugins
  action_script: print(collection.yaml_format)
  apply_condition:
    data_type: mib
    oid: 1.3.6.1.2.1.6.5.0
  cache_size: 1
  cache_ttl: 3600
  cache_unit: name
  enable: true
  name: tcpActiveOpens
  reflection_id: 41aa441e642411ebb6f3acde48001122
  update: '2021-02-08T09:02:30.960707+09:00'
  version: 2
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.6.6.0
  stamp: 1612759692
  type: Counter32
  value: 0
error: null
reflection:
  __FILE__: axis/handson/reflections/tcpPassiveOpens.yml
  __WORKSPACE__: axis-edge/hands-on_plugins
  action_script: print(collection.yaml_format)
  apply_condition:
    data_type: mib
    oid: 1.3.6.1.2.1.6.6.0
  cache_size: 1
  cache_ttl: 3600
  cache_unit: oid
  enable: true
  name: tcpPassiveOpens
  reflection_id: 60e8061669a811eb9619acde48001122
  update: '2021-02-08T10:17:21.831316+09:00'
  version: 2
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.31.1.1.1.6.1
  stamp: 1612759692
  type: Counter64
  value: 1412316
error: null
reflection:
  __FILE__: axis/handson/reflections/ifHCInOctets.yml
  __WORKSPACE__: axis-edge/hands-on_plugins
  action_script: |-
    if len(cache)==0:
        return

    if collection.value is None:
        return

    ifIndex = collection.oid.split(".")[-1]

    rifmap = {v: k for k, v in ifmap.items()}

    meterName = "{}.traffic.in.bps".format(rifmap[ifIndex].replace("/", ""))

    difference = 0
    if collection.value < cache[-1]["value"]:
        difference = (2**64-1)-cache[-1]["value"]+collection.value
    else:
        difference = collection.value-cache[-1]["value"]
        if difference < 0:
            difference*=-1

    v = difference*8/(collection.stamp-cache[-1]["stamp"])
    await push_metrics(endpoint="%s:%s" % (correlation_info.zabbix_host, correlation_info.zabbix_port),
                       host=collection.host,
                       key=meterName,
                       value=round(v, 4),
                       stamp=collection.stamp)
  apply_condition:
    data_type: mib
    oid: 1.3.6.1.2.1.31.1.1.1.6.{ifIndex}
  cache_size: 1
  cache_ttl: 3600
  cache_unit: oid
  enable: true
  name: ifHCInOctets
  reflection_id: dc9b295a69a811eb9619acde48001122
  update: '2021-02-08T13:28:53.786280+09:00'
  version: 4
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.31.1.1.1.6.2
  stamp: 1612759692
  type: Counter64
  value: 379200
error: null
reflection:
  __FILE__: axis/handson/reflections/ifHCInOctets.yml
  __WORKSPACE__: axis-edge/hands-on_plugins
  action_script: |-
    if len(cache)==0:
        return

    if collection.value is None:
        return

    ifIndex = collection.oid.split(".")[-1]

    rifmap = {v: k for k, v in ifmap.items()}

    meterName = "{}.traffic.in.bps".format(rifmap[ifIndex].replace("/", ""))

    difference = 0
    if collection.value < cache[-1]["value"]:
        difference = (2**64-1)-cache[-1]["value"]+collection.value
    else:
        difference = collection.value-cache[-1]["value"]
        if difference < 0:
            difference*=-1

    v = difference*8/(collection.stamp-cache[-1]["stamp"])
    await push_metrics(endpoint="%s:%s" % (correlation_info.zabbix_host, correlation_info.zabbix_port),
                       host=collection.host,
                       key=meterName,
                       value=round(v, 4),
                       stamp=collection.stamp)
  apply_condition:
    data_type: mib
    oid: 1.3.6.1.2.1.31.1.1.1.6.{ifIndex}
  cache_size: 1
  cache_ttl: 3600
  cache_unit: oid
  enable: true
  name: ifHCInOctets
  reflection_id: dc9b295a69a811eb9619acde48001122
  update: '2021-02-08T13:28:53.786280+09:00'
  version: 4
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.31.1.1.1.6.3
  stamp: 1612759692
  type: Counter64
  value: 376443
error: null
reflection:
  __FILE__: axis/handson/reflections/ifHCInOctets.yml
  __WORKSPACE__: axis-edge/hands-on_plugins
  action_script: |-
    if len(cache)==0:
        return

    if collection.value is None:
        return

    ifIndex = collection.oid.split(".")[-1]

    rifmap = {v: k for k, v in ifmap.items()}

    meterName = "{}.traffic.in.bps".format(rifmap[ifIndex].replace("/", ""))

    difference = 0
    if collection.value < cache[-1]["value"]:
        difference = (2**64-1)-cache[-1]["value"]+collection.value
    else:
        difference = collection.value-cache[-1]["value"]
        if difference < 0:
            difference*=-1

    v = difference*8/(collection.stamp-cache[-1]["stamp"])
    await push_metrics(endpoint="%s:%s" % (correlation_info.zabbix_host, correlation_info.zabbix_port),
                       host=collection.host,
                       key=meterName,
                       value=round(v, 4),
                       stamp=collection.stamp)
  apply_condition:
    data_type: mib
    oid: 1.3.6.1.2.1.31.1.1.1.6.{ifIndex}
  cache_size: 1
  cache_ttl: 3600
  cache_unit: oid
  enable: true
  name: ifHCInOctets
  reflection_id: dc9b295a69a811eb9619acde48001122
  update: '2021-02-08T13:28:53.786280+09:00'
  version: 4
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.31.1.1.1.10.1
  stamp: 1612759692
  type: Counter64
  value: 1142743
error: null
reflection: null
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.31.1.1.1.10.2
  stamp: 1612759692
  type: Counter64
  value: 0
error: null
reflection: null
collection:
  address: 192.168.2.200
  datetime: '2021-02-08T04:48:12+00:00'
  host: CSR1000v
  oid: 1.3.6.1.2.1.31.1.1.1.10.3
  stamp: 1612759692
  type: Counter64
  value: 2617
error: null
reflection: null
collection:
  address: 192.168.2.200
  body:
    power_state: poweredOn
  code: 200
  endpoint: http://localhost:8697
  headers:
    Cache-Control: no-cache
    Content-Length: '32'
    Content-Type: application/vnd.vmware.vmw.rest-v1+json
    Date: Mon, 08 Feb 2021 04:48:13 GMT
    X-Http-Reason: OK
  host: CSR1000v
  method: GET
  path: /api/vms/75CE72DHP742RGQCMLI1MCRFK8I1KRNS/power
  stamp: 1612759693
  url: null
error: null
reflection:
  __FILE__: axis/handson/reflections/vmStatus.yml
  __WORKSPACE__: axis-edge/hands-on_plugins
  action_script: |-
    if collection.code==200:
        await push_metrics(endpoint="%s:%s" % (correlation_info.zabbix_host, correlation_info.zabbix_port),
                           host=collection.host,
                           key="vmStatus",
                           value=1 if collection.body.power_state=="poweredOn" else 0,
                           stamp=collection.stamp)
  apply_condition:
    data_type: http
    path: /api/vms/{vmid}/power
  cache_size: 0
  cache_ttl: 3600
  cache_unit: name
  enable: true
  name: vmStatus
  reflection_id: e7d2897a61cf11eb9037acde48001122
  update: '2021-02-08T13:27:28.853317+09:00'
  version: 2
collection:
  address: 192.168.2.200
  host: CSR1000v
  name: ping
  response: round-trip min/avg/max/stddev = 20.973/20.973/20.973/0.000 ms
  stamp: 1612759692
error: null
reflection:
  __FILE__: axis/handson/reflections/pingDelay.yml
  __WORKSPACE__: axis-edge/hands-on_plugins
  action_script: |-
    if collection.response:
        if collection.response.startswith("round-trip"):
            await push_metrics(endpoint="%s:%s" % (correlation_info.zabbix_host, correlation_info.zabbix_port),
                               host=collection.host,
                               key="pingDelay",
                               value=float(collection.response.split("=")[-1].strip().split("/")[0]),
                               stamp=collection.stamp)
  apply_condition:
    data_type: script
    name: ping
  cache_size: 0
  cache_ttl: 3600
  cache_unit: name
  enable: true
  name: pingDelay
  reflection_id: ce146f9669a211eb9619acde48001122
  update: '2021-02-08T13:43:42.523874+09:00'
  version: 2
>>>

Tip

push_metricsの送信先は、現状zabbixのみがサポートされていますが、カスタムのsenderを実装したい場合は、FIFOに挿入してカスタムのworkerを実装することで実現できます。