Heroku で concurix-server を動かす

concurix-server のバージョン 0.2.19 以降を使用します。トレーサーのパラメータのうち、api_host には、concurix-server が走っている Heroku app URL を指定し、api_port は 80 を設定します。例えば、以下のようにします。

 

var concurix = require("concurix")({

  accountKey: "wfp:helloworld", // 必要 "wfp:"で始まる英数字文字列

  archiveInterval: 5000, // ミリ秒 規定値 60000

  api_host: "myapp.herokuapp.com", // 規定値 'localhost'

  api_port: 80 // 規定値 8103

})

Intel Edison のモニタリングに Concurix を使う

クリスマス休暇前に Intel Edison/Arduino を入手できました。今回は、Edison 上で helloworld を走らせ、Concurix を使ってモニターした話です。

Edison の詳細は Intel のサイトを見ていただくとして、つづめて言えば「500MHzで動作する32bitアーキテクチャ CPUに、IEEE802.11a/b/g/n対応無線LAN とBluetooth 4.0、メモリはRAM 1GB/Flash 4GBを備え、Nodejs 0.10.28 が入ったSystem on Chip (SoC)」で、用途は、Internet of Things (IoT) 、外観は以下の写真のようです。

f:id:setogit:20141223145455j:plain

そこに写っている物のリストを示します。

  • MacBook Pro は 15インチで、OSX Yosemite Version 10.10.1 です。
  • Intel Edison: Standard Power On Board Antenna + Arduino, Product Code: EDI1ARDUINALK
  • belkin Micro USB Charge/Sync Cable 1.2m/4feet、青コード、黒コードの二本、各$10 で購入
  • ativa USB 2.0 4-Port Hub item 900-447(必須ではありません。MacBook の USB ポートを二つ使いたくないという理由で、能動回路の付いていないものを $15 で購入)

2本の micro USB ケーブルは必須で、「USB ケーブルを変えたら上手く動作した」という投稿を少なからず目にしましたから、極端に安いものは要注意のようです。WiFi 接続が必要なので、WiFiルーターがあることが前提です。設置にかかった時間は正味、開梱から、ブラウザで モニタリングまで 三時間位だったと思います。それではステップを追って見ていきます。

開梱後、まず Edison の初期設定を、Intel サイトにある Getting Started に従って行います。 要点となる作業は3つで、1)ハードウエアの組み立て(5分)、2)Intel が提供する Nodejs を含むLinuxの最新イメージを Flash メモリに書き込む( 15分 )と、3)WiFi の設定(5分)です。Getting Started には、IoT開発のためのIDEやライブラリのインストールも含まれていますが、今回所期の目的のためには必要ありませんから、ここではスキップします。

ハードウエアの組み立て後、二本の micro USBケーブルをMacにつなぐと、電源 ON となり、1分ほどするとEdison のオートスタートが終わり、 OSX には EDISON という名前のデバイスが Finder に現れます。余談ですが Windows 7 PC でも同様です。ここで、「screen /dev/cu.usbserial* 11520 -L」として、ターミナル接続します。上の写真では、黒いUSBケーブル側がシリアル ターミナル接続を担当し、青いUSBケーブル側がデータ転送と電源を供給しているようです。2014年12月20日に Intel サイトからダウンロードしておいたイメージには Nodejs 0.10.28 が入っていました。次に、「configure_edison --setup」というコマンドで、root パスワードの設定とWiFiネットワークへの登録を行います。WiFi登録が済むと、ルーターがEdison に割り当てた IPアドレスが表示されます。これで Edison の初期設定が終わりました。

次に cx-helloworld(concurixトレーサを含むサンプルアプリ) を Edison にインストールします。PC・Mac環境で、cx-helloworld と concurix-server を動かして cx-helloworld アプリをトレースする環境をすでにお持ちであれば、 PC・Mac環境で動いている concurix-server はそのまま走らせておいて、cx-helloworld を Edison 上で動かすようにすると考えればよいです。その環境をお持ちでない方でも、上記のリンクから、まずPC・Mac環境にcx-helloworld と concurix-server を動かしておくと良いです。なぜかというと、そこから cx-helloworld を Edison にコピーします。また、Edison からのトレースデータは、その concurix-server に送るように設定します。

