GNUPLOT

- not so Frequently Asked Questions -

update 2004/11/29

集計結果のプロット

CGIを使って毎回集計する方法

前の方法では,リアルタイムな集計は できません.ここでは,CGIからperlのスクリプトを起動してaccess_logの集 計をする方法を紹介します.前節で作った webplot.plに,htmlを出力する機能を追加しましょう.

まず,前節と同様に最初に画像の場所のPATHを定義します.サーバ内での絶 対PATHと,httpdがアクセスする領域でのPATHが異なるので,これらを分け ておきます.

$abspath='/absolute/path/to/parent_of_image/';
$webpath='/relative/path/to/parent_of_image/';
$imgfile="access.png";
$logfile='/home/www/httpd/logs/access_log';
$gnuplot='/path/to/gnuplot';

$abspathは,イメージファイルを置くディレクトリで,サーバ 上での絶対PATHで表します.$webpathはhttpdのルートから見たPATH で,URLの一部になります.このCGIが呼ばれた時点でのイメージファイルを作 成しますので,このイメージファイル及びこのファイルを置くディレクトリ は,httpdに書き込みの許可を与えておく必要があります.

全体の流れは,前節のスクリプトと同じです.

open(LOG,$logfile);
while(<LOG>){
    if(/\.html/){
      split;
      $day = substr($_[3],1,2);
      $mon = substr($_[3],4,3);
      $year= substr($_[3],8,4);
      $count[$day]++;
    }
}
close(LOG);

$day=$#count;
$count[$day+1]=$count[$day];

& make_gnuplot;
open(GNUPLOT,"| ".$gnuplot);
foreach $i (0..$#plot){ print GNUPLOT $plot[$i]; }
for($i=1;$i<=$#count;$i++){
    printf(GNUPLOT "%10d%10d\n",$i,$count[$i]);
}
print GNUPLOT "end\n";
close(GNUPLOT);

& generate_html;
exit 0;

sub make_gnuplot{
  $i=0;
  $plot[$i++]=sprintf("set term png color\n");
  $plot[$i++]=sprintf("set output '%s'\n",$abspath.$imgfile);
  $plot[$i++]=sprintf("set size 0.7,0.7\n");
  $plot[$i++]=sprintf("set xrange [0:32]\n");
  $plot[$i++]=sprintf("set yrange [0:*]\n");
  $plot[$i++]=sprintf("set xtics 1,7,31\n");
  $plot[$i++]=sprintf("set mxtics 7\n");
  $plot[$i++]=sprintf("set nokey\n");
  $plot[$i++]=sprintf("set grid\n");
  $plot[$i++]=sprintf("set title '%s %s'\n",$mon,$year);
  $plot[$i++]=sprintf("plot '-' with step\n");
}

gnuplotでイメージを作った後,そのURLをHTMLにしてブラウザに返す部分 が新たに追加されます.ここをsubroutine generate_htmlとしています.


sub generate_html{
print << "EOF";
Content-Type: text/html


<html>
<head><title> access_log stat </title></head>
<body bgcolor="white">
<center><img src=\"$webpath$imgfile\"></center>
</body>
</html>
EOF

できあがったperlのスクリプトをcgi-binの中に置いておき,htmlドキュメ ントの中に次の様なリンクを作れば完成です.

< a href="/cgi-bin/webplot_cgi.pl/"> Web Plot </a>

一般に,イメージファイルはブラウザにキャッシュされるため,何度も続 けてブラウザからリクエストがあっても,イメージファイルの名前(上の例な らaccess.png)が同じなら,このイメージの中身が更新されてもブラウザはキャッ シュの内容を表示してしまい,毎回同じグラフが表示されます.これを避ける 簡単な方法は,毎回異なる名前でイメージを作成することです.perlはPIDを 変数$$に保持していますので,例えばこれを使って "access$$.png" とすれば 毎回異なるグラフを表示するようになります.但し,この方法だと次第にゴミ ファイルが溜って行く欠点がありますが.(ブラウザにキャッシュさせないように するheaderを送る方法もありますが,ここでは解説しません)

up