Meteorからfluentdへログを送信する

# 概要

Meteorからfluentdへログを送信するデモアプリケーションの説明です。

**環境**

下記の環境で動作確認を行いました。

* Windows7 (64bit)
* VirtualBox 5.0.8
* Vagrant 1.7.4
 * CentOS 6.5
* Meteor 1.2.0
 * fluent-logger 0.3.0
* Fluentd 0.12.12


**参考**

* [Vagrantbox.es] (http://www.vagrantbox.es/)
* [meteorhacks/npm] (https://github.com/meteorhacks/npm)
* [fluent-logger for Node.js] (https://github.com/fluent/fluent-logger-node)


## デモアプリケーション

Meteorからfluentdへログを送信するために下記のパッケージを使用します。

* fluent-logger for Node.jsというNodeのパッケージ
* meteorhacks:npmというMeteorのパッケージ

meteorhacks:npmはMeteorからNodeのパッケージを利用するためのものです。


### 雛形を作成します。

```bash:create
$ meteor create mt-example
Created a new Meteor app in 'mt-example'.

To run your new app:
  cd mt-example
  meteor

If you are new to Meteor, try some of the learning resources here:
  https://www.meteor.com/learn
```

### meteorhacks:npmを追加します。

```bash:add
$ cd mt-example
$ meteor add meteorhacks:npm

Changes to your project's package version selections:

meteorhacks:async  added, version 1.0.0
meteorhacks:npm    added, version 1.5.0

meteorhacks:npm: Use npm modules with your Meteor App
```

### packages.jsonファイルを作成します。

プロジェクトのルートディレクトリにpackages.jsonファイルを作成し、使用するパッケージを指定します。

```json:packages.json
{
  "fluent-logger": "0.3.0"
}
```

### mt-example.js

雛形のmt-example.jsに下記の修正を加えます。

`Meteor.npmRequire`でpackages.jsonに記述したNodeパッケージをロードします。

```js
var logger = Meteor.npmRequire('fluent-logger');
```

configureメソッドで送信先のfluentdを指定します。第1引数はtagprefixです。

```js
logger.configure('debug',{
    host: 'localhost',
    port: 24224,
    timeout: 3.0
});
```

emitメソッドでログを送信します。第1引数がタグ、第2引数がメッセージです。

```js
logger.emit('test', {message: msg});
```

**mt-example.js**

```js:mt-example.js
if (Meteor.isClient) {

  ...省略...

  Template.hello.events({
    'click button': function () {
      // increment the counter when button is clicked
      var cnt = Session.get('counter') + 1;
      Session.set('counter', cnt);
      Meteor.call('debug', 'client click log. count:' + cnt);
    }
  });

}

if (Meteor.isServer) {
  var logger = Meteor.npmRequire('fluent-logger');
  Meteor.startup(function () {
    logger.configure('debug',{
      host: 'localhost',
      port: 24224,
      timeout: 3.0
    });
    Meteor.call('debug','server startup log');
  });

 Meteor.methods({
    'debug':function debug(msg) {
      logger.emit('debug.test',{message: msg});
    },
    'info':function info(msg) {
      logger.emit('info.test',{message: msg});
    }
  });

}
```

アプリケーションを起動します。
パッケージ追加後の初回起動時は起動しないので、もう一度起動させます。

```bash:meteor
$ meteor
[[[[[ ~/mt-example ]]]]]

=> Started proxy.
=> Started MongoDB.
=> Creating container package for npm modules-

-> npm support has been initialized.
-> please start your app again.
```


```bash:meteor
$ meteor
[[[[[ ~/mt-example ]]]]]

=> Started proxy.
=> Started MongoDB.
npm-container: updating npm dependencies -- fluent-logger...

Changes to your project's package version selections:

npm-container  added, version 1.2.0

=> Started your app.

=> App running at: http://localhost:3000/
```

アプリケーションが起動したら下記のURLにアクセスして、"Click Me"ボタンを何回かクリックします。

http://192.168.33.10:3000/

![mf01.png](https://qiita-image-store.s3.amazonaws.com/0/22772/13815f7a-fa5c-aaf4-607f-9a0f474a5c63.png)


ボタンをクリックするたびにログが出力されることを確認します。
デフォルトのログ出力先は`/var/log/td-agent/td-agent.log`です。

```text:td-agent.log

2015-10-24 06:08:20 +0000 debug.debug.test: {"message":"server startup log"}
2015-10-24 06:08:36 +0000 debug.debug.test: {"message":"client click log. count:1"}
2015-10-24 06:08:38 +0000 debug.debug.test: {"message":"client click log. count:2"}
2015-10-24 06:08:40 +0000 debug.debug.test: {"message":"client click log. count:3"}
```



## インストール・設定メモ

当初はWindowsのみで開発しようとしましたが、方法が間違っているのかVC++などのコンパイル環境が悪いのかNodeパッケージの利用(コンパイル)ができずに断念しました。
このためVagrantを使用して仮想マシンを作成し、そこへGit、Ruby、Fluentd、Meteorをインストールして環境を構築しました。

以降の記事は、VirtualBoxおよびVagrantをインストール済みとして進めます。

### Vagrant

使用するVagrantのバージョンです。

```bat
> vagrant --version
Vagrant 1.7.4
```

CentOS6.5のboxを追加します。

```bat:box_add
> vagrant box add CentOS65 https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'CentOS65' (v0) for provider:
    box: Downloading: https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
    box: Progress: 100% (Rate: 480k/s, Estimated time remaining: --:--:--)
==> box: Successfully added box 'CentOS65' (v0) for 'virtualbox'!
```

Vagrantfileを作成します。ファイルは`d:\dev\vagrant\centos65`に配置します。

```bat:init
> cd d:\dev\vagrant\centos65
> vagrant init CentOS65
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
```

仮想マシンを起動します。

```bat:up
> vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> 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 => 2222 (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
    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.3.6
    default: VirtualBox Version: 5.0
==> default: Configuring and enabling network interfaces...
==> default: Mounting shared folders...
    default: /vagrant => D:/dev/vagrant/centos65
```

追加したboxを確認するにはbox listコマンドを実行します。

```bat:box_list
> vagrant box list
CentOS65 (virtualbox, 0)
```

停止はhaltコマンドを実行します。

```bat:halt
> vagrant halt
==> default: Attempting graceful shutdown of VM...
```

boxの削除はdestryoコマンドを実行します。

```bat:destroy
> vagrant destroy
    default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Destroying VM and associated drives...
```


#### 環境設定

ここからは仮想マシン上での環境設定作業になります。
仮想マシンにログインするアカウントはvagrant/vagrantです。

##### packageの更新

必要なパッケージのインストールと更新を行います。

```bat
$ sudo su
# yum update
```

```bat
# yum install -y gcc-c++ make openssl-devel libffi-devel libcurl-devel expat-devel cpan wget readline-devel
```

##### git

古いバージョンのgitをアンインストールします。

```bat
# git --version
git version 1.7.1
```

```bat
# yum remove git
```

ソースコードを取得してコンパイル、インストールを行います。

```bat
# cd /usr/local/src
# wget https://www.kernel.org/pub/software/scm/git/git-2.6.2.tar.gz
# tar -zxf git-2.6.2.tar.gz
# cd git-2.6.2
# make prefix=/usr/local all
# make prefix=/usr/local install
```

/etc/bashrcに下記の行を追加します。

```bash
export PATH=$PATH:/usr/local/bin
```

バージョンを確認します。

```bat
# source /etc/bashrc
# git --version
git version 2.6.2
```

##### rbenv

rbenvおよびruby-buildをインストールします。

```bat:rbenv
# cd /usr/local/src
# git clone git://github.com/sstephenson/rbenv.git
Cloning into 'rbenv'...
remote: Counting objects: 2162, done.
remote: Total 2162 (delta 0), reused 0 (delta 0), pack-reused 2162
Receiving objects: 100% (2162/2162), 374.21 KiB | 172.00 KiB/s, done.
Resolving deltas: 100% (1335/1335), done.
Checking connectivity... done.
```

ruby-build

```bat:ruby-build
# mkdir /usr/local/src/rbenv/plugins
# cd rbenv/plugins
# git clone git://github.com/sstephenson/ruby-build.git
Cloning into 'ruby-build'...
remote: Counting objects: 5062, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 5062 (delta 0), reused 0 (delta 0), pack-reused 5056
Receiving objects: 100% (5062/5062), 935.12 KiB | 237.00 KiB/s, done.
Resolving deltas: 100% (2773/2773), done.
Checking connectivity... done.
```

/etc/profile.d/rbenv.shを下記の内容で作成します。

```bat:rbenv.sh
export RBENV_ROOT="/usr/local/src/rbenv"
export PATH="${RBENV_ROOT}/bin:${PATH}"
eval "$(rbenv init -)"
```

バージョンを確認します。

```bat:version
# rbenv -v
rbenv 0.4.0-169-g0f44c57
```

##### ruby

rbenvでrubyをインストールします。

```bat:install
# rbenv install 2.2.3
Downloading ruby-2.2.3.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/df795f2f99860745a416092a4004b016ccf77e8b82dec956b120f18bdc71edce
Installing ruby-2.2.3...
Installed ruby-2.2.3 to /opt/rbenv/versions/2.2.3
```

```bat:global
# rbenv global 2.2.3
```

バージョンを確認します。

```bat:version
# ruby -v
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
# gem -v
2.4.5.1
```

bundlerをインストールします。

```bat:install_bundler
# gem install bundler
Fetching: bundler-1.10.6.gem (100%)
Successfully installed bundler-1.10.6
Parsing documentation for bundler-1.10.6
Installing ri documentation for bundler-1.10.6
Done installing documentation for bundler after 5 seconds
1 gem installed
```

パッケージを更新します。

```bat:update
# gem update --system
Updating rubygems-update
Fetching: rubygems-update-2.4.8.gem (100%)
Successfully installed rubygems-update-2.4.8
Parsing documentation for rubygems-update-2.4.8
Installing ri documentation for rubygems-update-2.4.8
Installing darkfish documentation for rubygems-update-2.4.8
Done installing documentation for rubygems-update after 1 seconds
Parsing documentation for rubygems-update-2.4.8
Done installing documentation for rubygems-update after 0 seconds
Installing RubyGems 2.4.8
RubyGems 2.4.8 installed
Parsing documentation for rubygems-2.4.8
Installing ri documentation for rubygems-2.4.8

...省略...

RubyGems system software updated
```


#### fluentd

インストールは[Installing Fluentd Using rpm Package] (http://docs.fluentd.org/articles/install-by-rpm)に説明されている通りです。

```bat:install
# curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
110   662  110   662    0     0   3886      0 --:--:-- --:--:-- --:--:-- 28782
This script requires superuser access to install rpm packages.

...省略...

Installed:
  td-agent.x86_64 0:2.2.1-0.el6

Complete!
```

```bat:which
# which
/usr/sbin/td-agent
```

confはデフォルトの設定のままで動作確認を行います。

```bat:cat
# cat /etc/td-agent/td-agent.conf
```

```text:td-agent.conf
####
## Output descriptions:
##

# Treasure Data (http://www.treasure-data.com/) provides cloud based data
# analytics platform, which easily stores and processes data from td-agent.
# FREE plan is also provided.
# @see http://docs.fluentd.org/articles/http-to-td
#
# This section matches events whose tag is td.DATABASE.TABLE
<match td.*.*>
  type tdlog
  apikey YOUR_API_KEY

  auto_create_table
  buffer_type file
  buffer_path /var/log/td-agent/buffer/td

  <secondary>
    type file
    path /var/log/td-agent/failed_records
  </secondary>
</match>

## match tag=debug.** and dump to console
<match debug.**>
  type stdout
</match>

####
## Source descriptions:
##

## built-in TCP input
## @see http://docs.fluentd.org/articles/in_forward
<source>
  type forward
</source>

# HTTP input
# POST http://localhost:8888/<tag>?json=<json>
# POST http://localhost:8888/td.myapp.login?json={"user"%3A"me"}
# @see http://docs.fluentd.org/articles/in_http
<source>
  type http
  port 8888
</source>

## live debugging agent
<source>
  type debug_agent
  bind 127.0.0.1
  port 24230
</source>
```

td-agentの起動、停止の方法は下記の通りです。

```bat
# /etc/init.d/td-agent start 
Starting td-agent:                                         [  OK  ]
```

```bat:stop
# /etc/init.d/td-agent stop
Shutting down td-agent:                                    [  OK  ]
```

```bat:status
# /etc/init.d/td-agent status
td-agent (pid  19030) is running...
```

自動起動、停止の設定を行っておきます。

```bat:autostart
# chkconfig td-agent on
# chkconfig --list | grep td-agent
td-agent        0:off   1:off   2:on    3:on    4:on    5:on    6:off
```

下記の方法で動作確認を行います。送信したデータがログに出力されることを確認します。

```bat
# curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test
```


#### meteor

インストールは[Installing Meteor on OS X, Linux and Windows] (https://www.meteor.com/install)に説明されている通りです。

```bat:install
# curl https://install.meteor.com/ | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6121    0  6121    0     0    790      0 --:--:--  0:00:07 --:--:--  3102
Downloading Meteor distribution
######################################################################## 100.0%

Meteor 1.2.0.2 has been installed in your home directory (~/.meteor).
Writing a launcher script to /usr/local/bin/meteor for your convenience.

To get started fast:

  $ meteor create ~/my_cool_app
  $ cd ~/my_cool_app
  $ meteor

Or see the docs at:

  docs.meteor.com
```

```bat
# which meteor
/usr/local/bin/meteor
```

meteorのバージョンを確認します。

```bat:version
$ meteor --version
vagrant, this is your first time using Meteor!
Installing a Meteor distribution in your home directory.
######################################################################## 100.0%
Meteor 1.2.0.2
```

meteorにバンドルされているnodeのバージョンを確認します。

```bat:node
$ pwd
/home/vagrant/.meteor/packages/meteor-tool/1.1.9/mt-os.linux.x86_64/dev_bundle/bin
$ ./node -v
v0.10.40
```