/// <summary> /// Copy constructor. /// </summary> /// <param name="source">The FieldLogItem instance to copy from.</param> protected FieldLogItem(FieldLogItem source) { Size = source.Size; EventCounter = source.EventCounter; Time = source.Time; Priority = source.Priority; SessionId = source.SessionId; ThreadId = source.ThreadId; WebRequestId = source.WebRequestId; LogItemSourceFileName = source.LogItemSourceFileName; FileFormatVersion = source.FileFormatVersion; }
public static FieldLogItemViewModel Create(FieldLogItem item) { FieldLogTextItem textItem = item as FieldLogTextItem; if (textItem != null) { return new FieldLogTextItemViewModel(textItem); } FieldLogDataItem dataItem = item as FieldLogDataItem; if (dataItem != null) { return new FieldLogDataItemViewModel(dataItem); } FieldLogExceptionItem exceptionItem = item as FieldLogExceptionItem; if (exceptionItem != null) { return new FieldLogExceptionItemViewModel(exceptionItem); } FieldLogScopeItem scopeItem = item as FieldLogScopeItem; if (scopeItem != null) { return new FieldLogScopeItemViewModel(scopeItem); } return null; }
/// <summary> /// Reads the next complete log item from the file. /// </summary> /// <returns>The next log item in the file.</returns> /// <remarks> /// This method will block until a complete log item is available in the file. /// </remarks> public FieldLogItem ReadLogItem() { byte[] bytes; FieldLogItemType type; int pos = -1, length; try { do { // Remember the log item start position in the file pos = (int)fileStream.Position; bool localWaitMode = WaitMode; if (!localWaitMode && pos == fileStream.Length) { return(null); } // Read the item type and length bytes = ReadBytes(4); if (bytes == null) { if (closeEvent.WaitOne(0)) { // Close was requested isClosing = true; WaitMode = false; return(null); } if (!WaitMode && localWaitMode) { // Follow-up file has been noticed return(null); } if (!localWaitMode) { throw new EndOfStreamException("Unexpected end of file."); } } // Parse type and length data type = (FieldLogItemType)((bytes[0] & 0xF0) >> 4); bytes[0] = (byte)(bytes[0] & 0x0F); if (BitConverter.IsLittleEndian) { Array.Reverse(bytes); } length = BitConverter.ToInt32(bytes, 0); // Check whether this is a text item if (type == FieldLogItemType.StringData) { // Read the item and add it to the text cache byte[] stringBytes = ReadBytes(length); // Parse the text data string str = Encoding.UTF8.GetString(stringBytes); // Add text to the cache textCache[pos] = str; } }while (type == FieldLogItemType.StringData); itemCount++; return(FieldLogItem.Read(this, type)); } catch (Exception ex) { throw new Exception( "Error reading from the log file \"" + FileName + "\" at position " + fileStream.Position + " (starting at " + pos + "). " + ex.Message, ex); } }
/// <summary> /// Reads the next log item from the log file group. If all files have been read until the /// end, this method blocks until a new log item was written to any file, or until the /// close event was set. /// </summary> /// <returns>The next log item, or null if there are no more log items and the waiting was cancelled.</returns> public FieldLogItem ReadLogItem() { while (true) { Task <bool>[] availableTasks; lock (readerLock) { availableTasks = readTasks .Where(t => t != null) .Concat(new Task <bool>[] { waitForNewFilePrioTask }) .Concat(new Task <bool>[] { closeTask }) .ToArray(); } Task.WaitAny(availableTasks); // We don't care about which task has finished. It may actually be multiple tasks. // We just test them all and use the result of all tasks that have finished. // Compare all completed readers' current value, find the smallest time and move // that enumerator one further. DateTime minTime = DateTime.MaxValue; FieldLogItem minTimeItem = null; FieldLogPriority minTimePrio = 0; foreach (var availableTask in availableTasks) { if (availableTask.IsCompleted) { // Search from the lowest priority up, as lower priorities appear more often for (int prioInt = 0; prioInt < readTasks.Length; prioInt++) { if (availableTask == readTasks[prioInt]) { // A reader enumerator task has finished, consider its result FieldLogPriority prio = (FieldLogPriority)prioInt; if (availableTask.Result) { // A new item of this priority is available. // Fetch the item from the reader. FieldLogItem item = readers[prio].Current; if (item.Time < minTime) { // The item's time is before any other item in this run, remember it minTime = item.Time; minTimeItem = item; minTimePrio = prio; } } else { // This priority's reader has finished, remove it. // Lock so that AddNewReader won't mess up if it finds a new file for this priority. lock (readerLock) { readers[prio].Dispose(); readers[prio] = null; readTasks[prioInt] = null; } } } } if (availableTask == waitForNewFilePrioTask) { // A file of a new priority was added and the WaitAny was interrupted, // to restart with the newly added reader added to the list of // available tasks. // Recreate the signal task and continue. waitForNewFilePrioTask = Task <bool> .Factory.StartNew(WaitForNewFilePrio); } if (availableTask == closeTask) { // The reader was requested to close. // Close all current enumerators, which then close all readers and // everything should tidy up itself... if (fsw != null) { fsw.EnableRaisingEvents = false; fsw.Dispose(); } foreach (var reader in readers.Values) { if (reader != null) { reader.Close(); } } return(null); } } } if (minTimeItem != null) { // We found an item. // Create new task for the next item of this priority var task = Task <bool> .Factory.StartNew(readers[minTimePrio].MoveNext); readTasks[(int)minTimePrio] = task; // Now return the next log item in time of all that are currently available return(minTimeItem); } // Restart this loop and wait for the next event } }