Log.cs
changeset 1574 dff8e7310cf9
parent 1528 d6496ec41718
child 1936 83060fe7965d
     1.1 --- a/Log.cs	Tue Feb 14 15:39:55 2017 +0100
     1.2 +++ b/Log.cs	Wed Feb 15 09:34:23 2017 +0100
     1.3 @@ -8,9 +8,12 @@
     1.4      /// </summary>
     1.5      internal class Log
     1.6      {
     1.7 -        private const string LOG_FILE_NAME        = "log.txt";
     1.8 -        private const int    LOG_LINES_TO_REPLACE = 100;        // The number of lines to replace when the log file gets cleaned up
     1.9 -        private const int    LOG_MAX_LINES        = 5000;      // The maximum lines a log file can reach before the first lines get replaced (FIFO)
    1.10 +        private const string LOG_FILE_NAME              = "log.txt";
    1.11 +        private const string LOG_FILE_FOLDER            = "pEp";
    1.12 +        private const string LOG_FILE_DATE_FORMAT       = "yyyyMMddHHmmss";
    1.13 +        private const string LOG_FILE_ARCHIVE_PREFIX    = "log_";
    1.14 +        private const int    LOG_MAX_LINES              = 20000;      // The maximum lines a log file can reach before the log gets rotated
    1.15 +        private const int    LOG_MAX_FILES              = 10;      // The maximum count of log files before deletion of the oldest
    1.16  
    1.17          private static int          logLineCount = 0;
    1.18          private static StreamWriter logWriter    = null;
    1.19 @@ -28,7 +31,7 @@
    1.20          /// <returns>The path of the log file.</returns>
    1.21          private static string GetLogFilePath()
    1.22          {
    1.23 -            return (Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "pEp", LOG_FILE_NAME));
    1.24 +            return (Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LOG_FILE_FOLDER, LOG_FILE_NAME));
    1.25          }
    1.26  
    1.27          /// <summary>
    1.28 @@ -106,7 +109,7 @@
    1.29                                  try
    1.30                                  {
    1.31                                      var lines = File.ReadAllLines(Log.GetLogFilePath());
    1.32 -                                    logLineCount = lines.Length;
    1.33 +                                    Log.logLineCount = lines.Length;
    1.34                                  }
    1.35                                  catch { }
    1.36                              }
    1.37 @@ -122,7 +125,9 @@
    1.38                          // If the maximum line count was reached, clean up the log file by removing the first lines.
    1.39                          if (Log.logLineCount >= Log.LOG_MAX_LINES)
    1.40                          {
    1.41 -                            Log.Sanitize();
    1.42 +                            // Log.Sanitize();
    1.43 +                            Log.Archive();
    1.44 +                            Log.logLineCount = 0;
    1.45                          }
    1.46                      }
    1.47                  }
    1.48 @@ -133,47 +138,6 @@
    1.49          }
    1.50  
    1.51          /// <summary>
    1.52 -        /// FIFO function to remove the first lines of the log file when a defined maximum 
    1.53 -        /// of lines has been reached. 
    1.54 -        /// </summary>
    1.55 -        private static void Sanitize()
    1.56 -        {
    1.57 -            try
    1.58 -            {
    1.59 -                lock (mutexLogFile)
    1.60 -                {
    1.61 -                    Log.Close();
    1.62 -
    1.63 -                    var lines = File.ReadAllLines(Log.GetLogFilePath());
    1.64 -
    1.65 -                    Log.Clear();
    1.66 -
    1.67 -                    int startIndex = (lines.Length - (Log.LOG_MAX_LINES - Log.LOG_LINES_TO_REPLACE));
    1.68 -                    if (startIndex < 0)
    1.69 -                    {
    1.70 -                        startIndex = 0;
    1.71 -                    }
    1.72 -
    1.73 -                    using (StreamWriter streamWriter = File.AppendText(Log.GetLogFilePath()))
    1.74 -                    {
    1.75 -                        for (int i = startIndex; i < lines.Length; i++)
    1.76 -                        {
    1.77 -                            if (string.IsNullOrEmpty(lines[i]) == false)
    1.78 -                            {
    1.79 -                                streamWriter.WriteLine(lines[i]);
    1.80 -                            }
    1.81 -                        }
    1.82 -                    }
    1.83 -
    1.84 -                    Log.logLineCount = (Log.LOG_MAX_LINES - Log.LOG_LINES_TO_REPLACE);
    1.85 -                }
    1.86 -            }
    1.87 -            catch { }
    1.88 -
    1.89 -            return;
    1.90 -        }
    1.91 -
    1.92 -        /// <summary>
    1.93          /// Reads all lines of text from the log file.
    1.94          /// This will never return null.
    1.95          /// </summary>
    1.96 @@ -258,5 +222,92 @@
    1.97  
    1.98              return;
    1.99          }
   1.100 +
   1.101 +
   1.102 +        /// <summary>
   1.103 +        /// Rotates the log by saving a copy of the current log file to an archived file 
   1.104 +        /// and deleting older archived logs if necessary.
   1.105 +        /// </summary>
   1.106 +        public static void Archive()
   1.107 +        {
   1.108 +            int counter = 0;
   1.109 +            string[] logFiles = null;
   1.110 +            string archiveFile = null;
   1.111 +
   1.112 +            // Create archive file with current date and timestamp
   1.113 +            try
   1.114 +            {
   1.115 +                archiveFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LOG_FILE_FOLDER, LOG_FILE_ARCHIVE_PREFIX);
   1.116 +                archiveFile += DateTime.Now.ToString(LOG_FILE_DATE_FORMAT);
   1.117 +                archiveFile += ".txt";
   1.118 +
   1.119 +                while (File.Exists(archiveFile))
   1.120 +                {
   1.121 +                    archiveFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LOG_FILE_FOLDER, LOG_FILE_ARCHIVE_PREFIX);
   1.122 +                    archiveFile += DateTime.Now.ToString(LOG_FILE_DATE_FORMAT);
   1.123 +                    archiveFile += ".txt";
   1.124 +
   1.125 +                    // Just to be sure in case there is an error somewhere
   1.126 +                    if (counter++ > 100)
   1.127 +                    {
   1.128 +                        throw new Exception("The file already exists.");
   1.129 +                    }
   1.130 +                }
   1.131 +            }
   1.132 +            catch (Exception e)
   1.133 +            {
   1.134 +                Log.Error("Could not archive log file. Error creating archive file. " + e.Message);
   1.135 +                archiveFile = null;
   1.136 +            }
   1.137 +
   1.138 +            // Move current log to archive log file
   1.139 +            if (archiveFile != null)
   1.140 +            {
   1.141 +                lock (mutexLogFile)
   1.142 +                {
   1.143 +                    Log.Close();
   1.144 +
   1.145 +                    try
   1.146 +                    {
   1.147 +                        File.Move(Log.GetLogFilePath(), archiveFile);
   1.148 +                    }
   1.149 +                    catch (Exception e)
   1.150 +                    {
   1.151 +                        Log.Warning("Could not archive log file. " + e.Message);
   1.152 +                    }
   1.153 +
   1.154 +                    Log.Clear();
   1.155 +                }
   1.156 +            }
   1.157 +
   1.158 +            // Delete older log files if necessary
   1.159 +            try
   1.160 +            {
   1.161 +                logFiles = Directory.GetFiles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LOG_FILE_FOLDER));
   1.162 +                logFiles = Array.FindAll(logFiles, a => a.ToUpperInvariant().Contains(LOG_FILE_ARCHIVE_PREFIX.ToUpperInvariant()));
   1.163 +            }
   1.164 +            catch
   1.165 +            {
   1.166 +                logFiles = null;
   1.167 +            }
   1.168 +
   1.169 +            if ((logFiles != null) &&
   1.170 +                (logFiles.Length > LOG_MAX_FILES))
   1.171 +            {
   1.172 +                Array.Sort(logFiles, StringComparer.Ordinal);
   1.173 +
   1.174 +                for (int i = 0; i < (logFiles.Length - LOG_MAX_FILES); i++)
   1.175 +                {
   1.176 +                    try
   1.177 +                    {
   1.178 +                        File.Delete(logFiles[i]);
   1.179 +                    }
   1.180 +                    catch (Exception e)
   1.181 +                    {
   1.182 +                        Log.Warning("LogRotate: Could not delete old log file. " + e.Message);
   1.183 +                    }
   1.184 +                }
   1.185 +            }
   1.186 +        }
   1.187      }
   1.188  }