uWSGIの統計情報をfluentd経由でNorikraに格納するまでのメモ

目次

検証背景

uWSGIには、統計情報を取得できるオプション設定がある。
The uWSGI Stats Server

  • uwsgitopで人間が見ながらチューニングするのは何だかんだで大変
  • uWSGIのJSONはネスト構造で複雑
  • Kibana化を見越して、InfluxDBでもよいかなと思ったけど、返ってくるJSONが複雑すぎた。
  • Norikraは複雑なJSONでもクエリを投げられるので、そこまで格納できれば監視&可視化に使うのはユーザが自由に行える

想定連携図

uWSGI_Norikra連携 各種ミドルウェアの連携は上記のイメージ。
なお、今回は全てローカル環境に構築した。

各ミドルウェアインストール

uwsgiインストール

pip install uwsgi

td-agentインストール

Overview of Streaming Import by Treasure Agent (td-agent)【リンク切れ】を参照のこと。
今回はUbuntuで試したけど、おそらくCentOSなどでも連携可能な筈

Norikraインストール

Norikraのインストールは、JRubyの環境を整えるのが面倒くさかったので、
下記サイトのdockerイメージで準備した(doker環境の準備方法は割愛)
Fluentd と Norikra をもっとカジュアルに使おう

各種設定情報

uWSGI

uWSGI起動方法

uwsgi --ini uwsgi_test.ini

こんな感じでuWSGIは起動できる。iniファイルの中身は以下の通り。

[uwsgi]
http=0.0.0.0:8080
stats=/tmp/stat.sock
chmod-socket=666
max-requests=100
vacuum=true

本番運用時は、リバースプロキシにnginxなどを配置する方がよさげ。
fluentdのin_execでローカルから統計情報を取得するため、stats用の設定を入れてある。
ちなみに、uWSGIの統計情報は、以下の様なJSONで返ってくる。

  • uWSGIの統計情報JSON
{
    "version": "2.0.11",
    "listen_queue": 0,
    "listen_queue_errors": 0,
    "signal_queue": 0,
    "load": 0,
    "pid": 4364,
    "uid": 0,
    "gid": 0,
    "cwd": "/root",
    "locks": [
        {
            "user 0": 0
        },
        {
            "signal": 0
        },
        {
            "filemon": 0
        },
        {
            "timer": 0
        },
        {
            "rbtimer": 0
        },
        {
            "cron": 0
        },
        {
            "rpc": 0
        },
        {
            "snmp": 0
        }
    ],
    "sockets": [
        {
            "name": "127.0.0.1:49294",
            "proto": "uwsgi",
            "queue": 0,
            "max_queue": 100,
            "shared": 0,
            "can_offload": 0
        }
    ],
    "workers": [
        {
            "id": 1,
            "pid": 5284,
            "accepting": 1,
            "requests": 5304,
            "delta_requests": 121,
            "exceptions": 0,
            "harakiri_count": 0,
            "signals": 0,
            "signal_queue": 0,
            "status": "idle",
            "rss": 0,
            "vsz": 0,
            "running_time": 1578271,
            "last_spawn": 1438499807,
            "respawn_count": 19,
            "tx": 551616,
            "avg_rt": 266,
            "apps": [],
            "cores": [
                {
                    "id": 0,
                    "requests": 5304,
                    "static_requests": 0,
                    "routed_requests": 0,
                    "offloaded_requests": 0,
                    "write_errors": 0,
                    "read_errors": 0,
                    "in_request": 0,
                    "vars": []
                }
            ]
        }
    ]
}

td-agent

  • td-agent.conf
<source>
    type exec
    format json
    command    python /etc/td-agent/uwsgi_stat.py
    run_interval 1s
    tag hoge
</source>
<match hoge>
    type    norikra
    norikra localhost:26571
    target_map_tag    true
</match>

今回、norikraはローカルに準備したので、この設定になっている。

  • in_execで実行するpythonスクリプト
#!/usr/bin/env python
import subprocess
import json
cmd = '/usr/local/bin/uwsgi --connect-and-read /tmp/stat.sock'
try:
    result = subprocess.Popen(cmd, stderr=subprocess.PIPE, shell=True)
    return_json = result.communicate()[1]
    #JSON DATA Validation
    json.loads(return_json)
    #JSON DATA to fluent
    print return_json
except Exception as e:
    print '{"uwsgistat_errmsg":"' + str(e) + '"}'

Norikraで投げるクエリ例

これは運用しながら、適宜クエリ内容を見直すことになるかと。
harakiri_countやexceptionsとかも登録しておいた方がよさそう。

  • listen_queue状況の確認例
select
  avg(listen_queue) as listen_queue_avg,
  avg(listen_queue_errors) as listen_queue_errors_avg
from
 hoge.win:time_batch(1 min)
  • 平均リクエスト時間の確認例
select
  avg(workers.$0.avg_rt) as workers_avg_rt
from
 hoge.win:time_batch(1 min)
  • 物理メモリ消費量の確認例
select
  avg(workers.$0.rss) as workers_rss
from
 hoge.win:time_batch(1 min)

結果

Norikraに格納された結果は、こんな感じ

Norikra画面

今回は、Norikraにデータを格納するまでに絞っているが、
あとはnorikra-clientを使って、ゴニョゴニョすれば色んなところで可視化できるかと。

まとめ

uWSGIの統計情報をfluentd経由でNorikraまで送信して、データを集計させることができた。
統計情報はfluentd経由で送信しているので、今後BigQueryやS3などに入れるといった要件にも対応できる筈