シェアする

  • このエントリーをはてなブックマークに追加

[CakePHP]1/n回の割合で最新のx件を残してログを削除

medium_1492818224

メモです。

業務アプリケーションで問題が起こった時に、エラーが発生した時どういう操作が行われたかを追うために、ページ変遷とPOSTされた値をログに記録しているのですが、POSTのデータまで保存しているので気づくとかなり大きなサイズになってしまいます。

今まではこうしたログもログインログなどと同じように取りっぱなしで削除処理は入れなかったんですが、データサイズを喰ってバックアップ時間が長くなってしまうので100回に1回、最新の10000件を残して削除する処理を入れて対処しました。

やりかた

DebugLoggingコンポーネントのstartupメソッドでログを取ったりしているとして、

class DebugLoggingComponent extends Component {

	private $debugLogId = null;
	private $DebugLog;
	private $start = 0;
	private $debugging = true;
	private $remainingLimit = 10000;	// ガーベージコレクション時に残すログ数

	public function __construct() {
		$this->start = microtime(true);
	}

	public function startup(Controller $controller) {

		// DebugLogのガーベージコレクション
		$this->logGC($controller);

		if ($controller->user['User']['id'] === '1') {
			$this->debugging = false;
		}
		if (!$this->debugging) {
			return;
		}
		$controller->loadModel('DebugLog');
		$this->DebugLog = $controller->DebugLog;
		$params = $controller->request->params;
		$save = array(
			'user_id' => (!empty($controller->user['User']['id'])) ? $controller->user['User']['id'] : 0,
			'admin' => (!empty($params['admin'])) ? $params['admin'] : 0,
			'controller' => $params['controller'],
			'action' => $params['action'],
		);
		if (!empty($controller->request->data)) {
			$save['data'] = var_export($controller->request->data, true);
		}
		if (!$this->DebugLog->save($save)) {
			$this->log('DebugLogの保存に失敗');
			$this->debugging = false;
			$this->log($controller->request->data);
			return;
		}
		$this->debugLogId = $controller->DebugLog->id;

	}

	public function __destruct() {
		if ($this->debugging) {
			$this->DebugLog->saveField('microtime', microtime(true) - $this->start);
		}
	}

	/**
	 * ログガーベージコレクション
	 * 100分の1の割合で最新の10000件を残してログを削除する
	 */
	private function logGC(&$controller) {

		if (rand(0, 99) === 0) {
			$this->log('GC');
			$controller->loadModel('DebugLog');
			$sql = 'SET @d = ( SELECT created FROM debug_logs ORDER BY created DESC limit '.$this->remainingLimit.',1 );
DELETE FROM debug_logs WHERE created < @d;';
			if (!$controller->DebugLog->query($sql)) {
				$this->log('DebugLogのガーベージコレクションに失敗');
			}
		}

	}

}

面倒くさいのでログをとってるコンポーネントごと貼ります。
こういうのガーベージコレクションっていうのですかね?こんなかんじで実装しました。

弄る必要がないので直書きしましたが、logGCメソッドのrand(0, 99)のところを$x – 1としてパラメータにしてもいいですね。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする