クエリのスクリプト化

Traffic Sentinelのクエリ スクリプト化機能は、特化したクエリを作成するための強力なメカニズムを提供します。 ただし、一般的なタイプのレポートのほとんどを標準レポーティング機能で作成できるので、スクリプティング インターフェースを使用する必要はほとんどありません。 通常、スクリプト化は、データを抽出して他のツール(ビリング アプリケーションなど)にインポートできるようにフォーマッティングしたり、複数のソースからのデータを1つのチャートまたはテーブルにまとめて表示する新しいタイプのレポートを作成する場合などに使用されます。

クエリを実行する

スクリプティング インターフェースは、レポート(Reports)>スクリプト(Script)メニューから利用できます。 下図は、スクリプト フォームにデフォルトのクエリ スクリプトが表示されている様子を示しています。

フォームのテキスト入力フィールドにスクリプトを入力するか貼り付けて実行(Submit)ボタンをクリックすると、スクリプトが評価されます。 デフォルト(Defaults)ボタンをクリックすると、テキスト入力フィールドの内容がデフォルト スクリプトに戻ります。 デフォルト スクリプトは、単純なtopNクエリを実行するものです。 この中のviewwhereintervalsortnformatおよびheadingの値を編集して、クエリを試しに実行し、結果を調べることができます。

下図は、一般的なクエリ実行結果を示しています。

戻る(Back)ボタンをクリックすると、スクリプト フォームに戻ります。

データをインポートする

クエリの結果を表示する場合は、TXTボタンをクリックすると、URLエンコードされたクエリを示すシンプル テキストによる結果を得ることができます。 このURLをコピーして使用すれば、いつでも同じクエリを実行できます。 wgetPerlなどのウェブ対応ツールでこのクエリURLを使用して、データを抽出することができます。

IQYボタンは、クエリをMicrosoft ExcelのIQYフォーマットで表示します。 このテキストを切り取って貼り付け、ノートパッドを使用してそのテキストを拡張子が.IQYのファイルに設定すると、Microsoft Excelでそのファイルを使用してWebクエリを実行することができます。
注記: Excelには、CSVフォーマットよりもHTMLテーブル フォーマットのデータがより適しています。 デフォルト クエリ スクリプトのformatを"html"に変更すると、結果をHTMLテーブル フォーマットで得ることができます。

クエリを作成する

Traffic Sentinelで使用されるスクリプティング言語はE4X拡張を持つJavaScript 1.6です。 Javascriptは、ウェブ ページ内で一般的に使用される簡易的なスクリプティング言語です(Visual Basicに非常によく似ています)。 Javascriptについては多くの無料チュートリアルがあります(Googleで"javascript tutorial"を検索してください)。 書籍をお探しなら、『Javascript: The Definitive Guide』が参考文献として優れています。

このチュートリアルの残りの部分では、スクリプトを用いてネットワークのトポロジーやトラフィックに関する情報にアクセスして計算を実行し、他のツールにインポートしやすいように結果を出力する方法の例を紹介します。
注記: ここで紹介するサンプル スクリプトを切り取り、スクリプト フォームに貼り付けて実行してみることができます。 Traffic Sentinelのコピーを利用できない場合は、sentinel.inmon.comでこれらのスクリプトを実行できます。

Print(出力)

Printファンクションは、標準のJavascript言語には含まれていませんが、printおよびprintlnという2つのグローバル ファンクションが追加され、スクリプトからテキスト出力を返すことができるようになりました。 printは結果を出力するファンクションで、printlnは結果を出力してから改行も行うファンクションです。

print("hello");
println(" world");
println("one plus one equals " + (1 + 1)); 

Print ファンクションは、スクリプトのテストに非常に有効です。 スクリプトにprint文を入れることにより、期待どおりの結果が得られているかどうかを確認することができるからです。

Network(ネットワーク)

Networkクラスは、ネットワーク ステートにアクセスするためのインターフェースです。エージェントとインターフェース、ネットワーク トポロジーおよびアドレス マッピングに関する情報を提供します。

次の例は、新規のnetworkオブジェクトを作成し、すべてのエージェントのリストを要求し、出力処理を繰り返してリスト内のすべてのエージェントのIPアドレスとシステム記述を出力するものです。

var n = new Network();
var agents = n.agents();
for(var i = 0; i < agents.length; i++) {
  n.path = agents[i];
  println("ip=" + n.agentIP() + " sysDescr=" + n.sysDescr());
};