Concurix トレーサは HTTP プロトコルを使って concurix-server にデータを送るので、concurix-server が動作している PC・Mac は Edison を接続するのと同じ WiFi ネットワークにあらかじめ接続し、concurix-server を走らせておきます。また、両方のローカルIPアドレスを知っておく必要があります。今回の設定ではルーターそのものが 192.168.1.1 で、Edison が 192.168.1.2 、MacBook は 192.168.1.3 でした。Edison を WiFi登録後に、MacBookの WiFi を ON にしたので、そうなりました。

IPアドレスが決まると、ssh が使えるようになります。データ転送は、scp を使って WiFi経由で行うほうが、115kbpsのシリアルよりも高速です。Mac 側の ssh config ファイルに次の三行をを追加しました。

  Host edisonhome
  HostName 192.168.1.2
  User root

ssh 接続し、Edison の /home/root/ に 「mkdir node_modules」します。そして PC・Mac から、/home/root/node_modules/ に cx-helloworld ディレクトリ全体を scp を使ってコピーします。コピーする前に cx-helloworld の concurix-root.js には以下のようにパラメータを設定しておきます。ここで api_host は、concurix-server が走っているホストに 貴方のWiFi ルーターが割り当てた IP アドレスですから、貴方の設定に応じて変えねばなりません。Mac では System Preferences の Network に行き、ステータスがConnectedになっているネットワークの下に表示されている "Wi-Fi is connected to *** Wireless and has the IP address ***.**.**.***." から確認できます。

f:id:setogit:20141223145453j:plain

最後に Edison 上で、cx-helloworld を走らせると、下図のように事前に Mac・PC 上で走らせておいた concurix-server に Edison から トレースデータの送信が始まります。f:id:setogit:20141223145454j:plain

sshによるターミナル接続が可能になると、黒いUSBケーブルの接続は必要なくなります。下の写真にあるように黒いUSBケーブルを外して、ssh 接続しても問題ありません。

f:id:setogit:20141223145456j:plain

concurix-server のログを見ていると Edison の IP アドレスからトレースデータが格納されていることがわかります。これでブラウザを使って Concurix ダッシュボードを見ることができるようになりました。目的は達成です。

f:id:setogit:20141223145452j:plain

さて、考えてみると、データ転送がWiFi経由で出来るので、青いUSBケーブルは電源供給のために使用しているだけということになります。ボード上、 micro USB端子と反対側にある電源端子に規定のACアダプタ(別途購入要)を接続するか何かして、電源を供給してやれば、青いUSBケーブルも必要なくなります。また、Linux が立ち上がった後、自動実行するスクリプトを作っておけば、スタンドアローンで Edison が動作するはずです。IoT モジュールの原型ですね。

温度センサー、モーションセンサーなどをデータ入力側に、様々なスイッチやスピーカ、サーボモータのコントローラを出力側につないで、Nodejs で データ処理するアプリを作ればロボットができそうです。蛇足ですが、そのロボットのアプリに、上述の require("concurix") の数行を追加すれば、Concurix を使った Edison IoT アプリのモニタリングができるようになります。

JavaScript コールバック関数のトレース

これは npm と githubソースコードを公開している 「Concurix profiling and monitoring ツール」 についてのブログです。そのツールは、もちろん、無料で使えます。マニュアルへのリンクは、npmjs.org にある cx-helloworld-readme-ja というパッケージになります。


いよいよ Flame Graph の真髄にせまる今回は、HTTP トランザクションのリクエスト側と、それを受けて処理するサーバ側のコールバック関数が、 Flame Graph の中でどのように見えるかを追跡します。helloworld を使います。helloworld のソースコードnpmjs.org にある cx-helloworld-readme-ja というパッケージにありますから実際に試してみたい方はそちらからインストールしてください。

以下のように、helloworld.js はいたって簡単で、request を使うリクエスト側と express を使うサーバ側の機能を持っていますから、モッテコイの構成です。 :-) 

f:id:setogit:20141218095335j:plain

Concurix ダッシュボード(下図)の Transaction History ビューには request GET と serve GET の二つのトランザクションが表示されています。

f:id:setogit:20141218120934j:plain

まず、request GET から見ていきます。request GET http://localhost:8123/ トランザクションをクリックすると、以下のように Transaction Sequence ビュー(下図)に移ります。

f:id:setogit:20141218093742j:plain

更に request GET http://localhost:8123/ をクリックすると Flame Graph ビュー(下図)に移ります。

f:id:setogit:20141218093756j:plain

