production.log

株式会社リブセンスでエンジニアをやっている星直史のブログです。

ファイル内の改行を置換するコマンド

2ファイル間で重複する / しない 行を出力する方法
こちらの操作をするときに、セットで、ファイル内の改行を置換するコマンドを調べることがあるので、
メモ程度に残しておく。

$ cat hogehoge.text
1
2
3
4
5

上記のファイルを1,2,3,4,5と出力したい場合のコマンド

cat hogehoge.text | sed -e :loop -e 'N; $!b loop' -e 's/\n/ /g'

2ファイル間で重複する / しない 行を出力する方法

タイトルの通り、何気に結構使う処理だけど都度調べているからメモとして残す。

a.text と b.textが以下の内容の時、1と 2,3,4,5を出力したい場合

$ cat a.text
1
2
3
4
5

$ cat b.text
2
3
4
5

$ sort {a,b}.text | uniq -u # ユニークな行を出力
$ sort {a,b}.text | uniq -d # 重複行を出力

@t_wada さんの「Mac の開発環境構築を自動化する (2015 年初旬編)」をAnsible ベストプラクティスに則り書き換えてみた

概要

t-wada.hatenablog.jp

Ansibleでmacの環境構築する際、id:t-wada さんの上記の記事を参考したのですが、 Ansible Best Practicesに沿っていなかったので、書き直してみました。

Ansibleを動かすまで

こちらは、t_wadaさんの記事のままです。

sudo xcodebuild -license
xcode-select --install
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew doctor
brew update
brew install python
brew install ansible

どこを直したのか

twada/macbook-provisioning

hoshinaoshi/macbook-provisioning

本家とforkしたリポジトリを比較しながら、修正した点を挙げていきます。 階層構造も修正しています。

【本家】

.
├── LICENSE
├── README.md
├── hosts
├── localhost.yml

【修正後】

.
├── LICENSE
├── README.md
├── ansible.cfg
├── group_vars
├── hosts
├── localhost.yml
├── roles
│   ├── homebrew
│   │   ├── defaults
│   │   ├── files
│   │   ├── handlers
│   │   ├── meta
│   │   ├── tasks
│   │   │   └── main.yml
│   │   ├── templates
│   │   └── vars
│   │       └── main.yml
│   ├── homebrew-cask
│   │   ├── defaults
│   │   ├── files
│   │   ├── handlers
│   │   ├── meta
│   │   ├── tasks
│   │   │   └── main.yml
│   │   ├── templates
│   │   └── vars
│   │       └── main.yml
│   ├── oh-my-zsh
│   │   ├── defaults
│   │   ├── files
│   │   ├── handlers
│   │   ├── meta
│   │   ├── tasks
│   │   │   └── main.yml
│   │   ├── templates
│   │   └── vars
│   └── ricty
│       ├── defaults
│       ├── files
│       ├── handlers
│       │   └── main.yml
│       ├── meta
│       ├── tasks
│       │   └── main.yml
│       ├── templates
│       └── vars
└── site.yml

*1

site.ymlを作成し、localhost.ymlをinclude

ベストプラクティスではsite.ymlをmaster playbookとします。 また、プロビジョニング対象の役割(production, stagingなど)ごとに実行するroleをまとめたplaybookも作ります。 今回はlocalhost.ymlのみですね。*2

これらのファイルはroleをincludeするだけに留め、ここに細かいタスクを書いていくことはしません。(後述)

ロールの割り振り

元々のlocalhost.ymlのタスクは大きく4つの処理をしています。

  • homebrew
  • homebrew-cask
  • oh-my-zsh
  • ricty

今回はローカル環境のみが対象ですが、複数のプロビジョニング対象があった場合に、個別に差し込めるようにするため、 これらのタスクをrolesディレクトリ配下にそれぞれの役割ごとに分割します。 directory-layout

loclhost.ymlに列挙された変数を各ロールに振り分ける。

loclhost.ymlにhomebrew_taps, homebrew_packages, homebrew_cask_packagesの3つが定義されていましたが、 これらはhomebrewとcaskで使用するので、

  • ./roles/homebrew/vars/main.yml
  • .roles/homebrew-cask/vars/main.yml

に記述します。

./roles/hogehoge/vars/main.ymlに変数を記述すると
./roles/hogehoge/tasks/main.ymlの実行時に自動で変数を読み込み、タスク内で使用することができます。

localhost.ymlに記述されているhandlersはricty用なので、ricty/handlers/main.ymlに移動

localhost.ymlに記述されているhandlerは、よく見るとRicty用の処理であるため、Rictyロールのhandlerとして定義します。 こちらは、varsと同様にhandlerも同role内のhandlerディレクトリに記述していれば、notifyをした際に呼び出されます。

- name: run fc-cache
  shell: fc-cache -vf

localhost.ymlでtasksとして記述された内容をroleに任せる。

これらのファイルはロールをインクルードするだけに留め、ここに細かいタスクを書いていくことはしません。(後述)

ここまでの書き換えで、各ロールにvars, tasks, handlerを分けることができたので、 localhost.ymlではロールをインクルードするだけにします。

