You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+236Lines changed: 236 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,3 +18,239 @@ Add the NuGet package to your project:
18
18
Though .NET supports implementing custom logger providers, it's fairly limited in what tools it provides to work with log information.
19
19
20
20
In particular, it's often desireable to define the _format_ of log entries independently of their target/destination. Using generics, log formatting enables you to represent individual log entries using any mutable reference type - even one contained in a third party library.
21
+
22
+
### Configuring the log format
23
+
24
+
Consider this (bucolic, somewhat overwrought) example:
using (logger.BeginScope("Tending the {Animal}", animal))
32
+
{
33
+
if (animal=="cows")
34
+
{
35
+
logger.LogInformation(FarmLog.Milking, "{MilkBuckets} buckets of milk", 3);
36
+
}
37
+
38
+
logger.LogInformation(FarmLog.Feeding, "Fat and happy", animal);
39
+
}
40
+
}
41
+
42
+
logger.LogWarning(FarmLog.CheckSupply, "Running low on {Supply}", "chicken feed");
43
+
logger.LogError(newTractorIsBrokenException("carburetor"), "Could not start tractor");
44
+
```
45
+
46
+
Enable formatted logging using the typed overload of [`IServiceCollection.AddLogging(...)`](/Logging.Formatting/FormattingServiceCollectionExtensions.cs). Specify the format using the methods of [`LoggingFormatBuilder<TFormat>`](/Logging.Formatting/Formatting/LoggingFormatBuilder.cs).
47
+
48
+
```c#
49
+
services.AddLogging(
50
+
() =>newFarmLog(),
51
+
builder=>
52
+
{
53
+
builder.OnMessage((x, y) =>x.Notes.Add(y));
54
+
55
+
builder.OnEntry(
56
+
(log, cat, lvl, id) =>
57
+
{
58
+
if (id==FarmLog.CheckSupply)
59
+
{
60
+
log.Location="Barn";
61
+
62
+
if (lvl==LogLevel.Warning)
63
+
{
64
+
log.Notes.Add("Need to go to the store");
65
+
}
66
+
}
67
+
});
68
+
69
+
// Properties are category scoped to prevent name collisions.
70
+
builder.OnProperty<Program>(
71
+
"Animal",
72
+
(log, obj) =>
73
+
{
74
+
log.Animal= (string)obj;
75
+
76
+
switch (obj)
77
+
{
78
+
case"cows":
79
+
log.Location="Field";
80
+
break;
81
+
82
+
case"pigs":
83
+
case"chickens":
84
+
log.Location="Barn";
85
+
break;
86
+
}
87
+
});
88
+
89
+
builder.OnException<TractorIsBrokenException>(
90
+
(log, ex) =>
91
+
{
92
+
log.Location="Garage";
93
+
log.Notes.Add($"Need to fix the {ex.PartName}");
94
+
});
95
+
96
+
// Configure logging providers...
97
+
});
98
+
```
99
+
100
+
For even greater control over log format, implement one or more custom log formatters.
101
+
102
+
```c#
103
+
classWeatherFormatter : ILogFormatter<FarmLog>
104
+
{
105
+
readonlyWeatherGaugegauge;
106
+
107
+
publicWeatherFormatter(WeatherGaugegauge)
108
+
{
109
+
this.gauge=gauge;
110
+
}
111
+
112
+
// Scope formatting is optional.
113
+
// Implementing a stack formatter involves both capturing state and enriching logs.
114
+
publicILogStackFormatter<FarmLog> Scopes=>null;
115
+
116
+
// Filter by category if you want to target only certain loggers (avoids some formatting overhead).
117
+
publicboolIsEnabled(stringcategory)
118
+
{
119
+
returntrue;
120
+
}
121
+
122
+
// Use state and/or the raw entry data to modify the typed entry.
entry.Weather=heat!=null&&rainy!=null?$"{heat} and {rainy}":heat??rainy;
134
+
}
135
+
}
136
+
```
137
+
138
+
The logging format builder provides a fluent API for the underlying [`LogFormatOptions<TFormat>`](/Logging.Formatting/Formatting/LogFormatOptions.cs), which can be also be configured directly.
139
+
140
+
```c#
141
+
// Use service container to resolve formatter dependencies.
You can configure this library to persist formatted entries to the file system. [`LogSerializeOptions<TFormat>`](/Logging.Formatting/Serialization/LogSerializeOptions.cs) and [`FileLoggingOptions`](/Logging.Formatting/Serialization/FileLoggingOptions.cs) provide some control over this behavior.
150
+
151
+
```c#
152
+
builder.Serialize(x=>x.AsJson()).ToFile();
153
+
```
154
+
155
+
This generates output from the above example as follows:
156
+
157
+
```json
158
+
{"HourOfDay":12,"Location":"Field","Animal":"cows","Weather":"cold and rainy","Notes":["3 buckets of milk"]}
159
+
{"HourOfDay":12,"Location":"Field","Animal":"cows","Weather":"cold and rainy","Notes":["Fat and happy"]}
160
+
{"HourOfDay":12,"Location":"Barn","Animal":"pigs","Weather":"cold and rainy","Notes":["Fat and happy"]}
161
+
{"HourOfDay":12,"Location":"Barn","Animal":"chickens","Weather":"cold and rainy","Notes":["Fat and happy"]}
162
+
{"HourOfDay":12,"Location":"Barn","Animal":null,"Weather":"cold and rainy","Notes":["Running low on chicken feed","Need to go to the store"]}
163
+
{"HourOfDay":12,"Location":"Garage","Animal":null,"Weather":"cold and rainy","Notes":["Could not start tractor","Need to fix the carburetor"]}
164
+
```
165
+
166
+
If JSON doesn't suit your needs, implement and configure a custom entry serializer:
Though file logging is currently the only use case with a built-in provider, you can write a custom logger provider using one or both of [`IBufferLoggerProvider<TFormat>`](/Logging.Formatting/Formatting/IBufferLoggerProvider.cs) and [`ILogSerializer<TFormat>`](/Logging.Formatting/Serialization/ILogSerializer.cs) to output formatted entries to different destinations.
202
+
203
+
An example provider uploading log data using HTTP requests:
0 commit comments