Skip to content

Commit ab897eb

Browse files
authored
Merge pull request #141 from sungam3r/audit
Add AuditTo support
2 parents 001fe1b + 7453ac2 commit ab897eb

File tree

5 files changed

+181
-2
lines changed

5 files changed

+181
-2
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright 2017 Serilog Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using Serilog.Configuration;
16+
using Serilog.Core;
17+
using Serilog.Events;
18+
using Serilog.Formatting;
19+
using Serilog.Sinks.SystemConsole;
20+
using Serilog.Sinks.SystemConsole.Output;
21+
using Serilog.Sinks.SystemConsole.Themes;
22+
using System;
23+
24+
namespace Serilog
25+
{
26+
/// <summary>
27+
/// Adds the AuditTo.Console() extension method to <see cref="LoggerAuditSinkConfiguration"/>.
28+
/// </summary>
29+
public static class ConsoleAuditLoggerConfigurationExtensions
30+
{
31+
/// <summary>
32+
/// Writes log events to <see cref="System.Console"/>.
33+
/// </summary>
34+
/// <param name="sinkConfiguration">Logger sink configuration.</param>
35+
/// <param name="restrictedToMinimumLevel">The minimum level for
36+
/// events passed through the sink. Ignored when <paramref name="levelSwitch"/> is specified.</param>
37+
/// <param name="outputTemplate">A message template describing the format used to write to the sink.
38+
/// The default is <code>"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"</code>.</param>
39+
/// <param name="syncRoot">An object that will be used to `lock` (sync) access to the console output. If you specify this, you
40+
/// will have the ability to lock on this object, and guarantee that the console sink will not be about to output anything while
41+
/// the lock is held.</param>
42+
/// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
43+
/// <param name="levelSwitch">A switch allowing the pass-through minimum level
44+
/// to be changed at runtime.</param>
45+
/// <param name="standardErrorFromLevel">Specifies the level at which events will be written to standard error.</param>
46+
/// <param name="theme">The theme to apply to the styled output. If not specified,
47+
/// uses <see cref="SystemConsoleTheme.Literate"/>.</param>
48+
/// <param name="applyThemeToRedirectedOutput">Applies the selected or default theme even when output redirection is detected.</param>
49+
/// <returns>Configuration object allowing method chaining.</returns>
50+
/// <exception cref="ArgumentNullException">When <paramref name="sinkConfiguration"/> is <code>null</code></exception>
51+
/// <exception cref="ArgumentNullException">When <paramref name="outputTemplate"/> is <code>null</code></exception>
52+
public static LoggerConfiguration Console(
53+
this LoggerAuditSinkConfiguration sinkConfiguration,
54+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
55+
string outputTemplate = ConsoleLoggerConfigurationExtensions.DefaultConsoleOutputTemplate,
56+
IFormatProvider? formatProvider = null,
57+
LoggingLevelSwitch? levelSwitch = null,
58+
LogEventLevel? standardErrorFromLevel = null,
59+
ConsoleTheme? theme = null,
60+
bool applyThemeToRedirectedOutput = false,
61+
object? syncRoot = null)
62+
{
63+
if (sinkConfiguration is null) throw new ArgumentNullException(nameof(sinkConfiguration));
64+
if (outputTemplate is null) throw new ArgumentNullException(nameof(outputTemplate));
65+
66+
var appliedTheme = !applyThemeToRedirectedOutput && (System.Console.IsOutputRedirected || System.Console.IsErrorRedirected) ?
67+
ConsoleTheme.None :
68+
theme ?? SystemConsoleThemes.Literate;
69+
70+
syncRoot ??= ConsoleLoggerConfigurationExtensions.DefaultSyncRoot;
71+
72+
var formatter = new OutputTemplateRenderer(appliedTheme, outputTemplate, formatProvider);
73+
return sinkConfiguration.Sink(new ConsoleSink(appliedTheme, formatter, standardErrorFromLevel, syncRoot), restrictedToMinimumLevel, levelSwitch);
74+
}
75+
76+
/// <summary>
77+
/// Writes log events to <see cref="System.Console"/>.
78+
/// </summary>
79+
/// <param name="sinkConfiguration">Logger sink configuration.</param>
80+
/// <param name="formatter">Controls the rendering of log events into text, for example to log JSON. To
81+
/// control plain text formatting, use the overload that accepts an output template.</param>
82+
/// <param name="syncRoot">An object that will be used to `lock` (sync) access to the console output. If you specify this, you
83+
/// will have the ability to lock on this object, and guarantee that the console sink will not be about to output anything while
84+
/// the lock is held.</param>
85+
/// <param name="restrictedToMinimumLevel">The minimum level for
86+
/// events passed through the sink. Ignored when <paramref name="levelSwitch"/> is specified.</param>
87+
/// <param name="levelSwitch">A switch allowing the pass-through minimum level
88+
/// to be changed at runtime.</param>
89+
/// <param name="standardErrorFromLevel">Specifies the level at which events will be written to standard error.</param>
90+
/// <returns>Configuration object allowing method chaining.</returns>
91+
/// <exception cref="ArgumentNullException">When <paramref name="sinkConfiguration"/> is <code>null</code></exception>
92+
/// <exception cref="ArgumentNullException">When <paramref name="formatter"/> is <code>null</code></exception>
93+
public static LoggerConfiguration Console(
94+
this LoggerAuditSinkConfiguration sinkConfiguration,
95+
ITextFormatter formatter,
96+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
97+
LoggingLevelSwitch? levelSwitch = null,
98+
LogEventLevel? standardErrorFromLevel = null,
99+
object? syncRoot = null)
100+
{
101+
if (sinkConfiguration is null) throw new ArgumentNullException(nameof(sinkConfiguration));
102+
if (formatter is null) throw new ArgumentNullException(nameof(formatter));
103+
104+
syncRoot ??= ConsoleLoggerConfigurationExtensions.DefaultSyncRoot;
105+
106+
return sinkConfiguration.Sink(new ConsoleSink(ConsoleTheme.None, formatter, standardErrorFromLevel, syncRoot), restrictedToMinimumLevel, levelSwitch);
107+
}
108+
}
109+
}

