@@ -869,6 +869,192 @@ The following example shows how to register filter rules in code:
869
869
* Log level ` Information ` and higher.
870
870
* All categories starting with ` "Microsoft" ` .
871
871
872
+ ## Create a custom logger
873
+
874
+ To add a custom logger to your application you need to add an own ` ILoggerProvider ` to the ` ILoggerFactory ` , that can be injected into the method ` Configure ` in the ` Startup.cs ` :
875
+
876
+ ``` csharp
877
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
878
+ public void Configure (
879
+ IApplicationBuilder app ,
880
+ IWebHostEnvironment env ,
881
+ ILoggerFactory loggerFactory )
882
+ {
883
+ loggerFactory .AddProvider (new CustomLoggerProvider (new CustomLoggerConfiguration ()));
884
+ ```
885
+
886
+ The `ILoggerProvider ` creates one or more `ILogger ` which are used by the framework to log the information .
887
+
888
+ ### The custom logger configuration
889
+
890
+ The idea is , to create different colored console entries per log level and event ID . To configure this we need a configuration type like this :
891
+
892
+ ~~~ csharp
893
+ public class ColoredConsoleLoggerConfiguration
894
+ {
895
+ public LogLevel LogLevel { get ; set ; } = LogLevel .Warning ;
896
+ public int EventId { get ; set ; } = 0 ;
897
+ public ConsoleColor Color { get ; set ; } = ConsoleColor .Yellow ;
898
+ }
899
+ ~~~
900
+
901
+ This sets the default level to `Warning ` and the color to `Yellow `. If the `EventId ` is set to 0, we will log all events .
902
+
903
+ ### Creating the custom logger
904
+
905
+ The actual logger is an `ILogger ` implementation gets a name and the configuration passed in via the constructor . The name is the category name , which usually is the logging source , eg . the type where the logger is created in :
906
+
907
+ ~~~ csharp
908
+ public class ColoredConsoleLogger : ILogger
909
+ {
910
+ private readonly string _name ;
911
+ private readonly ColoredConsoleLoggerConfiguration _config ;
912
+
913
+ public ColoredConsoleLogger (string name , ColoredConsoleLoggerConfiguration config )
914
+ {
915
+ _name = name ;
916
+ _config = config ;
917
+ }
918
+
919
+ public IDisposable BeginScope <TState >(TState state )
920
+ {
921
+ return null ;
922
+ }
923
+
924
+ public bool IsEnabled (LogLevel logLevel )
925
+ {
926
+ return logLevel == _config .LogLevel ;
927
+ }
928
+
929
+ public void Log <TState >(LogLevel logLevel , EventId eventId , TState state , Exception exception , Func < TState , Exception , string > formatter )
930
+ {
931
+ if (! IsEnabled (logLevel ))
932
+ {
933
+ return ;
934
+ }
935
+
936
+ if (_config .EventId == 0 || _config .EventId == eventId .Id )
937
+ {
938
+ var color = Console .ForegroundColor ;
939
+ Console .ForegroundColor = _config .Color ;
940
+ Console .WriteLine ($" {logLevel .ToString ()} - {eventId .Id } - {_name } - {formatter (state , exception )}" );
941
+ Console .ForegroundColor = color ;
942
+ }
943
+ }
944
+ }
945
+ ~~~
946
+
947
+ This creates a logger instance per category name with the `ILoggerProvider `, that needs to be created in the next step .
948
+
949
+ ### creating the custom LoggerProvider
950
+
951
+ The `LoggerProvider ` is the class that creates the logger instances . Maybe it is not needed to create a logger instance per category , but this makes sense for some Loggers , like NLog or log4net . Doing this you are also able to choose different logging output targets per category if needed :
952
+
953
+ ~~~ csharp
954
+ public class ColoredConsoleLoggerProvider : ILoggerProvider
955
+ {
956
+ private readonly ColoredConsoleLoggerConfiguration _config ;
957
+ private readonly ConcurrentDictionary < string , ColoredConsoleLogger > _loggers = new ConcurrentDictionary <string , ColoredConsoleLogger >();
958
+
959
+ public ColoredConsoleLoggerProvider (ColoredConsoleLoggerConfiguration config )
960
+ {
961
+ _config = config ;
962
+ }
963
+
964
+ public ILogger CreateLogger (string categoryName )
965
+ {
966
+ return _loggers .GetOrAdd (categoryName , name => new ColoredConsoleLogger (name , _config ));
967
+ }
968
+
969
+ public void Dispose ()
970
+ {
971
+ _loggers .Clear ();
972
+ }
973
+ }
974
+ ~~~
975
+
976
+ There 's no magic here. The method `CreateLogger` creates a single instance of the `ColoredConsoleLogger` per category name and stores it in the `ConcurrentDictionary`.
977
+
978
+ ### Usage and registration of the custom logger
979
+
980
+ Now you are able to register the logger in the `Startup .cs `:
981
+
982
+ ~~~ csharp
983
+ public void Configure (
984
+ IApplicationBuilder app ,
985
+ IHostingEnvironment env ,
986
+ ILoggerFactory loggerFactory )
987
+ {
988
+ // here is our CustomLogger
989
+ loggerFactory .AddProvider (new ColoredConsoleLoggerProvider (new ColoredConsoleLoggerConfiguration
990
+ {
991
+ LogLevel = LogLevel .Information ,
992
+ Color = ConsoleColor .Blue
993
+ }));
994
+ loggerFactory .AddProvider (new ColoredConsoleLoggerProvider (new ColoredConsoleLoggerConfiguration
995
+ {
996
+ LogLevel = LogLevel .Debug ,
997
+ Color = ConsoleColor .Gray
998
+ }));
999
+ ~~~
1000
+
1001
+ The loggers will automatically be used , if a log entry is crated .
1002
+
1003
+ But those registrations don 't really look nice . You are able to encapsulate the registrations to provide an API like this :
1004
+
1005
+ ```csharp
1006
+ // using the custom registration with default values:
1007
+ loggerFactory .AddColoredConsoleLogger ();
1008
+
1009
+ // using the custom registration with a new configuration instance:
1010
+ loggerFactory .AddColoredConsoleLogger (new ColoredConsoleLoggerConfiguration
1011
+ {
1012
+ LogLevel = LogLevel .Debug ,
1013
+ Color = ConsoleColor .Gray
1014
+ });
1015
+
1016
+ // using the custom registration with a configuration object:
1017
+ loggerFactory .AddColoredConsoleLogger (c =>
1018
+ {
1019
+ c .LogLevel = LogLevel .Information ;
1020
+ c .Color = ConsoleColor .Blue ;
1021
+ });
1022
+ ```
1023
+
1024
+ This means you need to write at least one extension method for the `ILoggerFactory `:
1025
+
1026
+ ~~~ csharp
1027
+ public static class ColoredConsoleLoggerExtensions
1028
+ {
1029
+ // custom registration with a configuration instance
1030
+ public static ILoggerFactory AddColoredConsoleLogger (
1031
+ this ILoggerFactory loggerFactory ,
1032
+ ColoredConsoleLoggerConfiguration config )
1033
+ {
1034
+ loggerFactory .AddProvider (new ColoredConsoleLoggerProvider (config ));
1035
+ return loggerFactory ;
1036
+ }
1037
+ // custom registration with default values
1038
+ public static ILoggerFactory AddColoredConsoleLogger (
1039
+ this ILoggerFactory loggerFactory )
1040
+ {
1041
+ var config = new ColoredConsoleLoggerConfiguration ();
1042
+ return loggerFactory .AddColoredConsoleLogger (config );
1043
+ }
1044
+ // custom registration with a configuration object
1045
+ public static ILoggerFactory AddColoredConsoleLogger (
1046
+ this ILoggerFactory loggerFactory ,
1047
+ Action < ColoredConsoleLoggerConfiguration > configure )
1048
+ {
1049
+ var config = new ColoredConsoleLoggerConfiguration ();
1050
+ configure (config );
1051
+ return loggerFactory .AddColoredConsoleLogger (config );
1052
+ }
1053
+ }
1054
+ ~~~
1055
+
1056
+
1057
+
872
1058
## Additional resources
873
1059
874
1060
* < xref : fundamentals / logging / loggermessage >
0 commit comments