TelemetryのコレクタとしてTelegrafを利用し、Prometheus・Grafanaを利用し可視化を行った際のメモ
(ネットワークシュミレータで実施)
Telemetryとは
ざっくり
- トラフィックや機器状態など情報を出力するネットワーク監視のための技術
- 従来のSNMPと比較して「柔軟性が高い」「リアルタイム性が高い」などのメリットがある
- 接続方式・メッセージ形式・通信形式が複数種類ある
- 接続方式:Dial-In / Dial-Out
- メッセージ形式:GPB、JSON など
- 通信形式:UDP、gRPCなど
今回は、JuniperのDial-Out(UDP)で確認しました
構成とアウトプットのイメージ
-
Telemetryを出すネットワーク機器としてvJunos-EVOを利用
サーバ側の準備
Ubuntuの準備
ネットワークシュミレータ内のUbuntuは以下を参考に準備(今回はUbuntu 24.04を利用)
Telegrafのインストール
root ユーザで、以下を実施
curl -fsSL https://repos.influxdata.com/influxdata-archive_compat.key -o /etc/apt/keyrings/influxdata-archive_compat.key
echo "deb [signed-by=/etc/apt/keyrings/influxdata-archive_compat.key] https://repos.influxdata.com/ubuntu stable main" | tee /etc/apt/sources.list.d/influxdata.list
apt update
apt -y install telegraf
以下のサイトを参考にしてます
Junos-EVOのprotoファイルのダウンロード
受け取ったTelemetryデータはバイナリのデータでそのままでは内容が不明なため、それを翻訳するために、Junos-EVOのprotoファイルをダウンロードしprotoファイル保存用のディレクトリを作成し保存する
# GitHubからJunosのtelemetry用protoファイルをダウンロード
git clone --depth 1 https://github.com/Juniper/telemetry.git
# protoファイル保存用のディレクトリを作成
mkdir -p /usr/include/protos/junos-evo
# Junos-EVOの24.2R1のファイルをコピー
cp telemetry/24.2/24.2R1-EVO/protos/* /usr/include/protos/junos-evo/
GitHubからダウンロードすると複数バージョンかつJunosとJunos-EVOそれぞれのprotoファイルがダウンロードされます。今回はルータにvJunosEvoのルータを利用しているので「24.2R1-EVO」を利用してます。
ルータ側の準備
以下の内容でコンフィグ設定
- JunosのTelemetryの設定は「set services analytics・・」で始まる箇所となります
- Telemetryの送信先は「10.99.0.1」でポート番号は「20000」
- 10秒おきに送信 (reporting-rateの部分)
- 送信はUDPでフォーマットはgpd
- UDP以外にもgRPCが選択できます
- Telemetryとして送る内容について今回は「in-octets」の入力バイト数のカウンタ
コンフィグは以下となります
(rootパスワードは仮で「root123」にしてます)
set version 23.4R2-S2.1-EVO
set system host-name vJunosEvolved
set system root-authentication encrypted-password "$6$MmGV7bPW$AuqgoIhnFiZQD9eLmmhS.Fwywh63knLvg96p9VLQXP5jSxMk3QXSBFph4Z3W1Hcvf34xdlIh0QRlHrh/j8rr5/"
set system syslog file interactive-commands interactive-commands any
set system syslog file messages any notice
set system syslog file messages authorization info
set services analytics streaming-server TELEMETRY_SV remote-address 10.99.0.1
set services analytics streaming-server TELEMETRY_SV remote-port 20000
set services analytics export-profile TELEMETRY_PROFILE local-address 10.99.0.2
set services analytics export-profile TELEMETRY_PROFILE local-port 21111
set services analytics export-profile TELEMETRY_PROFILE reporting-rate 10
set services analytics export-profile TELEMETRY_PROFILE format gpb
set services analytics export-profile TELEMETRY_PROFILE transport udp
set services analytics sensor TELEMETRY_SENSOR_IN_OCTETS server-name TELEMETRY_SV
set services analytics sensor TELEMETRY_SENSOR_IN_OCTETS export-name TELEMETRY_PROFILE
set services analytics sensor TELEMETRY_SENSOR_IN_OCTETS resource /interfaces/interface/state/counters/in-octets/
set services analytics sensor TELEMETRY_SENSOR_IN_OCTETS resource-filter et-*
set interfaces et-0/0/1 unit 0 family inet address 10.0.1.1/24
set interfaces et-0/0/2 unit 0 family inet address 10.0.2.1/24
set interfaces et-0/0/9 unit 0 family inet address 10.99.0.2/24
Telemetry受信データの確認と整形
Telegrafの設定
Telegrafの設定は「/etc/telegraf/telegraf.conf」になるため、こちらを以下の内容で編集
- UDP:20000ポートで待ち、受信の際はProtocol Buffersで処理
- 受信したデータについては、Junos-EVO用のprotoファイルを利用し内容をバイナリから変換
- 受信した内容を「/var/log/telegraf/metrics.json」に出力
telegraf.conf 設定内容はコチラ (データ受信確認用)
[agent]
interval = "10s" # データを収集する間隔
round_interval = true # [true] の場合 収集時間は :00, :10, :20 ...
metric_batch_size = 1000 # バッチ処理で Outoput に送信する際のメトリクスサイズ
metric_buffer_limit = 10000 # 使用するメモリーの上限値
collection_jitter = "0s" # メトリクス収集の遅延時間 - 各プラグインがメトリクス収集の際に設定値の範囲内でスリープ
flush_interval = "10s" # Output データを出力する間隔
flush_jitter = "0s" # データを出力する際の遅延時間
precision = "0s"
logfile = "/var/log/telegraf/telegraf.log" # ログファイルのパス
logtarget = "file" # 出力先: "file", "stderr", "stdout"
# デバッグ時に有効にする
#debug = true
# ------------------------------------------------------------------------------------------------------------------------
#
# Telemetry (JUNOS-EVO)
#
# ------------------------------------------------------------------------------------------------------------------------
[[inputs.socket_listener]]
service_address = "udp://:20000"
data_format = "xpath_protobuf"
xpath_protobuf_files = ["telemetry_top.proto",
"aftman-cos-oc_ifl_render.proto",
#"aftman-cos-oc_render.proto",
"aftman-npu-mem-oc_render.proto",
"aftman-npu-util-oc_render.proto",
"aftman-qos-voqmon-stats-oc_render.proto",
#"aftman-sensor-ldp-lsp-ingress-oc_render.proto",
#"aftman-sensor-ldp-lsp-ingress-udp-oc_render.proto",
#"aftman-sensor-ldp-lsp-transit-oc_render.proto",
#"aftman-sensor-ldp-lsp-transit-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-lsp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-lsp-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-egress-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-egress-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-ingress-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-ingress-udp-oc_render.proto",
#"aftman-sensor-lsp-ni-oc_render.proto",
#"aftman-sensor-lsp-oc_render.proto",
#"aftman-sensor-lsp-udp-oc_render.proto",
#"aftman-sensor-per-prefix-ipv4-oc_render.proto",
#"aftman-sensor-per-prefix-ipv4-udp-oc_render.proto",
#"aftman-sensor-per-prefix-ipv6-oc_render.proto",
#"aftman-sensor-per-prefix-ipv6-udp-oc_render.proto",
#"aftman-sensor-sr-egress-interface-openconfig_oc_render.proto",
#"aftman-sensor-sr-egress-interface_oc_render.proto",
#"aftman-sensor-sr-ingress-interface-openconfig_oc_render.proto",
#"aftman-sensor-sr-ingress-interface_oc_render.proto",
#"aftman-sensor-sr-sid_egress_oc_render.proto",
#"aftman-sensor-sr-sid_ingress_oc_render.proto",
#"aftman-sensor-sr-sid_ingress_openconfig_oc_render.proto",
#"aftman-sensor-srte-bsid-oc_render.proto",
#"aftman-sensor-srte-bsid-openconfig-oc_render.proto",
#"aftman-sensor-srte-bsid-udp-oc_render.proto",
#"aftman-sensor-srte-ingress-tunnel-oc_render.proto",
#"aftman-sensor-srte-ingress-tunnel-udp-oc_render.proto",
#"aftman-sensor-srte-ip-oc_render.proto",
#"aftman-sensor-srte-ip-openconfig-oc_render.proto",
#"aftman-sensor-srte-ip-udp-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-openconfig-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-udp-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-openconfig-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-udp-oc_render.proto",
#"aftman-sensor-srte-transit-tunnel-oc_render.proto",
#"aftman-sensor-srte-transit-tunnel-udp-oc_render.proto",
"aftsysinfo-oc_render.proto",
"agent.proto",
"alarmd_oc_render.proto",
"am-cos-egress-qstat-oc_render.proto",
#"am-cos-egress-qstat-udp-oc_render.proto",
"am-cos-interfaceset-stats_render.proto",
"am-cos-intf-qstat-ext-oc_render.proto",
"am-ddos-oc_render.proto",
"am-dfw-oc-render.proto",
"am-ic-pfe-oc_render.proto",
"am-if-oc_render.proto",
"am-if-udp-oc_render.proto",
"am-ifl-udp-oc_render.proto",
#"am-ifl-v4-udp-oc_render.proto",
#"am-ifl-v6-udp-oc_render.proto",
"am-intf-exp-udp-oc_render.proto",
"am-jflowui-udp-oc_render.proto",
"am-pfe-oc_render.proto",
"bfdd-junos-openconfig-bfd-render.proto",
#"brcm-cos-qstat-oc_render.proto",
#"brcm-host-interface-pipestats-oc_render.proto",
#"brcm-if-oc_render.proto",
#"brcm-interface-pipestats-oc_render.proto",
#"brcm-pfe-oc_render.proto",
#"brcm-pfe-udp_render.proto",
"cda-btchip-ic-npu-util-oc_render.proto",
#"cda-btchip-npu-util-oc_render.proto",
"cda-bxchip-npu-util-oc_render.proto",
"cda-bxchip-stats-oc_render.proto",
"cda-drop-lookup-pipestats-oc_render.proto",
"cda-drop-state-pipestats-oc_render.proto",
"cda-expr_pipestats-oc_render.proto",
"cda-pkt-lookup-pipestats-oc_render.proto",
#"cda-zephyr-stats-oc_render.proto",
"cda-zxchip-npu-util-oc_render.proto",
"cda-zxchip-stats-oc_render.proto",
"cfmd-junos-state-oam-cfm-render.proto",
#"cmevod-fpcenv-oc_render.proto",
"cosd_oc_evo.proto",
"ddosd-junos-state-ddos-protection-render.proto",
"dot1xd-junos-openconfig-if-8021x-render.proto",
"dot1xd-junos-state-dot1x-render.proto",
"dot1xd_oc.proto",
"ehmd_comp_oc.proto",
"ehmd_oc.proto",
"ehmd_system_chassis_native.proto",
"ehmd_system_oc.proto",
"evo-if-oc_render.proto",
"evo-interface-pipestats-oc_render.proto",
"evo-pkt-host-interface-pipestats-oc_render.proto",
"fabricHub_oc.proto",
"fabspoked-fchip-junos-openconfig-platform-render.proto",
"fabspoked-pfe-junos-openconfig-platform-pipeline-counters-render.proto",
"fibtd-junos-state-anomalies-fib-render.proto",
"fibtd-telemetry_oc.proto",
"fwstatsd_oc_evo_state.proto",
"fwstatsd_oc_ni.proto",
"gnmi.proto",
"GnmiJuniperTelemetryHeader.proto",
"GnmiJuniperTelemetryHeaderExtension.proto",
"gnmi_dialout.proto",
"gnmi_ext.proto",
"hwdfpc_oc.proto",
"hwdre-evo-openconfig-system-render.proto",
"hwdre-healthz-oc_render.proto",
"hwdre-junos-state-health-render.proto",
"hwdre_fpc_env.proto",
"hwdre_oc.proto",
"jexpr-drop-host-interface-pipestats-oc_render.proto",
"jexpr-ic-npu-mem-oc_render.proto",
"jexpr-junos-integrated_circuit-oc_render.proto",
"jexpr-junos-npu-pipeline-resource-util-oc_render.proto",
"jexpr-npu-mem-oc_render.proto",
"jexpr-pkt-lookup-pipestats-oc_render.proto",
"jsd-junos-state-grpc.proto",
"jsd_health_oc.proto",
"junos-pfe-npu-render.proto",
"junos-xmlproxyd_junos-rsvp-interface.proto",
"junos-xmlproxyd_junos-rtg-task-memory.proto",
"junos_state_interface_render.proto",
"l2ald_bd_render.proto",
"l2ald_evpn_render.proto",
"l2ald_fdb_render.proto",
"l2ald_oc.proto",
"l2ald_oc_intf.proto",
"l2cpd-junos-state-lldp-render.proto",
"l2cpd_oc.proto",
"l2cpd_stp_oc.proto",
"lacpd_oc.proto",
"license-check-features-oc.proto",
"master-eventd-state-system-syslog.proto",
"master-eventd_oc.proto",
"mgmt-ethd_oc_evo_intf_stats.proto",
"mib2d_native_evo_intf_state.proto",
"mib2d_oc_evo_intf_state.proto",
"na-grpcd-junos-state-gnmi.proto",
"na-grpcd_stats_oc.proto",
"oc_component_render.proto",
#"oc_interface_render.proto",
"oc_optics_render.proto",
"pfe_page_drop_oc.proto",
"picd_oc_component_render.proto",
"platformd-fabric-oc_render.proto",
"resiliencyd-cmerror_cfg-oc_render.proto",
"resiliencyd-cmerror_cfg-udp-oc_render.proto",
#"resiliencyd-cmerror_stats-oc_render.proto",
"resiliencyd-cmerror_stats-udp-oc_render.proto",
"resiliencyd-comp_ic_pipeline_errcnt-oc_render.proto",
"rmopd_native_sensors_render.proto",
"rmopd_probe_oc_render.proto",
"rpd-junos-openconfig-ospfv2-render.proto",
"rpd_bgp_junos_route_validation.proto",
"rpd_bgp_junos_state.proto",
"rpd_bgp_rib_oc.proto",
"rpd_evpn_global_render.proto",
"rpd_evpn_instance_junos_state.proto",
"rpd_evpn_rib_oc.proto",
"rpd_gribi_stats_oc.proto",
"rpd_if_ipv6_ra_oc.proto",
"rpd_igmp_oc.proto",
"rpd_ipv6_ra_oc.proto",
"rpd_isis_oc.proto",
"rpd_ldp_oc.proto",
"rpd_ni_bgp_oc.proto",
"rpd_ni_evpn_render.proto",
"rpd_ni_oc.proto",
"rpd_pim_oc.proto",
"rpd_policy_oc.proto",
"rpd_resiliency_interface.proto",
"rpd_rsvp_oc.proto",
"rpd_srte_policy_oc.proto",
"rpd_te_oc.proto",
"svcsd_sflow_oc.proto",
"svcsd_sflow_openconfig.proto",
"sysd-evo-openconfig-system-render.proto",
"vrrpd_oc.proto",
"xmlproxyd-junos-commit-entries-render.proto",
"xmlproxyd-junos-openconfig-system-commit-render.proto",
"xmlproxyd-junos-openconfig-system-render.proto"]
xpath_protobuf_type = "TelemetryStream"
xpath_protobuf_import_paths = ["/usr/include/protos/junos-evo"]
xpath_native_types = true
[[inputs.socket_listener.xpath]]
field_selection = "//*"
field_name_expansion = false
timestamp = "//timestamp"
timestamp_format = "unix_ns"
metric_name = "string('telemetry_junos_evo')"
#-------------------------------------------------------------------------------------
[[outputs.file]]
files = ["/var/log/telegraf/metrics.json"]
data_format = "json"
namepass = ["telemetry_junos_evo"] # メトリック名でフィルタリング
(参考)
protoファイルについてはいくつかコメントアウトしてます、他のprotoファイルの内容を重複しているものもあるみたいですべて指定してtelegrafを実行しようとするとエラーで起動できませんでした
# /usr/bin/telegraf -config /etc/telegraf/telegraf.conf
2025-XX-XXTXX:XX:23Z I! Loading config: /etc/telegraf/telegraf.conf
2025-XX-XXTXX:XX:23Z E! loading config file /etc/telegraf/telegraf.conf failed: error parsing socket_listener, adding parser failed: parsing protocol-buffer definition failed: brcm-pfe-oc_render.proto:9:9: symbol "components_counters" already defined at brcm-pfe-udp_render.proto:9:9
受信データの確認
ここまで設定して「/var/log/telegraf/metrics.json」を見るといくつかのTelemetryデータを定期的に受信しますが、「in-octets」は以下のように1行で複数IFの情報を受信します。
# tail -f /var/log/telegraf/metrics.json
{"fields":{"component_id":0,"in_octets":14348,"in_octets_1":14488,"in_octets_2":14389,"name":"et-0/0/2","name_1":"et-0/0/1","name_2":"et-0/0/9","sensor_name":"TELEMETRY_SENSOR_IN_OCTETS:/interfaces/interface/state/counters/in-octets/:/interfaces/interface/state/counters/in-octets/:evo-aftmand-bt","sequence_number":12,"sub_component_id":0,"system_id":"vJunosEvolved:10.99.0.2","timestamp":XXXXXXXXXXXXX,"version_major":1,"version_minor":0},"name":"telemetry_junos_evo","tags":{"host":"ubuntu-24"},"timestamp":XXXX}
データの整形
1行で複数IFを「_*」で表現されておりこのままだとPrometheusと連携しにくいため、1行を複数行に分解する
# 1行で「_*」で複数IFを出力
"in_octets":14348,"in_octets_1":14488,"in_octets_2":14389, "name":"et-0/0/2","name_1":"et-0/0/1","name_2":"et-0/0/9"・・・
# IFごとに複数行に分ける
"in_octets":14348,"name":"et-0/0/2"
"in_octets":14488,"name":"et-0/0/1"
"in_octets":14389,"name":"et-0/0/9"
整形については、telegraf.conf 内で Starlarkプロセッサを使って編集、Pythonに近い文法で編集ができます
(ただし、Pythonと完全に一致するわけではなく、一部の文法は使用できないという制限がありました)
Starlarkの内容
# Starlarkプロセッサでメトリクスを編集
[[processors.starlark]]
namepass = ["telemetry_junos_evo"] # 「telemetry_junos_evo」のみ処理させる
source = '''
fieldpass = ["system_id", "name*", "in_octets*"]
def apply(metric):
## デバッグ用
#return metric
# ホストネームとIPを取得
SYSTEM_ID = metric.fields["system_id"]
#string = "vJunosEvolved:10.99.0.2"
PARTS = SYSTEM_ID.split(":")
NUM_ELEMENTS = len(PARTS)
if NUM_ELEMENTS == 2:
HOST_NAME = PARTS[0]
HOST_IP = PARTS[1]
elif NUM_ELEMENTS == 1:
HOST_NAME = PARTS[0]
HOST_IP = ""
else:
HOST_NAME = ""
HOST_IP = ""
# 新しいメトリクスを保存するリスト
RETURN_METRICS = []
MAX_INDEX = 10000 # 最大インデックスの設定
#-------------------------------------------------------------------------------------
# 必要なフィールドがあるかチェックし、複数IFの1行をIF毎に1行に分解する
FIELDS_NAME = "in_octets"
HAS_BASE_FIELDS = FIELDS_NAME in metric.fields
# 基本フィールド (index がない場合) の処理
if HAS_BASE_FIELDS:
ADD_METRIC = []
ADD_METRIC = Metric("telemetry_junos_evo")
ADD_METRIC.tags["name"] = metric.fields["name"]
ADD_METRIC.tags["hostip"] = HOST_IP
ADD_METRIC.tags["hostname"] = HOST_NAME
ADD_METRIC.fields[FIELDS_NAME] = metric.fields[FIELDS_NAME]
RETURN_METRICS.append(ADD_METRIC)
# インデックス付きフィールドを処理
for INDEX in range(MAX_INDEX): # MAX_INDEX までのループ
IF_INDEX = INDEX + 1
CHECK_IF_NAME = "name_" + str(IF_INDEX)
CHECK_IF_DATA = FIELDS_NAME + "_" + str(IF_INDEX)
# 必要なフィールドがあるかチェック
HAS_BASE_FIELDS = CHECK_IF_DATA in metric.fields
if HAS_BASE_FIELDS:
ADD_METRIC = []
ADD_METRIC = Metric("telemetry_junos_evo")
ADD_METRIC.tags["name"] = metric.fields[CHECK_IF_NAME]
ADD_METRIC.tags["hostip"] = HOST_IP
ADD_METRIC.tags["hostname"] = HOST_NAME
ADD_METRIC.fields[FIELDS_NAME] = metric.fields[CHECK_IF_DATA]
RETURN_METRICS.append(ADD_METRIC)
else:
# フィールドが無ければforのloopを終了
break
#-------------------------------------------------------------------------------------
# 生成されたメトリクスを返す
return RETURN_METRICS
'''
上記を反映したtelegraf.confはこちら ↓ になります
telegraf.conf 設定内容はコチラ (データ整形後の受信確認用)
[agent]
interval = "10s" # データを収集する間隔
round_interval = true # [true] の場合 収集時間は :00, :10, :20 ...
metric_batch_size = 1000 # バッチ処理で Outoput に送信する際のメトリクスサイズ
metric_buffer_limit = 10000 # 使用するメモリーの上限値
collection_jitter = "0s" # メトリクス収集の遅延時間 - 各プラグインがメトリクス収集の際に設定値の範囲内でスリープ
flush_interval = "10s" # Output データを出力する間隔
flush_jitter = "0s" # データを出力する際の遅延時間
precision = "0s"
logfile = "/var/log/telegraf/telegraf.log" # ログファイルのパス
logtarget = "file" # 出力先: "file", "stderr", "stdout"
# デバッグ時に有効にする
#debug = true
# ------------------------------------------------------------------------------------------------------------------------
#
# Telemetry (JUNOS-EVO)
#
# ------------------------------------------------------------------------------------------------------------------------
[[inputs.socket_listener]]
service_address = "udp://:20000"
data_format = "xpath_protobuf"
xpath_protobuf_files = ["telemetry_top.proto",
"aftman-cos-oc_ifl_render.proto",
#"aftman-cos-oc_render.proto",
"aftman-npu-mem-oc_render.proto",
"aftman-npu-util-oc_render.proto",
"aftman-qos-voqmon-stats-oc_render.proto",
#"aftman-sensor-ldp-lsp-ingress-oc_render.proto",
#"aftman-sensor-ldp-lsp-ingress-udp-oc_render.proto",
#"aftman-sensor-ldp-lsp-transit-oc_render.proto",
#"aftman-sensor-ldp-lsp-transit-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-lsp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-lsp-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-egress-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-egress-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-ingress-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-ingress-udp-oc_render.proto",
#"aftman-sensor-lsp-ni-oc_render.proto",
#"aftman-sensor-lsp-oc_render.proto",
#"aftman-sensor-lsp-udp-oc_render.proto",
#"aftman-sensor-per-prefix-ipv4-oc_render.proto",
#"aftman-sensor-per-prefix-ipv4-udp-oc_render.proto",
#"aftman-sensor-per-prefix-ipv6-oc_render.proto",
#"aftman-sensor-per-prefix-ipv6-udp-oc_render.proto",
#"aftman-sensor-sr-egress-interface-openconfig_oc_render.proto",
#"aftman-sensor-sr-egress-interface_oc_render.proto",
#"aftman-sensor-sr-ingress-interface-openconfig_oc_render.proto",
#"aftman-sensor-sr-ingress-interface_oc_render.proto",
#"aftman-sensor-sr-sid_egress_oc_render.proto",
#"aftman-sensor-sr-sid_ingress_oc_render.proto",
#"aftman-sensor-sr-sid_ingress_openconfig_oc_render.proto",
#"aftman-sensor-srte-bsid-oc_render.proto",
#"aftman-sensor-srte-bsid-openconfig-oc_render.proto",
#"aftman-sensor-srte-bsid-udp-oc_render.proto",
#"aftman-sensor-srte-ingress-tunnel-oc_render.proto",
#"aftman-sensor-srte-ingress-tunnel-udp-oc_render.proto",
#"aftman-sensor-srte-ip-oc_render.proto",
#"aftman-sensor-srte-ip-openconfig-oc_render.proto",
#"aftman-sensor-srte-ip-udp-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-openconfig-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-udp-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-openconfig-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-udp-oc_render.proto",
#"aftman-sensor-srte-transit-tunnel-oc_render.proto",
#"aftman-sensor-srte-transit-tunnel-udp-oc_render.proto",
"aftsysinfo-oc_render.proto",
"agent.proto",
"alarmd_oc_render.proto",
"am-cos-egress-qstat-oc_render.proto",
#"am-cos-egress-qstat-udp-oc_render.proto",
"am-cos-interfaceset-stats_render.proto",
"am-cos-intf-qstat-ext-oc_render.proto",
"am-ddos-oc_render.proto",
"am-dfw-oc-render.proto",
"am-ic-pfe-oc_render.proto",
"am-if-oc_render.proto",
"am-if-udp-oc_render.proto",
"am-ifl-udp-oc_render.proto",
#"am-ifl-v4-udp-oc_render.proto",
#"am-ifl-v6-udp-oc_render.proto",
"am-intf-exp-udp-oc_render.proto",
"am-jflowui-udp-oc_render.proto",
"am-pfe-oc_render.proto",
"bfdd-junos-openconfig-bfd-render.proto",
#"brcm-cos-qstat-oc_render.proto",
#"brcm-host-interface-pipestats-oc_render.proto",
#"brcm-if-oc_render.proto",
#"brcm-interface-pipestats-oc_render.proto",
#"brcm-pfe-oc_render.proto",
#"brcm-pfe-udp_render.proto",
"cda-btchip-ic-npu-util-oc_render.proto",
#"cda-btchip-npu-util-oc_render.proto",
"cda-bxchip-npu-util-oc_render.proto",
"cda-bxchip-stats-oc_render.proto",
"cda-drop-lookup-pipestats-oc_render.proto",
"cda-drop-state-pipestats-oc_render.proto",
"cda-expr_pipestats-oc_render.proto",
"cda-pkt-lookup-pipestats-oc_render.proto",
#"cda-zephyr-stats-oc_render.proto",
"cda-zxchip-npu-util-oc_render.proto",
"cda-zxchip-stats-oc_render.proto",
"cfmd-junos-state-oam-cfm-render.proto",
#"cmevod-fpcenv-oc_render.proto",
"cosd_oc_evo.proto",
"ddosd-junos-state-ddos-protection-render.proto",
"dot1xd-junos-openconfig-if-8021x-render.proto",
"dot1xd-junos-state-dot1x-render.proto",
"dot1xd_oc.proto",
"ehmd_comp_oc.proto",
"ehmd_oc.proto",
"ehmd_system_chassis_native.proto",
"ehmd_system_oc.proto",
"evo-if-oc_render.proto",
"evo-interface-pipestats-oc_render.proto",
"evo-pkt-host-interface-pipestats-oc_render.proto",
"fabricHub_oc.proto",
"fabspoked-fchip-junos-openconfig-platform-render.proto",
"fabspoked-pfe-junos-openconfig-platform-pipeline-counters-render.proto",
"fibtd-junos-state-anomalies-fib-render.proto",
"fibtd-telemetry_oc.proto",
"fwstatsd_oc_evo_state.proto",
"fwstatsd_oc_ni.proto",
"gnmi.proto",
"GnmiJuniperTelemetryHeader.proto",
"GnmiJuniperTelemetryHeaderExtension.proto",
"gnmi_dialout.proto",
"gnmi_ext.proto",
"hwdfpc_oc.proto",
"hwdre-evo-openconfig-system-render.proto",
"hwdre-healthz-oc_render.proto",
"hwdre-junos-state-health-render.proto",
"hwdre_fpc_env.proto",
"hwdre_oc.proto",
"jexpr-drop-host-interface-pipestats-oc_render.proto",
"jexpr-ic-npu-mem-oc_render.proto",
"jexpr-junos-integrated_circuit-oc_render.proto",
"jexpr-junos-npu-pipeline-resource-util-oc_render.proto",
"jexpr-npu-mem-oc_render.proto",
"jexpr-pkt-lookup-pipestats-oc_render.proto",
"jsd-junos-state-grpc.proto",
"jsd_health_oc.proto",
"junos-pfe-npu-render.proto",
"junos-xmlproxyd_junos-rsvp-interface.proto",
"junos-xmlproxyd_junos-rtg-task-memory.proto",
"junos_state_interface_render.proto",
"l2ald_bd_render.proto",
"l2ald_evpn_render.proto",
"l2ald_fdb_render.proto",
"l2ald_oc.proto",
"l2ald_oc_intf.proto",
"l2cpd-junos-state-lldp-render.proto",
"l2cpd_oc.proto",
"l2cpd_stp_oc.proto",
"lacpd_oc.proto",
"license-check-features-oc.proto",
"master-eventd-state-system-syslog.proto",
"master-eventd_oc.proto",
"mgmt-ethd_oc_evo_intf_stats.proto",
"mib2d_native_evo_intf_state.proto",
"mib2d_oc_evo_intf_state.proto",
"na-grpcd-junos-state-gnmi.proto",
"na-grpcd_stats_oc.proto",
"oc_component_render.proto",
#"oc_interface_render.proto",
"oc_optics_render.proto",
"pfe_page_drop_oc.proto",
"picd_oc_component_render.proto",
"platformd-fabric-oc_render.proto",
"resiliencyd-cmerror_cfg-oc_render.proto",
"resiliencyd-cmerror_cfg-udp-oc_render.proto",
#"resiliencyd-cmerror_stats-oc_render.proto",
"resiliencyd-cmerror_stats-udp-oc_render.proto",
"resiliencyd-comp_ic_pipeline_errcnt-oc_render.proto",
"rmopd_native_sensors_render.proto",
"rmopd_probe_oc_render.proto",
"rpd-junos-openconfig-ospfv2-render.proto",
"rpd_bgp_junos_route_validation.proto",
"rpd_bgp_junos_state.proto",
"rpd_bgp_rib_oc.proto",
"rpd_evpn_global_render.proto",
"rpd_evpn_instance_junos_state.proto",
"rpd_evpn_rib_oc.proto",
"rpd_gribi_stats_oc.proto",
"rpd_if_ipv6_ra_oc.proto",
"rpd_igmp_oc.proto",
"rpd_ipv6_ra_oc.proto",
"rpd_isis_oc.proto",
"rpd_ldp_oc.proto",
"rpd_ni_bgp_oc.proto",
"rpd_ni_evpn_render.proto",
"rpd_ni_oc.proto",
"rpd_pim_oc.proto",
"rpd_policy_oc.proto",
"rpd_resiliency_interface.proto",
"rpd_rsvp_oc.proto",
"rpd_srte_policy_oc.proto",
"rpd_te_oc.proto",
"svcsd_sflow_oc.proto",
"svcsd_sflow_openconfig.proto",
"sysd-evo-openconfig-system-render.proto",
"vrrpd_oc.proto",
"xmlproxyd-junos-commit-entries-render.proto",
"xmlproxyd-junos-openconfig-system-commit-render.proto",
"xmlproxyd-junos-openconfig-system-render.proto"]
xpath_protobuf_type = "TelemetryStream"
xpath_protobuf_import_paths = ["/usr/include/protos/junos-evo"]
xpath_native_types = true
[[inputs.socket_listener.xpath]]
field_selection = "//*"
field_name_expansion = false
timestamp = "//timestamp"
timestamp_format = "unix_ns"
metric_name = "string('telemetry_junos_evo')"
#-------------------------------------------------------------------------------------
# Starlarkプロセッサでメトリクスを編集 ('telemetry_junos_evo')
[[processors.starlark]]
namepass = ["telemetry_junos_evo"] # 「telemetry_junos_evo」のみ処理させる
source = '''
fieldpass = ["system_id", "name*", "in_octets*"]
def apply(metric):
## デバッグ用
#return metric
# ホストネームとIPを取得
SYSTEM_ID = metric.fields["system_id"]
#string = "vJunosEvolved:10.99.0.2"
PARTS = SYSTEM_ID.split(":")
NUM_ELEMENTS = len(PARTS)
if NUM_ELEMENTS == 2:
HOST_NAME = PARTS[0]
HOST_IP = PARTS[1]
elif NUM_ELEMENTS == 1:
HOST_NAME = PARTS[0]
HOST_IP = ""
else:
HOST_NAME = ""
HOST_IP = ""
# 新しいメトリクスを保存するリスト
RETURN_METRICS = []
MAX_INDEX = 10000 # 最大インデックスの設定
#-------------------------------------------------------------------------------------
# 必要なフィールドがあるかチェックし、複数IFの1行をIF毎に1行に分解する
FIELDS_NAME = "in_octets"
HAS_BASE_FIELDS = FIELDS_NAME in metric.fields
# 基本フィールド (index がない場合) の処理
if HAS_BASE_FIELDS:
ADD_METRIC = []
ADD_METRIC = Metric("telemetry_junos_evo")
ADD_METRIC.tags["name"] = metric.fields["name"]
ADD_METRIC.tags["hostip"] = HOST_IP
ADD_METRIC.tags["hostname"] = HOST_NAME
ADD_METRIC.fields[FIELDS_NAME] = metric.fields[FIELDS_NAME]
RETURN_METRICS.append(ADD_METRIC)
# インデックス付きフィールドを処理
for INDEX in range(MAX_INDEX): # MAX_INDEX までのループ
IF_INDEX = INDEX + 1
CHECK_IF_NAME = "name_" + str(IF_INDEX)
CHECK_IF_DATA = FIELDS_NAME + "_" + str(IF_INDEX)
# 必要なフィールドがあるかチェック
HAS_BASE_FIELDS = CHECK_IF_DATA in metric.fields
if HAS_BASE_FIELDS:
ADD_METRIC = []
ADD_METRIC = Metric("telemetry_junos_evo")
ADD_METRIC.tags["name"] = metric.fields[CHECK_IF_NAME]
ADD_METRIC.tags["hostip"] = HOST_IP
ADD_METRIC.tags["hostname"] = HOST_NAME
ADD_METRIC.fields[FIELDS_NAME] = metric.fields[CHECK_IF_DATA]
RETURN_METRICS.append(ADD_METRIC)
else:
# フィールドが無ければforのloopを終了
break
#-------------------------------------------------------------------------------------
# 生成されたメトリクスを返す
return RETURN_METRICS
'''
#-------------------------------------------------------------------------------------
[[outputs.file]]
files = ["/var/log/telegraf/metrics.json"]
data_format = "json"
namepass = ["telemetry_junos_evo"] # メトリック名でフィルタリング
- 設定内容を反映させるため Telegraf をリスタート
- systemctl restart telegraf.service
Prometheusと連携
Prometheusのインストール
- Prometheusのインストール
- root ユーザで、以下を実施
apt -y install prometheus
systemctl enable prometheus
- 以下のサイトを参考にしてます
Prometheus側の設定
- 「/etc/prometheus/prometheus.yml」を編集する
- 事前にオリジナルのデータをコピーしておく
- cp -p /etc/prometheus/prometheus.yml /etc/prometheus/prometheus.yml.org
- 「/etc/prometheus/prometheus.ymlを編集
- 9273ポートでtelegrafのデータを取得する
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
scrape_configs:
- job_name: telegraf
static_configs:
- targets:
- localhost:9273
- 設定内容を反映させるため Prometheus をリスタート
- systemctl restart prometheus.service
Telegraf側の設定
- telegraf.conf に以下の設定をすることでPrometheusと連携できる
[[outputs.prometheus_client]]
listen = ":9273" # 9237ポートでprometheusと連携
collectors_exclude = ["gocollector", "process"] # デフォルトで利用される"gocollector", "process"は除外
namepass = ["telemetry_junos_evo"] # メトリック名でフィルタリング
- 設定内容を反映させるため Telegraf をリスタート
- systemctl restart telegraf.service
Prometheusで確認を行う
-
ブラウザで「http://[サーバのアドレス]:9090/」にログインして Prometheusの管理画面を開く
Grafana で Prometheus のデータを表示する
- Grafanaのインストールと設定は以下を参考にしてください
- ブラウザで「http://[サーバのアドレス]:3000/」にログインして Grafana の管理画面を開く
- 初期ユーザとパスワードはともに「admin」です
- Grafana と Prometheus の連携は他のサイトでもたくさん紹介されているため省略します。。。
- 最終的には以下のようなグラフ表示が出せます
最終的な設定ファイル
最終的な設定ファイルは以下となります
Telegraf
/etc/telegraf/telegraf.conf
telegraf.conf
[agent]
interval = "10s" # データを収集する間隔
round_interval = true # [true] の場合 収集時間は :00, :10, :20 ...
metric_batch_size = 1000 # バッチ処理で Outoput に送信する際のメトリクスサイズ
metric_buffer_limit = 10000 # 使用するメモリーの上限値
collection_jitter = "0s" # メトリクス収集の遅延時間 - 各プラグインがメトリクス収集の際に設定値の範囲内でスリープ
flush_interval = "10s" # Output データを出力する間隔
flush_jitter = "0s" # データを出力する際の遅延時間
precision = "0s"
logfile = "/var/log/telegraf/telegraf.log" # ログファイルのパス
logtarget = "file" # 出力先: "file", "stderr", "stdout"
# デバッグ時に有効にする
#debug = true
# ------------------------------------------------------------------------------------------------------------------------
#
# Telemetry (JUNOS-EVO)
#
# ------------------------------------------------------------------------------------------------------------------------
[[inputs.socket_listener]]
service_address = "udp://:20000"
data_format = "xpath_protobuf"
xpath_protobuf_files = ["telemetry_top.proto",
"aftman-cos-oc_ifl_render.proto",
#"aftman-cos-oc_render.proto",
"aftman-npu-mem-oc_render.proto",
"aftman-npu-util-oc_render.proto",
"aftman-qos-voqmon-stats-oc_render.proto",
#"aftman-sensor-ldp-lsp-ingress-oc_render.proto",
#"aftman-sensor-ldp-lsp-ingress-udp-oc_render.proto",
#"aftman-sensor-ldp-lsp-transit-oc_render.proto",
#"aftman-sensor-ldp-lsp-transit-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-lsp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-lsp-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-egress-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-egress-udp-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-ingress-oc_render.proto",
#"aftman-sensor-ldp-p2mp-per-if-ingress-udp-oc_render.proto",
#"aftman-sensor-lsp-ni-oc_render.proto",
#"aftman-sensor-lsp-oc_render.proto",
#"aftman-sensor-lsp-udp-oc_render.proto",
#"aftman-sensor-per-prefix-ipv4-oc_render.proto",
#"aftman-sensor-per-prefix-ipv4-udp-oc_render.proto",
#"aftman-sensor-per-prefix-ipv6-oc_render.proto",
#"aftman-sensor-per-prefix-ipv6-udp-oc_render.proto",
#"aftman-sensor-sr-egress-interface-openconfig_oc_render.proto",
#"aftman-sensor-sr-egress-interface_oc_render.proto",
#"aftman-sensor-sr-ingress-interface-openconfig_oc_render.proto",
#"aftman-sensor-sr-ingress-interface_oc_render.proto",
#"aftman-sensor-sr-sid_egress_oc_render.proto",
#"aftman-sensor-sr-sid_ingress_oc_render.proto",
#"aftman-sensor-sr-sid_ingress_openconfig_oc_render.proto",
#"aftman-sensor-srte-bsid-oc_render.proto",
#"aftman-sensor-srte-bsid-openconfig-oc_render.proto",
#"aftman-sensor-srte-bsid-udp-oc_render.proto",
#"aftman-sensor-srte-ingress-tunnel-oc_render.proto",
#"aftman-sensor-srte-ingress-tunnel-udp-oc_render.proto",
#"aftman-sensor-srte-ip-oc_render.proto",
#"aftman-sensor-srte-ip-openconfig-oc_render.proto",
#"aftman-sensor-srte-ip-udp-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-openconfig-oc_render.proto",
#"aftman-sensor-srte-per-lsp-ingress-udp-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-openconfig-oc_render.proto",
#"aftman-sensor-srte-per-lsp-transit-udp-oc_render.proto",
#"aftman-sensor-srte-transit-tunnel-oc_render.proto",
#"aftman-sensor-srte-transit-tunnel-udp-oc_render.proto",
"aftsysinfo-oc_render.proto",
"agent.proto",
"alarmd_oc_render.proto",
"am-cos-egress-qstat-oc_render.proto",
#"am-cos-egress-qstat-udp-oc_render.proto",
"am-cos-interfaceset-stats_render.proto",
"am-cos-intf-qstat-ext-oc_render.proto",
"am-ddos-oc_render.proto",
"am-dfw-oc-render.proto",
"am-ic-pfe-oc_render.proto",
"am-if-oc_render.proto",
"am-if-udp-oc_render.proto",
"am-ifl-udp-oc_render.proto",
#"am-ifl-v4-udp-oc_render.proto",
#"am-ifl-v6-udp-oc_render.proto",
"am-intf-exp-udp-oc_render.proto",
"am-jflowui-udp-oc_render.proto",
"am-pfe-oc_render.proto",
"bfdd-junos-openconfig-bfd-render.proto",
#"brcm-cos-qstat-oc_render.proto",
#"brcm-host-interface-pipestats-oc_render.proto",
#"brcm-if-oc_render.proto",
#"brcm-interface-pipestats-oc_render.proto",
#"brcm-pfe-oc_render.proto",
#"brcm-pfe-udp_render.proto",
"cda-btchip-ic-npu-util-oc_render.proto",
#"cda-btchip-npu-util-oc_render.proto",
"cda-bxchip-npu-util-oc_render.proto",
"cda-bxchip-stats-oc_render.proto",
"cda-drop-lookup-pipestats-oc_render.proto",
"cda-drop-state-pipestats-oc_render.proto",
"cda-expr_pipestats-oc_render.proto",
"cda-pkt-lookup-pipestats-oc_render.proto",
#"cda-zephyr-stats-oc_render.proto",
"cda-zxchip-npu-util-oc_render.proto",
"cda-zxchip-stats-oc_render.proto",
"cfmd-junos-state-oam-cfm-render.proto",
#"cmevod-fpcenv-oc_render.proto",
"cosd_oc_evo.proto",
"ddosd-junos-state-ddos-protection-render.proto",
"dot1xd-junos-openconfig-if-8021x-render.proto",
"dot1xd-junos-state-dot1x-render.proto",
"dot1xd_oc.proto",
"ehmd_comp_oc.proto",
"ehmd_oc.proto",
"ehmd_system_chassis_native.proto",
"ehmd_system_oc.proto",
"evo-if-oc_render.proto",
"evo-interface-pipestats-oc_render.proto",
"evo-pkt-host-interface-pipestats-oc_render.proto",
"fabricHub_oc.proto",
"fabspoked-fchip-junos-openconfig-platform-render.proto",
"fabspoked-pfe-junos-openconfig-platform-pipeline-counters-render.proto",
"fibtd-junos-state-anomalies-fib-render.proto",
"fibtd-telemetry_oc.proto",
"fwstatsd_oc_evo_state.proto",
"fwstatsd_oc_ni.proto",
"gnmi.proto",
"GnmiJuniperTelemetryHeader.proto",
"GnmiJuniperTelemetryHeaderExtension.proto",
"gnmi_dialout.proto",
"gnmi_ext.proto",
"hwdfpc_oc.proto",
"hwdre-evo-openconfig-system-render.proto",
"hwdre-healthz-oc_render.proto",
"hwdre-junos-state-health-render.proto",
"hwdre_fpc_env.proto",
"hwdre_oc.proto",
"jexpr-drop-host-interface-pipestats-oc_render.proto",
"jexpr-ic-npu-mem-oc_render.proto",
"jexpr-junos-integrated_circuit-oc_render.proto",
"jexpr-junos-npu-pipeline-resource-util-oc_render.proto",
"jexpr-npu-mem-oc_render.proto",
"jexpr-pkt-lookup-pipestats-oc_render.proto",
"jsd-junos-state-grpc.proto",
"jsd_health_oc.proto",
"junos-pfe-npu-render.proto",
"junos-xmlproxyd_junos-rsvp-interface.proto",
"junos-xmlproxyd_junos-rtg-task-memory.proto",
"junos_state_interface_render.proto",
"l2ald_bd_render.proto",
"l2ald_evpn_render.proto",
"l2ald_fdb_render.proto",
"l2ald_oc.proto",
"l2ald_oc_intf.proto",
"l2cpd-junos-state-lldp-render.proto",
"l2cpd_oc.proto",
"l2cpd_stp_oc.proto",
"lacpd_oc.proto",
"license-check-features-oc.proto",
"master-eventd-state-system-syslog.proto",
"master-eventd_oc.proto",
"mgmt-ethd_oc_evo_intf_stats.proto",
"mib2d_native_evo_intf_state.proto",
"mib2d_oc_evo_intf_state.proto",
"na-grpcd-junos-state-gnmi.proto",
"na-grpcd_stats_oc.proto",
"oc_component_render.proto",
#"oc_interface_render.proto",
"oc_optics_render.proto",
"pfe_page_drop_oc.proto",
"picd_oc_component_render.proto",
"platformd-fabric-oc_render.proto",
"resiliencyd-cmerror_cfg-oc_render.proto",
"resiliencyd-cmerror_cfg-udp-oc_render.proto",
#"resiliencyd-cmerror_stats-oc_render.proto",
"resiliencyd-cmerror_stats-udp-oc_render.proto",
"resiliencyd-comp_ic_pipeline_errcnt-oc_render.proto",
"rmopd_native_sensors_render.proto",
"rmopd_probe_oc_render.proto",
"rpd-junos-openconfig-ospfv2-render.proto",
"rpd_bgp_junos_route_validation.proto",
"rpd_bgp_junos_state.proto",
"rpd_bgp_rib_oc.proto",
"rpd_evpn_global_render.proto",
"rpd_evpn_instance_junos_state.proto",
"rpd_evpn_rib_oc.proto",
"rpd_gribi_stats_oc.proto",
"rpd_if_ipv6_ra_oc.proto",
"rpd_igmp_oc.proto",
"rpd_ipv6_ra_oc.proto",
"rpd_isis_oc.proto",
"rpd_ldp_oc.proto",
"rpd_ni_bgp_oc.proto",
"rpd_ni_evpn_render.proto",
"rpd_ni_oc.proto",
"rpd_pim_oc.proto",
"rpd_policy_oc.proto",
"rpd_resiliency_interface.proto",
"rpd_rsvp_oc.proto",
"rpd_srte_policy_oc.proto",
"rpd_te_oc.proto",
"svcsd_sflow_oc.proto",
"svcsd_sflow_openconfig.proto",
"sysd-evo-openconfig-system-render.proto",
"vrrpd_oc.proto",
"xmlproxyd-junos-commit-entries-render.proto",
"xmlproxyd-junos-openconfig-system-commit-render.proto",
"xmlproxyd-junos-openconfig-system-render.proto"]
xpath_protobuf_type = "TelemetryStream"
xpath_protobuf_import_paths = ["/usr/include/protos/junos-evo"]
xpath_native_types = true
[[inputs.socket_listener.xpath]]
field_selection = "//*"
field_name_expansion = false
timestamp = "//timestamp"
timestamp_format = "unix_ns"
metric_name = "string('telemetry_junos_evo')"
#-------------------------------------------------------------------------------------
# Starlarkプロセッサでメトリクスを編集 ('telemetry_junos_evo')
[[processors.starlark]]
namepass = ["telemetry_junos_evo"] # 「telemetry_junos_evo」のみ処理させる
source = '''
fieldpass = ["system_id", "name*", "in_octets*"]
def apply(metric):
## デバッグ用
#return metric
# ホストネームとIPを取得
SYSTEM_ID = metric.fields["system_id"]
#string = "vJunosEvolved:10.99.0.2"
PARTS = SYSTEM_ID.split(":")
NUM_ELEMENTS = len(PARTS)
if NUM_ELEMENTS == 2:
HOST_NAME = PARTS[0]
HOST_IP = PARTS[1]
elif NUM_ELEMENTS == 1:
HOST_NAME = PARTS[0]
HOST_IP = ""
else:
HOST_NAME = ""
HOST_IP = ""
# 新しいメトリクスを保存するリスト
RETURN_METRICS = []
MAX_INDEX = 10000 # 最大インデックスの設定
#-------------------------------------------------------------------------------------
# 必要なフィールドがあるかチェックし、複数IFの1行をIF毎に1行に分解する
FIELDS_NAME = "in_octets"
HAS_BASE_FIELDS = FIELDS_NAME in metric.fields
# 基本フィールド (index がない場合) の処理
if HAS_BASE_FIELDS:
ADD_METRIC = []
ADD_METRIC = Metric("telemetry_junos_evo")
ADD_METRIC.tags["name"] = metric.fields["name"]
ADD_METRIC.tags["hostip"] = HOST_IP
ADD_METRIC.tags["hostname"] = HOST_NAME
ADD_METRIC.fields[FIELDS_NAME] = metric.fields[FIELDS_NAME]
RETURN_METRICS.append(ADD_METRIC)
# インデックス付きフィールドを処理
for INDEX in range(MAX_INDEX): # MAX_INDEX までのループ
IF_INDEX = INDEX + 1
CHECK_IF_NAME = "name_" + str(IF_INDEX)
CHECK_IF_DATA = FIELDS_NAME + "_" + str(IF_INDEX)
# 必要なフィールドがあるかチェック
HAS_BASE_FIELDS = CHECK_IF_DATA in metric.fields
if HAS_BASE_FIELDS:
ADD_METRIC = []
ADD_METRIC = Metric("telemetry_junos_evo")
ADD_METRIC.tags["name"] = metric.fields[CHECK_IF_NAME]
ADD_METRIC.tags["hostip"] = HOST_IP
ADD_METRIC.tags["hostname"] = HOST_NAME
ADD_METRIC.fields[FIELDS_NAME] = metric.fields[CHECK_IF_DATA]
RETURN_METRICS.append(ADD_METRIC)
else:
# フィールドが無ければforのloopを終了
break
#-------------------------------------------------------------------------------------
# 生成されたメトリクスを返す
return RETURN_METRICS
'''
#-------------------------------------------------------------------------------------
## デバッグ用
#[[outputs.file]]
# files = ["/var/log/telegraf/metrics.json"]
# data_format = "json"
# namepass = ["telemetry_junos_evo"] # メトリック名でフィルタリング
#===================================================================================
# ------------------------------------------------------------------------------------------------------------------------
#
# Prometheusへの出力
#
# ------------------------------------------------------------------------------------------------------------------------
[[outputs.prometheus_client]]
listen = ":9273" # 9237ポートでprometheusと連携
collectors_exclude = ["gocollector", "process"] # デフォルトで利用される"gocollector", "process"は除外
namepass = ["telemetry_junos_evo"] # メトリック名でフィルタリング
Prometheus
/etc/prometheus/prometheus.yml
prometheus.yml
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
scrape_configs:
- job_name: telegraf
static_configs:
- targets:
- localhost:9273
最後に
Telegrafを利用して、JuniperのJUNOS-EVOの Dial-OutのTelemetryデータの収集・可視化まで確認できました。
今回はUDPでのTelemetryで確認しましたが、UDP以外にgRPCにもJUNOSは対応していて他社もgRPCの実装も多いみたいなので、次はgRPCのDial-OutなTelemetryもやってみたい