過去に蓄積されたデータの集計にNorikraを使う
最近Norikraを触っていて,ある程度使い方が分かってきたのと,丁度v1.0.0もリリースされたので,忘れないうちにこのタイミングでメモしておく.
本来Norikraはリアルタイムなログ等に対して処理をするものであるけども,今回は過去に蓄積されたログに対して集計処理を行ってみることにする*1.
今回のキーポイントは,
win:ext_timed_batch
を使って,ログの発生時刻を指定するLOOPBACK
を使って,あるクエリで発生したeventを別のtargetに直接流し込む
の2点.
やりたいこと
下のような,2台のホストで1分毎に生成されたデータがあるとする.
# host1.csv timestamp, metric1, metric2, ... 1396278000, 0, 0 1396278060, 1, 2 1396278120, 2, 4 1396278180, 3, 6 1396278240, 4, 8 1396278300, 5, 10 1396278360, 6, 12 1396278420, 7, 14 1396278480, 8, 16 1396278540, 9, 18 1396278600, 10, 20
# host2.csv timestamp, metric1, metric2, ... 1396278000, 0, 0 1396278060, 2, 4 1396278120, 4, 8 1396278180, 6, 12 1396278240, 8, 16 1396278300, 10, 20 1396278360, 12, 24 1396278420, 14, 28 1396278480, 16, 32 1396278540, 18, 36 1396278600, 20, 40
これらのデータに対し,同一時刻に発生したメトリックどうしを加算したい.
timestamp, metric1_sum, metric2_sum, ... 1396278000, 0, 0 1396278060, 3, 6 1396278120, 6, 12 1396278180, 9, 18 1396278240, 12, 24 1396278300, 15, 30 1396278360, 18, 36 1396278420, 21, 42 1396278480, 24, 48 1396278540, 27, 54 1396278600, 30, 60
さらに,5分間の平均値と最大値を調べたい.
timestamp, metric1_avg, metric1_max 1396278000, 6.0, 12 1396278300, 21.0, 27
実際には,ホスト数もメトリックももっとたくさんある,という想定. こういった用途であれば,データベースに突っ込んで集計するなり,自前で集計スクリプトを書くなりすれば対応できるような気がする.ただ,集計対象のメトリックが頻繁に変更されるような状況で,かつデータベースや集計スクリプトのメンテナンスにあまり重きを置けない場合*2,そのあたりを簡単に扱えるものが欲しくなってくる.そこでNorikra,という流れ.
過去のログを扱う::ext_timed_batchでログの発生時刻を指定する
通常,ログがnorikraに入った時のシステムの実時間=ログの発生時刻として扱われる.それだと過去のデータを処理対象とする場合困るので,発生時刻を外部から与えてやる必要がある.そこで使うのがext_timed_batch
.
例えばこんな感じのクエリを登録する.
select min(timestamp) as timestamp, sum(metric1) as metric_sum from host_data.win:ext_timed_batch(timestamp * 1000, 1 min, 1396278000000L) where hostname in ("host1", "host2")
このクエリを登録した状態で,ターゲットhost_data
に
[{"timestamp": 1396278000, "hostname": "host1", "metric1": 0}]
というようなデータを送ると,2014-04-01 00:00(JST) (=unix epochで1396278000)に発生したログとして扱ってもらえる.ext_timed_batch
の第3引数はtime windowの開始点を与える.設定しない場合,最初のイベントが発生した時刻を基準にbatchが実行されるようになる.外部から与えるtimestampのタイムゾーム周りがややこしい場合,明示的に指定しておいたほうが無難に思える.
注意点として,流し込むデータは時間順にソートされている必要がある.ext_timed_batch
に限らず*_batch
では,あるtime windowの境界を跨ぐデータが到着した時点で,前のtime windowに対するeventが発行される.なので,データが時間順にソートされていないと,正しい結果が得られない.
複数のクエリで処理する::LOOPBACK()でeventを別のtargetに送る
あるクエリを実行した後,その結果得られたeventに対して更にクエリを投げたい場合,以前であればeventをfetchした上で対象targetに送り直す必要があった*3.Norikra v1.0.0からLOOPBACK()
が導入され,この処理が自動化された.
使い方は簡単で,クエリ登録時のGroupをLOOPBACK(target名)
としてやればよい.
例えば,上で紹介したクエリのGroupをLOOPBACK(metric_aggregated)
とした上で,下のクエリを登録する.
select min(timestamp) as timestamp, avg(metric_sum) as metric_avg, max(metric_sum) as matric_max from metric_aggregated.win:ext_timed_batch(timestamp * 1000, 10 min, 1396278000000L)
この状態でターゲットhost_data
にeventを送ると,最初のクエリを実行した上でその結果がターゲットmetric_aggregated
に送られ,2番目のクエリが実行される.
あとはこのクエリのeventをfetchすれば,当初のお目当てのデータが得られる.
まとめ
今回は,過去に蓄積されたログデータの集計にNorikraを使ってみた.本来想定されている使い方ではない上に,ext_timed_batch使うのはオススメしないと@tagomorisさんが言っていたりするので,気付いていない落とし穴があるのかもしれない.
ただ,データ集計の条件が簡単に書ける&データストア類が必須でないという点は,コードを書いたりデータベースを運用することが日常的ではない場所で使う上で,意外とメリットになりそうな気はする.
サンプルコード
Python 3.3 + oursql 0.9.3 導入メモ
いくつか躓いた箇所があったのでメモ.
正しく動作する導入方法
Launchpad上のオフィシャルページからPython 3.x向けのパッケージをダウンロードし,展開する.
$ wget https://launchpad.net/oursql/py3k/py3k-0.9.3/+download/oursql-0.9.3.zip $ unzip oursql-0.9.3.zip
展開したパッケージ内に含まれるoursqlx/oursql.c
(Cythonが生成したコード)を削除する.
$ cd oursql-0.9.3 $ rm oursqlx/oursql.c
ビルトとインストールを実行.正しくimportできることを確認.
$ python setup.py build_ext $ python setup.py install $ python3.3 Python 3.3.0 (default, Sep 29 2012, 22:07:38) [GCC 4.7.2 20120921 (Red Hat 4.7.2-2)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import oursql >>>
上手く動作しない導入方法とその原因
pipから導入
pip
を使った場合,Python 2.x向けのパッケージがダウンロードされてしまう.そのため,setup.py
でSyntax Errorが発生し,導入できない.
$ pip install oursql Downloading/unpacking oursql Downloading oursql-0.9.3.1.tar.gz (164Kb): 164Kb downloaded Running setup.py egg_info for package oursql Traceback (most recent call last): File "<string>", line 14, in <module> File "/.../.virtualenvs/oursql/build/oursql/setup.py", line 53 print "cython not found, using previously-cython'd .c file." ^ SyntaxError: invalid syntax Complete output from command python setup.py egg_info: Traceback (most recent call last): File "<string>", line 14, in <module> File "/.../.virtualenvs/oursql/build/oursql/setup.py", line 53 print "cython not found, using previously-cython'd .c file." ^ SyntaxError: invalid syntax ---------------------------------------- Command python setup.py egg_info failed with error code 1 in /.../.virtualenvs/oursql/build/oursql Storing complete log in /.../.pip/pip.log
ダウンロードしたパッケージをそのまま導入
Launchpadからダウンロードしたzipファイル内には,Cythonで生成された.c
ファイルが同梱されている.そのため,python setup.py build_ext
すると,同梱されている.c
ファイルを利用してビルドが実行される.しかし,同梱されている.c
ファイルはバグの存在する過去のバージョンのPythonを用いて生成されているため,モジュールのimportに失敗してしまう.
$ wget https://launchpad.net/oursql/py3k/py3k-0.9.3/+download/oursql-0.9.3.zip $ unzip oursql-0.9.3.zip $ cd oursql-0.9.3 $ python setup.py build_ext $ python setup.py install $ python3.3 Python 3.3.0 (default, Sep 29 2012, 22:07:38) [GCC 4.7.2 20120921 (Red Hat 4.7.2-2)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import oursql Traceback (most recent call last): File "<stdin>", line 1, in <module> File "oursql.pyx", line 52, in init oursql (oursqlx/oursql.c:23138) ValueError: level must be >= 0 >>>
参考
- Bug #906007 “can't install on python 3” : Bugs : oursql
- Bug #1040093 “Not compatible with python 3” : Bugs : oursql
- Bug #1067767 “py3k branch does not work with python 3.3” : Bugs : oursql
- Issue 15610: PyImport_ImportModuleEx always fails in 3.3 with "ValueError: level must be >= 0" - Python tracker
Androidのjava.net.URIでIPv6 scope_idが扱えない件
タイトル通り.
URI v6linklocal = new URI("http://[fe80::1%9]/foo");
を呼ぶとURISyntaxException
が返ってくる.
scope_idについては,RFC 4007で文書化されている.しかしAndroid Developersに
A Uniform Resource Identifier that identifies an abstract or physical resource, as specified by RFC 2396.
と書かれている通り,Androidのjava.net.URIはRFC 2396に準拠している.そのため,最初に示したようなURIは誤りとして扱われる.
今のところ,直接的な対処法は無さそう.
Fedora17 デスクトップ環境構築メモ
すぐ忘れるのでメモ.随時追加.
環境
OSインストール直後
MIN_UID / MIN_GIDの変更
Fedora 16から,一般ユーザのUID/GIDが1000から始まるようになった.が,NFSの関係でUID/GIDを500にしたいので設定変更. 初回起動時のウィザード(firstboot)では適当なアカウントを作っておくのがポイント.起動後,/etc/login.defsを編集.
(snip)
UID_MIN 500
(snip)
GID_MIN 500
(snip)
参照
Trimを有効にする
/etc/fstabを編集.オプション"discard"を追加.
UUID=xxxx / ext4 defaults,discard 1 1
UUID=yyyy /boot ext4 defaults,discard 1 2
参照
アプリケーションのインストール & 設定
シェル関係
dotfiles類をgit resositoryから持ってくるためのスクリプト"setup-newenv.sh"を持ってきて実行.
$ sudo yum install git zsh screen
$ git clone https://gist.github.com/4411268.git
$ cd 4411268
$ sh setup-newenv.sh
$ chsh -s /usr/bin/zsh
アプリケーションのインストール
ひたすらインストール.
$ sudo yum install gcc automake kernel-devel \
gnome-tweak-tool gnome-shell-extension-dock gnome-shell-extension-alternative-status-menu gnome-shell-extension-remove-accessibility-icon \
dconf-editor gconf-editor vlgothic* \
python3 subversion tig \
haparm powertop \
thunderbird emacs ibus-skk \
virt-manager libvirt openssh-askpass remmina-plugins-rdp \
vlc
アプリケーションの設定
X
/etc/X11/xorg.conf.d/20-trackpoint.confを作成.ThinkPadのTrackpointでスクロールできるように.
Section "InputClass"
Identifier "Trackpoint Wheel Emulation"
MatchProduct "TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc. Composite TouchPad / TrackPoint|ThinkPad USB Keyboard with TrackPoint|USB Trackpoint pointing device|Composite TouchPad / TrackPoint"
MatchDevicePath "/dev/input/event*"
Option "EmulateWheel" "true"
Option "EmulateWheelButton" "2"
Option "Emulate3Buttons" "false"
Option "XAxisMapping" "6 7"
Option "YAxisMapping" "4 5"
EndSection
参照
Gnome
インストールしたshell extensionをgnome-tweak-toolで有効に.
dockを左に & サイズ調整.
$ gsettings set org.gnome.shell.extensions.dock position "left"
$ gsettings set org.gnome.shell.extensions.dock size "42"
xdg-user-dirs-updateを無効に.
$ cp /etc/xdg/user-dirs.conf .config/
$ vi .config/user-dirs.conf
(snip)
enabled=False
(snip)
ハイバネート
swapが無いとhibernateが使えないことをインストール後に知ったので作成.
$ sudo time dd if=/dev/zero of=/swap bs=1M count=8192
$ sudo mkswap /swap
$ sudo swapon /swap
$ sudo filefrag -v /swap
Filesystem type is: ef53
File size of /swap is 8589934592 (2097152 blocks, blocksize 4096)
ext logical physical expected length flags
0 0 1308672 2048
1 2048 1359872 1310720 4096
2 6144 1568768 1363968 4096
(snip)
$ sudo vi /etc/sysconfig/grub
(snip)
GRUB_CMDLINE_LINUX="... resume=/dev/sda2 resume_offset=1308672"
(snip)
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
$ sudo vi /etc/fstab
(snip)
/swap swap swap defaults 0 0
(snip)
SSHの踏み台有り・無しを,ネットワーク的居場所に応じて自動で切り替える
SSHで何がしかのホストに入るとき,自ホストのネットワーク的な居場所に応じて踏み台使用の有無を自動で切り替えるようなものを書いてみた.
やりたいこと
自分の居場所に関係無く,同一コマンドでSSHできるようにすることが最終的なゴール.
あるネットワークAからは踏み台無しでSSHできるけども,それ以外のネットワークからは踏み台を通さないとSSHできないようなホストがあるとする.
今までは,$HOME/.ssh/configに
Host univ-server1 Host server1.example.jp Host univ-server1-outside Host server1.example.jp ProxyCommand ssh univ-proxy nc %h %p Host univ-proxy Host proxy.example.jp
と書いておいて,ネットワークAからは
$ ssh univ-server1
ネットワークA以外からは
$ ssh univ-server1-outside
と叩くようにしていた.
これを,自分の居場所に関係無く
$ ssh univ-server1
と叩けば入れるような状況にしたい.使い分けが面倒だし.
方法
$HOME/.ssh/configを以下のような感じで書く.ssh-autoproxy.pyはgithubから持ってきて適当にパスの通った場所へ.
Host univ-server* ProxyCommand ssh-autoproxy.py univ-proxy %h %p 192.0.2.0/24 198.51.100.0/24 Host univ-server1 Host server1.example.jp Host univ-server2 Host server2.example.jp Host univ-proxy Host proxy.example.jp
上記の例では,192.0.2.0/24と198.51.100.0/24以外からは踏み台が必要なホストを想定している.
これで,踏み台使用の有無に関係なく,
$ ssh univ-server1
を叩けば入れるようになる.
Know issue
- インターネット接続性が無いと,アレな挙動を見せる
- v4/v6 dual stackな環境だと,アレな挙動を見せる
Code
githubからどうぞ.ipaddrモジュールはPEP 3144版が必要なので注意.
ACアダプタ接続時,画面オフしないようにする (Fedora16+Gnome3)
$ gsettings set org.gnome.settings-daemon.plugins.power sleep-display-battery 600 # バッテリー駆動時は600sで画面オフ $ gsettings set org.gnome.settings-daemon.plugins.power sleep-display-ac 0 # ACアダプタ接続時は画面オフしない
液晶モニタのスピーカーから音声を出すようにしていると,画面出力がオフになると同時に音声も切れてしまう,という問題がこれで解決.