Esempio n. 1
0
 /**
  * Raises the log event.
  *
  * @param text
  *  The text to log.
  * @param level
  *  The log level.
  */
 public void OnLog(string text, Logging.LogLevel level)
 {
     if (LogEvent != null)
     {
         LogEvent(text, level);
     }
 }
Esempio n. 2
0
        public StopWatchProfiler(string activity, Logging.LogLevel logLevel)
        {
            _activity = activity;
            _logLevel = logLevel;

            Start();
        }
Esempio n. 3
0
        private static _NLog.LogLevel ConvertLogLevel(Logging.LogLevel logLevel)
        {
            switch (logLevel)
            {
            case Logging.LogLevel.Trace:
                return(_NLog.LogLevel.Trace);

            case Logging.LogLevel.Debug:
                return(_NLog.LogLevel.Debug);

            case Logging.LogLevel.Info:
                return(_NLog.LogLevel.Info);

            case Logging.LogLevel.Warn:
                return(_NLog.LogLevel.Warn);

            case Logging.LogLevel.Error:
                return(_NLog.LogLevel.Error);

            case Logging.LogLevel.Fatal:
                return(_NLog.LogLevel.Fatal);

            case Logging.LogLevel.Off:
                return(_NLog.LogLevel.Off);

            default:
                return(_NLog.LogLevel.Debug);
            }
        }
