public void Format( JsonMessageFormatterStyle style, LogMessageField fields, LogMessage message, string newline, string expected) { // test set knows that the newline character sequence is not relevant, if newline == null // => set it explicitly to satisfy the formatter if (newline == null) newline = "\n"; var formatter = new JsonMessageFormatter { Style = style, Newline = newline }; if (fields.HasFlag(LogMessageField.Timestamp)) formatter.AddTimestampField(); if (fields.HasFlag(LogMessageField.HighPrecisionTimestamp)) formatter.AddHighPrecisionTimestampField(); if (fields.HasFlag(LogMessageField.LogWriterName)) formatter.AddLogWriterField(); if (fields.HasFlag(LogMessageField.LogLevelName)) formatter.AddLogLevelField(); if (fields.HasFlag(LogMessageField.Tags)) formatter.AddTagsField(); if (fields.HasFlag(LogMessageField.ApplicationName)) formatter.AddApplicationNameField(); if (fields.HasFlag(LogMessageField.ProcessName)) formatter.AddProcessNameField(); if (fields.HasFlag(LogMessageField.ProcessId)) formatter.AddProcessIdField(); if (fields.HasFlag(LogMessageField.Text)) formatter.AddTextField(); Assert.Equal(fields, formatter.FormattedFields); string output = formatter.Format(message); Assert.Equal(expected, output); }
public void Format_EscapingKeys(JsonMessageFormatterStyle style, LogMessageField fields) { var message = new LogMessage(); var formatter = new JsonMessageFormatter { Style = style, Newline = "\n" }; if (fields.HasFlag(LogMessageField.Timestamp)) formatter.AddTimestampField("u", sUnescapedString); if (fields.HasFlag(LogMessageField.HighPrecisionTimestamp)) formatter.AddHighPrecisionTimestampField(sUnescapedString); if (fields.HasFlag(LogMessageField.LogWriterName)) formatter.AddLogWriterField(sUnescapedString); if (fields.HasFlag(LogMessageField.LogLevelName)) formatter.AddLogLevelField(sUnescapedString); if (fields.HasFlag(LogMessageField.Tags)) formatter.AddTagsField(sUnescapedString); if (fields.HasFlag(LogMessageField.ApplicationName)) formatter.AddApplicationNameField(sUnescapedString); if (fields.HasFlag(LogMessageField.ProcessName)) formatter.AddProcessNameField(sUnescapedString); if (fields.HasFlag(LogMessageField.ProcessId)) formatter.AddProcessIdField(sUnescapedString); if (fields.HasFlag(LogMessageField.Text)) formatter.AddTextField(sUnescapedString); Assert.Equal(fields, formatter.FormattedFields); // prepare regex to match output string pattern; switch (style) { case JsonMessageFormatterStyle.Compact: pattern = "^{\"(.+)\":.+}$"; break; case JsonMessageFormatterStyle.OneLine: pattern = "^{ \"(.+)\" : .+ }$"; break; case JsonMessageFormatterStyle.Beautified: default: pattern = "^{\n \"(.+)\" : .+\n}$"; break; } var regex = new Regex(pattern); // check whether the key has been escaped properly (without escaping the solidus) formatter.EscapeSolidus = false; string output1 = formatter.Format(message); var match1 = regex.Match(output1); Assert.True(match1.Success); Assert.Equal(sEscapedString_WithoutSolidus, match1.Groups[1].Value); // check whether the key has been escaped properly (with escaping the solidus) formatter.EscapeSolidus = true; string output2 = formatter.Format(message); var match2 = regex.Match(output2); Assert.True(match2.Success); Assert.Equal(sEscapedString_WithSolidus, match2.Groups[1].Value); }
public void Format(LogMessageField fields, LogMessage message, string expected) { var formatter = new TableMessageFormatter(); if (fields.HasFlag(LogMessageField.Timestamp)) formatter.AddTimestampColumn(); if (fields.HasFlag(LogMessageField.HighPrecisionTimestamp)) formatter.AddHighPrecisionTimestampColumn(); if (fields.HasFlag(LogMessageField.LogWriterName)) formatter.AddLogWriterColumn(); if (fields.HasFlag(LogMessageField.LogLevelName)) formatter.AddLogLevelColumn(); if (fields.HasFlag(LogMessageField.Tags)) formatter.AddTagsColumn(); if (fields.HasFlag(LogMessageField.ApplicationName)) formatter.AddApplicationNameColumn(); if (fields.HasFlag(LogMessageField.ProcessName)) formatter.AddProcessNameColumn(); if (fields.HasFlag(LogMessageField.ProcessId)) formatter.AddProcessIdColumn(); if (fields.HasFlag(LogMessageField.Text)) formatter.AddTextColumn(); Assert.Equal(fields, formatter.FormattedFields); string output = formatter.Format(message); Assert.Equal(expected, output); }
/// <summary> /// Creates a <see cref="FileBackedLogMessageCollection"/>, attaches a <see cref="SelectableFileBackedLogMessageFilter"/> /// to it and configures it for various test cases. /// </summary> /// <param name="isGloballyEnabled"> /// <c>true</c> to enable the filter globally (specific filters are in effect); /// <c>false</c> to disable the filter globally (all messages bypass specific filters). /// </param> /// <param name="enabledSpecificFilters">Enabled specific filters (flags).</param> /// <param name="matchingSpecificFilters">Specific filters that should be configured to match (flags).</param> /// <param name="matchBehavior">Determines how to select matching messages.</param> /// <param name="collection">Receives the created collection the filter works on.</param> /// <param name="filter">Receives the created filter.</param> /// <param name="unfilteredMessages">Receives messages that have been put into the collection.</param> /// <param name="filteredMessages">Receives messages that pass the filter.</param> private void CreateFilterAndReferencePredicate( bool isGloballyEnabled, LogMessageField enabledSpecificFilters, LogMessageField matchingSpecificFilters, MatchBehavior matchBehavior, out FileBackedLogMessageCollection collection, out SelectableFileBackedLogMessageFilter filter, out LogFileMessage[] unfilteredMessages, out LogFileMessage[] filteredMessages) { // create collection and attach a filter to it collection = CreateCollection(500, out var generatedMessages); unfilteredMessages = generatedMessages.Cast <LogFileMessage>().ToArray(); filter = new SelectableFileBackedLogMessageFilter { Enabled = isGloballyEnabled }; filter.AttachToCollection(collection); var firstMessage = unfilteredMessages[0]; var lastMessage = unfilteredMessages[unfilteredMessages.Length - 1]; // -------------------------------------------------------------------------------------------------------- // configure timestamp filter // -------------------------------------------------------------------------------------------------------- DateTimeOffset from, to; filter.TimestampFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.Timestamp); if (matchingSpecificFilters.HasFlag(LogMessageField.Timestamp)) { // filter should match if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // match starting at the first message from = to = collection[0].Timestamp; } else { // match starting at the second message from = to = collection[1].Timestamp; } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // match up to the last message to = collection[collection.Count - 1].Timestamp; } else if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // match up to the second last message to = collection[collection.Count - 2].Timestamp; } filter.TimestampFilter.From = from; filter.TimestampFilter.To = to; } else { // filter should not match // => choose interval from last message (+ margin) to 'infinity' from = collection[collection.Count - 1].Timestamp + TimeSpan.FromMilliseconds(1); to = DateTimeOffset.MaxValue; filter.TimestampFilter.From = from; filter.TimestampFilter.To = to; } // -------------------------------------------------------------------------------------------------------- // configure application name filter // -------------------------------------------------------------------------------------------------------- filter.ApplicationNameFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.ApplicationName); bool applicationNameSelected = matchingSpecificFilters.HasFlag(LogMessageField.ApplicationName); var selectedApplicationNames = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the application name matching the first message in the set var specificFilter = filter .ApplicationNameFilter .Items .First(x => x.Value == firstMessage.ApplicationName); specificFilter.Selected = applicationNameSelected; if (applicationNameSelected) { selectedApplicationNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the application name matching the last message in the set var specificFilter = filter .ApplicationNameFilter .Items .First(x => x.Value == lastMessage.ApplicationName); specificFilter.Selected = applicationNameSelected; if (applicationNameSelected) { selectedApplicationNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select an application name matching messages in between, but surely not the first or the last one var specificFilter = filter .ApplicationNameFilter .Items .First(x => x.Value != firstMessage.ApplicationName && x.Value != lastMessage.ApplicationName); specificFilter.Selected = applicationNameSelected; if (applicationNameSelected) { selectedApplicationNames.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure process name filter // -------------------------------------------------------------------------------------------------------- filter.ProcessNameFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.ProcessName); bool processNameSelected = matchingSpecificFilters.HasFlag(LogMessageField.ProcessName); var selectedProcessNames = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the process name matching the first message in the set var specificFilter = filter .ProcessNameFilter .Items .First(x => x.Value == firstMessage.ProcessName); specificFilter.Selected = processNameSelected; if (processNameSelected) { selectedProcessNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the process name matching the last message in the set var specificFilter = filter .ProcessNameFilter .Items .First(x => x.Value == lastMessage.ProcessName); specificFilter.Selected = processNameSelected; if (processNameSelected) { selectedProcessNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select a process name matching messages in between, but surely not the first or the last one var specificFilter = filter .ProcessNameFilter .Items .First(x => x.Value != firstMessage.ProcessName && x.Value != lastMessage.ProcessName); specificFilter.Selected = processNameSelected; if (processNameSelected) { selectedProcessNames.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure process id filter // -------------------------------------------------------------------------------------------------------- filter.ProcessIdFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.ProcessId); bool processIdSelected = matchingSpecificFilters.HasFlag(LogMessageField.ProcessId); var selectedProcessIds = new HashSet <int>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the process id matching the first message in the set var specificFilter = filter .ProcessIdFilter .Items .First(x => x.Value == firstMessage.ProcessId); specificFilter.Selected = processIdSelected; if (processIdSelected) { selectedProcessIds.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the process id matching the last message in the set var specificFilter = filter .ProcessIdFilter .Items .First(x => x.Value == lastMessage.ProcessId); specificFilter.Selected = processIdSelected; if (processIdSelected) { selectedProcessIds.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select a process id matching messages in between, but surely not the first or the last one var specificFilter = filter .ProcessIdFilter .Items .First(x => x.Value != firstMessage.ProcessId && x.Value != lastMessage.ProcessId); specificFilter.Selected = processIdSelected; if (processIdSelected) { selectedProcessIds.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure log level filter // -------------------------------------------------------------------------------------------------------- filter.LogLevelFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.LogLevelName); bool logLevelSelected = matchingSpecificFilters.HasFlag(LogMessageField.LogLevelName); var selectedLogLevelNames = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the log level matching the first message in the set var specificFilter = filter .LogLevelFilter .Items .First(x => x.Value == firstMessage.LogLevelName); specificFilter.Selected = logLevelSelected; if (logLevelSelected) { selectedLogLevelNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the log level matching the last message in the set var specificFilter = filter .LogLevelFilter .Items .First(x => x.Value == lastMessage.LogLevelName); specificFilter.Selected = logLevelSelected; if (logLevelSelected) { selectedLogLevelNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select a log level matching messages in between, but surely not the first or the last one var specificFilter = filter .LogLevelFilter .Items .First(x => x.Value != firstMessage.LogLevelName && x.Value != lastMessage.LogLevelName); specificFilter.Selected = logLevelSelected; if (logLevelSelected) { selectedLogLevelNames.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure log writer filter // -------------------------------------------------------------------------------------------------------- filter.LogWriterFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.LogWriterName); bool logWriterSelected = matchingSpecificFilters.HasFlag(LogMessageField.LogWriterName); var selectedLogWriterNames = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the log writer name matching the first message in the set var specificFilter = filter .LogWriterFilter .Items .First(x => x.Value == firstMessage.LogWriterName); specificFilter.Selected = logWriterSelected; if (logWriterSelected) { selectedLogWriterNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the log writer name matching the last message in the set var specificFilter = filter .LogWriterFilter .Items .First(x => x.Value == lastMessage.LogWriterName); specificFilter.Selected = logWriterSelected; if (logWriterSelected) { selectedLogWriterNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select a log writer matching messages in between, but surely not the first or the last one var specificFilter = filter .LogWriterFilter .Items .First(x => x.Value != firstMessage.LogWriterName && x.Value != lastMessage.LogWriterName); specificFilter.Selected = logWriterSelected; if (logWriterSelected) { selectedLogWriterNames.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure tag filter // -------------------------------------------------------------------------------------------------------- filter.TagFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.Tags); bool tagSelected = matchingSpecificFilters.HasFlag(LogMessageField.Tags); var selectedTags = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the tag matching the first message in the set var specificFilter = filter .TagFilter .Items .First(x => firstMessage.Tags.Contains(x.Value)); specificFilter.Selected = tagSelected; if (tagSelected) { selectedTags.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the tag matching the last message in the set // (may also match the first as multiple tags can be attached to a message) var specificFilter = filter .TagFilter .Items .First(x => lastMessage.Tags.Contains(x.Value)); specificFilter.Selected = tagSelected; if (tagSelected) { selectedTags.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select the tag matching messages in between, but surely not the first or the last one var specificFilter = filter .TagFilter .Items .First(x => !firstMessage.Tags.Contains(x.Value) && !lastMessage.Tags.Contains(x.Value)); specificFilter.Selected = tagSelected; if (tagSelected) { selectedTags.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure text filter // (filtering for the first/last message or in-between is very difficult...) // -------------------------------------------------------------------------------------------------------- string searchText = matchingSpecificFilters.HasFlag(LogMessageField.Text) ? "1/a" : "~~~"; filter.TextFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.Text); filter.TextFilter.IsCaseSensitive = true; filter.TextFilter.SearchText = searchText; const bool isFilterCaseSensitive = true; // -------------------------------------------------------------------------------------------------------- // create predicate matching messages // -------------------------------------------------------------------------------------------------------- bool Predicate(LogFileMessage message) { // bypass specific filters when the global filter switch is disabled if (!isGloballyEnabled) { return(true); } if (enabledSpecificFilters.HasFlag(LogMessageField.Timestamp)) { // the filter selects all messages except the first and the last message in the collection if (message.Timestamp < from || message.Timestamp > to) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.ApplicationName)) { if (!selectedApplicationNames.Contains(message.ApplicationName)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.ProcessName)) { if (!selectedProcessNames.Contains(message.ProcessName)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.ProcessId)) { if (!selectedProcessIds.Contains(message.ProcessId)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.LogLevelName)) { if (!selectedLogLevelNames.Contains(message.LogLevelName)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.LogWriterName)) { if (!selectedLogWriterNames.Contains(message.LogWriterName)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.Tags)) { if (!selectedTags.Any(x => message.Tags.Contains(x))) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.Text)) { if (CultureInfo.InvariantCulture.CompareInfo.IndexOf(message.Text, searchText, isFilterCaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase) < 0) { return(false); } } return(true); } filteredMessages = unfilteredMessages.Where(Predicate).ToArray(); }
public void Format_EscapingValues(JsonMessageFormatterStyle style, LogMessageField fields) { var formatter = new JsonMessageFormatter { Style = style, Newline = "\n" }; string key = ""; var message = new LogMessage(); if (fields.HasFlag(LogMessageField.LogWriterName)) { key = "LogWriter"; formatter.AddLogWriterField(key); message.LogWriterName = sUnescapedString; } if (fields.HasFlag(LogMessageField.LogLevelName)) { key = "LogLevel"; formatter.AddLogLevelField(key); message.LogLevelName = sUnescapedString; } if (fields.HasFlag(LogMessageField.ApplicationName)) { key = "ApplicationName"; formatter.AddApplicationNameField(key); message.ApplicationName = sUnescapedString; } if (fields.HasFlag(LogMessageField.ProcessName)) { key = "ProcessName"; formatter.AddProcessNameField(key); message.ProcessName = sUnescapedString; } if (fields.HasFlag(LogMessageField.Text)) { key = "Text"; formatter.AddTextField(key); message.Text = sUnescapedString; } Assert.Equal(fields, formatter.FormattedFields); // prepare regex to match output string pattern; switch (style) { case JsonMessageFormatterStyle.Compact: pattern = "^{\"(.+)\":\"(.+)\"}$"; break; case JsonMessageFormatterStyle.OneLine: pattern = "^{ \"(.+)\" : \"(.+)\" }$"; break; case JsonMessageFormatterStyle.Beautified: default: pattern = "^{\n \"(.+)\" : \"(.+)\"\n}$"; break; } var regex = new Regex(pattern); // check whether the key has been escaped properly (without escaping the solidus) formatter.EscapeSolidus = false; string output1 = formatter.Format(message); var match1 = regex.Match(output1); Assert.True(match1.Success); Assert.Equal(key, match1.Groups[1].Value); Assert.Equal(sEscapedString_WithoutSolidus, match1.Groups[2].Value); // check whether the key has been escaped properly (with escaping the solidus) formatter.EscapeSolidus = true; string output2 = formatter.Format(message); var match2 = regex.Match(output2); Assert.True(match2.Success); Assert.Equal(key, match2.Groups[1].Value); Assert.Equal(sEscapedString_WithSolidus, match2.Groups[2].Value); }