VB C# .NET Freamworkの備忘録

C#, VB.NET Freamworkの備忘録を掲載しています。 コントロール、WPF、スレッド、共通関数と実用的なコードを掲載してきます。

2016年06月

log4net ログの世代管理にLogFileCleanupTaskついて紹介します。


使用方法
-------------------------------------------------------------
                //-------------------------------------------------
                // ログの削除(世代管理)
                //-------------------------------------------------
                new LogFileCleanupTask().CleanUp();
 
-------------------------------------------------------------

using System;
using System.IO;
using System.Linq;
using log4net;
using log4net.Appender;

namespace Common
{

    /// <summary>
    /// ログ世代管理のタスククラスです。
    /// </summary>
    public class LogFileCleanupTask
    {
        /// <summary>
        /// ログの世代管理の削除を行います。
        /// </summary>
        public void CleanUp()
        {
            var repo = LogManager.GetAllRepositories().FirstOrDefault();

            if (repo == null)
            {
                throw new NotSupportedException("Log4Netが設定されていません");
            }

            var app = repo.GetAppenders().FirstOrDefault(x => x.GetType() == typeof (RollingFileAppender));

            if (app != null)
            {
                var appender = app as RollingFileAppender;
                
                var directory = Path.GetDirectoryName(appender.File);
                var filePrefix = Path.GetFileName(appender.File);
                filePrefix = filePrefix.Substring(0, filePrefix.Length - appender.DatePattern.Replace("\"", "").Length);

// ログの最終保持日付
                var targetDate = DateTime.Now.Date.AddDays(-appender.MaxSizeRollBackups);
                
                // 削除の実行
                CleanUp(directory, filePrefix,targetDate, appender);
            }
        }

        /// <summary>
        /// ログの世代管理の削除の実行
        /// </summary>
        /// <param name="logDirectory">削除対象のディレクトリ.</param>
        /// <param name="logPrefix">ファイルのフォーマット名</param>
        /// <param name="lastDate">世代管理の開始日</param>
        /// <param name="appender">RollingFileAppender</param>
        private void CleanUp(string logDirectory, string logPrefix,DateTime lastDate, RollingFileAppender appender)
        {
            if (string.IsNullOrEmpty(logDirectory))
            {
                throw new ArgumentException("ログのディレクトリが存在しません");
            }

            if (string.IsNullOrEmpty(logDirectory))
            {
                throw new ArgumentException("ログのファイルフォーマット名の形式が存在しません");
            }

            var dirInfo = new DirectoryInfo(logDirectory);
            if (!dirInfo.Exists)
            {
                return;
            }

            // 削除
            dirInfo.GetFiles(String.Format("{0}*.*", logPrefix))
                .Where(info => GetLogDate(info, logPrefix, appender) < lastDate)
                .ForEach(info =>
                {
                    if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                        info.Attributes = FileAttributes.Normal;

                    Loggers.Log.Debug(string.Format("世代管理に伴い、過去のログファイルの削除を行います。ファイル:{0}",info.FullName));
                    // 削除
                    info.Delete();
                });

        }

        /// <summary>
        /// ログの作成日付を取得します。
        /// </summary>
        /// <param name="fileInfo">ファイル情報オブジェクト</param>
        /// <param name="logPrefix">ログファイル名のフォーマット</param>
        /// <param name="app">ログのアペンダー</param>
        /// <returns>ログの作成日付</returns>
        private DateTime GetLogDate(FileInfo fileInfo, string logPrefix,RollingFileAppender app)
        {
            var year = fileInfo.Name.Substring(logPrefix.Length + app.DatePattern.IndexOf("yyyy"), 4);
            var month = fileInfo.Name.Substring(logPrefix.Length + app.DatePattern.IndexOf("MM"), 2);
            var day = fileInfo.Name.Substring(logPrefix.Length + app.DatePattern.IndexOf("dd"), 2);

            return new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day));
        }
    }
}

