blog/content/post/2012/03/27/2012-03-27-00001548.md

130 lines
7.7 KiB
Markdown

---
title: nginxのアクセス数を集計するプラグイン
author: kazu634
date: 2012-03-27
wordtwit_post_info:
- 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";s:1:"1";s:5:"delay";s:1:"0";s:7:"enabled";s:1:"1";s:10:"separation";i:60;s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:5453;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
categories:
- つれづれ
---
<div class="section">
<p>
muninでnginxのアクセス数を集計するプラグインを作成してみました。
</p>
<h4>
やりたいこと
</h4>
<p>
nginxのログファイルからお手軽にアクセス数を集計したい。
</p>
<h4>
muninプラグインの仕様
</h4>
<ul>
<li>
configという引数を与えられると、muninのconfigを標準出力に出力する
</li>
<li>
引数なしの場合には、「属性名 数値」を出力する
</li>
<li>
5分毎に呼び出される
</li>
</ul>
<p>
詳細は<a href="http://munin-monitoring.org/wiki/HowToWritePlugins" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://munin-monitoring.org/wiki/HowToWritePlugins', ' HowToWritePlugins ? Munin ');" target="_blank"> HowToWritePlugins ? Munin </a>を参照のこと。
</p>
<h4>
nginxのログの仕様
</h4>
<ul>
<li>
1アクセスが1行のログとして書き込まれる
</li>
<li>
(私の場合は)24hごとにログがローテーションする
</li>
</ul>
<h4>
デザイン
</h4>
<ul>
<li>
1アクセスが1行のログとして書き込まれることから、wcコマンドで行数をカウントすればよさそう。この時点でシェルスクリプトで作成することに決定
</li>
<li>
直前にスクリプトを実行した際の行数と、現在の行数をカウントして、その差がアクセス数
</li>
<li>
ローテーションした場合には「現在の行数」< 「直前にスクリプトを実行した際の行数」の時。この時はアクセス数は0とする。次回の起動時にアクセス数としてカウントする。
</li>
</ul>
<h4>
作成したスクリプト
</h4>
<pre class="syntax-highlight">
<span class="synComment">#!/bin/bash</span>
<span class="synComment"># -----------</span>
<span class="synComment"># varibales</span>
<span class="synComment"># -----------</span>
<span class="synIdentifier">LOGFILE</span>=<span class="synStatement">&#34;</span><span class="synConstant">/var/log/nginx/front_proxy.access.log</span><span class="synStatement">&#34;</span>
<span class="synIdentifier">LASTDATA</span>=<span class="synStatement">&#34;</span><span class="synConstant">/tmp/.munin-nginx</span><span class="synStatement">&#34;</span>
<span class="synComment"># -----------------------</span>
<span class="synComment"># Handling the arguments</span>
<span class="synComment"># -----------------------</span>
<span class="synStatement">case</span> <span class="synPreProc">$1</span> <span class="synStatement">in</span>
config<span class="synStatement">)</span>
cat <span class="synStatement">&#60;&#60;'EOM'</span>
<span class="synConstant">graph_args -l 0</span>
<span class="synConstant">graph_scale no</span>
<span class="synConstant">graph_category nginx</span>
<span class="synConstant">graph_title Nginx Access</span>
<span class="synConstant">graph_vlabel access</span>
<span class="synConstant">access.label access</span>
<span class="synStatement">EOM</span>
<span class="synStatement">exit</span> <span class="synConstant"></span><span class="synStatement">;;</span>
<span class="synStatement">esac</span>
<span class="synComment"># -----------------------</span>
<span class="synComment"># Collecting data</span>
<span class="synComment"># -----------------------</span>
<span class="synIdentifier">CURRENT_LINENUM</span>=<span class="synSpecial">`wc -l </span><span class="synPreProc">${LOGFILE}</span><span class="synSpecial"> </span><span class="synStatement">|</span><span class="synSpecial"> perl -pe </span><span class="synStatement">&#34;</span><span class="synConstant">s/^ +//</span><span class="synStatement">&#34;</span><span class="synSpecial"> </span><span class="synStatement">|</span><span class="synSpecial"> cut -f </span><span class="synConstant">1</span><span class="synSpecial"> -d </span><span class="synStatement">&#34;</span><span class="synConstant"> </span><span class="synStatement">&#34;</span><span class="synSpecial">`</span>
<span class="synComment"># checks if the last recorded data exists or not:</span>
<span class="synStatement">if</span> <span class="synStatement">[</span> <span class="synStatement">-e</span> <span class="synPreProc">${LASTDATA}</span> <span class="synStatement">];</span> <span class="synStatement">then</span>
<span class="synComment"> # Get the last line number</span>
<span class="synIdentifier">LASTLINE</span>=<span class="synSpecial">`cat </span><span class="synPreProc">${LASTDATA}</span><span class="synSpecial">`</span>
<span class="synStatement">expr</span> <span class="synPreProc">${CURRENT_LINENUM}</span> \<span class="synStatement">&#60;</span> <span class="synPreProc">${LASTLINE}</span> <span class="synStatement">&#62;</span> /dev/null
<span class="synIdentifier">RESULT</span>=<span class="synPreProc">$?</span>
<span class="synComment"> # when the target log file is rotated,</span>
<span class="synStatement">if</span> <span class="synStatement">[</span> <span class="synPreProc">$RESULT</span> <span class="synStatement">-eq</span> <span class="synConstant"></span> <span class="synStatement">];</span> <span class="synStatement">then</span>
<span class="synComment"> # it returns 0</span>
<span class="synStatement">echo</span><span class="synConstant"> </span><span class="synStatement">&#34;</span><span class="synConstant">access.value 0</span><span class="synStatement">&#34;</span>
<span class="synComment"> # and sets 0 to the $LASTDATA</span>
<span class="synStatement">echo</span><span class="synConstant"> 0 </span><span class="synStatement">&#62;</span> <span class="synPreProc">${LASTDATA}</span>
<span class="synComment"> # not rotated</span>
<span class="synStatement">else</span>
<span class="synStatement">echo</span><span class="synConstant"> -n </span><span class="synStatement">&#34;</span><span class="synConstant">access.value </span><span class="synStatement">&#34;</span>
<span class="synStatement">echo</span><span class="synConstant"> </span><span class="synSpecial">`</span><span class="synStatement">expr</span><span class="synSpecial"> </span><span class="synPreProc">${CURRENT_LINENUM}</span><span class="synSpecial"> - </span><span class="synPreProc">${LASTLINE}</span><span class="synSpecial">`</span>
<span class="synStatement">echo</span><span class="synConstant"> </span><span class="synPreProc">${CURRENT_LINENUM}</span><span class="synConstant"> </span><span class="synStatement">&#62;</span> <span class="synPreProc">${LASTDATA}</span>
<span class="synStatement">fi</span>
<span class="synStatement">else</span>
<span class="synComment"> # if the log file does not exist, it returns 0</span>
<span class="synStatement">echo</span><span class="synConstant"> </span><span class="synStatement">&#34;</span><span class="synConstant">access.value 0</span><span class="synStatement">&#34;</span>
<span class="synComment"> # and sets the current line number to the $LASTDATA</span>
<span class="synStatement">echo</span><span class="synConstant"> </span><span class="synPreProc">${CURRENT_LINENUM}</span><span class="synConstant"> </span><span class="synStatement">&#62;</span> <span class="synPreProc">${LASTDATA}</span>
<span class="synStatement">fi</span>
<span class="synStatement">exit</span> <span class="synConstant"></span>
</pre>
</div>