public void Add(ClsLogItm CDI)
 {
     lock (this._LockObj)
     {
         this._LastIDX.WriteFullFence(CDI.Idx);
         this.LastLogItm = CDI;
         this.Values.Add(this.LastLogItm);
     }
 }
 public void AddRange(List <ClsLogItm> CDIList)
 {
     lock (this._LockObj)
     {
         foreach (ClsLogItm CDI in CDIList)
         {
             this._LastIDX.WriteFullFence(CDI.Idx);
             this.LastLogItm = CDI;
             this.Values.Add(this.LastLogItm);
         }
     }
 }
 public void Clear()
 {
     lock (this._LockObj)
     {
         NLog.LogManager.Flush();
         this.Values.Clear();
         this.LastLogItm = new ClsLogItm();
         this._LastIDX.WriteFullFence(0);
         this._LastAIServer   = "";
         this._LastCamera     = "";
         this._LastImage      = "";
         this.RecentlyAdded   = new ConcurrentQueue <ClsLogItm>();
         this.RecentlyDeleted = new ConcurrentQueue <ClsLogItm>();
         this.ErrorCount.WriteFullFence(0);
         this._Filename = this.GetCurrentLogFileName();
     }
 }
        private List <ClsLogItm> LoadLogFile(string Filename, bool Import, bool LimitEntries)
        {
            List <ClsLogItm> ret = new List <ClsLogItm>();

            //this.LastLoadMessages.Clear();

            if (Import)
            {
                this.Enabled = false;  //disable while we import
            }
            string ExtractZipPath = "";
            string file           = Path.GetFileName(Filename);

            Stopwatch sw = Stopwatch.StartNew();

            if (File.Exists(Filename))
            {
                try
                {
                    Global.UpdateProgressBar($"Loading {Path.GetFileName(Filename)}...", 1, 1, 1);

                    Global.WaitFileAccessResult result = Global.WaitForFileAccess(Filename, FileAccess.Read, FileShare.Read, 30000, 20);
                    if (result.Success)
                    {
                        //if its a zip file, extract that puppy...
                        string NewFilename = "";

                        if (Filename.EndsWith("zip", StringComparison.OrdinalIgnoreCase))
                        {
                            ExtractZipPath = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), "_" + file);
                            if (!Directory.Exists(ExtractZipPath))
                            {
                                Directory.CreateDirectory(ExtractZipPath);
                            }

                            //just extract the first file in the archive
                            using (ZipArchive archive = ZipFile.OpenRead(Filename))
                            {
                                foreach (ZipArchiveEntry entry in archive.Entries)
                                {
                                    string destinationPath = Path.GetFullPath(Path.Combine(ExtractZipPath, entry.FullName));
                                    entry.ExtractToFile(destinationPath, true);
                                    NewFilename = destinationPath;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            NewFilename = Filename;
                        }

                        lock (this._LockObj)
                        {
                            file = Path.GetFileName(NewFilename);
                            int  Invalid = 0;
                            bool OldFile = false;
                            using (StreamReader sr = new StreamReader(NewFilename))
                            {
                                int cnt = 0;
                                while (!sr.EndOfStream)
                                {
                                    cnt++;
                                    if (cnt > 1)
                                    {
                                        string line = sr.ReadLine();

                                        if (!OldFile && line.TrimStart().StartsWith("["))  //old log format, ignore
                                        {
                                            OldFile = true;
                                            this._LastIDX.WriteFullFence(0);
                                            break;
                                        }

                                        if (!Import)
                                        {
                                            //just spit out a list of log lines
                                            ClsLogItm CLI = new ClsLogItm(line);
                                            if (CLI.Level != LogLevel.Off)  //off indicates invalid - for example the old log format
                                            {
                                                CLI.FromFile = true;
                                                CLI.Filename = file;
                                                ret.Add(CLI);
                                            }
                                            else
                                            {
                                                Invalid++;
                                                if (Invalid > 50)
                                                {
                                                    this.Log($"Error: Too many invalid lines ({Invalid}) stopping load.");
                                                    ret.Clear();
                                                    break;
                                                }
                                                else
                                                {
                                                    this.Log($"Debug: {Invalid} line(s) in log file '{line}'");
                                                }
                                            }
                                        }
                                        else
                                        {
                                            //load into current log manager
                                            if (this._Store)
                                            {
                                                ClsLogItm CLI = new ClsLogItm(line);
                                                if (CLI.Level != LogLevel.Off)  //off indicates invalid - for example the old log format
                                                {
                                                    this.LastLogItm = CLI;
                                                    if (this.LastLogItm.Level >= this.MinLevel)
                                                    {
                                                        CLI.FromFile = true;
                                                        CLI.Filename = file;
                                                        this.Values.Add(this.LastLogItm);
                                                        this.RecentlyAdded.Enqueue(this.LastLogItm);
                                                        //keep the log list size down
                                                        if (LimitEntries && this.Values.Count > this.MaxGUILogItems)
                                                        {
                                                            this.RecentlyDeleted.Enqueue(this.Values[0]);
                                                            this.Values.RemoveAt(0);
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    Invalid++;
                                                    if (Invalid > 50)
                                                    {
                                                        this.Log($"Error: Too many invalid lines ({Invalid}) stopping load.");
                                                        ret.Clear();
                                                        this._LastIDX.WriteFullFence(0);
                                                        break;
                                                    }
                                                    else
                                                    {
                                                        this.Log($"Debug: {Invalid} line(s) in log file '{line}'");
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            if (OldFile)
                            {
                                //rename it to keep it out of our way next time
                                try
                                {
                                    this.Log($"Debug: File was in the old log format, renaming to OLDLOGFORMAT. {NewFilename}");
                                    File.Move(NewFilename, NewFilename + ".OLDLOGFORMAT");
                                }
                                catch (Exception ex)
                                {
                                    this.Log($"Error: While renaming log to OLDLOGFORMAT, got: {ex.Message}");
                                }
                            }
                        }
                    }
                    else
                    {
                        this.Log($"Error: Gave up waiting for exclusive file access after {result.TimeMS}ms with {result.ErrRetryCnt} retries for {Filename}");
                    }

                    if (Directory.Exists(ExtractZipPath))
                    {
                        Directory.Delete(ExtractZipPath, true);
                    }
                }
                catch (Exception ex)
                {
                    this.Log($"Error: {Global.ExMsg(ex)}");
                }
            }

            if (Import)
            {
                this.Enabled = true;  //enable after we import
            }
            Global.UpdateProgressBar($"", 0, 0, 0);

            this.LastLoadTimeMS = sw.ElapsedMilliseconds;

            return(ret);
        }
        public ClsLogItm Log(string Detail, string AIServer = "", string Camera = "", string Image = "", string Source = "", int Depth = 0, LogLevel Level = null, Nullable <DateTime> Time = default(DateTime?), [CallerMemberName()] string memberName = null)
        {
            if (!this.Enabled)
            {
                return(null);
            }

            lock (this._LockObj)
            {
                this._LastIDX.AtomicIncrementAndGet();
                this.LastLogItm          = new ClsLogItm();
                this.LastLogItm.Detail   = Detail.Replace("|", ";");
                this.LastLogItm.Filename = Path.GetFileName(this._Filename);

                this.LastLogItm.ThreadID = Thread.CurrentThread.ManagedThreadId;

                if (Source == null || string.IsNullOrWhiteSpace(Source))
                {
                    this.LastLogItm.Source = this._LastSource;
                }
                else
                {
                    this.LastLogItm.Source = Source;
                }

                if (Camera == null || string.IsNullOrWhiteSpace(Camera))
                {
                    this.LastLogItm.Camera = this._LastCamera;
                }
                else
                {
                    this.LastLogItm.Camera = Camera;
                    if (!Camera.StartsWith("Trace-"))
                    {
                        this._LastCamera = Camera;
                    }
                }

                if (AIServer == null || string.IsNullOrWhiteSpace(AIServer))
                {
                    this.LastLogItm.AIServer = this._LastAIServer;
                }
                else
                {
                    this.LastLogItm.AIServer = AIServer;
                    if (!AIServer.StartsWith("Trace-"))
                    {
                        this._LastAIServer = AIServer;
                    }
                }

                if (Image == null || string.IsNullOrWhiteSpace(Image))
                {
                    this.LastLogItm.Image = this._LastImage;
                }
                else
                {
                    this.LastLogItm.Image = Path.GetFileName(Image);
                }

                if (Time.HasValue)
                {
                    this.LastLogItm.Date = Time.Value;
                }
                else
                {
                    this.LastLogItm.Date = DateTime.Now;
                }

                if (memberName == ".ctor")
                {
                    memberName = "Constructor";
                }

                this.LastLogItm.Func = memberName.Replace("AITool.", "");

                //deepstack messages spam us...
                bool DeepstackDebug = !string.Equals(this.LastLogItm.Func, "handleredisprocmsg", StringComparison.OrdinalIgnoreCase) || string.Equals(this.LastLogItm.Func, "handleredisprocmsg", StringComparison.OrdinalIgnoreCase) && AppSettings.Settings.deepstack_debug;

                if (!DeepstackDebug)
                {
                    return(this.LastLogItm);
                }

                if (Level == null)
                {
                    if (this.LastLogItm.Detail.IndexOf("fatal:", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        Level = LogLevel.Fatal;
                    }
                    else if (this.LastLogItm.Detail.IndexOf("error:", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        Level = LogLevel.Error;
                    }
                    else if (this.LastLogItm.Detail.IndexOf("warning:", StringComparison.OrdinalIgnoreCase) >= 0 || this.LastLogItm.Detail.IndexOf("warn:", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        Level = LogLevel.Warn;
                    }
                    else if (this.LastLogItm.Detail.IndexOf("info:", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        Level = LogLevel.Info;
                    }
                    else if (this.LastLogItm.Detail.IndexOf("debug:", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        Level = LogLevel.Debug;
                    }
                    else if (this.LastLogItm.Detail.IndexOf("trace:", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        Level = LogLevel.Trace;
                    }
                    else
                    {
                        Level = LogLevel.Info;
                    }
                }

                bool HasError = false;

                //remove tags
                if (Level == LogLevel.Error)
                {
                    this.ErrorCount.AtomicIncrementAndGet();
                    HasError = true;
                    this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "error:", "");
                }
                else if (Level == LogLevel.Fatal)
                {
                    this.ErrorCount.AtomicIncrementAndGet();
                    HasError = true;
                    this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "fatal:", "");
                }
                else if (Level == LogLevel.Warn)
                {
                    this.ErrorCount.AtomicIncrementAndGet();
                    HasError = true;
                    this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "warn:", "");
                    this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "warning:", "");
                }
                else if (Level == LogLevel.Info)
                {
                    this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "info:", "");
                }
                else if (Level == LogLevel.Trace)
                {
                    this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "trace:", "");
                }
                else if (Level == LogLevel.Debug)
                {
                    this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "debug:", "");
                }

                if (this.LastLogItm.Detail.TrimStart().StartsWith("{"))
                {
                    this.LastLogItm.Color = Global.GetWordBetween(this.LastLogItm.Detail, "{", "}");
                    //strip out the color definition
                    this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "{" + this.LastLogItm.Color + "}", "");
                }

                //clean out any whitespace
                //this.LastLogItm.Detail = this.LastLogItm.Detail.TrimStart();

                if (this._CurDepth.ReadFullFence() + Depth > 0)
                {
                    this.LastLogItm.Detail = new string(' ', (this._CurDepth.ReadFullFence() + Depth * 2)) + this.LastLogItm.Detail;
                }

                this.LastLogItm.Depth = this._CurDepth.ReadFullFence() + Depth;
                this.LastLogItm.Level = Level;
                this.LastLogItm.Idx   = this._LastIDX.ReadFullFence();


                if (this._Store)
                {
                    if (Level >= this.MinLevel)
                    {
                        this.Values.Add(this.LastLogItm);
                        this.RecentlyAdded.Enqueue(this.LastLogItm);
                        //keep the log list size down
                        if (this.Values.Count > this.MaxGUILogItems)
                        {
                            this.RecentlyDeleted.Enqueue(this.Values[0]);
                            this.Values.RemoveAt(0);
                        }
                    }
                }

                this.NLogFileWriter.Log(Level, this.LastLogItm.ToString());

                if (Debugger.IsAttached)
                {
                    Console.WriteLine(this.LastLogItm.ToDetailString());
                }

                string itm = this.LastLogItm.ToString();

                //Send telegram error message
                if (AppSettings.Settings.send_telegram_errors &&
                    (HasError) &&
                    AppSettings.Settings.telegram_chatids.Count > 0 &&
                    AITOOL.TriggerActionQueue != null &&
                    !(itm.IndexOf("telegram", StringComparison.OrdinalIgnoreCase) >= 0) &&
                    !(itm.IndexOf("addtriggeraction", StringComparison.OrdinalIgnoreCase) >= 0))
                {
                    //await TelegramText($"[{time}]: {text}"); //upload text to Telegram
                    AITOOL.TriggerActionQueue.AddTriggerActionAsync(TriggerType.TelegramText, null, null, null, true, false, null, this.LastLogItm.ToDetailString());
                }

                //Send pushover error message
                if (AppSettings.Settings.send_pushover_errors &&
                    (HasError) &&
                    !string.IsNullOrEmpty(AppSettings.Settings.pushover_APIKey) &&
                    !string.IsNullOrEmpty(AppSettings.Settings.pushover_UserKey) &&
                    AITOOL.TriggerActionQueue != null &&
                    !(itm.IndexOf("pushover", StringComparison.OrdinalIgnoreCase) >= 0) &&
                    !(itm.IndexOf("addtriggeraction", StringComparison.OrdinalIgnoreCase) >= 0))
                {
                    AITOOL.TriggerActionQueue.AddTriggerActionAsync(TriggerType.Pushover, null, null, null, true, false, null, this.LastLogItm.ToDetailString());
                }

                if (HasError)
                {
                    NLog.LogManager.Flush();
                }
            }

            return(this.LastLogItm);
        }