Log.cs
author Thomas
Mon, 27 Nov 2017 12:06:46 +0100
changeset 1936 83060fe7965d
parent 1574 dff8e7310cf9
child 1979 cf610012e16d
permissions -rw-r--r--
Renaming enums and exceptions
Thomas@1246
     1
´╗┐using System;
Thomas@1246
     2
using System.IO;
Thomas@1246
     3
Thomas@1246
     4
namespace pEp
Thomas@1246
     5
{
Thomas@1246
     6
    /// <summary>
Thomas@1246
     7
    /// Class to handle all the logging of pEp for Outlook.
Thomas@1246
     8
    /// </summary>
Thomas@1246
     9
    internal class Log
Thomas@1246
    10
    {
Thomas@1574
    11
        private const string LOG_FILE_NAME              = "log.txt";
Thomas@1574
    12
        private const string LOG_FILE_FOLDER            = "pEp";
Thomas@1574
    13
        private const string LOG_FILE_DATE_FORMAT       = "yyyyMMddHHmmss";
Thomas@1574
    14
        private const string LOG_FILE_ARCHIVE_PREFIX    = "log_";
Thomas@1574
    15
        private const int    LOG_MAX_LINES              = 20000;      // The maximum lines a log file can reach before the log gets rotated
Thomas@1574
    16
        private const int    LOG_MAX_FILES              = 10;      // The maximum count of log files before deletion of the oldest
Thomas@1246
    17
Dean@1249
    18
        private static int          logLineCount = 0;
Dean@1249
    19
        private static StreamWriter logWriter    = null;
Dean@1249
    20
        private static object       mutexLogFile = new object();
Thomas@1246
    21
Thomas@1246
    22
        /**************************************************************
Thomas@1246
    23
         * 
Thomas@1246
    24
         * Methods
Thomas@1246
    25
         * 
Thomas@1246
    26
         *************************************************************/
Thomas@1246
    27
Thomas@1246
    28
        /// <summary>
Thomas@1246
    29
        /// Gets the path of the log file.
Thomas@1246
    30
        /// </summary>
Thomas@1246
    31
        /// <returns>The path of the log file.</returns>
Thomas@1246
    32
        private static string GetLogFilePath()
Thomas@1246
    33
        {
Thomas@1574
    34
            return (Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LOG_FILE_FOLDER, LOG_FILE_NAME));
Thomas@1246
    35
        }
Thomas@1246
    36
Thomas@1246
    37
        /// <summary>
Thomas@1246
    38
        /// Adds the given info text to the pEp for Outlook log.
Thomas@1246
    39
        /// </summary>
Thomas@1246
    40
        /// <param name="text">The text to add to the log.</param>
Thomas@1246
    41
        public static void Info(string text)
Thomas@1246
    42
        {
Thomas@1246
    43
            if (text != null)
Thomas@1246
    44
            {
Dean@1249
    45
                Log.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " | " + text);
Thomas@1246
    46
            }
Thomas@1246
    47
            return;
Thomas@1246
    48
        }
Thomas@1246
    49
Thomas@1246
    50
        /// <summary>
Thomas@1246
    51
        /// Adds the given error text to the pEp for Outlook log.
Thomas@1246
    52
        /// </summary>
Thomas@1246
    53
        /// <param name="text">The error text to add to the log.</param>
Thomas@1246
    54
        public static void Error(string text)
Thomas@1246
    55
        {
Thomas@1246
    56
            if (text != null)
Thomas@1246
    57
            {
Dean@1249
    58
                Log.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " |E| " + text);
Thomas@1246
    59
            }
Thomas@1246
    60
            return;
Thomas@1246
    61
        }
Thomas@1246
    62
Thomas@1246
    63
        /// <summary>
Thomas@1246
    64
        /// Adds the given warning text to the pEp for Outlook log.
Thomas@1246
    65
        /// </summary>
Thomas@1246
    66
        /// <param name="text">The warning text to add to the log.</param>
Thomas@1246
    67
        public static void Warning(string text)