---
- name: Setup my MacBook
  hosts: localhost
  connection: local
  gather_facts: no 
  roles:
    - { role: homebrew,      tags: [ homebrew ] }
    - { role: homebrew-cask, tags: [ homebrew-cask ] }
    - { role: oh-my-zsh,     tags: [ oh-my-zsh ] }
    - { role: ricty,         tags: [ ricty ] }

だいぶスッキリしましたね。

また、tagを切っておくと、指定したタグだけ実行 / 指定したタグをスキップなどができるので、追加しておきます。 ansible-playbook site.yml --tags "homebrew,ricty" ansible-playbook site.yml --skip-tags "oh-my-zsh"

playbook実行時の引数を極力減らせるように設定

HOMEBREW_CASK_OPTS="--appdir=/Applications" ansible-playbook -i hosts -vv localhost.yml

実行時にhostsの設定をしたり、HOMEBREW_CASK_OPTSを設定したりするのはめんどくさいので、

ansible.cfgを作成し、デフォルトの動作を設定をします。

[defaults]
hostfile = ./hosts

環境変数については、homebrew-caskのタスクの一部として実行するようにします。

- name: HOMEBREW_CASK_OPTS設定
  shell: export HOMEBREW_CASK_OPTS="--appdir=/Applications"
...後続の処理がずらずら〜

ここまでの設定で、実行時のコマンドが HOMEBREW_CASK_OPTS="--appdir=/Applications" ansible-playbook -i hosts -vv localhost.ymlansible-playbook -vv site.yml となりました。 シンプル!

まとめ

以上でAnsible ベストプラクティスを適用した、Mac の開発環境構築を自動化する (2015 年初旬編)です。

"mac ansible"などで検索すると、localhost.ymlにtasksがばーーーーーっと書かれたplaybookをよく目にする印象があります。

複数のプロビジョニング対象が存在する場合は、ベストプラクティスが有効だと思いますが、 構築する対象がローカル環境のみで、処理(や、ロール)が少ないのであれば、1ファイルにゴリゴリ書いても良いのではないかと感じました。

ただ、実際は、開発スタートをするまでにrbenvの設定をしたり、ミドルウェアの設定をしたりなんだりすると、localhost.ymlが肥大化してしまうのではないかと考えられるため、早め早めにロールだけでも分けて記述するのが落とし所かと思います。

こちらにコードを置いておきます。
https://github.com/hoshinaoshi/macbook-provisioning

今回Ansibleを初めて触ってみたのですが、ymlで書くのが地味に楽でした。
Ansibleの処理も「Ansible {{やりたいコマンド}}」で検索 => 1つ目の記事ではい理解〜というような感じでした。
自分は、初めての技術に触れるときは、初心者用の書籍を購入して、一読するのですが、Ansibleにおいては下記の書籍を買いました。

*1:中身が空のディレクトリは削除しても良いかも

*2:通常は複数のサーバーに対して行うので、若干無理矢理感がありますね

Rubyで使われるコロンの意味を調べてみた

概要

Rubyを初めて触ったときに、(当時の自分が触っていた)C#JAVAではコロンが使われておらず、 これはどのような意味なのかがよく話からたかったので、まとめてみました。

:symbol
"symbol"

こちらの違いについてまとめます。

Rubyにおけるコロンの意味とは?

Rubyにおけるコロンは、シンボルといいます。

:symbol 一見文字列と同種に見えるが、内部的には数値として扱われます。 そのため、比較や検索などの速度面が文字列と比べると高速になります。

  • ハッシュのキー
  • メソッドの引数として渡すクラス名、メソッド名、変数名、定数名

などについては、はシンボルを使用したほうが良いでしょう。

リファレンスでは

リファレンスを引用します。

Rubyの内部実装では、メソッド名や変数名、定数名、クラス名など の'名前'を整数で管理しています。これは名前を直接文字列として処理するよりも 速度面で有利だからです。そしてその整数をRubyのコード上で表現したものがシンボルです。 シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。 名前を管理するという役割上、シンボルと文字列は一対一に対応します。 また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。

文字列と見せかけて、内部の実装では整数として扱っている。といったところでしょうか。

検証してみた

> Rubyの内部実装では、メソッド名や変数名、定数名、クラス名など の'名前'を整数で管理しています。

つまり、メソッド名や変数名、定数名、クラス名を定義した瞬間にシンボルができるという意味です。 実際にやってみましょう。

class SymbolTest
end

symbol_var = 0

SYMLBOL_CONSTANT = 0

def symbol_method
end

p Symbol.all_symbols.include?(:SymbolTest)
=> true

p Symbol.all_symbols.include?(:symbol_method)
=> true

p Symbol.all_symbols.include?(:symbol_var)
=> true

p Symbol.all_symbols.include?(:SYMLBOL_CONSTANT)
=> true

見事に全てtrueを返しましたね。

> これは名前を直接文字列として処理するよりも 速度面で有利だからです。

文字列と数値なので、そりゃ高速になるだろうと反射的に思いましたが、こちらも検証してみます。

benchmarkというモジュールを使用して計測してみます。 実際のやり方はこちらを参考にしました。 Ruby でベンチマークを取る方法 - Qiita

require 'benchmark'

