/// <summary> /// Writes log events to an <see cref="IRichTextBox"/> control, used only for unit-testing purposes. /// </summary> /// <param name="sinkConfiguration">Logger sink configuration.</param> /// <param name="richTextBox">The RichTextBox control to write to.</param> /// <param name="restrictedToMinimumLevel">The minimum level for /// events passed through the sink. Ignored when <paramref name="levelSwitch"/> is specified.</param> /// <param name="outputTemplate">A message template describing the format used to write to the sink. /// The default is <code>"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"</code>.</param> /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param> /// <param name="levelSwitch">A switch allowing the pass-through minimum level /// to be changed at runtime.</param> /// <param name="theme">The theme to apply to the styled output. If not specified, /// uses <see cref="RichTextBoxConsoleTheme.Literate"/>.</param> /// <param name="dispatcherPriority">The priority at which messages will be sent to the UI thread when logging from a non-UI thread.</param> /// <param name="syncRoot">An object that will be used to `lock` (sync) access to the <see cref="IRichTextBox"/> instance. If you specify this, you /// will have the ability to lock on this object, and guarantee that the RichTextBox sink will not be about to output anything while /// the lock is held.</param> /// <returns>Configuration object allowing method chaining.</returns> /// <exception cref="ArgumentNullException">When <paramref name="sinkConfiguration"/> is <code>null</code></exception> /// <exception cref="ArgumentNullException">When <paramref name="outputTemplate"/> is <code>null</code></exception> internal static LoggerConfiguration RichTextBox( this LoggerSinkConfiguration sinkConfiguration, IRichTextBox richTextBox, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, string outputTemplate = _defaultRichTextBoxOutputTemplate, IFormatProvider formatProvider = null, LoggingLevelSwitch levelSwitch = null, RichTextBoxTheme theme = null, DispatcherPriority dispatcherPriority = DispatcherPriority.Background, object syncRoot = null) { if (sinkConfiguration is null) { throw new ArgumentNullException(nameof(sinkConfiguration)); } if (outputTemplate is null) { throw new ArgumentNullException(nameof(outputTemplate)); } var appliedTheme = theme ?? RichTextBoxConsoleThemes.Literate; syncRoot ??= _defaultSyncRoot; var formatter = new XamlOutputTemplateRenderer(appliedTheme, outputTemplate, formatProvider); return(sinkConfiguration.Sink(new RichTextBoxSink(richTextBox, formatter, dispatcherPriority, syncRoot), restrictedToMinimumLevel, levelSwitch)); }
public void FormatProviderWithDestructuredProperties(string format, bool shouldUseCustomFormatter) { var frenchFormatProvider = new CultureInfo("fr-FR"); var defaultFormatProvider = CultureInfo.InvariantCulture; var date = new DateTime(2018, 01, 01); const double number = 12.345; var expectedFormattedDate = shouldUseCustomFormatter ? date.ToString(frenchFormatProvider) : date.ToString("O", defaultFormatProvider); var expectedFormattedNumber = shouldUseCustomFormatter ? number.ToString(frenchFormatProvider) : number.ToString(defaultFormatProvider); var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Message" + format + "}", frenchFormatProvider); var evt = DelegatingSink.GetLogEvent(l => { l.Information("{@Item}", new { MyDate = date, MyNumber = number, }); }); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Contains(expectedFormattedDate, sw.ToString()); Assert.Contains(expectedFormattedNumber, sw.ToString()); }
public void LowercaseFormatSpecifierIsSupportedForStrings() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Name:w}", CultureInfo.InvariantCulture); var evt = DelegatingSink.GetLogEvent(l => l.Information("{Name}", "Nick")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal("nick", sw.ToString()); }
public void MessageTemplatesContainingFormatStringPropertiesRenderCorrectly() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Message}", CultureInfo.InvariantCulture); var evt = DelegatingSink.GetLogEvent(l => l.Information("{Message}", "Hello, world!")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal("\"Hello, world!\"", sw.ToString()); }
public void AppliesJsonFormattingToPropertiesTokenWhenSpecified(string format, string expected) { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Properties" + format + "}", null); var evt = DelegatingSink.GetLogEvent(l => l.ForContext("Name", "World").Information("Hello")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal(expected, sw.ToString()); }
public void AppliesJsonFormattingToMessageStructuresWhenSpecified(string format, string expected) { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Message" + format + "}", null); var evt = DelegatingSink.GetLogEvent(l => l.Information("{@Obj}", new { Name = "World" })); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal(expected, sw.ToString()); }
public void DoNotDuplicatePropertiesAlreadyRenderedInOutputTemplate() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Foo} {Properties}", CultureInfo.InvariantCulture); var evt = DelegatingSink.GetLogEvent(l => l.ForContext("Foo", 42).ForContext("Bar", 42).Information("Hello from bar!")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal("42 {Bar=42}", sw.ToString()); }
public void NonMessagePositionalPropertiesAreRendered() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Properties}", CultureInfo.InvariantCulture); var evt = DelegatingSink.GetLogEvent(l => l.ForContext("Foo", 42).Information("Hello from {0}!", "bar")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal("{Foo=42}", sw.ToString()); }
public void AppliesCustomFormatterToEnums() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Message}", new SizeFormatter(CultureInfo.InvariantCulture)); var evt = DelegatingSink.GetLogEvent(l => l.Information("Size {Size}", Size.Large)); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal("Size Huge", sw.ToString()); }
public void AlignmentAndWidthCanBeCombined() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Level,5:w3}", CultureInfo.InvariantCulture); var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal(" inf", sw.ToString()); }
public void DefaultLevelLengthIsFullText() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Level}", CultureInfo.InvariantCulture); var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal("Information", sw.ToString()); }
public void FixedLengthLevelSupportsLowerCasing() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Level:w3}", CultureInfo.InvariantCulture); var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal("inf", sw.ToString()); }
public void UsesFormatProvider() { var french = new CultureInfo("fr-FR"); var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Message}", french); var evt = DelegatingSink.GetLogEvent(l => l.Information("{0}", 12.345)); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal("12,345", sw.ToString()); }
public void FixedLengthLevelIsSupported( LogEventLevel level, int width, string expected) { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, $"{{Level:t{width}}}", CultureInfo.InvariantCulture); var evt = DelegatingSink.GetLogEvent(l => l.Write(level, "Hello")); var sw = new StringWriter(); formatter.Format(evt, sw); Assert.Equal(expected, sw.ToString()); }
public void AnEmptyPropertiesTokenIsAnEmptyStructureValue() { var formatter = new XamlOutputTemplateRenderer(RichTextBoxTheme.None, "{Properties}", null); var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello")); var sw = new StringWriter(); formatter.Format(evt, sw); // /!\ different behavior from Serilog Core : https://github.com/serilog/serilog/blob/5c3a7821aa0f654e551dc21e8e19089f6767666b/test/Serilog.Tests/Formatting/Display/MessageTemplateTextFormatterTests.cs#L268-L278 // // var expected = new StructureValue(Enumerable.Empty<LogEventProperty>()).ToString(); // // expected == "{ }" // Assert.Equal(expected, sw.ToString()); // Assert.Equal("{}", sw.ToString()); }