はじめに:「ログ削除」は“未来のトラブル調査”と“ディスク容量”の綱引き調整
ちゃんとログを出し始めると、次に必ず出てくるのが「ログが消えない問題」です。
ログは残しておきたい、でもディスクは有限。このバランスを取るために必要なのが ログ削除の仕組み です。
ここで大事なのは、「なんとなく古そうだから消す」ではなく、
「何日分は必ず残す」「圧縮済みは何ヶ月残す」といった“ルールをコードにする”ことです。
そのルールを C# の小さなユーティリティとして形にしていきます。
ログ削除の考え方を整理する
「どこまで遡れれば十分か」を先に決める
まず最初に決めるべきは、「どこまで遡ってログを見られれば業務的に十分か」です。
例えば、次のようなイメージです。
アプリケーションログは 30 日分あれば十分
監査ログは 1 年分必要
圧縮済みログは 90 日分残せばよい
この「保管期間」が決まると、削除のルールが一気にシンプルになります。
「作成日時が X 日より前のファイルは削除する」という形に落とし込めるからです。
ここでの重要ポイントは、「技術側だけで勝手に期間を決めない」ことです。
監査・法務・業務担当と話して、「どこまで必要か」を合意してからコードにしましょう。
基本形:古いログファイルを日数で削除する
DirectoryInfo と FileInfo を使ったシンプルな削除
まずは一番シンプルな「N 日より前のログを削除する」ユーティリティを書いてみます。
using System;
using System.IO;
public static class LogCleaner
{
public static void DeleteOldLogs(string logDirectory, string searchPattern, int keepDays)
{
var dir = new DirectoryInfo(logDirectory);
if (!dir.Exists) return;
var threshold = DateTime.Now.AddDays(-keepDays);
foreach (var file in dir.GetFiles(searchPattern))
{
if (file.CreationTime < threshold)
{
file.Delete();
}
}
}
}
C#使い方の例は次の通りです。
// 拡張子 .log のログを 30 日より前のものは削除
LogCleaner.DeleteOldLogs("logs", "*.log", keepDays: 30);
// 圧縮済みログ (.zip) を 90 日より前のものは削除
LogCleaner.DeleteOldLogs("logs", "*.zip", keepDays: 90);
C#ここでの重要ポイントは、「削除対象を searchPattern で絞る」ことです。*.log や app-*.log のようにしておけば、同じフォルダに他のファイルがあっても巻き込まずに済みます。
ファイル名に日付が入っている場合の削除
「ファイル名の日付」を基準にするパターン
ログローテーションで、ファイル名に日付を含めているケースも多いです。
例として、次のようなファイル名を考えます。
app-20260415.logapp-20260416.logapp-20260417.log
この場合、「ファイルの作成日時」ではなく「ファイル名の中の日付」で判定したいことがあります。
バックアップやコピーの影響で CreationTime が変わることがあるからです。
using System;
using System.IO;
using System.Globalization;
public static class LogCleanerByName
{
public static void DeleteOldLogsByDateInName(string logDirectory, int keepDays)
{
var dir = new DirectoryInfo(logDirectory);
if (!dir.Exists) return;
var threshold = DateTime.Today.AddDays(-keepDays);
foreach (var file in dir.GetFiles("app-*.log"))
{
var nameWithoutExt = Path.GetFileNameWithoutExtension(file.Name); // app-20260415
var datePart = nameWithoutExt.Substring("app-".Length); // 20260415
if (!DateTime.TryParseExact(
datePart,
"yyyyMMdd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var date))
{
continue;
}
if (date < threshold)
{
file.Delete();
}
}
}
}
C#使い方はシンプルです。
LogCleanerByName.DeleteOldLogsByDateInName("logs", keepDays: 30);
C#ここでの重要ポイントは、「ファイル名の規則を決めておくと、削除ロジックがシンプルになる」ことです。app-YYYYMMDD.log のような一貫した命名は、ローテーション・圧縮・削除すべてで効いてきます。
圧縮ログと生ログで保管期間を分ける
「生ログは短く、圧縮ログは長く」残す設計
前の会話で触れたように、ログ圧縮とログ削除はセットで考えるときれいです。
例えば、次のようなルールをコードに落とし込めます。
生ログ(.log)は 7 日分だけ残す
圧縮ログ(.zip / .gz)は 90 日分残す
これをユーティリティとしてまとめると、こんなイメージになります。
public static class LogMaintenance
{
public static void Cleanup(string logDirectory)
{
// 生ログは 7 日で削除
LogCleaner.DeleteOldLogs(logDirectory, "*.log", keepDays: 7);
// 圧縮ログは 90 日で削除
LogCleaner.DeleteOldLogs(logDirectory, "*.zip", keepDays: 90);
LogCleaner.DeleteOldLogs(logDirectory, "*.gz", keepDays: 90);
}
}
C#アプリ起動時や、専用のバッチからこう呼び出します。
LogMaintenance.Cleanup("logs");
C#ここでの重要ポイントは、「“どの拡張子のログを何日残すか”をコードとして明文化する」ことです。
これを 1 箇所にまとめておくと、運用ルールの変更にも強くなります。
削除処理をいつ・どこで動かすか
「本処理とは切り離したメンテナンス」として動かす
ログ削除は、基本的に「定期メンテナンス」です。
本来の業務処理とは切り離して、次のようなタイミングで動かすのが現実的です。
コンソールアプリなら、起動時に一度だけ Cleanup を呼ぶ
Web アプリやサービスなら、Windows タスクスケジューラや cron で、1 日 1 回専用バッチを実行する
例えば、ログメンテナンス専用の小さなコンソールアプリを作っておきます。
static void Main(string[] args)
{
var logDir = args.Length > 0 ? args[0] : "logs";
LogMaintenance.Cleanup(logDir);
}
C#これを OS のスケジューラから毎日実行するだけで、
ログ削除が自動で回り続けます。
ここでの重要ポイントは、「ログ削除が本処理のパフォーマンスや安定性に影響しないようにする」ことです。
重い削除処理を業務ピーク時間に走らせるのは避けましょう。
「消しすぎない」ための注意点
削除前に一度は「本当に消していいか」を確認する
ログ削除は、一度やると元には戻せません。
なので、最初に導入するときは、次のようなステップを踏むと安全です。
最初の数日は「削除対象をログに出すだけ」にする
削除対象の一覧を見て、「本当に消してよいファイルだけが対象になっているか」を確認する
問題なさそうなら、実際の file.Delete() を有効にする
例えば、こういう形にしておきます。
public static void DeleteOldLogsWithPreview(string logDirectory, string searchPattern, int keepDays, bool dryRun)
{
var dir = new DirectoryInfo(logDirectory);
if (!dir.Exists) return;
var threshold = DateTime.Now.AddDays(-keepDays);
foreach (var file in dir.GetFiles(searchPattern))
{
if (file.CreationTime < threshold)
{
Console.WriteLine($"Delete target: {file.FullName}");
if (!dryRun)
{
file.Delete();
}
}
}
}
C#最初は dryRun: true で実行し、
対象が妥当だと確認できたら dryRun: false に切り替えます。
ここでの重要ポイントは、「“削除ロジックのテスト”を、実際に消す前に必ずやる」ことです。
特にパターンマッチ(*.log など)を間違えると、関係ないファイルまで消してしまう危険があります。
まとめ:「ログ削除ユーティリティ」は“ログを守りつつディスクも守るための最後の番人”
ログ削除の本質は、
必要な期間分のログはきちんと残しつつ、
それを超えたものは自動で整理し、
ディスクを健全な状態に保つこと
です。
押さえておきたいポイントは次の通りです。
「どこまで遡れれば十分か」を業務側と合意し、その日数をコードに落とすこと。
DirectoryInfo / FileInfo を使えば、「N 日より前のファイルを削除する」処理はシンプルに書けること。
ファイル名に日付を含めておくと、名前ベースで削除対象を判定できて、ローテーション・圧縮と連携しやすいこと。
生ログと圧縮ログで保管期間を分け、「短期は生ログ・長期は圧縮ログ」という設計にするとバランスが良いこと。
削除処理は本処理とは切り離し、定期バッチとして安全な時間帯に動かすこと。
導入時は必ず「ドライラン(削除対象の確認)」を挟んでから本番削除に切り替えること。
ここまで腹落ちしていれば、
「ディスクがいっぱいになってから慌てて手動削除する」状態から卒業して、
“計画的にログを残し、計画的にログを消す”エンジニアに一歩近づけます。
