ちなみに、Fluentdのin_tailプラグインのmultilineで頑張って分析することも考えたのですが、先日のTreasure Data Tech Talkの懇親会で古橋さんに相談したところ、「パーサの処理が複雑なら、Embulkのparserプラグインを自分で書いたほうが楽ですよ」とアドバイスを頂いたので、今回はEmbulkで行くことにしました。
defrun(file_input)
while file = file_input.next_file
file.each do |buffer|
# parsering code
record = ["col1", 2, 3.0]
page_builder.add(record)
endend
page_builder.finish
end
で、あとはこの file.each do |buffer| 以降の処理を書き換えるだけ、と思ったのですが……このbufferには行の区切りを無視してログが書き込まれます。例えば、"2015-03-14 20:16:45, 183"という時刻の"2015-03-"までが前のバッファ、"14 20:16:45, 183"が次のバッファに分かれるといったことが普通に起こってしまいます。この結合を自前で行わなければいけないとしたら、ちょっと面倒ですよね……。
中身はembulk new ruby-parserコマンドで生成したひな形の、ほとんどそのままで、編集したのはREADME.mdと、lib/embulk/parser/multiline-log-sample.rbのみです。今回は、手元にある特殊なログを解析する、というユースケースのため、guessの方は書きませんでした。
moduleTypeifEmbulk.java?
defself.from_java(java_type)
java_type.getName.to_sym
enddefself.new_java_type(ruby_type)
case ruby_type
when:booleanJava::Types::BOOLEANwhen:longJava::Types::LONGwhen:doubleJava::Types::DOUBLEwhen:stringJava::Types::STRINGwhen:timestampJava::Types::TIMESTAMPelseraiseArgumentError, "Unknown type #{ruby_type.inspect}: supported types are :boolean, :long, :double, :string and :timestamp"endendendend
# Return new line from any file or nildefread_new_line(decoder)
begin
line = decoder.poll
rescue# At first time, java.lang.IllegalStateException is thrownendif line == nilreturnnilif decoder.nextFile == false
read_new_line(decoder)
else
line
endend
def add(page)
# filtering code:
idx = 3
page.each do |record|
case record[idx]
when /^login failure:/
record[idx] = "login failure"
when /^login by/
record[idx] = "login"
end
page_builder.add(record)
end
end
def add(page)
# find index of "comment" column
columns = page.schema.select{|c| c.name == "comment" }
idx = columns[0].index
# filtering code:
page.each do |record|
case record[idx]
when /^login failure:/
record[idx] = "login failure"
when /^login by/
record[idx] = "login"
end
page_builder.add(record)
end
end
あと、IoT向けFluentdであるFluent-Bitについて、開発者のEduardo Silva氏による講演もありました(今回の目玉?)。mBaaSのようなものは認識していたのですが、IoT機器からCPUなどのメトリクスやらsyslogやらを収集というのは個人的に盲点でした。まだvery early stateなプロジェクトということなので、今後に注目したいと思います。
詳細は後述しますが、なんと、GitHub Wikiには全文検索機能がありません。そのため、全文検索を行いたい場合は、WebブラウザにGitHub Wiki Searchをインストールする必要があります。Chromeの場合はWebストアからGitHub Wiki Searchをインストール可能です。
Firefoxの場合は、Userscripts.orgからGreasemonkeyスクリプトが配布されているようですが、このサイトはずっと落ちているようで、ミラーサイトからダウンロードするしかないようです。
*1:GitHub WikiとGollumの関係について、GitHubにもGollumのページにも、明確に書いてあるところが見つけられませんでした。この理解で正しいのでしょうか? 自分が探してみた範囲では、wicketstuff/core Wikiに "The Github wiki is implemented using github/gollum."との記載がありました。
% bundle exec rake inventory=./hosts status=running -T
rake spec:bar.example.com # Run tests for host 'bar.example.com'
rake spec:dbservers:one.example.com # Run tests for group 'dbservers'
rake spec:dbservers:three.example.com # Run tests for group 'dbservers'
rake spec:dbservers:two.example.com # Run tests for group 'dbservers'
rake spec:foo.example.com # Run tests for host 'foo.example.com'
rake spec:mail.example.com # Run tests for host 'mail.example.com'
rake spec:one.example.com # Run tests for host 'one.example.com'
rake spec:three.example.com # Run tests for host 'three.example.com'
rake spec:two.example.com # Run tests for host 'two.example.com'
rake spec:webservers:bar.example.com # Run tests for group 'webservers'
rake spec:webservers:foo.example.com # Run tests for group 'webservers'
irb(main):004:0> hosts = IniFile.load('./hosts')
IniFile::Error: Could not parse line: "web01"
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:578:in `error'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:532:in `block in parse'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:515:in `each_line'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:515:in `parse'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:400:in `parse'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:128:in `block in read'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:128:in `open'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:128:in `read'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:80:in `initialize'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:31:in `new'
from /Library/Ruby/Gems/2.0.0/gems/inifile-3.0.0/lib/inifile.rb:31:in `load'
from (irb):4
from /usr/bin/irb:12:in `<main>'
2015-09-26追記: 記事を書いた時は30〜50「気圧」防水と誤解していたのですが、実際は30〜50m water registance、つまり30「m」防水であるとG+のコミュニティで教えてもらいました。上の記載も修正しました。 日本時計協会 (JCWA)のページや Water Resistant mark (Wikipedia)によると、30m防水(Pebble Time)は水泳には適さない、50m防水(Pebble)は適する、とのこと。僕はPebble Timeを水泳に使ってしまっていますが、これは非推奨の無理な使い方をしている、という前提で読んでください。
Play Storeで"Swim.com"で検索してインストールしてもいいですが、検索結果の上位には出てこず、この記事を書いた時点では25位くらいに出てきました。この時点で「このアプリ大丈夫なのか?」と不安になるかもしれませんが(僕はなりました)、大丈夫です。Storeの評価も現時点で2.6と低めですが、大丈夫です。正直使いづらいアプリですが、徐々に改善されてます。
Swim.com brings all the functionality of a smart swim watch onto Pebble with the most advanced swimming app yet. The Swim.com app automatically records distance swum, lap times, pace, strokes and other key metrics to provide feedback about your swim. Workouts can be automatically synced to Swim.com using the companion app where you can track your progress, connect and compete. INSTRUCTIONS FOR USE: http://i.imgur.com/WDPLeyY.png
Also, many times two swims of the exact distance in the same body of water will not record the same distance because each time the watch is submerged it loses contact with the satellite and tries to regain each time it is out of the water. There is about a 10% +/- margin of error.
そのため、PebbleでのSwim.com利用は許してもらえたらラッキーくらいに考えておいて、もしこのアプリを目当てにPebbleを購入するのであれば、プールの方に事前に相談したほうがよさそうです。監視員の方と何度か話した感じからすると、Pebble Time Steelに金属バンドを付けたようなものだと「人にぶつかると危険だから」という理由で使わせてもらえないかもしれません。まあ、そもそも、水中で使うつもりならSteelは選ばないと思いますけどね。
まとめ
日本でPebbleを買っている AND プールで泳いでいる という条件を満たすユーザが少ないのか、日本語の情報はさっぱり見つからない Swim.com をご紹介しました。
Otto の目標は、このようにアプリケーションの依存関係が定義された1個の Appfile を元に、複数のアプリケーションが動作するVM群(またはコンテナ群)を一括セットアップできるようにすることです。この機能があることをもって、HashiCorpは、Otto は "Built for Microservices"であると標榜しています。
この目標に魅力を感じて、僕も最近少しずつOttoを試しています。ただ、Otto はリリースされたばかりの version 0.1 ということで、この機能(Dependency)はまだ未実装な部分が多いようです。自分の理解のためもあり、現状をまとめてみました。
otto compileコマンドを実行すると、このAppfileをもとに、Vagrant、Terraform、Consulなどの設定ファイルが自動生成されます。生成されたファイルは .otto フォルダ以下に格納されています。この処理を Otto では「コンパイル」と呼んでいます。
Otto 0.1.0 には、source = "github.com/hashicorp/otto/examples/mongodb"を指定するとコンパイルに失敗するというバグがあったのですが、最新版では解決しています。
happyturn% otto compile
==> Loading Appfile...
==> Fetching all Appfile dependencies...
Fetching dependency: git::https://github.com/hashicorp/otto.git//examples/mongodb
==> Compiling...
Application: otto-getting-started (ruby)
Project: otto-getting-started
Infrastructure: aws (simple)
Compiling infra...
Compiling foundation: consul
==> Compiling dependency 'mongodb'...
==> Compiling main application...
==> Compilation success!
This means that Otto is now ready to start a development environment,
deploy this application, build the supporting infrastructure, and
more. See the help for more information.
Supporting files to enable Otto to manage your application from
development to deployment have been placed in the output directory.
These files can be manually inspected to determine what Otto will do.
happyturn% otto dev
==> Creating local development environment with Vagrant if it doesn't exist...
Raw Vagrant output will begin streaming in below. Otto does
not create this output. It is mirrored directly from Vagrant
while the development environment is being created.
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'hashicorp/precise64'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'hashicorp/precise64' is up to date...
==> default: Setting the name of the VM: dev_default_1446212147870_20376
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: hostonly
==> default: Forwarding ports...
default: 22 => 2200 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2200
default: SSH username: vagrant
default: SSH auth method: private key
default:
default: Vagrant insecure key detected. Vagrant will automatically replace
default: this with a newly generated keypair for better security.
default:
default: Inserting generated public key within guest...
default: Removing insecure key from the guest if it's present...
default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
default: The guest additions on this VM do not match the installed version of
default: VirtualBox! In most cases this is fine, but in rare cases it can
default: prevent things such as shared folders from working properly. If you see
default: shared folder errors, please make sure the guest additions within the
default: virtual machine match the version of VirtualBox you have installed on
default: your host and reload your VM.
default:
default: Guest Additions Version: 4.2.0
default: VirtualBox Version: 4.3
==> default: Configuring and enabling network interfaces...
==> default: Mounting shared folders...
default: /vagrant => /Users/myoshiz/Otto/otto-getting-started
default: /otto/foundation-1 => /Users/myoshiz/Otto/otto-getting-started/.otto/compiled/app/foundation-consul/app-dev
default: /otto/foundation-mongodb-1 => /Users/myoshiz/Otto/otto-getting-started/.otto/compiled/dep-24cbbebc-fc41-53b4-c844-60d642fb523c/foundation-consul/app-dev-dep
default: /otto-deps/mongodb-24cbbebc-fc41-53b4-c844-60d642fb523c => /Users/myoshiz/Otto/otto-getting-started/.otto/appfile/deps/b80064b1b081e385b5c0cf62e2b2b3f0
==> default: Running provisioner: shell...
default: Running: inline script
==> default: stdin: is not a tty
==> default: [otto] Installing Consul...
==> default: [otto] Installing dnsmasq for Consul...
==> default: [otto] Configuring consul service: otto-getting-started
==> default: Running provisioner: shell...
default: Running: inline script
==> default: stdin: is not a tty
==> default: Running provisioner: docker...
default: Installing Docker (latest) onto machine...
==> default: Starting Docker containers...
==> default: -- Container: mongodb
==> default: Running provisioner: shell...
default: Running: inline script
==> default: stdin: is not a tty
==> default: [otto] Configuring consul service: mongodb
==> default: Running provisioner: shell...
default: Running: inline script
==> default: stdin: is not a tty
==> default: [otto] Setting locale to en_US.UTF-8...
==> default: Running provisioner: shell...
default: Running: inline script
==> default: [otto] Adding apt repositories and updating...
==> default: [otto] Installing Ruby 2.2 and supporting packages...
==> default: [otto] Configuring Ruby environment...
==> default: [otto] Installing Bundler...
==> default: [otto] Bundling gem dependencies...
==> default: [otto] Configuring Git to use SSH instead of HTTP so we can agent-forward private repo auth...
==> Caching SSH credentials from Vagrant...
==> Development environment successfully created!
IP address: 100.115.125.105
A development environment has been created for writing a generic
Ruby-based app.
Ruby is pre-installed. To work on your project, edit files locally on your
own machine. The file changes will be synced to the development environment.
When you're ready to build your project, run 'otto dev ssh' to enter
the development environment. You'll be placed directly into the working
directory where you can run 'bundle' and 'ruby' as you normally would.
You can access any running web application using the IP above.
ローカル環境への構築結果の確認
これで、1台のVMが起動し、そのうえでRubyアプリケーションと、MongoDBが動作するコンテナが動くようになりました。VMが1台しか動いていないことは、以下のコマンドで確認できます。ちなみに、otto dev vagrant [subcommand]で、Vagrantの任意のサブコマンドを実行できます。このように、ローカル環境に関しては、OttoはVagrantの単なるラッパーです。
happyturn% otto dev vagrant status
==> Executing: 'vagrant status'
Current machine states:
default running (virtualbox)
otto dev sshコマンドで、いま起動したVMにログインできます。
happyturn% otto dev ssh
==> Executing SSH. This may take a few seconds...
Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic x86_64)
* Documentation: https://help.ubuntu.com/
New release '14.04.3 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Welcome to your Vagrant-built virtual machine.
Last login: Fri Sep 14 06:23:18 2012 from 10.0.2.2
vagrant@precise64:/vagrant$ consul members
Node Address Status Type Build Protocol DC
precise64 10.0.2.15:8301 alive server 0.5.2 2 dc1
vagrant@precise64:/vagrant$ curl http://mongodb.service.consul:27017
It looks like you are trying to access MongoDB over HTTP on the native driver port.
happyturn% otto build
==> Detecting infrastructure credentials for: otto-getting-started (aws)
Cached and encrypted infrastructure credentials found.
Otto will now ask you for the password to decrypt these
credentials.
Encrypted Credentials Password
Infrastructure credentials are required for this operation. Otto found
saved credentials that are password protected. Please enter the password
to decrypt these credentials. You may also just hit <enter> and leave
the password blank to force Otto to ask for the credentials again.
Enter a value:
==> Querying infrastructure data for build...
==> Building deployment archive...
==> Building deployment artifact with Packer...
Raw Packer output will begin streaming in below. Otto
does not create this output. It is mirrored directly from
Packer while the build is being run.
otto output will be in this color.
==> otto: Prevalidating AMI Name...
==> otto: Inspecting the source AMI...
==> otto: Creating temporary keypair: packer 563377c3-5671-2d2f-a472-67471e05270c
==> otto: Creating temporary security group for this instance...
==> otto: Authorizing access to port 22 the temporary security group...
==> otto: Launching a source AWS instance...
otto: Instance ID: i-665669d9
==> otto: Waiting for instance (i-665669d9) to become ready...
==> otto: Waiting for SSH to become available...
==> otto: Connected to SSH!
==> otto: Provisioning with shell script: /var/folders/4s/c_r4lqx92wnd6ml3tz8q6mm80000gn/T/packer-shell148828306
==> otto: Uploading /Users/myoshiz/Otto/otto-getting-started/.otto/compiled/app/foundation-consul/app-build/ => /tmp/otto/foundation-1
==> otto: Provisioning with shell script: /var/folders/4s/c_r4lqx92wnd6ml3tz8q6mm80000gn/T/packer-shell567335967
otto: [otto] Installing Consul...
otto: [otto] Installing dnsmasq for Consul...
otto: [otto] Configuring consul service: otto-getting-started
==> otto: Uploading /var/folders/4s/c_r4lqx92wnd6ml3tz8q6mm80000gn/T/otto-slug-758424784 => /tmp/otto-app.tgz
==> otto: Provisioning with shell script: build-ruby.sh
otto: [otto] Waiting for cloud-config to complete...
otto: [otto] Adding apt repositories and updating...
otto: [otto] Installing Ruby, Passenger, Nginx, and other packages...
otto: [otto] Installing Bundler...
otto: [otto] Extracting app...
otto: [otto] Adding application user...
otto: [otto] Setting permissions...
otto: [otto] Configuring nginx...
otto: [otto] Bundle installing the app...
otto: Fetching gem metadata from https://rubygems.org/..........
otto: Fetching version metadata from https://rubygems.org/..
otto: Installing rack 1.6.4
otto: Installing rack-protection 1.5.3
otto: Installing tilt 2.0.1
otto: Installing sinatra 1.4.6
otto: Using bundler 1.10.6
otto: Bundle complete! 1 Gemfile dependency, 5 gems now installed.
otto: Gems in the groups development and test were not installed.
otto: Bundled gems are installed into ./vendor/bundle.
otto: [otto] ...done!
==> otto: Stopping the source instance...
==> otto: Waiting for the instance to stop...
==> otto: Creating the AMI: otto-getting-started 1446213571
otto: AMI: ami-c03e4daa
==> otto: Waiting for AMI to become ready...
==> otto: Terminating the source AWS instance...
==> otto: Cleaning up any extra volumes...
==> otto: No volumes to clean up, skipping
==> otto: Deleting temporary security group...
==> otto: Deleting temporary keypair...
Build 'otto' finished.
==> Builds finished. The artifacts of successful builds are:
--> otto: AMIs were created:
us-east-1: ami-c03e4daa
==> Storing build data in directory...
==> Build success!
The build was completed successfully and stored within
the directory service, meaning other members of your team
don't need to rebuild this same version and can deploy it
immediately.
happyturn% ssh ubuntu@52.91.29.204
Welcome to Ubuntu 14.04.3 LTS (GNU/Linux 3.13.0-63-generic x86_64)
* Documentation: https://help.ubuntu.com/
System information as of Fri Oct 30 14:15:28 UTC 2015
System load: 0.39 Memory usage: 5% Processes: 80
Usage of /: 15.9% of 7.74GB Swap usage: 0% Users logged in: 0
Graph this data and manage this system at:
https://landscape.canonical.com/
Get cloud support with Ubuntu Advantage Cloud Guest:
http://www.ubuntu.com/business/services/cloud
ローカル環境の場合と違い、dockerコマンドはインストールされていません。
ubuntu@ip-10-0-2-222:~$ which docker
ubuntu@ip-10-0-2-222:~$
ubuntu@ip-10-0-2-222:~$ consul members
Node Address Status Type Build Protocol DC
ip-10-0-2-222 10.0.2.222:8301 alive client 0.5.2 2 dc1
ip-10-0-2-6 10.0.2.6:8301 alive server 0.5.2 2 dc1