/// <summary> /// Add new duplication entry (Tuple of log entry (original) and collection of log entries (duplications)) /// </summary> /// <param name="entry"></param> /// <param name="timeOfOriginal"></param> private void AddNewDuplicationEntry(Log9KEntry entry, Log9KTime timeOfOriginal) { if (!CheckForDuplicationMethods()) { return; } int duplicationKey = KeyForDuplicationDictionary(entry); Log9KUtil.InvokeInUiThread(() => { if (DuplicationsDictionary.ContainsKey(duplicationKey)) { return; } ObservableCollection <DuplicationLeaf> times = new ObservableCollection <DuplicationLeaf>(); if (timeOfOriginal == null) { times = new ObservableCollection <Tuple <Log9KTime, uint> > { new DuplicationLeaf(entry.Time, entry.ID) }; } DuplicationNode de = new DuplicationNode( entry, times ); DuplicationsDictionary.Add(duplicationKey, de); }); }
/// <summary> /// Add entries from queue of inner logs that occured before Log9KCore created /// </summary> private void AddLogEntriesFromQueue() { if (_preInstanceCreatedInnerLogQueue.Count > 0) { Log9KEntry e = _preInstanceCreatedInnerLogQueue.Dequeue(); InnerLog(e); } }
/// <summary> /// First - add to collection and only after add to duplications dict /// </summary> /// <param name="entry"></param> private void AddToCollectionAndToDuplicationsDictionary(Log9KEntry entry) { if (LogEntryCollection.IsMaxSizeReached) { LineNumberTopTempFile++; } CollectionAdd(entry); AddToDuplicationsDictionary(entry); }
/// <summary> /// Add log entry to ALL tab /// </summary> /// <param name="logEntry"></param> private void AddToAllTab(Log9KEntry logEntry) { if (TabAll == null) { InnerLog("Ошибка: при добавлении лога — вкладка ALL равна null"); return; } TabAll.AddLogEntry(logEntry); }
/// <summary> /// Helper method used by public loggin methods /// </summary> /// <param name="logEntry"></param> private bool Log(Log9KEntry logEntry) { if (logEntry == null) { InnerLog("Ошибка: в методе Log() переданный объект класса Log9KEntry равен null!"); return(false); } AddLogEntryToTabs(logEntry); return(true); }
/// <summary> /// Find duplication entry for given entry /// </summary> /// <param name="entry"></param> /// <returns></returns> protected DuplicationNode LookupForDuplication(Log9KEntry entry) { int duplicationKey = KeyForDuplicationDictionary(entry); if (!DuplicationsDictionary.ContainsKey(duplicationKey)) { return(null); } return(DuplicationsDictionary[duplicationKey]); }
/// <summary> /// Log method for custom type entries /// </summary> /// <param name="logCustomType"></param> /// <param name="message"></param> /// <param name="level"></param> public bool Log(string logCustomType, string message, Levels level = Levels.PRIMARY) { if (string.IsNullOrEmpty(message) || string.IsNullOrEmpty(logCustomType)) { return(false); } Log9KEntry logEntry = new Log9KEntry(logCustomType, message, level); return(Log(logEntry)); }
/// <summary> /// Add entry to tab of it's type /// </summary> /// <param name="entry"></param> private void AddToConcreteTypeTab(Log9KEntry entry) { Log9KTab entryTypeTab = GetTab(entry.TypeString); if (entryTypeTab == null) { InnerLog("Ошибка: при добавлении лога — вкладка " + entry.TypeString + " равна null"); return; } entryTypeTab.AddLogEntry(entry); }
/// <summary> /// Writes bytes of entry to temporary file (serialization) /// </summary> /// <param name="entry">entry to write</param> protected void WriteToTempFile(Log9KEntry entry) { if (entry.Type == LogEntryTypes.CUSTOM && entry.CustomType == Log9KCore.INNER_LOG_TAB) { return; } byte[] entryBytes = EntryToBytes(entry); Log9KUtil.InvokeInUiThread(() => { Log9KUtil.AppendByteArrayToFile(FilenameTempFile, entryBytes); }); }
/// <summary> /// <para>Primary log method, log message with given type</para> /// <remarks>Not for custom type entries!!!</remarks> /// </summary> /// <param name="type"></param> /// <param name="message"></param> /// <param name="level"></param> public bool Log(LogEntryTypes type, string message, Levels level = Levels.PRIMARY) { if (string.IsNullOrEmpty(message)) { InnerLog("Ошибка: в методе Log() строка message пуста либо равна null!"); return(false); } Log9KEntry logEntry = new Log9KEntry(type, message, level); return(Log(logEntry)); }
private void FilterByTime(DateTime start, DateTime end, out uint lineStart, out uint lineEnd) { lineStart = 0; lineEnd = 0; bool foundStart = false, foundEnd = false; uint i = 0; while (!foundStart) { if (i >= Log9KEntry.Counter - 1) { break; } Log9KEntry entry = ReadEntry(i); if (entry == null) { break; } DateTime entryTime = entry.Time.ToDateTime(); if (entryTime > start) { foundStart = true; lineStart = i; } i++; } while (!foundEnd) { if (i >= Log9KEntry.Counter - 1) { if (foundStart) { lineEnd = i; } break; } Log9KEntry entry = ReadEntry(i); if (entry == null) { lineEnd = i; break; } DateTime entryTime = entry.Time.ToDateTime(); if (entryTime > end) { foundEnd = true; lineEnd = i; } i++; } }
/// <summary> /// Read log entry from temp file on given linenumber /// </summary> /// <param name="lineNumber"></param> /// <returns></returns> protected Log9KEntry ReadEntry(uint lineNumber) { byte[] buffer; if (!Log9KUtil.ReadFixedSizeByteArrayEntry(FilenameTempFile, Log9KEntry.ENTRY_SIZE, lineNumber, out buffer)) { Log9KCore.Instance.InnerLog("Ошибка: Log9KUtil.ReadFixedSizeByteArrayEntry вернул false"); return(null); } Log9KEntry entry = EntryFromBytes(buffer); return(entry); }
public override DispatcherOperation LoadEntries(uint startFromID) { if (startFromID > Log9KEntry.Counter) { return(null); } startFromID--; if (IsAddingNewestEntries) { IsAddingNewestEntries = false; } if (ScrollToLastLog) { ScrollToLastLog = false; } uint lineNumber; if (startFromID == 0) { return(null); } if (Application.Current == null) { return(null); } DispatcherOperation a = Application.Current.Dispatcher.BeginInvoke(new Action(() => { if (!FindLineNumber(startFromID, out lineNumber)) { Log9KCore.Instance.InnerLog("Ошибка: при загрузке логов метод FindLineNumber вернул false"); return; } LineNumberTopTempFile = lineNumber; LogEntryCollection.Clear(); for (int i = 0; i < LogEntryCollection.MaxCollectionSize; i++) { Log9KEntry entry = ReadEntry(lineNumber); if (entry == null) { break; } LogEntryCollection.Add(entry); lineNumber++; } }), DispatcherPriority.Background); return(a); }
/// <summary> /// CompareTo() /// </summary> /// <param name="obj"></param> /// <returns> /// <para>- 1 if given entry is more than current</para> /// <para> 1 if given entry is less than current</para> /// <para> 1 otherwise</para> /// </returns> public int CompareTo(object obj) { Log9KEntry entry = obj as Log9KEntry; if (entry == null) { return(1); } if (entry.ID > ID) { return(-1); } return(1); }
/// <summary> /// Insert log entry to given position, in UI thread /// </summary> /// <param name="i"></param> /// <param name="entry"></param> protected void CollectionInsert(int i, Log9KEntry entry) { if (Application.Current == null) { return; } if (_logEntryCollection == null) { return; } Log9KUtil.InvokeInUiThread(() => { _logEntryCollection.Insert(i, entry); }); }
/// <summary> /// Equals() /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { Log9KEntry entryObj = obj as Log9KEntry; if (entryObj == null) { return(false); } if (!IsInnerLog()) { return(ID == entryObj.ID); } // All inner log entries have ID == 0 return(entryObj.GetHashCode() == GetHashCode()); }
private bool ReadNewerLogEntryAndCheckIt(out Log9KEntry entry, uint lineNumber) { entry = ReadEntry(lineNumber); if (entry == null) { return(false); } uint lastLogEntryInCollectionID = LogEntryCollection[LogEntryCollection.Count - 1].ID; uint entryIDshoulBe = lastLogEntryInCollectionID + 1; if (entry.ID == entryIDshoulBe) { return(true); } return(false); }
private bool ReadOlderLogEntryAndCheckIt(out Log9KEntry entry, uint lineNumber) { entry = ReadEntry(lineNumber); if (entry == null) { return(false); } uint firstLogEntryInCollectionID = LogEntryCollection[0].ID; uint entryIDshoulBe = firstLogEntryInCollectionID - 1; if (entry.ID == entryIDshoulBe) { return(true); } return(false); }
/// <summary> /// Add duplicate to existing entry, for adding new duplication entry use AddNewDuplicationEntry /// </summary> /// <param name="entry"></param> private void AddToDuplicationEntry(Log9KEntry entry) { if (!CheckForDuplicationMethods()) { return; } int duplicationKey = KeyForDuplicationDictionary(entry); Log9KUtil.InvokeInUiThread(() => { DuplicationNode duplicationEntry = DuplicationsDictionary[duplicationKey]; duplicationEntry.Item2.Add(new DuplicationLeaf(entry.Time, entry.ID)); if (duplicationEntry.Item2.Count == 2) { DuplicationsCollection.Add(duplicationEntry); } }); }
/// <summary> /// Append log entry ToString to current tab's log file /// </summary> /// <param name="entry"></param> private void AppendEntryToFile(Log9KEntry entry) { if (_directoryNotCreated) { Log9KUtil.CreateDirIfNotExists(_dirname); _directoryNotCreated = false; } if (Application.Current == null) { return; } Application.Current.Dispatcher.BeginInvoke( new Action(() => { Log9KUtil.AppendStringToFile(FilenameLogFile, entry.ToString()); }), DispatcherPriority.Background ); }
/// <summary> /// Adds entry to duplications dictionary: /// <para>if it is not met before creates new DuplicationEntry, /// else adds time of given entry in list of existing DuplicationEntry</para> /// </summary> /// <param name="entry"></param> private void AddToDuplicationsDictionary(Log9KEntry entry) { if (entry.Level == Levels.SECONDARY) { return; } DuplicationNode duplicationEntry = LookupForDuplication(entry); if (duplicationEntry == null) { AddNewDuplicationEntry(entry, null); } else { entry.IsDuplicate = true; duplicationEntry.Item1.IsDuplicate = true; AddToDuplicationEntry(entry); } }
/// <summary> /// Load most recent logs from temporary file /// </summary> public override void LoadLastLogs() { LogEntryCollection.StartRemovingFromTop(); LogEntryCollection.Clear(); uint entriesNumber; bool success = Log9KUtil.GetEntriesNumberInFile( FilenameTempFile, Log9KEntry.ENTRY_SIZE, out entriesNumber ); if (!success) { Log9KCore.Instance.InnerLog("Ошибка: метод Log9KUtil.GetEntriesNumberInFile вернул false"); return; } if (Application.Current == null) { return; } Application.Current.Dispatcher.BeginInvoke( new Action(() => { bool notEnd = true; uint z = 0; for (uint i = entriesNumber; notEnd; i--) { Log9KEntry e = ReadEntry(i); if (e != null) { LogEntryCollection.Insert(0, e); } if (i == 0 || z >= LogEntryCollection.MaxCollectionSize) { notEnd = false; } z++; } }), DispatcherPriority.Background ); }
private void FilterApplyToCollection(uint lineStart, uint lineEnd) { IsAddingNewestEntries = false; LogEntryCollection.Clear(); uint i = 0; for (uint j = lineStart; j < lineEnd; j++) { Log9KEntry entry = ReadEntry(j); if (entry != null) { CollectionAdd(entry); i++; } if (i >= LogEntryCollection.MaxCollectionSize) { break; } } LineNumberTopTempFile = lineStart; }
/// <summary> /// Writes ToString of entry to log file (logging) /// </summary> /// <param name="entry"></param> protected void WriteToLogFile(Log9KEntry entry) { if (IsInnerLogTab()) { AppendEntryToFile(entry); return; } if (!IsAllTab()) { if (Log9KCore.Settings.IsWritingEachTabEnabled) { AppendEntryToFile(entry); } } else { if (Log9KCore.Settings.IsWritingToFileEnabled) { AppendEntryToFile(entry); } } }
/// <summary> /// Main Logging method in tab. Adds log entry to tab, checks duplications and other stuff /// </summary> /// <param name="entry"></param> public virtual void AddLogEntry(Log9KEntry entry) { // if type of tab/log entry not equal and we are not in ALL tab then return if (!AreLogEntryAndTabTypesEqual(entry) && !IsAllTab()) { Log9KCore.Instance.InnerLog("Ошибка: лог " + entry + " почему-то попал во вкладку " + TabType); return; } // Don't add inner logs to ALL tab if (IsAllTab() && entry.Type == LogEntryTypes.CUSTOM && entry.CustomType == Log9KCore.INNER_LOG_TAB) { return; } // Adding new log entries if it is enabled, // Adding to duplications dictionary in any way if (IsAddingNewestEntries) { AddToCollectionAndToDuplicationsDictionary(entry); } else { AddToDuplicationsDictionary(entry); } // Writing to temp file only for ALL tab if (IsAllTab()) { WriteToTempFile(entry); } WriteToLogFile(entry); }
/// <summary> /// Deserialization /// </summary> /// <param name="entry"></param> /// <returns></returns> public static Log9KEntry FromByteArray(byte[] entry) { int i = 0; Buffer.BlockCopy(entry, i, _idBytes, 0, SIZE_ID); i += SIZE_ID; Buffer.BlockCopy(entry, i, _typeBytes, 0, SIZE_TYPE); i += SIZE_TYPE; LogEntryTypes type = (LogEntryTypes)_typeBytes[0]; Buffer.BlockCopy(entry, i, _levelBytes, 0, SIZE_LEVEL); i += SIZE_LEVEL; Buffer.BlockCopy(entry, i, _isDuplicateBytes, 0, SIZE_IS_DUPLICATE); i += SIZE_IS_DUPLICATE; Buffer.BlockCopy(entry, i, _unixTimeBytes, 0, SIZE_UNIX_TIME); i += SIZE_UNIX_TIME; Buffer.BlockCopy(entry, i, _millisecondsBytes, 0, SIZE_MILLISECONDS); i += SIZE_MILLISECONDS; if (type == LogEntryTypes.CUSTOM) { Buffer.BlockCopy(entry, i, _customTypeBytes, 0, SIZE_CUSTOM_TYPE); } i += SIZE_CUSTOM_TYPE; Buffer.BlockCopy(entry, i, _messageBytes, 0, SIZE_MESSAGE); uint id = BitConverter.ToUInt32(_idBytes, 0); Levels level = (Levels)_levelBytes[0]; bool isDuplicate = BitConverter.ToBoolean(_isDuplicateBytes, 0); uint unixTime = BitConverter.ToUInt32(_unixTimeBytes, 0); int milliseconds = BitConverter.ToInt32(_millisecondsBytes, 0); string message = Log9KUtil.GetString(_messageBytes); message = Log9KUtil.SplitStringWithNullEnding(message); string customType = Log9KUtil.GetString(_customTypeBytes); customType = Log9KUtil.SplitStringWithNullEnding(customType); Log9KEntry e = new Log9KEntry(type, message, new Log9KTime(unixTime, milliseconds)) { ID = id, CustomType = customType, IsDuplicate = isDuplicate, Level = level }; if (type == LogEntryTypes.CUSTOM) { e.TypeString = customType; } return(e); }
/// <summary> /// <para>Callback for event when log entry duplication occured.</para> /// <para>Adds new TreeViewItem to TreeView, if that duplication is new.</para> /// <para>Otherwise it refreshes number of occurs in TreeViewItem header /// (number in parenthesis).</para> /// </summary> /// <param name="e"></param> private void c_DuplicationEntryAdded(Log9KTab.DuplicationEntryAddedEventArgs e) { if (e.TabName == null || e.Message == null) { return; } if (!_tabItemDictionary.ContainsKey(e.TabName)) { return; } Util9K.InvokeInUiThread(() => { Log9KTab log9KTab = _log9KCore.Log9KTabsDictionary[e.TabName]; Log9KEntry log9KEntry = log9KTab.DuplicationsDictionary[e.DuplicationKey].Item1; ObservableCollection <Log9KTime> timesList = log9KTab.DuplicationsDictionary[e.DuplicationKey].Item2; TabItem tabItem = _tabItemDictionary[e.TabName]; try { Grid tabGrid = (Grid)tabItem.Content; TreeView treeView = (TreeView)tabGrid.Children[_treeViewIndex]; if (e.IsNewDuplication) { /* Adding new TreeViewItem */ StackPanel headerStackPanel = new StackPanel { Orientation = Orientation.Horizontal }; /* --- TYPE Message (number of duplications) --- */ /* Foreground color for TYPE */ Brush foreground = _typeToColorConverter.Convert(e.TabType); /* Type TextBlock */ string type; if (e.TabType == Log9KCore.LogEntryType.CUSTOM) { type = e.EntryCustomType; } else { type = e.TabType.ToString(); } headerStackPanel.Children.Add(new TextBlock { Text = type, Foreground = foreground, FontWeight = FontWeights.Bold }); /* Message TextBlock */ headerStackPanel.Children.Add(new TextBlock { Text = e.Message, Margin = new Thickness(5, 0, 0, 0) }); /* Number of duplications TextBlock */ headerStackPanel.Children.Add(new TextBlock { Text = "(2)", FontWeight = FontWeights.Bold, Margin = new Thickness(5, 0, 0, 0) }); TreeViewItem treeViewItem = new TreeViewItem { Header = headerStackPanel, ItemsSource = timesList }; treeView.Items.Add(treeViewItem); } else { /* Updating number of duplications in parenthesis */ foreach (TreeViewItem treeViewItem in treeView.Items) { StackPanel headerStackPanel = (StackPanel)treeViewItem.Header; TextBlock typeTextBlock = (TextBlock)headerStackPanel.Children[0]; TextBlock messageTextBlock = (TextBlock)headerStackPanel.Children[1]; if (messageTextBlock.Text.Equals(e.Message) && typeTextBlock.Text.Equals(log9KEntry.TypeString)) { TextBlock numberOfDuplicationTextBlock = (TextBlock)headerStackPanel.Children[2]; int numberOfDuplication = timesList.Count; numberOfDuplicationTextBlock.Text = "(" + numberOfDuplication + ")"; } } } } catch (InvalidCastException) { } }); }
/// <summary> /// Helper method for InnerLoggin /// </summary> /// <param name="e"></param> private void InnerLog(Log9KEntry e) { Log(e); }
/// <summary> /// Load one newer log entry from temp file /// </summary> /// <returns></returns> public override bool LoadNewerLogEntry() { if (IsAddingNewestEntries) { return(false); } Log9KEntry entry = null; bool success = false; uint tries = 0; while (!success) { if (tries > 100) { break; } byte[] entryBytes; if (!Log9KUtil.ReadFixedSizeByteArrayEntry(FilenameTempFile, Log9KEntry.ENTRY_SIZE, LineNumberBottomTempFile, out entryBytes)) { return(false); } entry = EntryFromBytes(entryBytes); uint lastLogEntryInCollectionID = LogEntryCollection[LogEntryCollection.Count - 1].ID; uint entryIDshoulBe = lastLogEntryInCollectionID + 1; if (entry.ID != entryIDshoulBe) { if (entry.ID < entryIDshoulBe) { LineNumberBottomTempFile++; } else if (entry.ID > entryIDshoulBe) { LineNumberBottomTempFile--; } } else { success = true; } tries++; } if (tries > 100) { uint lineNumber = LineNumberBottomTempFile; for (int i = 0; i < 200; i++) { lineNumber--; if (ReadNewerLogEntryAndCheckIt(out entry, lineNumber)) { LineNumberBottomTempFile = lineNumber; break; } } for (int i = 0; i < 200; i++) { lineNumber++; if (ReadNewerLogEntryAndCheckIt(out entry, lineNumber)) { LineNumberBottomTempFile = lineNumber; break; } } } if (entry != null) { CollectionAdd(entry); } return(true); }
/// <summary> /// Add log entry to ALL tab an tab with corresponding type /// </summary> /// <param name="entry"></param> private void AddLogEntryToTabs(Log9KEntry entry) { AddToAllTab(entry); AddToConcreteTypeTab(entry); }