Benchmark.bm 10 do |r| 
  str = "0123456789"
  str_hash = { "0123456789" => 1 }
  r.report "String" do
    9999999.times { str_hash[str] }
  end 

  sym = :"0123456789"
  sym_hash = { "0123456789" =>  1 }
  r.report "Symbol" do
    9999999.times { sym_hash[sym] }
  end 
end

                 user     system      total        real
String       1.190000   0.000000   1.190000 (  1.190577)
Symbol       0.810000   0.000000   0.810000 (  0.815450)

文字列に比べて、シンボルは30%前後早くなっていますね。 すごいぞシンボル。

> 名前を管理するという役割上、シンボルと文字列は一対一に対応します。 また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。

同じ名前のシンボルであれば、いくつ生成してもオブジェクトIDが1つという意味ですかね。

hoge1 = "hoge"
hoge2 = "hoge"
puts hoge1.equal?(hoge2)
=> false

puts hoge1.object_id
=> 70281989413340

puts hoge2.object_id
=> 70281989361520

sym1 = :hoge
sym2 = :hoge
puts sym1.equal?(sym2)
=> true

puts sym1.object_id
=> 539048

puts sym2.object_id
=> 539048

こちらもリファレンス通りですね。

まとめ

冒頭でも書きましたが、Rubyにおけるコロンは、"シンボル"と呼びます。 一見文字列と同じように見えますが、内部的には整数と同様に扱われます。 そのため

  • 文字列と比較すると処理が高速
  • 同じ値であれば、生成されるオブジェクトは1つ。

また、クラス、メソッド、変数、定数を定義すると、その名前のシンボルも生成されます。

文字列とシンボルの使い分けとしては、

  • ハッシュのキー
  • メソッドの引数として渡すクラス名、メソッド名、変数名、定数名

などは、文字列ではなく、シンボルを使用したほうが良いでしょう。

こちらの本はRubyについて、今でもリファレンス的に使用している本なので、オススメします。
※今回のシンボルについては、ここまで詳細には書かれていませんが、全範囲を網羅的に書かれています。

homebrewでinstallしたcurlがbrew cask install時のTLS1.2ではOSX標準のcurlが邪魔をしてうまく反映されなかった時の対処法

概要

homebrewでinstallしたTLS 1.2 接続できるcurlbrew installでTLS1.2接続しなければならないパッケージのinstall時に、OSX標準のcurlを見に行ってしまい、うまくinstallできなかったので、その対処方法を書きます。

具体的には、brew cask install sourcetreeをした際に、curl https://downloads.atlassian.com/software/sourcetree/SourceTree_2.3.2.zipを叩くのですが、 そこでssl handshake failedとなり失敗していました。

手順

homebrewで最新のcurlをinstallしOpenSSLを使用するように変更

確認に使用したコマンドなども含めつつ説明していきます。

まずは、curlでTLS1.2で接続していないことを確認します。

