예제 #1
0
        /// <summary>
        /// Add a "failed" log to the registry. This is often a log entry that could not be parsed fully by the log parser.
        /// </summary>
        /// <returns>A failed log entry. <see cref="ILogEntry.IsValid"/> will return <c>false</c> for these entries. Once a log is done being parsed, <see cref="NotifyFailedLogParsed(ILogEntry)"/> should be called.</returns>
        /// <remarks><see cref="LogRegistryExtensions.GetBy(ILogRegistry, LogAttribute)"/> might not return these entries. <see cref="LogRegistryExtensions.GetByTimetstamp"/> will only return these entries if the timestamp exists.</remarks>
        /// <seealso cref="LogParserFailureHandling"/>
        public ILogEntry AddFailedLog()
        {
            addFailedLogMeter.Mark();

            var entry = new FailedLogEntry();

            lock (logsBeingProcessed)
            {
                logsBeingProcessed.Add(entry);
                logsBeingProcessedCounter.Increment();
            }
            return(entry);
        }
예제 #2
0
 private void ProcessingComplete(FailedLogEntry failedLog)
 {
     lock (logsBeingProcessed)
     {
         var index = logsBeingProcessed.FindIndex(en => en.ID == failedLog.ID);
         if (index < 0)
         {
             throw new ArgumentException("Failed log does not exist in this registry", "entry"); // Argument name comes from NotifyFailedLogParsed
         }
         logsBeingProcessed.RemoveAt(index);
         logsBeingProcessedCounter.Decrement();
         failedLog.LogRegistryNotified();
         if (!failedLog.IsEmpty)
         {
             storage.AddLogSorted(failedLog);
         }
     }
 }
예제 #3
0
        /// <summary>
        /// Clone a log entry into this log registry.
        /// </summary>
        /// <param name="entry">The log entry to clone.</param>
        /// <returns>The cloned log entry.</returns>
        public ILogEntry CloneLog(ILogEntry entry)
        {
            if (entry == null)
            {
                return(null);
            }

            if (ContainsLog(entry))
            {
                return(entry);
            }
            var existingClone = FindClone(entry);

            if (existingClone != null)
            {
                return(existingClone);
            }

            var addToRegistry   = false;
            var addToProcessing = false;
            IInternalLogEntry cloneEntry;

            if (entry is LogEntry || (entry.IsValid && !(entry is FailedLogEntry)))
            {
                cloneEntry    = new LogEntry(entry.Timestamp, entry.Message);
                addToRegistry = true;
            }
            else
            {
                var failedCloneEntry = new FailedLogEntry();
                if (entry.HasAttribute(LogAttribute.Timestamp))
                {
                    failedCloneEntry.AddAttribute(LogAttribute.Timestamp, entry.GetAttribute <object>(LogAttribute.Timestamp));

                    if (entry is IInternalLogEntry entryInternal)
                    {
                        if (entryInternal.HasTimestampChanged)
                        {
                            // there's a timestamp, but it's still marked as changed. We get an exception if add gets invoked again, so it has only been added once and hasn't been notifed, which means it's still in processing
                            addToProcessing = true;
                        }
                        else
                        {
                            // there's a timestamp, but it hasn't been marked as changed. It means the timestamp change has been reset which only happens in notify
                            failedCloneEntry.ResetTimestampChanged();
                            addToRegistry = true;
                        }
                    }
                }
                else if (entry is FailedLogEntry failedLog)
                {
                    // Edge cases
                    // - no timestamp, not empty : it's not empty, but it lacks a timestamp. It may or may not have been processed
                    // - no timestamp, empty : empty doesn't mean it hasn't been processed (which means it's not in the process list) but also doesn't mean it has been processed (which means it can be discarded)

                    if (failedLog.IsRegistryNotified)
                    {
                        // It it has been processed, then it remains in processing unless it's empty.
                        failedCloneEntry.LogRegistryNotified();
                        if (!failedLog.IsEmpty)
                        {
                            addToProcessing = true;
                        }
                    }
                    else
                    {
                        // If it hasn't been processed, then add it to processing
                        addToProcessing = true;
                    }
                }

                if (entry.HasAttribute(LogAttribute.Message))
                {
                    failedCloneEntry.AddAttribute(LogAttribute.Message, entry.GetAttribute <object>(LogAttribute.Message));
                }

                cloneEntry = failedCloneEntry;
            }

            foreach (var attribute in Enum.GetValues(typeof(LogAttribute)).Cast <LogAttribute>())
            {
                if (attribute == LogAttribute.Timestamp || attribute == LogAttribute.Message)
                {
                    continue;
                }
                if (entry.HasAttribute(attribute))
                {
                    cloneEntry.AddAttribute(attribute, entry.GetAttribute <object>(attribute));
                }
            }

            if (addToRegistry)
            {
                storage.AddLogSorted(cloneEntry);
            }
            else if (addToProcessing)
            {
                lock (logsBeingProcessed)
                {
                    logsBeingProcessed.Add(cloneEntry);
                    logsBeingProcessedCounter.Increment();
                }
            }
            return(cloneEntry);
        }