Esempio n. 4
0
        /*
         * public SqLiteDAO GetOrCreateSqLiteDAO()
         * {
         *  return GetOrCreateSqLiteDAO(_DefaultDbFilenameWithoutPath);
         * }
         *
         * public SqLiteDAO GetOrCreateSqLiteDAO(string dbLogFilenameWithoutPath)
         * {
         *  SqLiteDAO result = null;
         *  // We're supposed to recieve a filename without path information. But we'll go ahead and fixup if necessary
         *  if ((dbLogFilenameWithoutPath.Contains("\\")) || (dbLogFilenameWithoutPath.Contains("/")))
         *  {
         *      dbLogFilenameWithoutPath = Path.GetFileName(dbLogFilenameWithoutPath);
         *  }
         *  string fullDBLogPathAndFilename = Path.Combine(FolderForDatabase, dbLogFilenameWithoutPath);
         *
         *  // We need to be thread-safe in this operation
         *  lock (_SQLiteFilesMgr_Lock)
         *  {
         *      foreach (SqLiteDAO nextDBLayer in _SQLiteFiles)
         *      {
         *          // If we found an item with the same underlying filename, return it
         *          if (string.Compare(nextDBLayer.SqLiteDbPathAndFilename, fullDBLogPathAndFilename, true) == 0)
         *          {
         *              result = nextDBLayer;
         *              break;
         *          }
         *      }
         *
         *      // If the desired layer doesn't exist in our list yet, create a new one and add it to the list
         *      if (result == null)
         *      {
         *          string dbConnectStr = string.Format("data source={0}", fullDBLogPathAndFilename);
         *          result = new SqLiteDAO(dbConnectStr, fullDBLogPathAndFilename);
         *          _SQLiteFiles.Add(result);
         *      }
         *  }
         *
         *  // Regardless of if we found an existing DB layer or created a new one, we will perform the DB Metadata check.
         *  // (This check will be very quick if it has already been validated, and will block until schema validation is finalized by any thread)
         *  // Note that this should be done outside of the "Lock" becasue we only want to lock out other threads when finding/modifying the
         *  // list of DB layers -- not when using them.
         *  // Before using the database, we need to be sure it has the correct Metadata/Schema information.
         *  // We will try to get exclusive access to a variable to see if whether or not the Metadata has been checked.
         *  // If we get exclusing access and DB Metadata hasn't been validated yet, we will do so now.
         *  if (!Monitor.TryEnter(result.MetadataHasBeenChecked_Lock))
         *  {
         *      // Somebody else already has this object locked. Let's immediately record this fact
         *      Logging.AddTextToGenericLog(Logging.LogLevel.Debug, "SqLite Metadata check is already locked by another thread. (" + _DefaultDbFilenameWithoutPath + ")",
         *          System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, System.Threading.Thread.CurrentThread.ManagedThreadId);
         *
         *      // Now we will do a normal Lock so we are blocked until the Metadata check is finished
         *      lock (result.MetadataHasBeenChecked_Lock)
         *      {
         *          Logging.AddTextToGenericLog(Logging.LogLevel.Debug, "Finished waiting for SqLite Metadata check to complete on different thread. (" + _DefaultDbFilenameWithoutPath + ")",
         *              System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, System.Threading.Thread.CurrentThread.ManagedThreadId);
         *      }
         *  }
         *  else
         *  {
         *      // The Monitor.TryEnter was successful, so we have a lock on the object. We will need to do Monitor.Exit when done
         *      try
         *      {
         *          if (result.MetadataHasBeenChecked == false)
         *          {
         *              Logging.AddTextToGenericLog(Logging.LogLevel.Debug, "Acquired exclusive access to verify SqLite Metadata. (" + _DefaultDbFilenameWithoutPath + ")",
         *                  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, System.Threading.Thread.CurrentThread.ManagedThreadId);
         *
         *              SqLiteMetadataManager _DBMetadata = new SqLiteMetadataManager(false, LogMessage, result, _Metadata_OverstayVios.Tables);
         *              _DBMetadata.CheckAllTables(true);
         *              // Set flag so other threads know the Metadata check has already been performed
         *              result.MetadataHasBeenChecked = true;
         *
         *              // Update Metadata progress log in a thread-safe manner
         *              Logging.AddTextToGenericLog(Logging.LogLevel.Debug, "Finished SqLite Metadata verification. (" + _DefaultDbFilenameWithoutPath + ")",
         *                  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, System.Threading.Thread.CurrentThread.ManagedThreadId);
         *          }
         *          else
         *          {
         *              Logging.AddTextToGenericLog(Logging.LogLevel.Debug, "No SqLite Metadata check needed -- it's already been performed. (" + _DefaultDbFilenameWithoutPath + ")",
         *                  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, System.Threading.Thread.CurrentThread.ManagedThreadId);
         *          }
         *      }
         *      finally
         *      {
         *          // Set flag so other threads know the Metadata check has already been performed
         *          result.MetadataHasBeenChecked = true;
         *
         *          // Finally we will do the Monitor.Exit which does the unlocking
         *          Monitor.Exit(result.MetadataHasBeenChecked_Lock);
         *      }
         *  }
         *
         *  // Now we need to request DB transaction in the current DB access layer (This should never be done prior to the DB metadata being checked!)
         *  // Do a thread-safe increment of the counter to indicate transactions should stay active
         *  if (result != null)
         *  {
         *      lock (result.ClientCountWantingTransactionToStayOpen_Lock)
         *      {
         *          if (result.ClientCountWantingTransactionToStayOpen == 0)
         *          {
         *              result.ClientCountWantingTransactionToStayOpen++;
         *
         *              // Start a DB session so things are a bit faster in this bulk operation...
         *              // (The actual StartTransaction process will depend on how many "listeners" are wanting the transaction to stay active, and current state, etc.)
         *              result.StartTransactionSession();
         *          }
         *      }
         *  }
         *
         *  // Return our final result
         *  return result;
         * }
         */
        #endregion

        public void LogMessage(System.Diagnostics.TraceLevel logLevel, string textToLog, string classAndMethod, int threadID)
        {
            Logging.LogLevel convertedLogLevel = Logging.LogLevel.Debug;
            switch (logLevel)
            {
            case System.Diagnostics.TraceLevel.Error:
                convertedLogLevel = Logging.LogLevel.Error;
                break;

            case System.Diagnostics.TraceLevel.Info:
                convertedLogLevel = Logging.LogLevel.Info;
                break;

            case System.Diagnostics.TraceLevel.Verbose:
                convertedLogLevel = Logging.LogLevel.Debug;
                break;

            case System.Diagnostics.TraceLevel.Warning:
                convertedLogLevel = Logging.LogLevel.Warning;
                break;

            case System.Diagnostics.TraceLevel.Off:
                convertedLogLevel = Logging.LogLevel.DebugTraceOutput;
                break;

            default:
                convertedLogLevel = Logging.LogLevel.Debug;
                break;
            }

            Logging.AddTextToGenericLog(convertedLogLevel, textToLog, classAndMethod, threadID);
        }
        public void Log <TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter)
        {
            if (IsEnabled(logLevel))
            {
                var message = formatter(state, exception);
                var source  = $"{_categoryName}";

                if (exception != null)
                {
                    exception.ToExceptionless().Submit();
                }
                else
                {
                    Logging.LogLevel exlessLogLevel = logLevel switch
                    {
                        LogLevel.Trace => Logging.LogLevel.Trace,
                        LogLevel.Information => Logging.LogLevel.Info,
                        LogLevel.Warning => Logging.LogLevel.Warn,
                        LogLevel.Error => Logging.LogLevel.Error,
                        LogLevel.Critical => Logging.LogLevel.Fatal,
                        _ => Logging.LogLevel.Debug,
                    };
                    var eventBuilder = ExceptionlessClient.Default
                                       .CreateLog(source, message, exlessLogLevel);

                    if (eventId != null)
                    {
                        eventBuilder.SetProperty("Event", $"{eventId}");
                    }

                    eventBuilder.Submit();
                }
            }
        }