$ curl --dump-header - https://www.example.com --tlsv1.2 --verbose 
*   Trying nnn.nnn.nnn.nnn...
* Connected to www.example.com (nnn.nnn.nnn.nnn) port 443 (#0)
* SSL peer handshake failed, the server most likely requires a client certificate to connect
* Closing connection 0
curl: (35) SSL peer handshake failed, the server most likely requires a client certificate to connect

次に、最新のOpenSSLでTLS1.2が使用できることを確認します。

$ openssl s_client -connect www.example.com:443 -tls1_2
CONNECTED(00000003)
...

既存のcurlにOpenSSLが使われていないことを確認します。

$ which curl
/usr/bin/curl
$ curl --version
curl 7.43.0 (x86_64-apple-darwin14.0) libcurl/7.43.0 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz UnixSockets

上記の通りOpenSSLが含まれていません。

homebrewで改めてcurlをinstallします。

$ brew install --with-openssl curl
$ brew link curl --force

OpenSSLが使用できているか確認します。

$ which curl
/usr/local/bin/curl

$ curl --version
curl 7.51.0 (x86_64-apple-darwin14.5.0) libcurl/7.51.0 **OpenSSL/1.0.2j** zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP UnixSockets 

OpenSSL/1.0.2jが適用されていることが確認できました。

念のために、TLS1.2で接続できるかも確認してみます。

$ curl --dump-header - https://www.google.com --tlsv1.2 --verbose
* Rebuilt URL to: https://www.google.com/
*   Trying 216.58.200.196...
* TCP_NODELAY set
* Connected to www.google.com (216.58.200.196) port 443 (#0)
...
...
* Curl_http_done: called premature == 0
* Connection #0 to host www.google.com left intact

問題なくTLS1.2接続できていますね。

シンボリックリンクを張る

この時点で、brew cask install sourcetreeを実行してもssl handshake failedになります。 前回の記事同様パスの影響を受けているのではないかと考えましたので、 brew cask installで見ているcurlシンボリックリンクで無理やりbrew installしたcurlを参照させます。

$ sudo mv /usr/bin/curl /usr/bin/curl_back
$ sudo ln -s /usr/local/bin/curl /usr/bin/curl
$ brew cask install sourcetree
==> Caveats
Cask sourcetree installs files under "/usr/local". The presence of such
files can cause warnings when running "brew doctor", which is considered
to be a bug in Homebrew-Cask.

==> Downloading https://downloads.atlassian.com/software/sourcetree/SourceTree_2.3.2.zip
Already downloaded: /Users/user_name/Library/Caches/Homebrew/Cask/sourcetree--2.3.2.zip
==> Verifying checksum for Cask sourcetree
==> Moving App 'SourceTree.app' to '/Applications/SourceTree.app'
==> Symlinking Binary 'stree' to '/usr/local/bin/stree'
🍺  sourcetree was successfully installed!

うまくいきました。 シンボリックリンクで無理やり変更しているので、ワークアラウンド感がハンパないですね。 うまいやり方があれば是非教えていただきたいです。

homebrewでinstlalしたOpenSSLが反映されず、OSX標準のOpenSSLが使用されてしまう場合の対処方法

概要

OSX標準のOpenSSLが古く、tls1.2で通信できず、curlが失敗する事案が発生してしまいました。 対処方法を調べても、

`brew update
brew upgrade openssl
brew link openssl --force

で治りました^^

という記事が多かったのですが、上記の対応でもopenssl versionが古いままだったので、その対処方法を書きます。

手順

手順は下記の通りです。

  • homebrewで最新のOpenSSLをinstallし、リンクを張る
  • OpenSSLのパスを確認
  • 環境変数の設定

homebrewで最新のOpenSSLをinstall

この記事にたどり着いた人は、既に実行済みかつ、5,000万回は同じことを見ていると思いますが、 念のため記載しておきます。

$ which openssl #opensslのパスを確認 /usr/bin/openssl となってるはず
$ openssl version #バージョンの確認
$ brew update #brewのアップデート
$ brew list #opensslがインストールされているか確認
$ brew info openssl #最新版の情報取得
$ brew upgrade openssl #アップグレード
$ brew link openssl

OpenSSLのパスを確認

だいたいの記事では、これで治りました報告が多かったのですが、自分の場合は、 この時点でopenssl versionをやっても古いままでした。

今一度、パスを確認してみると

$ openssl version
OpenSSL 0.9.8zg 14 July 2015

$ which openssl
/usr/bin/openssl

$ brew info openssl
openssl: stable 1.0.2j (bottled) [keg-only]
ずらずら〜〜
/usr/local/Cellar/openssl/1.0.2j (1,695 files, 12M)

OSX 標準のOpenSSLのパスが/usr/bin/opensslだったのに対して homebrewでinstallしたOpenSSLが/usr/local/Cellar/openssl/1.0.2jなのが分かります。

環境変数の設定

これまでの結果から、読み込まれる順番が問題なのではないか?と推測し、 $PATHの設定を疑いました。

$ echo "export PATH=/usr/local/Cellar/openssl/1.0.2j/bin:$PATH" >> ~/.bash_profile
$ source ~/.bash_profile
$ which openssl
/usr/local/Cellar/openssl/1.0.2j/bin/openssl
$ openssl version
OpenSSL 1.0.2j  26 Sep 2016

予想通りでした。 brew link opensslだけでは正常に反映されておらず、基本的なパスなどの確認を怠っていたがために小一時間ハマってしまいました。

AWSアカウント開設直後 & EC2インスタンス立ち上げ直後に最低限行うべきこと

概要

以前からクラウド破産クラウド破産と耳に入ってはいたが、個人で利用しているAWSアカウントはほぼノーガードでした。
また、ピクスタの来期AWS予算を策定していく中で、こんな金額がいきなり身に降りかかってきたら生命保険に入ることを考えてしまうだろうと思ったため、
個人のアカウントも最低限セキュリティ対策をすることにしました。

やったこと(IAM & Billing)

  • MFA導入
  • IAM設定
    • グループ、ユーザー、IAMユーザーに対してのMFA設定
  • コストエクスプローラーのの有効化
  • アカウント設定
    • 秘密の質問など
  • CloudTrailの有効化
  • Trusted Advisor チェックの実施

ここまで箇条書きにしてみたものの、クラスメソッドさんの記事を参考にしました。

個人で使用する分には、IAMグループでAdministratorAccessを設定するのは、やむなしかと思ったのですが、 組織で使用する場合には、適切にグループの権限設定をした方が吉だと思いました。

やったこと(EC2)

アカウント全般もさることながら、EC2インスタンスもAmazonLinuxのAMIをまんま使用していたので、
稼働中のインスタンスに対してもセキュリティ向上のために下記を参考に諸々実施しました。

大きくは、

  • ec2-userの削除
  • sshdのLISTENポート変更
  • git-secretsの使用

がセキュリティ上、有用ってところでしょうか。

特に自分の場合は、個人で開発を進めているとアクセスキーとシークレットキーを誤ってcommitしてしまう事案が多発しているので、
git-secretsは入れておくべきだと感じました。

まとめ

実際にやってみて感じたのは、項目は多少多いものの、設定自体は簡単でした。 今更ながらですが、デフォルト設定のままだと不正利用された時に何も言えなくなるので、最初に締めべきとこは締めた方が良いと思います。

Re:dashのインストールから定期実行までの手順と使用感のまとめ

前回までの記事で

と、Webサービスのデータ解析をする上で必要なデータソースから取り込む手順を書きました。
今回は、それを定期的に実行する設定の手順を書きます。

Re:dashの設定

  1. クエリ画面にアクセス
  2. Refresh Scheduleのリンクを押下
  3. 実行スケジュールを設定。 上記の設定で決まった時間、決まった間隔で実行することが可能です。

また、Re:dashはクエリで取得するデータはページにアクセスする度に取得するわけではなく、内部に保存することで高速に情報を取得するようになっています。
取得するのに時間がかかるクエリは、深夜に実行しておくのが賢い使い方かもしれません。

f:id:watasihasitujidesu:20160815165803p:plain

Googleスプレッドシートの設定

  1. メニュバー > アドオン > Google Analytics > Schedule reportsを押下
  2. Enable reports to run automatically. にチェック
  3. 実行する間隔と時間を設定

f:id:watasihasitujidesu:20160815165828p:plain

f:id:watasihasitujidesu:20160815165842p:plain

以上で定期実行の設定は終わりです。
GoogleスプレッドシートとRe:dashの設定は、多少互いの実行時間を気にする必要はありますが、
ここまでできれば、自動でデータが取得できるので、Re:dashでダッシュボードを設定したり、
良い感じにグラフを組み合わせることで、データ可視化 & 共有プラットフォームの構築が可能になります。

まとめ

個人的には、
これまでRailsActiveRecordでデータ取得して〜
Viewでhtml書いて〜
Google Chartsでグラフ描画して〜
あ、そうだそうだ、絞り込みも追加して〜

と、自分でゴリゴリ書いていくのではなく、閲覧系の機能はRe:dashにお任せして、
更新系機能やRe:dashで実現しきれない部分だけは自分で作っていた方が良いと思いました。

また、難しいと感じる点は2点あります。

1点目は
GoogleスプレッドシートSQLの出力イメージをRe:dashで使えるように考えるは難しいのではないかと感じています。
特に、非エンジニアに運用を展開するときは、そこを厚めにサポートしなければ組織根付いていかないのかなと思っています。

2点目は
ダッシュボードに属させるクエリの管理です。
ここのカテゴライズを考えておかなければ、結局「あのデータどこに行ったっけ?エンジニアに聞いたろ」
ということが発生してしまうので、エンジニアの手間があまり軽減しない可能性があると思いました。

Re:dashがここまでデータ抽出 => 可視化を簡単に出来るとは思いませんでした。
難しいと感じる点で書いた2点、すなわち組織への展開と運用方法の確立さえうまくいけば、
エンジニアやディレクターの工数軽減できるサービスだと思います。

GoogleAnalyticsからGoogleスプレッドシートに自動でデータを取得する

前回の記事では、Googleスプレッドシートの値をRe:dashに取り込む方法を紹介しました。 今回は、GoogleAnalyticsのデータをGoogleスプレッドシートに取り込む手順を紹介しようと思います。

1. Googleスプレッドシートのアドオンを取得する。 GoogleスプレッドシートのアドオンにGoogleAnalyticsががあるので、それを取得します。 f:id:watasihasitujidesu:20160815123805p:plain f:id:watasihasitujidesu:20160815123833p:plain

2. メニューバー > アドオン > GoogleAnalytics > Create new reportで取得情報を設定する

Create new reportを選択すると右側に情報入力欄が表示されます。 そこの、 1) Name Your Report(これは好きな名前でOK) 2) Select Account Information - Account - Property - View (Profile) を設定してください。 上記の設定は、情報取得元になります。

入力が完了したらCreate Reportボタンを押下します。 f:id:watasihasitujidesu:20160815123904p:plain f:id:watasihasitujidesu:20160815123915p:plain

3. 取得したい情報を入力する。 2の手順が完了するとReport Configurationというシートが追加されます。 そのシートの下記項目を埋めていきます。

  • Metrics(縦軸)
  • Dimensions(横軸)

今回は、下記の内容を記入して実行してみます。

項目名 入力値
Metrics ga:sessions
Dimensions ga:date,ga:medium
Sort -ga:sessions

上記は直近7日間を日ごとに、参照元別のセッション数を出すための切り口を設定しています。

4. 実行する メニューバー > アドオン > GoogleAnalytics > Run reportsで値を取得します。

f:id:watasihasitujidesu:20160815123937p:plain

取得した値を元にRe:dashに適用できるようにピボットテーブルなどで加工すると、Google AnalyticsのデータをRe:dashで表示できるようになります。

Googleスプレッドシートの値をRe:dashに取り込む

Re:dashではDataSourceにGoogleスプレッドシートを指定することができます。 Googleスプレッドシートからデータを取り込む場合、 GoogleAPIConsoleからAPI Keyを発行するなど、手順が多かったので、今回の記事でまとめようと思います。

1. GoogleAPIConsoleにアクセス

2. 新規プロジェクト作成 Re:dash用のプロジェクトを作成します。 f:id:watasihasitujidesu:20160814130146p:plain

3. API Keyを作成

  • 画面左のサイドナビより認証情報をクリック f:id:watasihasitujidesu:20160814130147p:plain

  • 認証情報を作成 > サービス アカウントキーを選択 f:id:watasihasitujidesu:20160814130145p:plain

  • サービスアカウント種別を新しいサービスアカウントを選択し、各項目を入力。キーのタイプはJSONを選択 f:id:watasihasitujidesu:20160814130148p:plain

  • 画面左のサイドナビよりダッシュボードをクリック > APIを有効にするをクリック f:id:watasihasitujidesu:20160814130142p:plain

  • 検索フォームに"Drive"と入力すると出てくるGoogle Drive APIを選択 f:id:watasihasitujidesu:20160814130143p:plain

  • 有効にする をクリック f:id:watasihasitujidesu:20160814130144p:plain

これで、Googleスプレッドシートを操作するAPIキーの取得と、APIの有効化が終わりました。

4. Googleスプレッドシートで、APIと連携

  • API Keyを作成する過程で、秘密鍵jsonとしてDLできたはずです。このjsonファイルにemailが記載されているので、それをコピーしておきます。 
  • Googleスプレッドシートの共有設定で、先ほどコピーしたemailと共有する。

f:id:watasihasitujidesu:20160814131317p:plain

5. Re:dashでDataSourceを追加 Re:dash側でデータソースを追加します。
typeはGoogleSpreadSheetを選択し、API Keyを取得する際にDLしてきたjsonをファイル選択して、作成します。

f:id:watasihasitujidesu:20160814131333p:plain

6. クエリ作成 クエリ作成は少し、注意する必要があります。
取り込みたいGoogleスプレッドシートのURLが
https://docs.google.com/spreadsheets/d/10fdasFMDSjige4dfsaOMGF0asfmm1/edit#gid=2008635114
というURLで、左から2番目のシートを取り込みたい場合のクエリは

10fdasFMDSjige4dfsaOMGF0asfmm1|1
となります。
注意することは2つあります。
1. スプレッドシートのURLとシートの番号は|で区切る
2. シートの番号は左から0,1,2...となる。
10fdasFMDSjige4dfsaOMGF0asfmm1|1

f:id:watasihasitujidesu:20160814132025p:plain

この方法を参考に、自身のクエリを作り、実行すると、GoogleスプレッドシートのデータをRe:dashに取り込むことができます

Re:dashでデータソースとしてMysqlを追加する

saitou.hatenablog.com 前回の記事でRe:dashを使えるようにしましたので、今回はDataSourceとしてMySQLを追加してみます。

1. ログインする 初期ユーザーのログインidとpassは下記の通りです。 ID: admin PASS: admin

2. 画面右上のDBマークをクリックする

f:id:watasihasitujidesu:20160814123142p:plain

3. New DataSourceをクリック

f:id:watasihasitujidesu:20160814123151p:plain

4. 項目を埋めていく

f:id:watasihasitujidesu:20160814123204p:plain

5. DBが作成されたことを確認

f:id:watasihasitujidesu:20160814123155p:plain

6. クエリを実行してみる http://作成したインスタンスのIP/queries/new 上記にアクセスし、DataSourceを作成したDBを選択すると、 画面左側にスキーマ情報が表示されました。 スキーマが表示されれば接続自体できていますので、クエリを作成-実行してみてください。

f:id:watasihasitujidesu:20160814123206p:plain

Re:dashはスキーマを確認できるだけではなく、クエリの整形や、 グラフのpngダウンロード, 数値のCSV, Excelダウンロードまでサポートしています。

また、作成したグラフは範囲を指定することで、特定の日付に絞り込んだりすることができるので、 いちから自分で画面を作るより、だいぶ楽です。

データ可視化, 共有プラットフォームとして人気のRe:dashをAWS EC2で試してみるまでの手順

うちの会社では

ということが数多くあります。

正直Railsで実装するとなると、viewまで書かなければならなくしんどいのと、 GAからデータ取得し、スプレッドシートに貼り付けという作業をdailyでやり続けるめんどくささがありました。

これらの作業を自動で取得からグラフ作成できる良いツールはないかと探していたところ、 Re:dashと言われるデータ可視化, 共有プラットフォームツールがあるということで、試してみました。

今回はAWS EC2を使用してログインするところまでの手順を書こうと思います。

Re:dashとは

Re:dashとは、DataSource*1*2にクエリを投げ、返って来た結果を簡単にグラフ化、共有、ダッシュボードに登録することで、
データ可視化や共有プラットフォームとして機能することが期待できるツールです。 また、クエリは定期実行*3させたり、クエリをForkして使いまわせたりできます。 データやグラフについても、CSV, ExcelでDLや、iframeでhtmlに組み込み、png画像としてDLできたりします。

f:id:watasihasitujidesu:20160814120841p:plain

AWS EC2で試す手順

  1. AMIを使用する。 AWSで試すのであれば、AMIを使用するのが、最速です。 リージョンが東京*4であればami-b30ec9d2というAMIIDですぐに環境を立ち上げることができます。

f:id:watasihasitujidesu:20160814120845p:plain

  1. セキュリティグループの設定 Re:dashの操作方法は2種類あります。
  2. Webからアクセスして操作する方法
  3. ssh接続して操作する方法

なので、セキュリティグループで22(ssh), 80(http), 443(https)を開けておく必要があります。 また、AMIのOSはubuntuですので、ssh接続する際のユーザーはubuntuを指定する必要があります*5
ssh -i ~/.ssh/public.key ubuntu@ip-adress

  1. ログインしてみる
  2. で作成したインスタンスのIPにアクセスしてみましょう。
    アクセスするとIDとPASSを入力するフォームがあるので、
    初期ユーザの
    ID: admin
    PASS: admin
    でログインできるはずです。

AWS EC2のAMIを使用すれば、少しの時間でRe:dashを使えるようになります。
AWS以外にも

  • Google Compute Engine
  • Docker Compose
  • Heroku
  • apt-get などサポートしているので、初期導入までは比較的容易に済みそうです。

*1:MySQL, PostgreSQL, TDなど

*2:Google SpreadSheetも含まれるのでDataSourceと表記しました

*3:毎分, 時, 週, 月など

*4:ap-northeast-1

*5:普段ubuntuを触らないので、ssh接続するのに小一時間くらいハマりました

Qtがないとcapybara-webkitがbundle installできないので対処する方法

概要

Qtがないとcapybara-webkitをinstallできないって毎回怒られるんだけど、
毎回やりかた忘れちゃうのでメモ

手順

Qtのインストール

# qt4
$ wget https://download.qt.io/official_releases/qt/4.8/4.8.7/qt-everywhere-opensource-src-4.8.7.tar.gz
$ tar xzvf qt-everywhere-opensource-src-4.8.7.tar.gz
$ rm qt-everywhere-opensource-src-4.8.7.tar.gz
$ cd qt-everywhere-opensource-src-4.8.7
$ ./configure -opensource -nomake examples -nomake tests
$ sudo gmake -j2 # 2並列で1時間くらいかかる
$ sudo gmake install
$ sudo ln -s /usr/local/Trolltech/Qt-4.8.7/bin/qmake /usr/bin/qmake

# qt5
$ more /etc/yum.repos.d/cent6.repo
[CentOS6riken]
name=Extra Packages for Enterprise Linux 6 - $basearch
baseurl=ftp://ftp.riken.jp/Linux/centos/6/os/x86_64/
#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
$ sudo yum install qt5-qtwebkit-devel
$ sudo ln -s /usr/lib64/qt5/bin/qmake /usr/bin/qmake

Xvfbのインストール

Qtをインストールした後にbundle installをするとHeadless::Exception: Xvfb not found on your systemと怒られるので、Xvfbをインストールする。

sudo yum install -y libXcomposite.x86_64 xorg-x11-server-Xvfb.x86_64

エンジニア版 人を動かすだと感じた TeamGeekを読みました。

最近はコードより人とやりとりすることが多くなってきたので、TeadmGeekを読んでみました。
今回はその感想を書きたいと思います。

エンジニアが他人とうまくやっていく知見が詰まった本

TeadmGeekは、チームで仕事をするプログラマーに向けた本です。
また、他人とうまく仕事をするということにフォーカスを当てているので、プログラムの話は一切出てきません。

この本は6章立てです。

  • ソフトウェア開発はチームスポーツである
  • チームの文化を作る効用
  • リーダーの必要性
  • 良くない振る舞い(行動的な意味)を排除する方法
  • 開発チームが属する組織に対しての操作技法

一人のエンジニアとしての心構えとして有名な3本柱、HRT(謙虚、尊敬、信頼)の重要性や、
チーム文化の重要性、組織に対しての行動の仕方などが書いています。

HRT(謙虚、尊敬、信頼)

チームで開発を進めていくと衝突する、あらゆる人間関係は、謙虚、尊敬、信頼の欠如により、発生するものだと書かれています。
謙虚、尊敬、信頼とだけ聞くと、自らの意見を殺た方がよいのか?と思ったのですが、そういうことではなく、
チームとしてよりよい成果を得るための効率的なコミニュケーション方法だと学ぶことができます。

本のなかでは、実際の事例を基に、テクニックを活かすとこうなる!というような構成で書かれています。

この本を読んだ後に思ったのは、
HRTを知らない人(例えば超絶自分勝手な人)に対峙した場合に、一歩引いた視点で接することができるのではないかと思いました。
本書の狙い通り、なるべく衝突を回避すべく、落ち着いて誠実に対応できるでしょう。

チームには文化が必要

開発チームが共有する文化(経験・価値・目標)は、効率的なコミニュケーションや、エンジニアリングに必要ということはなんとなくわかっていて、本にも書いていたのですが、
発見があった点は、新しく入ってきたメンバーに対しての抵抗力にもなるというところでした。

文化がないチームに新しくメンバーが入ってきた場合、入ってきたばかりのメンバーの声が強ければ、
一瞬にしてその人価値観が文化になってしまう恐れがあると書かれていました。

発足してから時間が経ったチームには、文化を明文化する必要性が見えてきたのは良かったです。

チームにはリーダーが必要

この本では、リーダーに"なってしまった"人のための行動のコツについても書いてあります。 具体的には下記のことが書かれています。

  • 初期の心理状態
  • 陥りやすい悩み
  • 心構え
  • エンジニアとリーダーは仕事が違うこと
  • 行動のアンチパターン
  • 良い行動パターン

リーダーは、チームの触媒になるよう、目標を掲げたり、メンバーやチームの成功と幸せを考えたりと、
コードを書いていた時とは違う時間の使い方をしなければならないと、この本でも書いていました。

マネージャー向けに書かれた本でも書かれていたのは、以前のエントリでも学びましたが、
エンジニア向けに書かれたこの本でも同様のことが書かれていたので、妙な納得感がありました。

良くない振る舞い(行動的な意味)を排除する方法

リーダーからもう一歩上の視点になったことについても書かれていました。
良くない振る舞い(行動的な意味)を排除する方法*1と、
開発チームが属している組織に対しての行動についてです。

基本的には、HRTの精神で臨むことを前提として書かれています。
良くない振る舞いに対しては、相手の想いと伝え方を最大限考え、対処するのがベストプラクティスだと学べます。
また、良くない振る舞いをしている人であったとしても、基本的には自分の中での正義があるので、
そのベクトルを揃えるために、チームの文化も必要だと感じました。

組織に対しての行動

エンジニアは、より良いコードを書くことばかりに集中していてはダメだと書いています。
組織でうまく働くことについても書かれています。

本を読んで感じたのは、入社した瞬間の信頼貯金0の状態から、組織に信頼され、自分の意見や運命をコントロールできるポジションにつくまでの行動について書かれていると思いました。

エンジニアとしては、リリースよりもリファクタリングや技術的な解決に目が行きがちだが、
組織としては、サービスのローンチやユーザーに与えるインパクトの方が圧倒的に価値があることを、認めるべきと書かれています。

エンジニアは開発するだけが全てではなく、客観的(会社やビジネス側から見る視点)に見た事実を理解した上で、技術を活かすアプローチではないと、苦しくなると、だいぶ生々しいことが書かれています。

まとめ

この本はエンジニア版の人を動かす*2だと思いました。
HRTを基本原則として、チームで成果を出すための知見が詰まった本なので、ほぼ全てのエンジニアにお勧めできる本だと思います。

また、リーダーとしての視点や、エンジニア個人として組織内での動き方についても書かれているので、"チームで成果を出す"という点以外でも十分学びを得られる本だと思います。

*1:本の中では有害な人の追い出し方と書いていますが、有害な人=特定の個人と勘違いしやすいので、良くない振る舞い(行動的な意味)を排除する方法としています。

*2:D・カーネギー

Solr 4.10.4でSolrCloudを試してみました。

ピクスタの開発部で開発合宿を開催したので、
Solr4からの新機能であるSolrCloudを試してみました。
前回の記事はこちらです。

また参考にした書籍は↓こちらです

分散インデクシングやレプリケーションを自前で構築してもいいけど・・・

前回の記事では、インデクシング時の偏り、エラーによる単一障害によるシステム全体のダウンなどを挙げました。
SolrCloudは、分散インデクシングやレプリケーションのメリットを活かしつつ、
これらの問題を回避できる分散環境の仕組みを提供します。

具体的にはZooKeeperというものが組み込まれており、それがnodeのステータス管理、分散検索時のフェイルオーバー、単一障害点などをなくす仕組みになっています。

今回は、シャード数2, レプリケーション数2の4台構成のシステムを想定して、環境を構築していきます。

まずは各nodeの基となるデータを作成します。

$ cd ~/solr-4.10.4/
$ cp -R example/ node1
$ cp -R example/ node2
$ cp -R example/ node3
$ cp -R example/ node4

SolrCloudの起動

node1を立ち上げる際にzookeeperの起動と設定も同時に行います。

$ cd ~/solr-4.10.4/node1
$ java -Dbootstrap_confdir=./solr/collection1/conf -Dcollection.configName=myconf -DzkRun -DnumShards=2 -jar start.jar

注意する点が一点あります。
書籍では
java -DzkRun -DzkHost=http://localhost:9983 -Dbootstrap_conf=true -DnumShards=2 -jar start.jar
と書いてあるのですが、bootstrap_conf=trueだけでは、zookeeperがconfigファイルを読み込めないので、
bootstrap_confdirを設定する必要があります。

続いて、node2, node3, node4をzookerrperの管理下で起動します。

$ cd ~/solr-4.10.4/node2
$ java -Djetty.port=8985 -DzkHost=localhost:9983 -jar start.jar

$ cd ~/solr-4.10.4/node3
$ java -Djetty.port=8987 -DzkHost=localhost:9983 -jar start.jar

$ cd ~/solr-4.10.4/node4
$ java -Djetty.port=8989 -DzkHost=localhost:9983 -jar start.jar

node4まで立ち上げたらSolrCloud(zookeeper)が起動しているhttp://localhost:8983にアクセスしてみましょう。
zookeeperを立ち上げた状態であれば、サイドバーにCloudというタブがあるはずなので、表示してみましょう。

f:id:watasihasitujidesu:20160124011240p:plain

設定した通り、シャード数2, レプリケーション数2の構成が出来上がりました。
ここまで簡単に環境ができるとはあっぱれ。

また、SolrCloudではRest APIを提供しており、管理画面からだけではなく、CLIで設定を変更できます。
一覧や詳細はこちらを参照してみてください

CLIを使用しても、レプリケーション数やシャード数を変更することができるので、
サーバー監視ツールからのalertなどで、状況に応じて柔軟にスケールすることができます。

今回の開発合宿では手元の書籍がSolr4系だったので、それで進めてきたのですが、
今後は5系でも同様の構成が作成できるように学んで行こうと思います。