public ObservableCollection <LogFileItem> ApplyColor(ObservableCollection <LogFileItem> logFileItems, List <FilterFileItem> filterFileItems, bool showAll = false) { DateTime timer = DateTime.Now; SetStatus(string.Format("ApplyColor:start time: {0}", timer.ToString("hh:mm:ss.fffffff"))); List <FilterFileItem> filterItems = VerifyFilterPatterns(filterFileItems); try { foreach (LogFileItem item in logFileItems) { if (item.FilterIndex < 0) { item.Background = Settings.BackgroundColor; item.Foreground = Settings.ForegroundColor; } else { FilterFileItem filterItem = filterItems.FirstOrDefault(x => x.Index == item.FilterIndex); item.Foreground = filterItem.Foreground; item.Background = filterItem.Background; } } SetStatus(string.Format("ApplyColor:total time in seconds: {0}", DateTime.Now.Subtract(timer).TotalSeconds)); if (showAll) { return(logFileItems); } else { return(new ObservableCollection <LogFileItem>(logFileItems.Where(x => x.FilterIndex > -2))); } } catch (Exception e) { SetStatus("ApplyColor:exception" + e.ToString()); return(new ObservableCollection <LogFileItem>()); } }
public ObservableCollection <LogFileItem> ApplyFilter(LogTabViewModel logTab, LogFile logFile, List <FilterFileItem> filterFileItems, FilterCommand filterCommand) { Mouse.OverrideCursor = Cursors.Wait; DateTime timer = DateTime.Now; SetStatus(string.Format("ApplyFilter:start time: {0} log file: {1} ", timer.ToString("hh:mm:ss.fffffff"), logFile.Tag)); List <FilterFileItem> filterItems = VerifyFilterPatterns(filterFileItems, logTab); Debug.Print(string.Format("ApplyFilter: filterItems.Count={0}:{1}", Thread.CurrentThread.ManagedThreadId, filterItems.Count)); // set regex cache size to number of filter items for better performance // https: //msdn.microsoft.com/en-us/library/gg578045(v=vs.110).aspx Regex.CacheSize = filterItems.Count; int inclusionFilterCount = filterItems.Count(x => x.Include == true); ParallelOptions po = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount // / 2 }; try { Parallel.ForEach(logFile.ContentItems, po, logItem => { if (string.IsNullOrEmpty(logItem.Content)) { Debug.Print(string.Format("ApplyFilter: logItem.Content empty={0}:{1}", Thread.CurrentThread.ManagedThreadId, logItem.Content)); // used for goto line as it needs all line items logItem.FilterIndex = int.MinValue; return; } int filterIndex = int.MaxValue; // int.MinValue; int includeFilters = inclusionFilterCount; if (Settings.CountMaskedMatches) { logItem.Masked = new int[filterItems.Count, 1]; } // clear out groups logItem.Group1 = string.Empty; logItem.Group2 = string.Empty; logItem.Group3 = string.Empty; logItem.Group4 = string.Empty; bool matchSet = false; for (int fItem = 0; fItem < filterItems.Count; fItem++) { int filterItemIndex = filterFileItems[fItem].Index; bool match = false; FilterFileItem filterItem = filterItems[fItem]; Debug.Print(string.Format("ApplyFilter: loop:{0} filterItem.Pattern={1}:{2} logItem.Content:{3}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterItem.Filterpattern, logItem.Content)); // unnamed and named groups //if (logTab.GroupCount > 0 && filterItem.Regex) if (filterItem.GroupCount > 0 && filterItem.Regex) { MatchCollection mc = Regex.Matches(logItem.Content, filterItem.Filterpattern, RegexOptions.Singleline | (filterItem.CaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase)); if (mc.Count > 0) { match = true; foreach (Match m in mc) { if (!string.IsNullOrEmpty(m.Groups[1].Value.ToString())) { logItem.Group1 += (string.IsNullOrEmpty(logItem.Group1) ? "" : ";\n") + m.Groups[1].Value.ToString(); } if (!string.IsNullOrEmpty(m.Groups[2].Value.ToString())) { logItem.Group2 += (string.IsNullOrEmpty(logItem.Group2) ? "" : ";\n") + m.Groups[2].Value.ToString(); } if (!string.IsNullOrEmpty(m.Groups[3].Value.ToString())) { logItem.Group3 += (string.IsNullOrEmpty(logItem.Group3) ? "" : ";\n") + m.Groups[3].Value.ToString(); } if (!string.IsNullOrEmpty(m.Groups[4].Value.ToString())) { logItem.Group4 += (string.IsNullOrEmpty(logItem.Group4) ? "" : ";\n") + m.Groups[4].Value.ToString(); } } } } else if (filterItem.Regex && Regex.IsMatch(logItem.Content, filterItem.Filterpattern, RegexOptions.Singleline | (filterItem.CaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase))) { match = true; } else if (!filterItem.Regex) { bool andMatch = true; if (filterItem.StringOperators) { Debug.Print(string.Format("ApplyFilter: loop:{0} string with operators " + "thread id:{1} filter index:{2} filter string: {3}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, filterItem.Filterpattern)); // check for ' AND ' and ' OR ' operators foreach (string andPattern in Regex.Split(filterItem.Filterpattern, " AND ")) { Debug.Print(string.Format("ApplyFilter: loop:{0} string andPattern " + "thread id:{1} filter index:{2} filter string: {3}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, andPattern)); match = false; string[] ors = Regex.Split(andPattern, " OR "); if (ors.Length > 1) { foreach (string orPattern in ors) { Debug.Print(string.Format("ApplyFilter: loop:{0} string orPattern " + "thread id:{1} filter index:{2} filter string: {3}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, orPattern)); // only match one if (filterItem.CaseSensitive && logItem.Content.Contains(orPattern)) { match = true; Debug.Print(string.Format("ApplyFilter: loop:{0} string orPattern match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, orPattern, logItem.Content)); break; } else if (logItem.Content.ToLower().Contains(orPattern.ToLower())) { match = true; Debug.Print(string.Format("ApplyFilter: loop:{0} string orPattern match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, orPattern, logItem.Content)); break; } else { Debug.Print(string.Format("ApplyFilter: loop:{0} string orPattern NO match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, orPattern, logItem.Content)); } } } else { // match all if (filterItem.CaseSensitive && logItem.Content.Contains(andPattern)) { match = true; Debug.Print(string.Format("ApplyFilter: loop:{0} string andPattern all match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, andPattern, logItem.Content)); } else if (logItem.Content.ToLower().Contains(andPattern.ToLower())) { match = true; Debug.Print(string.Format("ApplyFilter: loop:{0} string andPattern all match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, andPattern, logItem.Content)); } else { Debug.Print(string.Format("ApplyFilter: loop:{0} string andPattern all NO match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, andPattern, logItem.Content)); } } andMatch &= match; } match = andMatch; } else { // normal string match if (filterItem.CaseSensitive && logItem.Content.Contains(filterItem.Filterpattern)) { match = true; Debug.Print(string.Format("ApplyFilter: loop:{0} string andPattern one match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, filterItem.Filterpattern, logItem.Content)); } else if (logItem.Content.ToLower().Contains(filterItem.Filterpattern.ToLower())) { match = true; Debug.Print(string.Format("ApplyFilter: loop:{0} string andPattern one match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, filterItem.Filterpattern, logItem.Content)); } else { Debug.Print(string.Format("ApplyFilter: loop:{0} string andPattern one NO match " + "thread id:{1} filter index:{2} filter string: {3} logItem content: {4}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex, filterItem.Filterpattern, logItem.Content)); } } } Debug.Print(string.Format("ApplyFilter:** loop:{0} filterItem Match={1}:{2} **", filterItemIndex, Thread.CurrentThread.ManagedThreadId, match)); if (!matchSet) { if (match && filterItem.Include && !filterItem.Exclude) { filterIndex = filterItemIndex; Debug.Print(string.Format("ApplyFilter: loop:{0} filterItem.Include not exclude setting filterIndex={1}:{2}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex)); matchSet = true; includeFilters--; // break; } else if (!match && filterItem.Include && filterItem.Exclude) { // dynamic filter with and quickfindand but no match so exit filterIndex = int.MinValue; Debug.Print(string.Format("ApplyFilter: loop:{0} no match filterItem.Include and exclude setting filterIndex={1}:{2}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex)); matchSet = true; includeFilters = 0; // break; } else if (match && filterItem.Include && filterItem.Exclude) { // dynamic filter with and quickfindand but with match filterIndex = int.MinValue; Debug.Print(string.Format("ApplyFilter: loop:{0} match filterItem.Include and exlude setting filterIndex={1}:{2}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex)); matchSet = false; includeFilters = 0; // break; } else if (match && filterItem.Exclude) { filterIndex = (fItem * -1) - 2; Debug.Print(string.Format("ApplyFilter: loop:{0} filterItem.Exclude and match filterIndex={1}:{2}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex)); matchSet = true; // break; } else if (!match && !filterItem.Exclude) { filterIndex = int.MinValue; Debug.Print(string.Format("ApplyFilter: loop:{0} not filterItem.Exclude and not match filterIndex={1}:{2}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex)); } else if (match) { filterIndex = filterItemIndex; Debug.Print(string.Format("ApplyFilter: loop:{0} setting filterIndex={1}:{2}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterIndex)); matchSet = true; // break; } else if (filterItem.Include) { includeFilters--; } } else if (matchSet && match && Settings.CountMaskedMatches) { logItem.Masked[fItem, 0] = 1; Debug.Print(string.Format("ApplyFilter: loop:{0} masked match filterIndex={1}:{2}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, filterItemIndex)); } if (matchSet && !Settings.CountMaskedMatches) { Debug.Print(string.Format("ApplyFilter: loop:{0} not filterItem.Exclude CountMaskedMatches={1}:{2}", filterItemIndex, Thread.CurrentThread.ManagedThreadId, Settings.CountMaskedMatches)); if (includeFilters == 0) { break; } } } Debug.Print(string.Format("ApplyFilter: loop finished set filterIndex={0}:{1}", Thread.CurrentThread.ManagedThreadId, filterIndex)); logItem.FilterIndex = filterIndex; }); // write totals negative indexes arent displayed and are only used for counting int filterCount = 0; for (int i = 0; i < filterFileItems.Count; i++) { int filterItemIndex = filterFileItems[i].Index; filterFileItems[i].Count = logFile.ContentItems.Count(x => x.FilterIndex == filterItemIndex | x.FilterIndex == (i * -1) - 2); if (Settings.CountMaskedMatches) { filterFileItems[i].MaskedCount = logFile.ContentItems.Count(x => (x.FilterIndex != int.MaxValue) & (x.FilterIndex != int.MinValue) && x.Masked[i, 0] == 1); SetStatus(string.Format("ApplyFilter:filterItem masked counttotal: {0}", filterFileItems[i].MaskedCount)); } SetStatus(string.Format("ApplyFilter:filterItem counttotal: {0}", filterFileItems[i].Count)); filterCount += filterFileItems[i].Count; } double totalSeconds = DateTime.Now.Subtract(timer).TotalSeconds; SetStatus(string.Format("ApplyFilter:total time in seconds: {0}\n\tlines per second: {1} " + "\n\tlogfile total lines count: {2}\n\tlogfile filter lines count: {3}\n\tlog file: {4}" + "\n\tnumber of filters: {5}\n\tcalculated lines per second for single query: {6}", totalSeconds, logFile.ContentItems.Count / totalSeconds, logFile.ContentItems.Count, filterCount, logFile.Tag, filterItems.Count, logFile.ContentItems.Count / totalSeconds * filterItems.Count)); Mouse.OverrideCursor = null; return(new ObservableCollection <LogFileItem>(logFile.ContentItems.Where(x => x.FilterIndex > -2))); } catch (Exception e) { SetStatus("ApplyFilter:exception" + e.ToString()); Mouse.OverrideCursor = null; return(new ObservableCollection <LogFileItem>()); } }
private List <FilterFileItem> VerifyFilterPatterns(List <FilterFileItem> filterFileItems, LogTabViewModel logTab = null) { bool getGroups = false; int groupCount = 0; List <string> groupNames = new List <string>(); if (logTab != null) { getGroups = true; } List <FilterFileItem> filterItems = new List <FilterFileItem>(); foreach (FilterFileItem filterItem in filterFileItems) { if (string.IsNullOrEmpty(filterItem.Filterpattern)) { continue; } FilterFileItem newFilter = new FilterFileItem() { Background = filterItem.Background, Enabled = filterItem.Enabled, Exclude = filterItem.Exclude, Filterpattern = filterItem.Filterpattern, Foreground = filterItem.Foreground, Include = filterItem.Include, Regex = filterItem.Regex, Index = filterItem.Index }; if (newFilter.Regex) { try { Regex test = new Regex(filterItem.Filterpattern); if (getGroups) { // unnamed groups newFilter.GroupCount = test.GetGroupNumbers().Length - 1; groupCount = Math.Max(groupCount, newFilter.GroupCount); } } catch { SetStatus("not a regex:" + filterItem.Filterpattern); newFilter.Regex = false; newFilter.Filterpattern = Regex.Escape(filterItem.Filterpattern); } } else { // check for string operators and flag if (newFilter.Filterpattern.Contains(" AND ") | newFilter.Filterpattern.Contains(" OR ")) { newFilter.StringOperators = true; } } filterItems.Add(newFilter); } if (getGroups) { logTab.SetGroupCount(Math.Max(groupCount, groupNames.Count)); } return(filterItems); }