New Relicで使用するSNMP Trap用のプロファイル定義ファイルの作成方法

記事タイトルとURLをコピーする

みなさんこんにちは。マネージドサービス課の塩野です。

New Relicでネットワーク監視を行う場合、公式ドキュメント自体は存在するもののドキュメントの解像度が低くて設定方法がよくわからんぞという場面に度々ぶち当たることがあります。今回はそのあたりを考慮した設定方法についてまとめてみました。一部設定については公式ドキュメントや Kentik社の KtranslateレポジトリのWikiなどにも記載がない裏仕様の情報が含まれていますので、公式ドキュメントに記載がないからといってメーカーに問い合わせしないでください。

目次

概要

New Relic を使ってシステム全体のオブザーバビリティを向上しようとした際に、New Relicの機能にネットワーク監視機能があって使ってみたいという話はちらほら頂くことがありますが、実際にどうするんだっけという部分についてはドキュメントを読んでもふわっとした書き方をしているケースが多く、インターネットでもあまり情報がないような状態ではないかと思います。

今回はYAMAHAから提供されているMIBファイルを使用して実際に設定ファイルを作りこんて行く際にどの辺に気を付けてどのように設定していったらいいかという点をまとめてみました。特にSNMPの場合は機器の状態を監視サーバから見に行くSNMP Polling機能と機器で発生したイベントを監視サーバに通知するSNMP Trapの機能があり、この記事では後者のSNMP Trapの定義ファイルをNew Relic向けに作成する内容を記載しています。

SNMP Trapの設定をおこなうと、例えばスイッチポートアップダウンの検出、ハードウェア異常(ファン、電源、温度)、ループ検出などなど様々なイベントがSNMP Trap経由で通知されます。今回の記事で記載している定義ファイル無しに設定した場合、New Relic NPMの表示上で 1.3.6.1.4.1.1182.2.5.0.6 のイベントが発生したという通知になり、通知されたところで 1.3.6.1.4.1.1182.2.5.0.6 のイベントってなんだっけとなってしまい非常に使いづらい状態に陥ります。これが yrSwPowerUnitFailure というイベントで通知されたらやっぱり見やすいですよね。なので、監視を効率的に処理するには、適切な定義ファイルが必要になるというお話です。

作業を始める前に、YAMAHAのMIBファイルを変換したjsonファイル、YAMLをサポートするテキストエディタ、そしてNew Relic NPMで使用されるktranslateというSNMP処理エージェントは別途ご準備をお願いします。

※当記事では YAMAHA-RT-SWITCH.json を使用して実際に作りこみを行います。

MIB定義ファイルの基本を理解する

定義ファイルはYAML形式で記述します。YAMLは階層構造を持つ設定ファイル形式で、インデントにはスペース2つまたは4つを使用します。リスト項目はハイフン(-)で始まり、キーと値はコロン(:)で区切ります。文字列は引用符なしでも記載できるため、比較的読みやすい形式です。

基本的な構造は次のようになります。

traps:
  - trap_oid: <OID文字列>
    trap_name: <トラップ名>
    drop_undefined: <true/false>
    attributes: <属性定義>
    events:
      - name: <変数名>
        OID: <変数のOID>
        tag: <表示名>
        enum: <列挙型定義>

定義ファイルを作成する上で最も重要な点として、ファイル名は必ずtraps.yamlまたはtraps.ymlにする必要があります。これは、New Relic NPMで使用されるktranslateがこの特定のファイル名を探すためです。詳細はまとめの項に記載しますが、この内容については2025/09/13時点で公式ドキュメントに記載されていないように見受けられますのでご注意ください。

主要なパラメータを詳しく見てみよう

trap_oidについて

trap_oidは、トラップメッセージを一意に識別するOID(Object Identifier)です。完全一致の指定だけでなく、ワイルドカードを使った階層的マッチングも可能です。例えば、1.3.6.1.4.1.1182.2.5.0.1と指定すれば特定のトラップのみを、1.3.6.1.4.1.1182.2.5.0.*と指定すればその配下のすべてのトラップをキャッチできます。