Thomas@1246
    68
        {
Thomas@1246
    69
            if (text != null)
Thomas@1246
    70
            {
Dean@1249
    71
                Log.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " |W| " + text);
Thomas@1246
    72
            }
Thomas@1246
    73
            return;
Thomas@1246
    74
        }
Thomas@1246
    75
Thomas@1246
    76
        /// <summary>
Thomas@1246
    77
        /// Adds the given verbose text to the pEp for Outlook log only
Thomas@1246
    78
        /// when verbose logging is enabled.
Thomas@1246
    79
        /// </summary>
Thomas@1246
    80
        /// <param name="text">The verbose text to add to the log.</param>
Thomas@1246
    81
        public static void Verbose(string text)
Thomas@1246
    82
        {
Thomas@1246
    83
            if ((text != null) &&
Thomas@1246
    84
                (Globals.ThisAddIn != null) &&
Thomas@1246
    85
                (Globals.ThisAddIn.Settings.IsVerboseLoggingEnabled))
Thomas@1246
    86
            {
Dean@1249
    87
                Log.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " |V| " + text);
Thomas@1246
    88
            }
Thomas@1246
    89
            return;
Thomas@1246
    90
        }
Thomas@1246
    91
Thomas@1246
    92
        /// <summary>
Thomas@1246
    93
        /// Writes the given text to the log file.
Thomas@1246
    94
        /// </summary>
Thomas@1246
    95
        /// <param name="text">The text to write to the log file.</param>
Thomas@1246
    96
        private static void Write(string text)
Thomas@1246
    97
        {
Thomas@1246
    98
            try
Thomas@1246
    99
            {
Thomas@1246
   100
                if (text != null)
Thomas@1246
   101
                {
Thomas@1246
   102
                    lock (mutexLogFile)
Thomas@1246
   103
                    {
Thomas@1246
   104
                        if (Log.logWriter == null)
Thomas@1246
   105
                        {
Thomas@1246
   106
                            // If file exists, set line counter to file line count
Thomas@1246
   107
                            if (File.Exists(Log.GetLogFilePath()))
Thomas@1246
   108
                            {
Thomas@1246
   109
                                try
Thomas@1246
   110
                                {
Thomas@1246
   111
                                    var lines = File.ReadAllLines(Log.GetLogFilePath());
Thomas@1574
   112
                                    Log.logLineCount = lines.Length;
Thomas@1246
   113
                                }
Thomas@1246
   114
                                catch { }
Thomas@1246
   115
                            }
Thomas@1246
   116
Thomas@1246
   117
                            // Open the file
Thomas@1246
   118
                            Log.logWriter = File.AppendText(Log.GetLogFilePath());
Thomas@1246
   119
                        }
Thomas@1246
   120
Thomas@1246
   121
                        Log.logWriter.WriteLine(text);
Thomas@1246
   122
Thomas@1246
   123
                        Log.logLineCount++;
Thomas@1246
   124
Thomas@1246
   125
                        // If the maximum line count was reached, clean up the log file by removing the first lines.
Thomas@1246
   126
                        if (Log.logLineCount >= Log.LOG_MAX_LINES)
Thomas@1246
   127
                        {
Thomas@1574
   128
                            // Log.Sanitize();
Thomas@1574
   129
                            Log.Archive();
Thomas@1574
   130
                            Log.logLineCount = 0;
Thomas@1246
   131
                        }
Thomas@1246
   132
                    }
Thomas@1246
   133
                }
Thomas@1246
   134
            }
Thomas@1246
   135
            catch { }
Thomas@1246
   136
Thomas@1246
   137
            return;
Thomas@1246
   138
        }
Thomas@1246
   139
Thomas@1246
   140
        /// <summary>
Thomas@1246
   141
        /// Reads all lines of text from the log file.
Thomas@1246
   142
        /// This will never return null.
Thomas@1246
   143
        /// </summary>
Thomas@1246
   144
        /// <returns>The lines of text in the log file.</returns>
Thomas@1246
   145
        public static string Read()