path属性は、環境設定に定義されているネットワーク デバイスの階層的な分類を参照します(ネットワーク階層の詳細については、Traffic Sentinelの環境設定のチュートリアルを参照してください)。 この属性によりパスが設定され、以降のクエリの適用範囲が制限されます。前の例では、エージェントのパスを設定してクエリを実行したので、クエリではエージェント固有のデータが得られました。

また、networkオブジェクトには、引数の配列を入力して結果の配列を出力する数々のMapファンクションがあります。 次の例では、vendorMapファンクションを使用してMACアドレスの配列に関連付けられるベンダー名を検索しています。

var n = new Network();
var macs = ["000480F54600","001321B21CE1","0002556F2F78"];
var vendors = n.vendorMap(macs);
for(var i = 0; i < macs.length; i++) println(macs[i] + " " + vendors[i]); 

Query(クエリ)

Queryクラスは、トラフィック データベースからインターフェース カウンタ データやトラフィック フロー情報を抽出するために使用されます。 トラフィック データベースはいくつかのビューからなり、各ビューには一連の属性があります。

  • historytrmx  履歴に基づくトラフィック フロー データ(例: 前月の上位ウェブ サーバー)について問い合わせるためのビューです。
  • historycounters  履歴に基づくインターフェース カウンタのトレンド(例: あるリンクの前月の利用トレンド)について問い合わせるためのビューです。
  • rttraffic  履歴にまとめられる前の、短期間のトラフィック フロー(例: 過去10分間の上位ブロードキャスト ソース)について問い合わせるためのビューです。
  • rtcounters  短期間のインターフェース カウンタのトレンド(例: あるリンクにおける過去20分間のエラー トレンド)について問い合わせるためのビューです。
  • events  イベント ログについて問い合わせる(例: 最も多く発生したクリティカル イベントのタイプを特定する)ためのビューです。
注記: 上のリストのリンクをクリックすると、各ビューのすべての属性について詳細を表示できます。

ビュー内の属性は、集約時にカテゴリーを形成する「キー」と、累積される「値」の2種類に大別されます。 たとえば、ipsourceはカテゴリーで、bytesは値です。 ipsource属性とbytes属性を指定してクエリを実行すると、各ソースIPアドレスの合計バイト数が結果として得られます。

クエリを作成するためには、ビューを指定し、属性と対象期間を選択し、結果のソート方法を指定する必要があります。 下の例では簡易的なクエリが作成されます。

var q = new Query();
q.view     = "historytrmx";
q.select   = "ipsource,bytes";
q.where    = "sourcezone != EXTERNAL";
q.interval = "today";
q.sort     = "bytes";
q.truncate = 5;
var t = q.run();
t.printCSV(true);

このスクリプトは上位5個のローカルIPソース アドレスをバイト数順にソートして表示するためのクエリを実行します。 q.run()文はクエリを評価し、結果としてテーブルを返します。

同じクエリをこれより簡易的な方法で作成するには、Query.topNファンクションを使用します。次のスクリプトにより実行されるクエリは、上のスクリプトによるものと全く同じです。

var q = Query.topN("historytrmx",
                   "ipsource,bytes",
                   "sourcezone != EXTERNAL",
                   "today",
                   "bytes",
                   5);
var t = q.run();
t.printCSV(true); 

この例では、データはビュー内の値属性の1つによりソートされています。 代わりに1つのキー属性の一意の値がいくつあるかを数え、それを値として使用するのが有効な場合もあります。 そのようなクエリは、(多くの場合、インターネット ワームやポート スキャンに関連する)スキャン動作を見きわめようとする場合に特に有用です。 次の例は、countファンクションをクエリに応用できることを示しています。

var q = Query.topN("historytrmx",
                   "ipsource,count(ipdestination)",
                   "destinationport = TCP:80 & sourcezone != EXTERNAL",
                   "today",
                   "count(ipdestination)",
                   5);
var t = q.run();
t.printCSV(true);
このクエリは、ローカル ネットワーク上のホストによりTCPポート80を用いてアドレス スキャンされた回数をカウントし、その回数が特に多いホストを回数順に並べたリストを出力します。

一般的に用いられるもう一つのタイプのクエリとしては、時間経過に伴う変化のトレンドを示すものがあります。 次のスクリプトでは、Query.trendファンクションを使用してクエリを作成しています。

