diff --git a/src/Serilog.Sinks.SystemConsole/ColoredConsoleLoggerConfigurationExtensions.cs b/src/Serilog.Sinks.SystemConsole/ColoredConsoleLoggerConfigurationExtensions.cs
new file mode 100644
index 000000000..a7c599e20
--- /dev/null
+++ b/src/Serilog.Sinks.SystemConsole/ColoredConsoleLoggerConfigurationExtensions.cs
@@ -0,0 +1,52 @@
+// Copyright 2013-2016 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using Serilog.Configuration;
+using Serilog.Core;
+using Serilog.Events;
+using Serilog.Sinks.SystemConsole;
+
+namespace Serilog
+{
+ public static class ColoredConsoleLoggerConfigurationExtensions
+ {
+ const string DefaultConsoleOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}";
+
+ ///
+ /// Writes log events to , using color to differentiate
+ /// between levels.
+ ///
+ /// Logger sink configuration.
+ /// The minimum level for
+ /// events passed through the sink. Ignored when is specified.
+ /// A switch allowing the pass-through minimum level
+ /// to be changed at runtime.
+ /// A message template describing the format used to write to the sink.
+ /// the default is "{Timestamp} [{Level}] {Message}{NewLine}{Exception}".
+ /// Supplies culture-specific formatting information, or null.
+ /// Configuration object allowing method chaining.
+ public static LoggerConfiguration ColoredConsole(
+ this LoggerSinkConfiguration sinkConfiguration,
+ LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
+ string outputTemplate = DefaultConsoleOutputTemplate,
+ IFormatProvider formatProvider = null,
+ LoggingLevelSwitch levelSwitch = null)
+ {
+ if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
+ if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate));
+ return sinkConfiguration.Sink(new ColoredConsoleSink(outputTemplate, formatProvider), restrictedToMinimumLevel, levelSwitch);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Serilog.Sinks.SystemConsole/Serilog.Sinks.SystemConsole.xproj b/src/Serilog.Sinks.SystemConsole/Serilog.Sinks.SystemConsole.xproj
new file mode 100644
index 000000000..93f396b17
--- /dev/null
+++ b/src/Serilog.Sinks.SystemConsole/Serilog.Sinks.SystemConsole.xproj
@@ -0,0 +1,18 @@
+
+
+
+ 14.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+ 50b24aca-d8f0-4268-a477-871b0a92a04a
+ Serilog
+ ..\..\artifacts\obj\$(MSBuildProjectName)
+ ..\..\artifacts\bin\$(MSBuildProjectName)\
+
+
+ 2.0
+
+
+
\ No newline at end of file
diff --git a/src/Serilog.Sinks.SystemConsole/Sinks/ColoredConsole/ColoredConsoleSink.cs b/src/Serilog.Sinks.SystemConsole/Sinks/ColoredConsole/ColoredConsoleSink.cs
new file mode 100644
index 000000000..c7d85189a
--- /dev/null
+++ b/src/Serilog.Sinks.SystemConsole/Sinks/ColoredConsole/ColoredConsoleSink.cs
@@ -0,0 +1,177 @@
+// Copyright 2013-2016 Serilog Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.IO;
+using Serilog.Core;
+using Serilog.Events;
+using System.Collections.Generic;
+using Serilog.Formatting.Display;
+using Serilog.Parsing;
+
+using IPropertyDictionary = System.Collections.Generic.IReadOnlyDictionary;
+
+namespace Serilog.Sinks.SystemConsole
+{
+ class ColoredConsoleSink : ILogEventSink
+ {
+ readonly IFormatProvider _formatProvider;
+
+ class Palette
+ {
+ public ConsoleColor Base { get; set; }
+ public ConsoleColor BaseText { get; set; }
+ public ConsoleColor Highlight { get; set; }
+ public ConsoleColor HighlightText { get; set; }
+ }
+
+ static readonly Palette DefaultPalette = new Palette
+ {
+ Base = ConsoleColor.Black,
+ BaseText = ConsoleColor.Gray,
+ Highlight = ConsoleColor.DarkGray,
+ HighlightText = ConsoleColor.Gray
+ };
+
+ static readonly IDictionary LevelPalettes = new Dictionary
+ {
+ { LogEventLevel.Verbose, new Palette { Base = ConsoleColor.Black, BaseText = ConsoleColor.DarkGray,
+ Highlight = ConsoleColor.Black, HighlightText = ConsoleColor.Gray } },
+ { LogEventLevel.Debug, new Palette { Base = ConsoleColor.Black, BaseText = ConsoleColor.Gray,
+ Highlight = ConsoleColor.Black, HighlightText = ConsoleColor.White } },
+ { LogEventLevel.Information, new Palette { Base = ConsoleColor.Black, BaseText = ConsoleColor.White,
+ Highlight = ConsoleColor.DarkBlue, HighlightText = ConsoleColor.White } },
+ { LogEventLevel.Warning, new Palette { Base = ConsoleColor.Black, BaseText = ConsoleColor.Yellow,
+ Highlight = ConsoleColor.DarkYellow, HighlightText = ConsoleColor.White } },
+ { LogEventLevel.Error, new Palette { Base = ConsoleColor.Black, BaseText = ConsoleColor.Red,
+ Highlight = ConsoleColor.Red, HighlightText = ConsoleColor.White } },
+ { LogEventLevel.Fatal, new Palette { Base = ConsoleColor.DarkRed, BaseText = ConsoleColor.White,
+ Highlight = ConsoleColor.Red, HighlightText = ConsoleColor.White } }
+ };
+
+ readonly object _syncRoot = new object();
+ readonly MessageTemplate _outputTemplate;
+
+ public ColoredConsoleSink(string outputTemplate, IFormatProvider formatProvider)
+ {
+ if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate));
+ _outputTemplate = new MessageTemplateParser().Parse(outputTemplate);
+ _formatProvider = formatProvider;
+ }
+
+ const string StackFrameLinePrefix = " ";
+
+ public void Emit(LogEvent logEvent)
+ {
+ if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
+
+ var outputProperties = OutputProperties.GetOutputProperties(logEvent);
+ var palette = GetPalette(logEvent.Level);
+ var output = Console.Out;
+
+ lock (_syncRoot)
+ {
+ try
+ {
+ foreach (var outputToken in _outputTemplate.Tokens)
+ {
+ var propertyToken = outputToken as PropertyToken;
+ if (propertyToken == null)
+ {
+ RenderOutputToken(palette, outputToken, outputProperties, output);
+ }
+ else switch (propertyToken.PropertyName)
+ {
+ case OutputProperties.MessagePropertyName:
+ RenderMessageToken(logEvent, palette, output);
+ break;
+ case OutputProperties.ExceptionPropertyName:
+ RenderExceptionToken(palette, propertyToken, outputProperties, output);
+ break;
+ default:
+ RenderOutputToken(palette, outputToken, outputProperties, output);
+ break;
+ }
+ }
+ }
+ finally { Console.ResetColor(); }
+ }
+ }
+
+ void RenderExceptionToken(Palette palette, MessageTemplateToken outputToken, IPropertyDictionary outputProperties, TextWriter output)
+ {
+ var sw = new StringWriter();
+ outputToken.Render(outputProperties, sw, _formatProvider);
+ var lines = new StringReader(sw.ToString());
+ string nextLine;
+ while ((nextLine = lines.ReadLine()) != null)
+ {
+ if (nextLine.StartsWith(StackFrameLinePrefix))
+ SetBaseColors(palette);
+ else
+ SetHighlightColors(palette);
+ output.WriteLine(nextLine);
+ }
+ }
+
+ void RenderMessageToken(LogEvent logEvent, Palette palette, TextWriter output)
+ {
+ foreach (var messageToken in logEvent.MessageTemplate.Tokens)
+ {
+ var messagePropertyToken = messageToken as PropertyToken;
+ if (messagePropertyToken != null)
+ {
+ SetHighlightColors(palette);
+ messageToken.Render(logEvent.Properties, output, _formatProvider);
+ }
+ else
+ {
+ SetBaseColors(palette);
+ messageToken.Render(logEvent.Properties, output, _formatProvider);
+ }
+ }
+ }
+
+ void RenderOutputToken(Palette palette, MessageTemplateToken outputToken, IPropertyDictionary outputProperties, TextWriter output)
+ {
+ SetBaseColors(palette);
+ outputToken.Render(outputProperties, output, _formatProvider);
+ }
+
+ static Palette GetPalette(LogEventLevel level)
+ {
+ Palette palette;
+ if (!LevelPalettes.TryGetValue(level, out palette))
+ palette = DefaultPalette;
+
+ return palette;
+ }
+
+ static void SetBaseColors(Palette palette)
+ {
+ SetColors(palette.Base, palette.BaseText);
+ }
+
+ static void SetHighlightColors(Palette palette)
+ {
+ SetColors(palette.Highlight, palette.HighlightText);
+ }
+
+ static void SetColors(ConsoleColor background, ConsoleColor foreground)
+ {
+ Console.BackgroundColor = background;
+ Console.ForegroundColor = foreground;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Serilog.Sinks.SystemConsole/project.json b/src/Serilog.Sinks.SystemConsole/project.json
new file mode 100644
index 000000000..1df5ab3e7
--- /dev/null
+++ b/src/Serilog.Sinks.SystemConsole/project.json
@@ -0,0 +1,24 @@
+{
+ "version": "2.0.0-beta-*",
+ "description": "The colored console sink for Serilog",
+ "authors": [ "Serilog Contributors" ],
+ "tags": [ "serilog", "console", "coloredconsole" ],
+ "projectUrl": "http://serilog.net",
+ "licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0",
+ "iconUrl": "http://serilog.net/images/serilog-sink-nuget.png",
+ "dependencies": {
+ "Serilog": { "target": "project" }
+ },
+ "compilationOptions": {
+ "keyFile": "../../assets/Serilog.snk"
+ },
+ "frameworks": {
+ "net45": {
+ },
+ "dotnet5.1": {
+ "dependencies": {
+ "System.Console": "4.0.0-beta-23516"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Serilog/LoggerConfigurationFullNetFxExtensions.cs b/src/Serilog/LoggerConfigurationFullNetFxExtensions.cs
index acb5a403d..0a521a095 100644
--- a/src/Serilog/LoggerConfigurationFullNetFxExtensions.cs
+++ b/src/Serilog/LoggerConfigurationFullNetFxExtensions.cs
@@ -44,32 +44,6 @@ public static class LoggerConfigurationFullNetFxExtensions
public const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}";
public const long DefaultFileSizeLimitBytes = 1L * 1024 * 1024 * 1024;
const string DefaultConsoleOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}";
-
- ///
- /// Writes log events to , using color to differentiate
- /// between levels.
- ///
- /// Logger sink configuration.
- /// The minimum level for
- /// events passed through the sink. Ignored when is specified.
- /// A switch allowing the pass-through minimum level
- /// to be changed at runtime.
- /// A message template describing the format used to write to the sink.
- /// the default is "{Timestamp} [{Level}] {Message}{NewLine}{Exception}".
- /// Supplies culture-specific formatting information, or null.
- /// Configuration object allowing method chaining.
- public static LoggerConfiguration ColoredConsole(
- this LoggerSinkConfiguration sinkConfiguration,
- LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
- string outputTemplate = DefaultConsoleOutputTemplate,
- IFormatProvider formatProvider = null,
- LoggingLevelSwitch levelSwitch = null)
- {
- if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
- if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate));
- return sinkConfiguration.Sink(new ColoredConsoleSink(outputTemplate, formatProvider), restrictedToMinimumLevel, levelSwitch);
- }
-
#if LOGCONTEXT
///