トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

BugTrack-plugin/220

ページの作成や編集にはユーザ登録が必要です。

アクセスログ上限指定

  • 投稿者: ryon
  • カテゴリ: 修正
  • 優先度: 普通
  • 状態: 提案
  • 日時: 2005年07月12日 19時40分15秒

 内容

アクセスログを上限より大きくしない。BugTrack-plugin/216の改良版・・・というには大きく変わりすぎ。

  • 上限サイズはsetup.datで下記の様にkbyte単位で指定。
    • access_log_limit_kbyte = 1024
  • ログがaccess_log_limit_kbyteで指定したサイズを超えそうになると古い行を自動的に削除。
  • rename関数を使って排他制御実施。
  • ログサイズは1MBで5000件強くらい。

 変更点

core/ShowPageプラグインの78行目からの3行を

	open(LOG,">>".$wiki->config('log_dir')."/".$wiki->config('access_log_file')) or die $!;
	print LOG Util::url_encode($page)." ".&log_date()." $ip $ref $ua\n";
	close(LOG);

次のとおりに変更します。

	my $tmp = time;
	my $logname = $wiki->config('log_dir')."/".$wiki->config('access_log_file');
	my $readtmpname = $logname.".".$tmp.".0";			# テンポラリ名は重複しない一意の名前に
	my $writetmpname = $logname.".".$tmp.".1";			# 上に同じ
	my $write_record = Util::url_encode($page)." ".&log_date()." $ip $ref $ua\n";
	my $logsize = (stat($logname))[7];
	my $limit_size = $wiki->config('access_log_limit_kbyte') *1024;
	my $seek = $limit_size - length($write_record);
	my $tmp = 1;
	until (rename $logname,$readtmpname) {				# 排他制御
		die $! if (++$tmp > 6);
		sleep ($tmp / 2);					# 混雑時は待ち時間を長くする
	}
#	rename $logname, $readtmpname;					# for DEBUG
	if ($limit_size && $logsize > $seek) {				# (現在ログサイズ+追記量 > 限度サイズ)か判定
		open(READTMP,"<".$readtmpname) or die $!;
		seek(READTMP,- $seek,2);				# サイズ合わせのため(限度サイズ-追記量)だけシーク
		open(WRITETMP,">".$writetmpname) or die $!;
		my $readlinedata = <READTMP> ;				# 行の途中かも知れないので最初の一行は破棄
		while ($readlinedata = <READTMP>){			# 旧ファイルから新ファイルにせっせとピーコ
			print WRITETMP $readlinedata;
		}
		close(READTMP);
		print WRITETMP $write_record;				# 最後に新しい行を追加
		close(WRITETMP);
		rename $writetmpname, $logname;				# 新ファイルをログファイルに改名
		unlink $readtmpname;					# 旧ファイルは捨てます
	} else {
		open(LOG,">>".$readtmpname) or die $!;
		print LOG $write_record;
		close(LOG);
		rename $readtmpname, $logname;
	}

一意性を上げるために最初の4行(よく考えるとテンポラリ名に$lognameを入れる必要がない)を変更します。(thanks typer氏)

	my $tmp = time.".".$$;								#現在時刻&プロセス番号
	my $logname = $wiki->config('log_dir')."/".$wiki->config('access_log_file');
	my $readtmpname = $wiki->config('log_dir')."/".$tmp.".0.tmp";	# テンポラリ名は重複しない一意の名前に
	my $writetmpname = $wiki->config('log_dir')."/".$tmp.".1.tmp";	# 上に同じ

 代替案

日数指定方式だと次のような処理になるのかと・・・

  • 排他制御(リネーム)
  • 旧ログを読み込みモードでオープン
  • 1行目を読み込む
  • 指定日数以内なら、一度クローズして追記処理(変更無し)へ
  • 指定日数超過なら、
    • 指定日数内になるまで行読み繰り返し
    • 新ログを書き込みモードでオープン&1行書き込み
    • 旧ログにデータがある限り、ひたすら行コピー
    • 全ファイルクローズ
    • 旧ログ削除、新ログをリネーム

日付指定は access_log_limit_days = 7 とか

日付の比較はDate::CaclモジュールのDate_to_Days関数でできるようです。

log_dateサブルーチンも一部修正が必要かと。サブルーチン内でlocaltimeを参照するのではなく、あらかじめ参照しておいて引数で渡すように。

 ライセンス

お・ま・か・せ

 対応バージョン

3.5.8で動作確認中。

 実働サンプル

改良版を投稿したため、こちらのサンプルは停止します。

 コメント

  • DEBUGのための余分な行がついたままだったので修正しました。 - ryon (2005年07月15日 00時24分48秒)
  • 上限の管理をファイルサイズで見るというのは一般的なのでしょうか? サンプルを拝見させていただきましたが、更新するたびに、一番古い日付のカウンタがデクリメントされていくのはどうも不自然に感じます。(一般的にはどうだかは分かりませんが) サイズではなく日数で管理するという案はいかがでしょう? accessdaysその他が日単位で表現する以上、これらに影響を与えない方式が望ましいと思います。 - あき (2005年07月16日 10時39分33秒)
  • 表示を少し変えさしてもらいます - typer (2005年07月16日 13時08分04秒)
  • $tmpには時間だけでなくプロセスナンバも入れると一意性があがります - typer (2005年07月16日 13時13分02秒)
  • 確かに日単位で管理できた方が機能的には優れています。 - ryon (2005年07月16日 22時06分06秒)
  • 修正乙です>typer氏 - ryon (2005年07月16日 22時06分43秒)
  • BugTrack-plugin/222に日数制限版を投稿しました。 - ryon (2005年07月17日 22時29分32秒)
お名前: コメント:

最終更新時間:2006年02月12日 06時45分19秒