"Synchronous vs. Asynchronous Waterfall"を見ると、 request GET には3つの処理ステップがあることが分かります。即ち、赤丸で囲んだ sync: http#request and 10 functions と async: request GET http://localhost:8123/ そして Request.prototype.onRequestResponse>response.on 'end' listener and 1 function です。これは 、http#request と レスポンスの間でサーバ側の処理がasync で行われていることを示しています。http#request and 10 functions とは、Flame Graph の下から2段目の request#Request.prototype.init>defer() fn argument 以上の全てのブロックを意味しています。全部で11関数あるかどうか数えてみてください。もう一つ赤丸で囲んだ Total Cost はリクエストGET http://localhost:8123/ の発生に クライエント側で282 マイクロ秒かかったことを示しています。

Flame Graph を上に見ていくと下から5段目に request#Request.prototype.start とあります。そのブロックをセレクトすると同様の 情報が Inspector に表示されます。ここではスクリーンショットは載せてありませんが(試してみてください)、File name: cx-helloworld/node_modules/request/request.js の Line: 887 となっています。

f:id:setogit:20141218093805j:plain

そのソースファイルを見ると(上図)、909行目、 912行目、 913行目にそれぞれ copy, debug, self.httpModule.request の関数を呼んでいます。この三つの関数は Flame Graph では下から6段目にある三つのブロックに対応しています。debug は小さいです。

以上が request GET の三つのステップの最初のステップです。二つ目の async はここでは何も現れません。後述します。三つ目のステップは、request GET http://localhost:8123/ リクエストがサーバで処理されて、クライエント側のコールバック関数が呼ばれるステップです。下図にあるように、このステップは2.62マイクロ秒と極短く、Flame Graph でも赤丸で囲んだように極小さいブロックで表示されています。

f:id:setogit:20141218093816j:plain

Inspector を見ると、request#Request.prototype.onRequestResponse>response.on 'end' listener で、File name: request.js , Line: 976 (下図) を見ると response.on の 'end' リスナー関数が debug を呼んでいることが分かります。

f:id:setogit:20141218093826j:plain

果たせるかな、上図の Flame Graph の 赤丸で囲んだ部分の下から三段目の極細いブロックにマウスカーソルを移動してみると Inspector には request#debug と表示されます。

 

ここまでがリクエスト処理のトレースです。次にサーバ処理のトレースを見てみます。サーバ側の処理はクライエント側では、async として現れていました。

 

 Concurix ダッシュボードから serve GET/ トランザクションをクリックし、Transaction Sequence の相当する行をクリックすると、Flame Graph ビューの "Synchronous vs. Asynchronous Waterfall" には一つの sync 処理が表示されているだけです。(下図) サーバ側の処理にかかった時間は 271 マイクロ秒です。

f:id:setogit:20141218094154j:plain

更に Flame Graph を調べると、cx-helloworld/node_modules/express/lib/router/layer.js の 73 行目から express#handle 関数を呼んでいることなど、細部の挙動を見て取れます。 

来週はシアトルでクリスマス休暇をいただく予定です。「英語にローカライズしないの」という声も聞かれます。

Flame Graphの使用法 -- 学びて時に之を習ふ

11 月にNodeFest Tokyo 2014 で話してきました。タイトルは A Profiling and Monitoring Method for Nodejs Applications というのですが、Lightening Talk ということもあり、そこでカバーできなかったこと、その後加わった便利な機能、経験に基づく Best Practicesなど、皆さんのお役に立ちそうなことを、会場で伺ったご意見を考慮して、何回かに分けて書いてみようと思います。

ちなみに、これは npm と githubソースコードを公開している 「Concurix profiling and monitoring ツール」 についてです。もちろん、無料で使えます。NodeFest Tokyo 2014 に参加されなかった方のためにマニュアルへのリンクをあげておきますと、npmjs.org にある cx-helloworld-readme-ja というパッケージになります。

 


 

Flame Graph の効用については、Netflix Tech Blog 2014年11月19日 とか、Brendan Gregg が2014年9月17日のブログで、とても良く説明していますから細かいところは、そちらをご一読いただくとして、一言で言うと Flame Graph はソフトウエア・プログラムの動態を可視化する強力なツールです。Flame Graph による可視化は Concurix には標準で入っているので、今日の私のブログでは、その先を書きます。npmjs.org にある cx-helloworld-readme-ja というパッケージの「技を極める」に述べてある「 flame graphの読み方、解析の仕方」の続きと考えてください。 