var q = Query.trend("historytrmx",
                   "time,bytes",
                   "protocol = TCP",
                   "yesterday",
                   "hour");
var t = q.run();
t.printCSV(true);

このスクリプトは、TCPトラフィックの合計バイト数の1時間ごとのトレンドを明らかにします。 合計バイト数ではなくバイト レート(つまり、各期間の毎秒の平均バイト数)を知りたい場合は、下のようにbytesの代わりにrate(bytes)という式を使用してください。

var q = Query.trend("historytrmx",
                   "time,rate(bytes)",
                   "protocol = TCP",
                   "yesterday",
                   "hour");
var t = q.run();
t.printCSV(true);

Table(テーブル)

Tableクラスは、クエリ結果を表示するために使用されます。 テーブルは、テーブルの列についての情報(列名やタイプなど)と何行かのデータで構成されます。

var q = Query.topN("historytrmx",
                   "ipsource,bytes",
                   "sourcezone != EXTERNAL",
                   "today",
                   "bytes",
                   5);
var t = q.run();
var n = new Network();
var addresses = t.column(0);
var locations = n.locationMap(addresses);
t.insertColumn("location","interface",locations,1);
t.printCSV(true); 

このスクリプトは、アドレスが設定されているテーブル列(列0)にアクセスし、n.locationMapファンクションを使用して、スイッチ インターフェースをネットワークに接続する各アドレスを探し出します。 さらに、insertColumnファンクションを使用して、テーブル内のアドレスの直後にロケーション情報を挿入します(挿入される列の名前はlocationで、タイプはinterfaceとして宣言されます)。

SNMP

SNMPクラスは、ネットワーク内のデバイスに SNMP (Simple Network Management Protocol) リクエストを発行するときに使用されます。多くの標準的なSNMP変数は、すでに Networkクラス (例;sysName(), ifName() など) を用いることで可能です。これは、可能であればネットワーククラスから情報を引き出すのに非常に効果的です。一般的に、SNMPクラスは、デバイスからTraffic Sentinelが常時モニターしていないデータやベンダー固有の情報を収集するのに使われます。

以下のスクリプトは、どのようにしてベンダー固有の情報が収集されるかを示しています。この例は、Foundry Networks社製スイッチの温度情報を収集しています。:

var selectedAgents = new Array();
var n = new Network();
for each (var agent in n.agents()) {
  n.path = agent;
  var id = n.sysObjectID();
  if(id && id.indexOf(".1.3.6.1.4.1.1991.") == 0) selectedAgents.push(agent);
}

var s = new SNMP();
s.oid = ".1.3.6.1.4.1.1991.1.1.1.1.18.0";
var t = Table.create(["Agent","Name","Degrees C"],
                     ["agent","string","integer"]);
for each(var agent in selectedAgents) {
  n.path = agent;
  s.host = agent;
  try {
    var val = s.get();
    if(val[0]) t.addRow(new Array(agent, n.sysName(), parseInt(val[0]) / 2));
  } catch(ex) {};
}
t.printCSV(true);
スクリプトの最初のパートでネットワーク・オブジェクトを使用して、全てのエージェントを列挙しています。Foundry Networksのエージェントは、それぞれのエージェントのsysObjectIDがFoundry Networks の接頭子として".1.3.6.1.4.1.1991."を持つものをチェックすることにより識別されます。スクリプトの2番目のパートは現在のシャーシの温度の収集のためのリクエストを選択されたエージェントのそれぞれに対して送出し、テーブルとしてその結果がまとめられます。

readurl

readurl 機能は、スクリプト内にデータをインポートするために使用されます。以下の例は、どのようにして readurl がオンラインの情報ソースにアクセスするかを示しています。:

var addr = "64.151.76.40";
var url = "//www.radb.net/cgi-bin/radb/whois.cgi?obj=" + addr;
var res = readurl(url);
var match = /descr:[\s]+([^\n]+)/.exec(res);
println(match[1]);
このスクリプトは、IPアドレスに関する情報に対して、Merit Routing Asset Database(RADb) を参照し、URLを構成します。その取得したTEXT情報は、正規表現によって構文解釈され descr: フィールドの値がプリントされます。

次の例は、XMLファイルをインポートして、それを使用して、情報をルックアップします:

