autoload [rails][ruby]
http://guides.rubyonrails.org/autoloading_and_reloading_constants.html
ソースを変更した際に、ソースを自動でよみなおしてくれるが、
ルールにあわせておかないと、そこからはずれてしまうので、注意と。
Docker で Sensu + Graphite + Grafana 環境構築
監視環境を新規に構築するにあたり、上記構成で環境を構築したのでそのメモです。
まで、ふんわりできました。以下、作ったDockerfile群
- https://github.com/tomyhero/docker-sensu
- https://github.com/tomyhero/docker-sensu-dashboard-uchiwa
- https://github.com/tomyhero/docker-sensu-dashboard-graphite
- https://github.com/tomyhero/docker-grafana
以下が、セットアップ手順です。
手順1: graphiteのセットアップ
git clone https://github.com/tomyhero/docker-sensu-dashboard-graphite.git cd docker-sensu-dashboard-graphite docker build -t tomyhero/sensu-dashboard-graphite . docker run --name sensu-dashboard-graphite -it -d \ -v /opt/graphite/data:/app/graphite \ -p 10200:80 \ -p 2003:2003 \ -e "ROOT_USER_NAME=tomyhero" \ -e "ROOT_PASSWORD=mysecret" \ -e "ROOT_EMAIL=tomohiro.teranishi@gmail.com" \ tomyhero/sensu-dashboard-graphite bash
- hostの /opt/graphite/data 配下に永続データ(統計データ)の保存
- webを 10200 portでアクセスできるようにし、host側のnginxでproxyします
- 2003 port は carbon-cacheに対して、コマンドを送るため
手順2: sensuのセットアップ
get clone https://github.com/tomyhero/docker-sensu.git cd docker-sensu docker build -t tomyhero/sensu . docker run --name sensu -it -d \ -p 5672:5672 \ -p 4567:4567 \ -e GRAPHITE_HOST=$(docker inspect --format {{.NetworkSettings.IPAddress}} sensu-dashboard-graphite) \ -e "MAIL_TO=tomohiro.teranishi@gmail.com" \ -e "START_SENSU_CLIENT=false" \ -e "DASHBOARD_URL=http://uchiwa.localhost/" \ -e "ON_SENSU_HANDLER_NOTIFICATION_SLACK=true" \ -e "SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXXX/XXXXXXXXXXXXX" \ tomyhero/sensu bash
- 5672port は rabbitmq です
- 4567port は API用です
- $(docker inspect --format {{.NetworkSettings.IPAddress}} sensu-dashboard-graphite) graphiteのIPの出力
- sensu clientを起動するなら START_SENSU_CLIENT=true
- dashboard urlには あとででてくるuchiwaのURLを記載。
- ON_SENSU_HANDLER_NOTIFICATION_SLACK - slackへの通知を有効にする場合 true に
- SLACK_WEBHOOK_URL slackのwebhook urlを記載
- その他必要に応じての設定は、https://github.com/tomyhero/docker-sensu ドキュメントで確認。
手順3: uchiwaのセットアップ
git clone https://github.com/tomyhero/docker-sensu-dashboard-uchiwa.git cd docker-sensu-dashboard-uchiwa docker build -t tomyhero/sensu-dashboard-uchiwa . docker run --name=sensu-dashboard-uchiwa -it -d \ -p 11003:3000 \ -e="SENSU_HOST=sensu.localhost" \ tomyhero/sensu-dashboard-uchiwa
- 11003 portでwebにアクセス
手順4: grafanaのセットアップ
git clone https://github.com/tomyhero/docker-grafana.git cd docker-grafana docker build -t tomyhero/grafana . docker run --name grafana -it -d -p 13000:3000 \ -v /opt/grafana/data:/app/grafana \ -e "GRAFANA_ADMIN_USER=tomyhero" \ -e "GRAFANA_ADMIN_PASSWORD=secret" \ -e "GRAFANA_AUTH_BASIC_ENABLED=false" \ tomyhero/grafana bash
- hostの /opt/grafana/data 配下に、grafanaの設定データを保存
- GRAFANA_AUTH_BASIC_ENABLED は環境に応じて。。。
手順5: sensu clinent
centosの環境なら
wget -O https://raw.githubusercontent.com/tomyhero/docker-sensu/master/bin/client-install-centos.sh chmod 775 client-install-centos.sh ./client-install-centos.sh
/etc/sensu/config.json 作成。中身は自分で。
{ "rabbitmq": { "host": "localhost", "vhost": "/sensu", "user": "sensu", "password": "secret" } }
/etc/sensu/conf.d/client.json を作成。中身は自分で。
{ "client": { "name": "tool", "address": "localhost", "subscriptions": [ "basic","nginx","mysql" ] } }
起動
service sensu-client start tail -f /var/log/sensu/sensu-client.log
手順6: hostのnginx設定
upstream grafana { server localhost:13000; } upstream sensu { server localhost:11002; } upstream uchiwa { server localhost:11003; } upstream graphite { server localhost:11004; } // これと同じ感じを graphite,uchiwa,grafana でも用意 server { listen *:80; server_name sensu.localhost; access_log /var/log/nginx/sensu.localhost.access.log main; error_log /var/log/nginx/sensu.localhost.error.log; set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; location / { proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://sensu; } }
まとめ
取り急ぎ、サーバの状態の把握、状態異常の通知を受け取る環境が、dockerで簡単に作れるようになった。
sensu clientが落ちた時の通知、sensu server等が落ちた時等にどうするんだとかも、そのうち考えないと。
あと、自分用品質のDockerfileなので、ちょいちょい変更が入りそう。
goji ミドルウェアー内で404の判断を、ServeHTTPの手前でする方法
routerのmatch処理前のフックになるので、
冗長だけど、matchを自分ですればできるって話
- goji.DefaultMux.Router を読み込む
- web.GetMatch(*c) が動作するようになるので、それを活用
package main import ( "fmt" "github.com/zenazn/goji" "github.com/zenazn/goji/web" "net/http" ) func main() { goji.Get("/hello/:name", hello) goji.Use(goji.DefaultMux.Router) goji.Use(Check) goji.Serve() } func hello(c web.C, w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %s!", c.URLParams["name"]) } func Check(c *web.C, h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { pattern := web.GetMatch(*c).Pattern if pattern != nil { fmt.Println("ok") } else { fmt.Println("404") } h.ServeHTTP(w, r) } return http.HandlerFunc(fn) }
XCode6とSwiftで、viewControllerの上にviewControllerをポップアップみたいに出すやつ
ポップアップみたいなのを、実現したかったので適当に作った。
透明のレイヤーをかぶせたりしていて、もっと全うにできる方法が別にあるのかもしれない。
押すと、これがでる。青いエリアがView。その上に見えないけど、buttonを配備している。見えない閉じるボタン。
二つviewControllerを作る。ポップアップを開くボタンを作って、関連付けをする。present Modally ってやつ。
で、こんな感じ。
Presentationを、Over Current Contextにしておかないと、一つ目のviewControllerの描画をしないかんじになって、真っ黒になってまうので、設定が必要。
あと、ViewとButtonのBackgroundを Defaultにしておくこと。透明にするために。
ポップアップを、透明の背景ボタンを押したら閉じるように、閉じるしょり。
@IBAction func close(sender: AnyObject) { self.dismissViewControllerAnimated(false, completion: nil) }
とりあえず、動く。いいやり方なのかわからないけど。
XCode6で Bundle Identifier の名前とかを変更する
Bundle Identifierの値は、素直な感じに変更できない。
Unkoとかのままにしたくない。
Product Nameの Unkoを Lazy に変更する。
そうすると、Bundle Identifier が変更される。
ただ、まだUnkoにまみれてる。
右上の、xcodeproje ファイルの名前を変更すると、以下のように他変更する提案をしてきてきて、素敵。
いうても、まだ Unko いっぱいいるので、手動で Lazyに全部何も考えずrenameしていく。
UnkoTests.swift のファイル名だけではなく、中身のクラス名もrenameするのわすれずに。
だいたい、画面からはUnkoがきえた。
ファイルシステムから、調べる。うようよいる。置換をコンソールからガンガンやってみる。
バイナリーのファイル以外は、全部なおした。バイナリーのは、まぁ、適当にほっとく。
これで、気兼ねなく、適当に名前をつけて、後で変更できるね。
自己責任だけどね!
Cacheクラス
前回作った、configクラスを使いつつ、シングルトン化し、
ブロックの結果をキャッスする関数を生やしたかんじ。
ソース
require 'singleton' require 'memcache' require 'bei/config' require 'pp' module Bei class Cache < Memcache include Singleton def initialize super ( { :servers => Bei::Config.instance.get(:memcached_servers) } ) end def cacheable(key,expire=60*3) raise "NO_BLOCK_ERROR" unless block_given? unless( value = self.get(key) ) #pp 'from value' value = yield() self.set(key,value,expire) else #pp 'from cache' end return value end end
使い方
こんな
かん
じ
cache = Bei::Cache.instance() # Memcache の継承なので、既にある関数はそのまま使える。 cache.set('hi','hihihi') hi = cache.get('hi') # blockからデータ取得 my_data = cache.cachable('my/3/data', 60 * 1) { { :user_id => 3 } } # 3 # memcachedからデータ取得 my_data = cache.cachable('my/3/data', 60 * 1) { { :user_id => 2 } } # 3 (2じゃない)
自分用のConfigクラス
railsでどうすればいいのかわからなかったので、取り急ぎ作った。
require 'singleton' module Bei class Config include Singleton def initialize file = Rails.root.to_s + '/config/environments/config_' + ENV['RAILS_ENV'] + '.rb' @config = eval ( open(file).read ) end def get(key) return Marshal::load(Marshal.dump(@config[key])) #deep clone end end end
config/environments/config_test.rb
{ :twitter_consumer => { :key => 'foo', :secrete => 'bar' } }
使い方。
config = Bei::Config.instance().get(:twitter_consumer)