Esempio n. 6
0
        public override Logging.ILogger CreateLogger(Logging.LogLevel lvl, string name)
        {
            var ass  = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
            var repo = LogManager.GetRepository(ass);
            var log  = LogManager.GetLogger(repo.Name, name);

            return(new log4netLogger(log));
        }
Esempio n. 7
0
        public StopWatchProfiler(string activity, Logging.LogLevel logLevel, string logMethod, int threadID = -1)
        {
            _activity  = activity;
            _logLevel  = logLevel;
            _logMethod = logMethod;
            _threadID  = threadID;

            Start();
        }
Esempio n. 8
0
 private void LoggingLevelChanged(object sender, SelectionChangedEventArgs e)
 {
     Logging.LogLevel level = (Logging.LogLevel)Enum.Parse(typeof(Logging.LogLevel), ((ComboBoxItem)LoggingSelection.SelectedItem).Tag.ToString());
     Logging.SetLogLevel(level);
     if (level != (Logging.LogLevel)Enum.Parse(typeof(Logging.LogLevel), Properties.Settings.Default.LogLevel))
     {
         Logging.Write($"Log Level set to {level.ToString()}");
         Properties.Settings.Default.LogLevel = level.ToString();
     }
 }
Esempio n. 9
0
        public void OnLog(Logging.LogLevel level, string msg)
        {
            if (_isEnabled == false)
            {
                return;
            }

            Dispatcher.InvokeAsync(() =>
            {
                LogTextBox.Text += msg;
            });
        }
Esempio n. 10
0
 private static void Logger_onLog(Logging.LogLevel level, string module, string msg)
 {
     if (DebugHud.hud == null)
     {
         DebugHud.lines.Add(msg);
     }
     else
     {
         if (DebugHud.lines.Count > 0)
         {
             foreach (string s in DebugHud.lines)
             {
                 DebugHud.hud.Add_Line(s);
             }
             DebugHud.lines.Clear();
         }
         DebugHud.hud.Add_Line(msg);
     }
 }
Esempio n. 11
0
        /// <summary>
        /// <para>Records text to specific log file, categorized at the passed logLevel.</para>
        /// <para>Method will also be recorded if its not null or empty.</para>
        /// <para>Thread ID will also be recorded if its not -1.</para>
        /// </summary>
        /// <param name="logLevel"></param>
        /// <param name="textToLog"></param>
        /// <param name="method">
        /// <para>Optional information about where in code the logged event occurred.</para>
        /// <para>A common parameter value to pass is:</para>
        /// <para>  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name</para>
        /// </param>
        /// <param name="threadID">
        /// <para>Optional information to indicate which thread triggered the logging event. Thread ID is not logged if passed value is -1.</para>
        /// </param>
        static public void AddTextToSpecificLog(Logging.LogLevel logLevel, string logNameWithoutPathOrTimestampPrefix, string textToLog, string method, int threadID = -1)
        {
            /*Debug.WriteLine("Adding text to log queue via thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());*/

            // If the log level is the special DebugTraceOutput option, then simply send to Debug Diagnostics trace listner,
            // otherwise we will add to a queue to be written to log file
            if (logLevel == LogLevel.DebugTraceOutput)
            {
                System.Diagnostics.Debug.WriteLine(textToLog);
                return;
            }

            // Add item to the Producer/Consumer queue and immediately return back to caller.
            // The Consumer thread will write to the underlying log file in the background after
            //it receives its signal and acquires a concurrency lock
            Logging.Instance.EnqueueItem(() =>
            {
                Logging.Instance.PersistQueuedItem(logLevel, logNameWithoutPathOrTimestampPrefix, textToLog, method, threadID);
            });
        }
        public static string LogText(string Message, Exception ex, Logging.LogLevel MessageLogLevel)
        {
            Message += "\r\n";
            Message += "Message: " + ex.Message + "\r\n";
            Message += "Stacktrace: " + ex.StackTrace + "\r\n";

            Exception inner = ex.InnerException;
            int       i     = 0;

            while (inner != null)
            {
                i++;
                Message += "Inner Exception (" + i.ToString() + ") :";
                Message += "Message:" + inner.Message + "\r\n";
                Message += "Stacktrace: " + ex.StackTrace + "\r\n";
                inner    = inner.InnerException;
            }

            return(LogText(Message, MessageLogLevel));
        }
        public static string LogText(string Message, Exception ex, Logging.LogLevel MessageLogLevel)
        {
            Message += "\r\n";
            Message += "Exception: " + ex.ToString() + "\r\n";

            Exception inner = ex.InnerException;
            int       i     = 0;

            while (inner != null)
            {
                i++;
                Message += "Inner Exception (" + i.ToString() + ") :";
                Message += "Exception:" + inner.ToString() + "\r\n";
                inner    = inner.InnerException;
            }


            log4net.LogManager.GetLogger("test").Info(Message, ex);

            return(internalLogText(Message, MessageLogLevel));
        }