Thomas@1246
   146
        {
Thomas@1246
   147
            string log = "";
Thomas@1246
   148
            string path;
Thomas@1246
   149
            StreamReader logReader;
Thomas@1246
   150
Thomas@1246
   151
            try
Thomas@1246
   152
            {
Thomas@1246
   153
                Log.Close();
Thomas@1246
   154
Thomas@1246
   155
                lock (mutexLogFile)
Thomas@1246
   156
                {
Thomas@1246
   157
                    path = Log.GetLogFilePath();
Thomas@1246
   158
                    if (File.Exists(path))
Thomas@1246
   159
                    {
Thomas@1246
   160
                        logReader = new StreamReader(path);
Thomas@1246
   161
                        log = logReader.ReadToEnd();
Thomas@1246
   162
Thomas@1246
   163
                        logReader.Close();
Thomas@1246
   164
                    }
Thomas@1246
   165
                }
Thomas@1246
   166
Thomas@1246
   167
                // Never allow null
Thomas@1246
   168
                if (log == null)
Thomas@1246
   169
                {
Thomas@1246
   170
                    log = "";
Thomas@1246
   171
                }
Thomas@1246
   172
            }
Thomas@1246
   173
            catch { }
Thomas@1246
   174
Thomas@1246
   175
            return (log);
Thomas@1246
   176
        }
Thomas@1246
   177
Thomas@1246
   178
        /// <summary>
Thomas@1246
   179
        /// Closes and releases any open log file writer.
Thomas@1246
   180
        /// </summary>
Thomas@1246
   181
        public static void Close()
Thomas@1246
   182
        {
Thomas@1246
   183
            try
Thomas@1246
   184
            {
Thomas@1246
   185
                lock (mutexLogFile)
Thomas@1246
   186
                {
Thomas@1246
   187
                    if (Log.logWriter != null)
Thomas@1246
   188
                    {
Thomas@1246
   189
                        Log.logWriter.Flush();
Thomas@1246
   190
                        Log.logWriter.Close();
Thomas@1246
   191
                        Log.logWriter.Dispose();
Thomas@1246
   192
                        Log.logWriter = null;
Thomas@1246
   193
                    }
Thomas@1246
   194
                }
Thomas@1246
   195
            }
Thomas@1246
   196
            catch { }
Thomas@1246
   197
Thomas@1246
   198
            return;
Thomas@1246
   199
        }
Thomas@1246
   200
Thomas@1246
   201
        /// <summary>
Thomas@1246
   202
        /// Clears all logged text by deleting the file.
Thomas@1246
   203
        /// </summary>
Thomas@1246
   204
        public static void Clear()
Thomas@1246
   205
        {
Thomas@1246
   206
            string path;
Thomas@1246
   207
Thomas@1246
   208
            try
Thomas@1246
   209
            {
Thomas@1246
   210
                Log.Close();
Thomas@1246
   211
Thomas@1246
   212
                lock (mutexLogFile)
Thomas@1246
   213
                {
Thomas@1246
   214
                    path = Log.GetLogFilePath();
Thomas@1246
   215
                    if (File.Exists(path))
Thomas@1246
   216
                    {
Thomas@1246
   217
                        File.Delete(path);
Thomas@1246
   218
                    }
Thomas@1246
   219
                }
Thomas@1246
   220
            }
Thomas@1246
   221
            catch { }
Thomas@1246
   222
Thomas@1246
   223
            return;
Thomas@1246
   224
        }
Thomas@1574
   225
Thomas@1574
   226
Thomas@1574
   227
        /// <summary>
Thomas@1574
   228
        /// Rotates the log by saving a copy of the current log file to an archived file 
Thomas@1574
   229
        /// and deleting older archived logs if necessary.
Thomas@1574
   230
        /// </summary>
Thomas@1574
   231
        public static void Archive()