drop_undefinedの動作

drop_undefinedパラメータは、定義されていないトラップや変数の扱いを制御します。trueに設定すると定義外のものは破棄され、falseまたは未定義の場合はすべて処理されます。開発段階ではfalseにしておき、本番環境ではtrueにするという使い分けが一般的です。

attributesによる追加情報

トラップに関連する追加属性を定義できます。severityで重要度を、categoryで分類を指定するなど、監視システムでの処理に役立つメタデータを付与できます。

attributes:
  severity: critical
  category: hardware

eventsセクションの詳細な役割

eventsセクションは、SNMP Trapメッセージの中核となる部分です。ここでは、トラップに含まれる各変数(Variable Binding)の詳細な定義を行います。

まず、基本的な構成要素から見ていきましょう。nameパラメータには、元のMIBファイルで定義されている変数名をそのまま指定します。これは、YAMAHA-RT-SWITCH.jsonファイルのobjects配列に記載されている名前と一致させる必要があります。例えば、スイッチの製品タイプを表すyrSwProductなどです。

OIDパラメータには、その変数の実際のObject Identifierを指定します。ここで重要なのは、スカラー値の場合は末尾に.0を付加することです。これはSNMPの仕様によるもので、単一の値を持つオブジェクトには必ずインスタンス識別子として.0が必要になります。

tagパラメータは、監視システムでの表示名を定義します。元のMIB名は技術的な命名規則に従っているため、そのまま使うと分かりにくいことがあります。例えば、yrSwProductproduct_typeとして定義することで、より直感的に理解できるようになります。この命名は、監視画面やアラート通知での可読性に直接影響するため、慎重に選ぶ必要があります。

最も興味深い機能の一つがenumパラメータです。SNMP Trapでは、多くの状態値が数値で送信されてきます。例えば、ファンの状態が「1」や「2」といった数値で表現されていても、それが何を意味するのかは一見して分かりません。enumを使用することで、これらの数値を意味のある文字列にマッピングできます。

events:
  - name: yrSwFanStatus
    OID: 1.3.6.1.4.1.1182.2.5.2.1.7.0
    tag: fan_status
    enum:
      normal: 1    # 1という値を受信したら"normal"として表示
      lock: 2      # 2という値を受信したら"lock"として表示
      none: 3      # 3という値を受信したら"none"として表示

このマッピングにより、監視画面では「ファン状態: 2」ではなく「ファン状態: lock」と表示されるようになり、オペレーターは即座に問題を認識できます。

また、eventsセクションは配列形式になっているため、一つのトラップに複数の変数を含めることができます。例えば、スイッチ発見のトラップでは、スイッチの台数、製品タイプ、MACアドレスといった複数の情報を同時に送信できます。これらの変数は、トラップが発生した際にすべて一緒に処理され、監視システムに送られます。

変数の処理順序も重要です。ktranslateは、eventsセクションに記載された順番で変数を処理します。そのため、相互に関連する変数がある場合は、適切な順序で定義することが推奨されます。

YAMAHA RTのMIBを分析する

提供されたJSONファイルから必要な情報を抽出する際は、class: "notificationtype"を持つエントリを探します。これらがTrap定義です。各Trapのoid値と、objects配列内の変数名を確認していきます。

サンプルのYAMAHA MIBでは、スイッチ発見(yrSwFindSwitch)、スイッチダウン検出(yrSwDetectDown)、ファンロック(yrSwFanLock)、電源異常(yrSwOverSupply)、温度異常(yrSwOverTemp)など、多岐にわたるTrapタイプがあり、それぞれのTrapには固有のOIDが割り当てられています。

なお、ベンダーのMIBファイルからヒューマンリーダブルなJSON形式に変換する方法については下記記事をご参照ください。

blog.serverworks.co.jp

参考:YAMAHA RT のMIBファイル