Esempio n. 14
0
 public void Log(Logging.LogLevel level, object obj, Exception exception)
 {
     if (level == Logging.LogLevel.Fatal)
     {
         Fatal(obj, exception);
     }
     else if (level == Logging.LogLevel.Error)
     {
         Error(obj, exception);
     }
     else if (level == Logging.LogLevel.Warn)
     {
         Warn(obj, exception);
     }
     else if (level == Logging.LogLevel.Info)
     {
         Info(obj, exception);
     }
     else if (level >= Logging.LogLevel.Debug)
     {
         Debug(obj, exception);
     }
 }
Esempio n. 15
0
 public void Log(Logging.LogLevel level, Logging.LogOutputProvider messageProvider)
 {
     if (level == Logging.LogLevel.Fatal)
     {
         Fatal(messageProvider);
     }
     else if (level == Logging.LogLevel.Error)
     {
         Error(messageProvider);
     }
     else if (level == Logging.LogLevel.Warn)
     {
         Warn(messageProvider);
     }
     else if (level == Logging.LogLevel.Info)
     {
         Info(messageProvider);
     }
     else if (level >= Logging.LogLevel.Debug)
     {
         Debug(messageProvider);
     }
 }
Esempio n. 16
0
 public void LogFormat(Logging.LogLevel level, IFormatProvider formatProvider, string format, params object[] args)
 {
     if (level == Logging.LogLevel.Fatal)
     {
         FatalFormat(formatProvider, format, args);
     }
     else if (level == Logging.LogLevel.Error)
     {
         ErrorFormat(formatProvider, format, args);
     }
     else if (level == Logging.LogLevel.Warn)
     {
         WarnFormat(formatProvider, format, args);
     }
     else if (level == Logging.LogLevel.Info)
     {
         InfoFormat(formatProvider, format, args);
     }
     else if (level >= Logging.LogLevel.Debug)
     {
         DebugFormat(formatProvider, format, args);
     }
 }
Esempio n. 17
0
        /// <summary>
        /// Is logging enabled for this logger at this <paramref name="logLevel"/>?
        /// </summary>
        /// <param name="logLevel"></param>
        /// <returns></returns>
        public bool IsEnabled(Logging.LogLevel logLevel)
        {
            switch (logLevel)
            {
            case LogLevel.Trace:
            case LogLevel.Debug:
                return(_logger.IsDebugEnabled);

            case LogLevel.Info:
                return(_logger.IsInfoEnabled);

            case LogLevel.Warn:
                return(_logger.IsWarnEnabled);

            case LogLevel.Error:
                return(_logger.IsErrorEnabled);

            case LogLevel.Fatal:
                return(_logger.IsFatalEnabled);

            default:
                return(false);
            }
        }
Esempio n. 18
0
        private static void LogLine(string message, Logging.LogLevel logLevel)
        {
            switch (logLevel)
            {
            case Logging.LogLevel.Normal:
                if (!s_minimalOutput)
                {
                    Logger.Info(message);
                }
                break;

            case Logging.LogLevel.Warning:
                Logger.Warn(message);
                break;

            case Logging.LogLevel.Error:
            case Logging.LogLevel.Failure:
                Logger.Error(message);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, message: null);
            }
        }