var url = "//www.inmon.com/tutorials/db.xml";
var db = new XML(readurl(url));
println(db.server.(name=="Web").address);
db.xml ドキュメントは、それぞれに名称やアドレスが記述されたいくつかのサーバーに関するレコードが含まれています。E4X は、XML固有の機能のサポートを javascript に拡張し、クエリ・クリエイト・モディファイやXMLドキュメントのプリントなどのメカニズムを提供します。

最後に、readurl は、スクリプトの最初で javascript機能のライブラリや値をロードするのに使用出来ます。:

var initscript = readurl("//www.inmon.com/tutorials/init.js");
eval(initscript);
println(descr("64.151.76.40"));
init.js スクリプトは、簡単にRADb ルックアップ機能を実装した descr() 機能を含みます。

スクリプトを使用する

スクリプトの主な使用方法は3つあります。 クエリのURLを用いてウェブベースでクエリを実行する方法、queryコマンドに入力して実行する方法、そしてTraffic Sentinelレポーティング ツールで使用するためにスクリプトをXMLテンプレートに組み込む方法です。

URL

クエリのURLは以下のフォーマットになります。

/inmsf/Query?script=script&authenticate=basic&resultFormat=txt
ここで、scriptはjavascriptのソースです。

このURLを使って、スクリプトにさらに他の引数を渡すこともできます。 このURLの中の

input_name=value
という形式の属性はどれも、次の形式の代入としてスクリプトに渡されます。
var name = value;

下のスクリプトはこの処理の実例を示しています。

var addrs = [];
if(typeof(address) != 'undefined') addrs = address.split(",");
var n = new Network();
var locations = n.locationMap(addrs);
for(var i = 0; i < addrs.length; i++) {
  n.path = locations[i];
  print(addrs[i]+ " " + n.sysName() + " " + n.ifName()); 
};

このスクリプトは、addressパラメータ(アドレス文字列)が定義されているかどうか(つまり、addressパラメータがスクリプトに渡されたかどうか)を調べます。 アドレス文字列が定義されている場合、その文字列はカンマ区切りのリストと見なされ、一つ一つのアドレスに分割されてアドレス配列の各要素に設定されます。 locationMapファンクションが各アドレスをネットワークに接続するインターフェースを特定し、このようにして得られたエージェントおよびインターフェースの情報が出力されます。

下のフォームは、このスクリプトをウェブ フォームに埋め込む方法を示しています。ボタンをクリックして結果を見てみましょう。

ブラウザを使用してこのページのhtmlソースを表示し、このフォームの構造を調べてください。 文字列の区切りには二重引用符ではなく一重引用符が用いられているので、このスクリプトを1つのフォーム フィールドとして含めることができます。

コマンド ライン

コマンド ラインでのqueryファンクションは、標準のTraffic Sentinelインストールに含まれています。 このコマンドは、/usr/local/inmsf/bin/queryにあります。 下の例のように、queryコマンドはスクリプトを標準の入力方法とします。

echo "println('hello world');" | /usr/local/inmsf/bin/query
あるいは、下の例のようにスクリプト ファイルから入力することもできます。
/usr/local/inmsf/bin/query /scripts/hello.js

コマンド ラインでのqueryファンクションは、標準のLinuxツールを用いてトラフィック データにアクセスするときなどに役立ちます。 コマンド ラインでのqueryはウェブ サーバーとネットワークをバイパスするので、URLベースのクエリより信頼できます。 このコマンドの主な用途の一つに、ビリングを目的とするトラフィック会計データの周期的抽出があります。 Linuxのcronサービスは、利用状況データ(ビリング システム内のビリング レコードの更新に使用されるデータ)をクエリで取得するスクリプトを周期的に実行することができます。

XMLレポート テンプレート

レポート テンプレートの作成というチュートリアルでは、クエリ スクリプトに基づいてレポート テンプレートを作成する方法を説明しています。 このスクリプトを発展させて、カスタマイズしたチャートやテーブルをレポート内に作成することができます。 レポート テンプレートを作成しておけば、それをオンデマンドで、あるいはスケジュールにより実行してレポートを作成し、イベントを生成することができます。

ウィジェット・テンプレートの作成 というチュートリアルでは、クエリ スクリプトに基づいてウィジェット・テンプレートを作成する方法を説明しています。 このスクリプトは、ウィジェット内のチャートやテーブルの表示機能を拡張することが出来ます。ウィジェット・テンプレートを作成しておけば、ダッシュボード上で利用できます。