{
  "imports": {
    "SNMPv2-CONF": [
      "MODULE-COMPLIANCE",
      "NOTIFICATION-GROUP"
    ],

<一部省略>

  "yrSwDetectDown": {
    "class": "notificationtype",
    "name": "yrSwDetectDown",
    "objects": [
      {
        "module": "YAMAHA-RT-SWITCH",
        "object": "yrSwNumber"
      },
      {
        "module": "YAMAHA-RT-SWITCH",
        "object": "yrSwProduct"
      },
      {
        "module": "YAMAHA-RT-SWITCH",
        "object": "yrSwPhysAddress"
      }
    ],
    "oid": "1.3.6.1.4.1.1182.2.5.0.2"
  },
  "yrSwLoopDetectPort": {
    "class": "notificationtype",
    "name": "yrSwLoopDetectPort",
    "objects": [
      {
        "module": "YAMAHA-RT-SWITCH",
        "object": "yrSwLoopDetectPortStatus"
      }
    ],
    "oid": "1.3.6.1.4.1.1182.2.5.3.0.1"
  },

<一部省略>

  "yrSwTemp": {
    "class": "objecttype",
    "maxaccess": "read-only",
    "name": "yrSwTemp",
    "nodetype": "column",
    "oid": "1.3.6.1.4.1.1182.2.5.2.1.9",
    "status": "mandatory",
    "syntax": {
      "class": "type",
      "type": "INTEGER"
    }
  }
}

高度な機能:動的OIDの活用

通常のOID定義に加えて、変数を含む動的なOIDの定義も可能です。例えば、インターフェースごとに異なる値を持つような場合、次のように記述できます。

events:
  - name: dynamicInterface
    OID: 1.3.6.1.4.1.1182.2.5.{ifIndex:1}.{status:1}
    tag: interface_status_dynamic

この記法では、{変数名:長さ}の形式でOIDの一部を変数として扱います。{変数名:*}とすれば、残りのすべての値をワイルドカードとして取得することも可能です。

実際にYAMLファイルを作成してみる

それでは、実際にファイルを作成していきましょう。まず基本構造から始めます。ファイル名はtraps.yamlとします。

最初に、スイッチ発見のTrapを定義してみます。このTrapは新しいスイッチが検出されたときに送信されます。

traps:
  - trap_oid: 1.3.6.1.4.1.1182.2.5.0.1
    trap_name: yrSwFindSwitch
    drop_undefined: false
    attributes:
      severity: info
      category: discovery
    events:
      - name: yrSwNumber
        OID: 1.3.6.1.4.1.1182.2.5.1.0
        tag: switch_count
      - name: yrSwProduct
        OID: 1.3.6.1.4.1.1182.2.5.2.1.2.0
        tag: product_type
        enum:
          swx2200-8g: 2
          swx2100-16g: 6
          # 他の製品タイプも同様に定義

次に、より重要度の高いファンロックのTrapを定義します。冷却ファンが停止した場合に送信されるこのTrapは、機器の故障につながる可能性があるため、critical扱いとします。

  - trap_oid: 1.3.6.1.4.1.1182.2.5.0.3
    trap_name: yrSwFanLock
    drop_undefined: false
    attributes:
      severity: critical
      category: hardware
    events:
      - name: yrSwFanStatus
        OID: 1.3.6.1.4.1.1182.2.5.2.1.7.0
        tag: fan_status
        enum:
          normal: 1
          lock: 2
          none: 3

このように、各Trapタイプごとに適切な定義を追加していきます。完成したファイルには、すべてのTrapタイプの定義が含まれることになります。

カスタマイズのポイント

タグ名を付ける際は、snake_case(小文字とアンダースコア)を使用することをお勧めします。fan_statusloop_port_statusのように、意味が明確で簡潔な名前を選びましょう。

複数のTrapタイプを管理する場合は、関連するものをコメントでグループ化すると見通しがよくなります。ハードウェア監視関連、ネットワーク監視関連といった具合に分類することで、メンテナンスが容易になります。

enum値は、状態を表す値には必ず定義するようにしましょう。ただし、温度や電圧のように数値そのものが重要な場合は、enumは不要です。適切に使い分けることで、監視画面での表示を最適化できます。

ファイルの配置と有効化

作成したファイルは、New Relic NPM環境のktranslateのカスタムプロファイルディレクトリに配置します。 Docker コンテナを利用している場合は、カスタムプロファイル関連ファイルをまとめて /etc/ktranslate/profiles などに配置するようにすればカスタムプロファイルのみ参照する設定となります。また標準プロファイルとカスタムプロファイルを併用したい場合は、/etc/ktranslate/profiles/custom/ に配置するとよいでしょう。設定後、New Relic NPM環境のktranslateを再起動すれば、新しい定義が有効になります。

トラブルシューティング

設定がうまくいかない場合は、まずYAMLの構文をチェックしましょう。yamllintツールやPythonのyamlモジュールを使って検証できます。

ログの確認も重要です。ktranslateのログを見れば、プロファイルの読み込み状況やTrap受信時の動作を確認できます。特に、ファイル名が正しいか、OIDが正確に記載されているか、インデントが統一されているかを確認してください。

Trapが受信できない場合は、ネットワーク接続を確認します。ファイアウォールでUDP 162番ポートが開いているか、スイッチ側のSNMP Trap送信先設定が正しいかを確認しましょう。tcpdumpを使えば、実際にパケットが到達しているかを確認できます。

まとめ

New RelicのNPM用プロファイル定義ファイルを作成する際に気をつけなければいけない点はある程度記載しましたが、公式ドキュメントに書かれていない=サポートに聞いても解決しないという点はユーザーとしてもう少し何とかならないかなと思うところはありますが、Ktranslate自体がOSSで公開されているため最悪コードをみれば挙動がわかるという点ではドキュメントより実際に動いているアプリケーションのコードの方が信頼性が高いように思います。

本文の中で「ファイル名は必ずtraps.yamlまたはtraps.ymlにする必要がある」と記載しましたが、下記レポジトリの /pkg/inputs/snmp/mibs/profile.go に実はヒントが隠されています。このファイルはこうしたカスタムプロファイルや標準プロファイルを読み込むためのコードが書かれているファイルになりますが、profile.go の中の loadProfileDir 関数に下記のような記述があります。

func (mdb *MibDB) loadProfileDir(profileDir string, extends map[string]*Profile) error {
    files, err := os.ReadDir(profileDir)
                 :

        if file.Name() == "traps.yaml" || file.Name() == "traps.yml" { // Traps are pulled out into seperate files.
            err := mdb.parseTrapsFromYml(fname, file, extends)

                 :

github.com

私自身、アプリケーション開発者というロールではありませんのでコードの内容を深く解説することはできませんが、少なくともファイル名固定でパース処理をしているというのはここから充分に伝わってきます。そのためKtranslateのコードからファイル名は traps.yaml のような名称で保存すべきですし、実際に traps.yaml で意図した通り動作していることも確認しております。OSSの場合は自分でコードの改修ができなかったとしても少々手荒い方法ですがある程度コードの内容から把握することができますので、困った時はコードを眺めてみることをオススメします。

さて、余談な話はここまでにして、今回紹介した手順に従えばNew Relic NPM環境で実際のコード動作に即した正確なTrap定義ファイルを作成できると思います。ネットワーク監視を試してみたいと思われた方は、ぜひお使いのデバイスに合わせてNew Relic NPM環境用のプロファイルを作成してみてはいかがでしょうか。

宣伝

弊社では、お客様環境のオブザーバビリティを加速するためのNew Relicアカウント開設を含めた伴走型のNew Relic導入支援サービスをご提供しております。 もしご興味をお持ちの方は、こちらのお問合せフォームよりお問合せ頂けましたら幸いでございます。

◆ 塩野 正人
◆ マネージドサービス部 所属
◆ X(Twitter):@shioccii
◆ 過去記事はこちら

前職ではオンプレミスで仮想化基盤の構築や運用に従事。現在は運用部隊でNew Relicを使ってサービス改善に奮闘中。New Relic User Group運営