Thomas@1574
   232
        {
Thomas@1574
   233
            int counter = 0;
Thomas@1574
   234
            string[] logFiles = null;
Thomas@1574
   235
            string archiveFile = null;
Thomas@1574
   236
Thomas@1574
   237
            // Create archive file with current date and timestamp
Thomas@1574
   238
            try
Thomas@1574
   239
            {
Thomas@1574
   240
                archiveFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LOG_FILE_FOLDER, LOG_FILE_ARCHIVE_PREFIX);
Thomas@1574
   241
                archiveFile += DateTime.Now.ToString(LOG_FILE_DATE_FORMAT);
Thomas@1574
   242
                archiveFile += ".txt";
Thomas@1574
   243
Thomas@1574
   244
                while (File.Exists(archiveFile))
Thomas@1574
   245
                {
Thomas@1574
   246
                    archiveFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LOG_FILE_FOLDER, LOG_FILE_ARCHIVE_PREFIX);
Thomas@1574
   247
                    archiveFile += DateTime.Now.ToString(LOG_FILE_DATE_FORMAT);
Thomas@1574
   248
                    archiveFile += ".txt";
Thomas@1574
   249
Thomas@1574
   250
                    // Just to be sure in case there is an error somewhere
Thomas@1574
   251
                    if (counter++ > 100)
Thomas@1574
   252
                    {
Thomas@1574
   253
                        throw new Exception("The file already exists.");
Thomas@1574
   254
                    }
Thomas@1574
   255
                }
Thomas@1574
   256
            }
Thomas@1936
   257
            catch (Exception ex)
Thomas@1574
   258
            {
Thomas@1936
   259
                Log.Error("Could not archive log file. Error creating archive file. " + ex.ToString());
Thomas@1574
   260
                archiveFile = null;
Thomas@1574
   261
            }
Thomas@1574
   262
Thomas@1574
   263
            // Move current log to archive log file
Thomas@1574
   264
            if (archiveFile != null)
Thomas@1574
   265
            {
Thomas@1574
   266
                lock (mutexLogFile)
Thomas@1574
   267
                {
Thomas@1574
   268
                    Log.Close();
Thomas@1574
   269
Thomas@1574
   270
                    try
Thomas@1574
   271
                    {
Thomas@1574
   272
                        File.Move(Log.GetLogFilePath(), archiveFile);
Thomas@1574
   273
                    }
Thomas@1936
   274
                    catch (Exception ex)
Thomas@1574
   275
                    {
Thomas@1936
   276
                        Log.Warning("Could not archive log file. " + ex.ToString());
Thomas@1574
   277
                    }
Thomas@1574
   278
Thomas@1574
   279
                    Log.Clear();
Thomas@1574
   280
                }
Thomas@1574
   281
            }
Thomas@1574
   282
Thomas@1574
   283
            // Delete older log files if necessary
Thomas@1574
   284
            try
Thomas@1574
   285
            {
Thomas@1574
   286
                logFiles = Directory.GetFiles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LOG_FILE_FOLDER));
Thomas@1574
   287
                logFiles = Array.FindAll(logFiles, a => a.ToUpperInvariant().Contains(LOG_FILE_ARCHIVE_PREFIX.ToUpperInvariant()));
Thomas@1574
   288
            }
Thomas@1574
   289
            catch
Thomas@1574
   290
            {
Thomas@1574
   291
                logFiles = null;
Thomas@1574
   292
            }
Thomas@1574
   293
Thomas@1574
   294
            if ((logFiles != null) &&
Thomas@1574
   295
                (logFiles.Length > LOG_MAX_FILES))
Thomas@1574
   296
            {
Thomas@1574
   297
                Array.Sort(logFiles, StringComparer.Ordinal);
Thomas@1574
   298
Thomas@1574
   299
                for (int i = 0; i < (logFiles.Length - LOG_MAX_FILES); i++)
Thomas@1574
   300
                {
Thomas@1574
   301
                    try
Thomas@1574
   302
                    {
Thomas@1574
   303
                        File.Delete(logFiles[i]);
Thomas@1574
   304
                    }
Thomas@1936
   305
                    catch (Exception ex)
Thomas@1574
   306
                    {
Thomas@1936
   307
                        Log.Warning("LogRotate: Could not delete old log file. " + ex.ToString());
Thomas@1574
   308
                    }
Thomas@1574
   309
                }
Thomas@1574
   310
            }
Thomas@1574
   311
        }
Thomas@1246
   312
    }
Thomas@1246
   313
}