Esempio n. 19
0
 void Log(string message, Logging.LogLevel level)
 {
     Logging.Logger.Log(message, level: level, source: nameof(SubscribeClient), category: Logging.MessageCategory.Subscriber);
 }
Esempio n. 20
0
 /// <summary>
 /// Dispatch a new diagnostic event
 /// </summary>
 /// <param name="message">the diagnostic message</param>
 /// <param name="severity">event severity</param>
 /// <param name="exception">the exception releated to the diagnostic event</param>
 public static void DispatchDiagnosicEvent(string message, Logging.LogLevel severity, Exception exception = null)
 {
     DiagnosticeEvent?.Invoke(message, severity, exception);
 }
Esempio n. 21
0
 public void LOG(Logging.LogLevel level, string message, Exception innerException = null)
 => _wrappedLogger.Log(_map[level], innerException, message);
Esempio n. 22
0
        /// <summary>
        /// Is logging enabled for this logger at this <paramref name="logLevel"/>?
        /// </summary>
        /// <param name="logLevel"></param>
        /// <returns></returns>
        public bool IsEnabled(Logging.LogLevel logLevel)
        {
            var convertLogLevel = ConvertLogLevel(logLevel);

            return(IsEnabled(convertLogLevel));
        }
Esempio n. 23
0
 public void LOGITEM(Logging.LogLevel level, string message, string pathToFile, Exception innerException = null)
 => LOG(level, string.Concat(message, $"{{rp#file#{pathToFile}}}"), innerException);
Esempio n. 24
0
 public static IServiceCollection AddIllarionTestLogging(this IServiceCollection serviceCollection, ITestOutputHelper output, Logging.LogLevel minLevel)
 {
     serviceCollection.AddLogging(b => b.AddXunit(output, minLevel));
     return(serviceCollection);
 }
Esempio n. 25
0
 void Log(string message, Logging.LogLevel level)
 {
     Logging.Logger.Log(message, level: level, category: Logging.MessageCategory.Subscriber);
 }
Esempio n. 26
0
 /// <summary>
 /// Records text to default log file, categorized at the passed logLevel.
 /// </summary>
 /// <param name="logLevel"></param>
 /// <param name="textToLog"></param>
 static public void AddTextToGenericLog(Logging.LogLevel logLevel, string textToLog)
 {
     Logging.AddTextToGenericLog(logLevel, textToLog, string.Empty, -1);
 }
Esempio n. 27
0
 /// <summary>
 /// <para>Records text to default log file, categorized at the passed logLevel.</para>
 /// <para>Method will also be recorded if its not null or empty.</para>
 /// <para>Thread ID will also be recorded if its not -1.</para>
 /// </summary>
 /// <param name="logLevel"></param>
 /// <param name="textToLog"></param>
 /// <param name="method">
 /// <para>Optional information about where in code the logged event occurred.</para>
 /// <para>A common parameter value to pass is:</para>
 /// <para>  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name</para>
 /// </param>
 /// <param name="threadID">
 /// <para>Optional information to indicate which thread triggered the logging event. Thread ID is not logged if passed value is -1.</para>
 /// </param>
 static public void AddTextToGenericLog(Logging.LogLevel logLevel, string textToLog, string method, int threadID = -1)
 {
     Logging.AddTextToSpecificLog(logLevel, Logging._DefaultLogName, textToLog, method, threadID);
 }
 public static void LogTextToLog4Net(string message, Logging.LogLevel messageLogLevel = LogLevel.Information, Exception exception = null)
 {
     log4net.LogManager.GetLogger("test").Info(message, exception);
 }