リトライ処理を実施する際に利用するRetryExecutorについて紹介します。

使用方法
-------------------------------------------------------------------------------
            //------------------------------------------
            // リトライ用の実行クラスの生成
            //------------------------------------------
            _executor = new RetryExecutor(new RetryPolicy()
            {
                MaxRetryNum = CommonData.Instance.RetryCount,
                RetrySleep = CommonData.Instance.RetryWaitSecond * 1000
            });


            //------------------------------------------
            // リトライ処理実行
            //------------------------------------------
            var result = _executor.Execute(() =>
            {
//  繰り返し実行したい処理を記載

                return trendData;
 }, ex =>
            {
                // エラー処理

            }); 


-------------------------------------------------------------------------------

using System;
using System.Threading;

namespace Common
{
    /// <summary>
    /// リトライ処理が必要な場合の、リトライのルールを定義する抽象クラスです。
    /// </summary>
    public class RetryPolicy
    {
        /// <summary>
        /// 最大リトライ回数
        /// </summary>
        public int MaxRetryNum { get; set; }

        /// <summary>
        /// リトライ時のベースとなる処理停止時間(ミリ秒)
        /// </summary>
        public int RetrySleep { get; set; }
    }

    /// <summary>
    /// リトライ処理が必要な箇所で指定された条件によってリトライを行うためのクラスです。
    /// </summary>
    public class RetryExecutor
    {
        private readonly RetryPolicy _policy;

        /// <summary>
        /// リトライルールを受け取ってインスタンスを生成します。
        /// </summary>
        /// <param name="policy"></param>
        public RetryExecutor(RetryPolicy policy)
        {
            _policy = policy;
        }

        /// <summary>
        /// リトライをかけながら指定された処理を実行します。
        /// </summary>
        /// <param name="executeAction">実行する処理</param>
        public virtual void Execute(Action executeAction)
        {
            for (var retryNum = 1; retryNum <= _policy.MaxRetryNum + 1; retryNum++)
            {
                try
                {
                    executeAction();
                    break;
                }
                catch (Exception ex)
                {
                    Loggers.Log.Error(ex.ToString());

                    if (retryNum > _policy.MaxRetryNum)
                    {
                        throw new Exception(string.Format("リトライ回数をオーバーしたため、処理を終了します。最大リトライ回数:{0}", (_policy.MaxRetryNum).ToString()));
                    }

                    Loggers.Log.Warn(string.Format("一定時間[{0}ミリ秒]待機した後、リトライします。リトライ回数:{1}", _policy.RetrySleep.ToString(), retryNum.ToString()));
                    Thread.Sleep(_policy.RetrySleep);
                }
            }
        }

        /// <summary>
        /// リトライをかけながら指定された処理を実行します。
        /// </summary>
        /// <param name="executeAction">実行する処理</param>
        /// <param name="errorAction">処理実行時に発生したエラー処理</param>
        public virtual T Execute<T>(Func<T> executeAction, Action<Exception> errorAction = null)
        {
            var result = default(T);
            for (var retryNum = 1; retryNum <= _policy.MaxRetryNum + 1; retryNum++)
            {
                try
                {
                    result = executeAction();
                    break;
                }
                catch (Exception ex)
                {
                    Loggers.Log.Error(ex.ToString());

                    if (errorAction != null)
                    {
                        errorAction(ex);
                    }

                    if (retryNum > _policy.MaxRetryNum)
                    {
                        throw new Exception(string.Format("リトライ回数をオーバーしたため、処理を終了します。最大リトライ回数:{0}", (_policy.MaxRetryNum).ToString()));
                    }

                    Loggers.Log.Warn(string.Format("一定時間[{0}ミリ秒]待機した後、リトライします。リトライ回数:{1}",_policy.RetrySleep.ToString(), retryNum.ToString()));
                    Thread.Sleep(_policy.RetrySleep);
                }
            }

            return result;
        }
    }
}
 

↑このページのトップヘ