src/Serilog.Sinks.Console/ConsoleLoggerConfigurationExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ namespace Serilog
2828
/// </summary>
2929
public static class ConsoleLoggerConfigurationExtensions
3030
{
31-
static readonly object DefaultSyncRoot = new object();
32-
const string DefaultConsoleOutputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}";
31+
internal static readonly object DefaultSyncRoot = new object();
32+
internal const string DefaultConsoleOutputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}";
3333

3434
/// <summary>
3535
/// Writes log events to <see cref="System.Console"/>.

test/Serilog.Sinks.Console.Tests/Approval/Serilog.Sinks.Console.approved.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
namespace Serilog
22
{
3+
public static class ConsoleAuditLoggerConfigurationExtensions
4+
{
5+
public static Serilog.LoggerConfiguration Console(this Serilog.Configuration.LoggerAuditSinkConfiguration sinkConfiguration, Serilog.Formatting.ITextFormatter formatter, Serilog.Events.LogEventLevel restrictedToMinimumLevel = 0, Serilog.Core.LoggingLevelSwitch? levelSwitch = null, Serilog.Events.LogEventLevel? standardErrorFromLevel = default, object? syncRoot = null) { }
6+
public static Serilog.LoggerConfiguration Console(this Serilog.Configuration.LoggerAuditSinkConfiguration sinkConfiguration, Serilog.Events.LogEventLevel restrictedToMinimumLevel = 0, string outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", System.IFormatProvider? formatProvider = null, Serilog.Core.LoggingLevelSwitch? levelSwitch = null, Serilog.Events.LogEventLevel? standardErrorFromLevel = default, Serilog.Sinks.SystemConsole.Themes.ConsoleTheme? theme = null, bool applyThemeToRedirectedOutput = false, object? syncRoot = null) { }
7+
}
38
public static class ConsoleLoggerConfigurationExtensions
49
{
510
public static Serilog.LoggerConfiguration Console(this Serilog.Configuration.LoggerSinkConfiguration sinkConfiguration, Serilog.Formatting.ITextFormatter formatter, Serilog.Events.LogEventLevel restrictedToMinimumLevel = 0, Serilog.Core.LoggingLevelSwitch? levelSwitch = null, Serilog.Events.LogEventLevel? standardErrorFromLevel = default, object? syncRoot = null) { }
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using Xunit;
5+
using Serilog.Sinks.SystemConsole.Themes;
6+
7+
namespace Serilog.Sinks.Console.Tests.Configuration
8+
{
9+
[Collection("ConsoleSequentialTests")]
10+
public class ConsoleAuditLoggerConfigurationExtensionsTests
11+
{
12+
[Fact]
13+
public void OutputFormattingIsIgnored()
14+
{
15+
using (var stream = new MemoryStream())
16+
{
17+
var sw = new StreamWriter(stream);
18+
19+
System.Console.SetOut(sw);
20+
var config = new LoggerConfiguration()
21+
.AuditTo.Console(theme: AnsiConsoleTheme.Literate,
22+
applyThemeToRedirectedOutput: false);
23+
24+
var logger = config.CreateLogger();
25+
26+
logger.Error("test");
27+
stream.Position = 0;
28+
29+
using (var streamReader = new StreamReader(stream))
30+
{
31+
var result = streamReader.ReadToEnd();
32+
var controlCharacterCount = result.Count(c => Char.IsControl(c) && !Char.IsWhiteSpace(c));
33+
Assert.Equal(0, controlCharacterCount);
34+
}
35+
}
36+
}
37+
38+
[Fact]
39+
public void OutputFormattingIsPresent()
40+
{
41+
using (var stream = new MemoryStream())
42+
{
43+
var sw = new StreamWriter(stream);
44+
45+
System.Console.SetOut(sw);
46+
var config = new LoggerConfiguration()
47+
.AuditTo.Console(theme: AnsiConsoleTheme.Literate,
48+
applyThemeToRedirectedOutput: true);
49+
50+
var logger = config.CreateLogger();
51+
52+
logger.Error("test");
53+
stream.Position = 0;
54+
55+
using (var streamReader = new StreamReader(stream))
56+
{
57+
var result = streamReader.ReadToEnd();
58+
var controlCharacterCount = result.Count(c => Char.IsControl(c) && !Char.IsWhiteSpace(c));
59+
Assert.NotEqual(0, controlCharacterCount);
60+
}
61+
}
62+
}
63+
}
64+
}

test/Serilog.Sinks.Console.Tests/Configuration/ConsoleLoggerConfigurationExtensionsTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Serilog.Sinks.Console.Tests.Configuration
88
{
9+
[Collection("ConsoleSequentialTests")]
910
public class ConsoleLoggerConfigurationExtensionsTests
1011
{
1112
[Fact]

0 commit comments

Comments
 (0)