Esempio n. 29
0
        private void PersistQueuedItem(Logging.LogLevel logLevel, string logNameWithoutPathOrTimestampPrefix, string textToLog, string method, int threadID = -1)
        {
            /*Debug.WriteLine("Executing PersistQueuedItem via thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());*/

            // Just exit if this is at an undesired logging level
            if (Convert.ToInt32(logLevel) < Convert.ToInt32(Logging._MinimumLogLevelToWrite))
            {
                return;
            }

            // Create a string builder that represents all info we will log
            StringBuilder finalTextToLog = new StringBuilder();

            finalTextToLog.Append(DateTime.UtcNow.ToString("yyyyMMdd_THHmmssZ") + " | " + logLevel.ToString() + " | " + textToLog);
            if (!string.IsNullOrEmpty(method))
            {
                finalTextToLog.Append(" | " + "Method = " + method);
            }
            if (threadID != -1)
            {
                finalTextToLog.Append(" | " + "Thread = " + threadID.ToString());
            }

            // Build the full base filename, including path. The final filename will be altered to include a timestamp prefix in the name
            // Note: Just for info, an alternative way to build the full path is: System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/Logs/" + logNameWithoutPathOrTimestampPrefix);
            string logBaseFileName = Path.Combine(HttpRuntime.AppDomainAppPath, @"App_Data\Logs\" + logNameWithoutPathOrTimestampPrefix);

            // Extract the folder from the complete file path
            string logFileFolder = Path.GetDirectoryName(logBaseFileName);

            // Create folder if it doesn't exist already
            try
            {
                if (!Directory.Exists(logFileFolder))
                {
                    Directory.CreateDirectory(logFileFolder);
                }
            }
            catch { }

            // Check to see if we should cleanup any old log files
            // To reduce strain, let's only do log file maintenance after every 25 activities
            if ((Logging._LoggedItemCountSinceCleanup == 0) || ((Logging._LoggedItemCountSinceCleanup % 25) == 0))
            {
                // Do log file cleanup in a separate thread
                CleanupOldLogFiles(logBaseFileName, Logging._LogFileRetentionDays);
            }

            // Increment the logged item count, but avoid maintaining a large number
            Logging._LoggedItemCountSinceCleanup++;
            if (Logging._LoggedItemCountSinceCleanup > 1024)
            {
                Logging._LoggedItemCountSinceCleanup = 0;
            }

            try
            {
                // Determine the filename we will use for logging (We will roll-over to new filename when date changes, or when current log file reaches max size threshold)
                string   fullLogFileName      = "";
                DateTime existingLogTimeStamp = DateTime.MinValue;
                try
                {
                    // Find list of today's files for current desired log filename suffix.
                    // Loop through them to find the latest
                    string[] logFiles = Directory.GetFiles(logFileFolder, DateTime.UtcNow.ToString("yyyyMMdd") + "*" + logNameWithoutPathOrTimestampPrefix, SearchOption.TopDirectoryOnly);
                    foreach (string nextLogFile in logFiles)
                    {
                        try
                        {
                            string   justFilename     = Path.GetFileName(nextLogFile);
                            DateTime logFileTimeStamp = DateTime.SpecifyKind(System.Xml.XmlConvert.ToDateTime(justFilename.Substring(0, 17), "yyyyMMdd_THHmmssZ"), DateTimeKind.Utc);
                            if (logFileTimeStamp > existingLogTimeStamp)
                            {
                                fullLogFileName      = nextLogFile;
                                existingLogTimeStamp = logFileTimeStamp;
                            }
                        }
                        catch
                        {
                        }
                    }

                    // If we found the latest existing file, we will use it unless it has already reached maximum size allowed
                    if (fullLogFileName != "")
                    {
                        FileInfo LastLogFileInfo = new FileInfo(fullLogFileName);
                        if (LastLogFileInfo.Length >= (Logging._LogFileMaxSizeInMB * 1024 * 1024))
                        {
                            fullLogFileName = "";
                        }
                    }
                }
                catch
                {
                }

                // If we don't have a useable name yet, start a new one (and keep track of it)
                if (fullLogFileName == "")
                {
                    fullLogFileName = Path.Combine(logFileFolder, DateTime.UtcNow.ToString("yyyyMMdd_THHmmssZ") + " " + logNameWithoutPathOrTimestampPrefix);
                }

                lock (Logging._LogFileLock)  // wait your turn - avoid concurrent access errors
                {
                    using (FileStream logFileStream = new FileStream(fullLogFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        using (StreamWriter logWriter = new StreamWriter(logFileStream))
                        {
                            // We need to make sure we are writing at the end of the file (to append text)
                            logFileStream.Seek(0, SeekOrigin.End);

                            // Append the final text to end of file
                            logWriter.WriteLine(finalTextToLog.ToString());

                            // Close file and cleanup
                            if (logWriter.BaseStream.CanWrite == true)
                            {
                                logWriter.Flush();
                            }
                        }
                    }
                }
            }
            catch
            {
            }
        }