前置きが、長くなってしまいました。今日のブログのタイトル「学びて時に之を習ふ」はご存知のように「子曰く」で始まる論語の一節です。何故そういうタイトルにしたかというと、「学びて」とは「プログラムをデザインして、書いて、デバグし、よし、Ship it !」と言った後で「時に之を習う」すなわち、「つらつらとソースコードを読み返し、動態など観て悦に入る」のに Flame Graph を使うのも一興と思ったからです。

そんなことをしているうちに、筆者は思いがけずバグを発見したのです。どういう性質のバグかというと、我々は Concurix ツールConcurix ツールの開発に使っているのですが、Flame Graph を観て「民のカマドは賑わっておる」などと思っていると、ある時、呼ばれるはずのない関数が Flame Graph に現れているのを発見。Concurix ツールは、対応するソースコードの位置を、JSファイル名と行数でガチに表示しますから、その部分を中心にブレークしてみると、おお、なんと、if 文の条件が間違っておりました。

という訳で、今日のブログのポイントです。Flame Graph の使い方として、それまでは「コールスタックがどうなっているか、どのコード部分にどの位時間がかかっているか」に注目して見ていました。すなわち、Flame Graph の縦方向の積み重ねに注目して関数呼び出し関係を、各々の四角の大きさ(幅)で処理時間を観ていたのです。勿論、それはそれで強力であることに変わりはありませんが、更に、横方向に並んている四角(呼ばれた関数)は妥当な呼ばれ方なのかも注目する価値があるという事でした。これは目からウロコの経験で「学びて時に之を習ふ」という言葉が浮かんだという次第です。

最後に、Ghost のサンプルコードに Concurix を設定してモニタリングを行っている私共のサイトの Flame Graph を以下に示します。リアルタイムで観てみたいという方は、このサイトをアクセスしてみてください。開発マシンなので動いていないこともありますから、「Not Enough Trace Data」と表示された場合は、ゴメンなさい。また、後ほどお試しください。

次回は、Flame Graphとコールバック関数のトレースに関して書いてみたいと思っています。

f:id:setogit:20141205031832j:plain

フライト・レコーダ を Nodejs で作るとどうなるか

11 月にNodeFest Tokyo 2014 で話してきました。タイトルは A Profiling and Monitoring Method for Nodejs Applications というのですが、Lightening Talk ということもあり、そこでカバーできなかったこと、その後加わった便利な機能、経験に基づく Best Practicesなど、皆さんのお役に立ちそうなことを、会場で伺ったご意見を考慮して、何回かに分けて書いてみようと思います。

ちなみに、これは npm と githubソースコードを公開している 「Concurix profiling and monitoring ツール」 についてです。もちろん、無料で使えます。NodeFest Tokyo 2014 に参加されなかった方のためにマニュアルへのリンクをあげておきますと、npmjs.org にある cx-helloworld-readme-ja というパッケージになります。

 


 

ご存知のようにフライト・レコーダというのはブラックボックスともいい、Wikipedia によると、「飛行中のコックピット内で操縦士たちが交わした会話や航空交通管制機関との交信内容、機体の飛行状況を記録し続けることにより、事故原因究明のための手掛かりとするべく旅客機に搭載されている。すべてを記録すると記録量が膨大になるため、古いデータを消しながら直近の出来事をエンドレスに(記録を書き換えながら)記録する。このため、一定時間以前のデータは記録に残らない。」とあります。

今日のブログのタイトルを、当初、「Nodejs アプリにフライト・レコーダ を設置した話」としたのですが、フライト・レコーダの定義は、上記のようですから、「Nodejs アプリに設置した」は真実とは考え難い。そこで、いろいろとお知恵を拝借し、 Nodejs とフライト・レコーダを入れ替えて、「もし仮に」というニュアンスを含むフライト・レコーダ を Nodejsで作るとどうなるか」というタイトルに落ち着きました。

もう少し想像力を働かせていただきます。そのブラックボックスに時々刻々、記録されている様々なメトリクスを、リアルタイムで、世界中どこからでもブラウザを使ってモニタすることもできるのです。最後に、そのフライト・レコーダを設置するのは旅客機ではなく、貴方が運営されている Web サービスのプロダクション・システムだと考えていただきたい。

それが、Concurix を使ったオフライン解析、と言うと、言い得て妙です。詳細はnpmjs.org にある cx-helloworld-readme-ja というパッケージをご覧ください。

次回は、Flame Graph に関して書いてみたいと思っています。