Skip to content

Commit

Permalink
Merge pull request #41 from serilog/dev
Browse files Browse the repository at this point in the history
3.0.0 Release
  • Loading branch information
nblumhardt authored Jun 2, 2021
2 parents e63a0d5 + f0fcfdc commit c6192d6
Show file tree
Hide file tree
Showing 124 changed files with 5,344 additions and 229 deletions.
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ _Serilog.Expressions_ adds a number of expression-based overloads and helper met
## Formatting with `ExpressionTemplate`

_Serilog.Expressions_ includes the `ExpressionTemplate` class for text formatting. `ExpressionTemplate` implements `ITextFormatter`, so
it works with any text-based Serilog sink:
it works with any text-based Serilog sink, including `Console`, `File`, `Debug`, and `Email`:

```csharp
// using Serilog.Templates;
Expand All @@ -96,7 +96,19 @@ Log.Logger = new LoggerConfiguration()
// [21:21:40 INF (Sample.Program)] Cart contains ["Tea","Coffee"] (first item is Tea)
```

Note the use of `{Cart[0]}`: "holes" in expression templates can include any valid expression over properties from the event.
Templates are based on .NET format strings, and support standard padding, alignment, and format specifiers.

Along with standard properties for the event timestamp (`@t`), level (`@l`) and so on, "holes" in expression templates can include complex
expressions over the first-class properties of the event, like `{SourceContex}` and `{Cart[0]}` in the example..

Templates support customizable color themes when used with the `Console` sink:

```csharp
.WriteTo.Console(new ExpressionTemplate(
"[{@t:HH:mm:ss} {@l:u3}] {@m}\n{@x}", theme: TemplateTheme.Code))
```

![Screenshot showing colored terminal output](https://raw.githubusercontent.com/serilog/serilog-expressions/dev/assets/screenshot.png)

Newline-delimited JSON (for example, replicating the [CLEF format](https://github.com/serilog/serilog-formatting-compact)) can be generated
using object literals:
Expand All @@ -112,7 +124,7 @@ using object literals:

The following properties are available in expressions:

* **All first-class properties of the event** — no special syntax: `SourceContext` and `Cart` are used in the formatting examples above
* **All first-class properties of the event** - no special syntax: `SourceContext` and `Cart` are used in the formatting examples above
* `@t` - the event's timestamp, as a `DateTimeOffset`
* `@m` - the rendered message
* `@mt` - the raw message template
Expand Down Expand Up @@ -339,8 +351,9 @@ convert the result to plain-old-.NET-types like `string`, `bool`, `Dictionary<K,
User-defined functions can be plugged in by implementing static methods that:

* Return `LogEventPropertyValue?`,
* Have arguments of type `LogEventPropertyValue?`, and
* If the `ci` modifier is supported, accept a `StringComparison` in the first argument position.
* Have arguments of type `LogEventPropertyValue?`,
* If the `ci` modifier is supported, accept a `StringComparison`, and
* If culture-specific formatting or comparisons are used, accepts an `IFormatProvider`.

For example:

Expand Down Expand Up @@ -370,3 +383,8 @@ var myFunctions = new StaticMemberNameResolver(typeof(MyFunctions));
var expr = SerilogExpression.Compile("IsHello(User.Name)", new[] { myFunctions });
// Filter events based on whether `User.Name` is `'Hello'` :-)
```

## Acknowledgements

Includes the parser combinator implementation from [Superpower](https://github.com/datalust/superpower), copyright Datalust,
Superpower Contributors, and Sprache Contributors; licensed under the Apache License, 2.0.
Binary file added assets/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 22 additions & 7 deletions example/Sample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using Serilog;
using Serilog.Debugging;
using Serilog.Templates;
using Serilog.Templates.Themes;

namespace Sample
{
Expand All @@ -24,7 +26,8 @@ static void TextFormattingExample1()
.WriteTo.Console(new ExpressionTemplate(
"[{@t:HH:mm:ss} {@l:u3}" +
"{#if SourceContext is not null} ({Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1)}){#end}] " +
"{@m} (first item is {coalesce(Items[0], '<empty>')})\n{@x}"))
"{@m} (first item is {coalesce(Items[0], '<empty>')})\n{@x}",
theme: TemplateTheme.Code))
.CreateLogger();

log.Information("Running {Example}", nameof(TextFormattingExample1));
Expand All @@ -41,7 +44,7 @@ static void JsonFormattingExample()
using var log = new LoggerConfiguration()
.Enrich.WithProperty("Application", "Example")
.WriteTo.Console(new ExpressionTemplate(
"{ {@t, @mt, @l: if @l = 'Information' then undefined() else @l, @x, ..@p} }\n"))
"{ {@t: UtcDateTime(@t), @mt, @l: if @l = 'Information' then undefined() else @l, @x, ..@p} }\n"))
.CreateLogger();

log.Information("Running {Example}", nameof(JsonFormattingExample));
Expand Down Expand Up @@ -75,23 +78,35 @@ static void PipelineComponentExample()

static void TextFormattingExample2()
{
// Emulates `Microsoft.Extensions.Logging`'s `ConsoleLogger`.

var melon = new TemplateTheme(TemplateTheme.Literate, new Dictionary<TemplateThemeStyle, string>
{
// `Information` is dark green in MEL.
[TemplateThemeStyle.LevelInformation] = "\x1b[38;5;34m",
[TemplateThemeStyle.String] = "\x1b[38;5;159m",
[TemplateThemeStyle.Number] = "\x1b[38;5;159m"
});

using var log = new LoggerConfiguration()
.WriteTo.Console(new ExpressionTemplate(
"{@l:w4}: {SourceContext}\n" +
"{#if Scope is not null}" +
" {#each s in Scope}=> {s}{#delimit} {#end}\n" +
"{#end}" +
" {@m}\n" +
"{@x}"))
"{@x}",
theme: melon))
.CreateLogger();

var program = log.ForContext<Program>();
program.Information("Starting up");
program.Information("Host listening at {ListenUri}", "https://hello-world.local");

// Emulate data produced by the Serilog.AspNetCore integration
var scoped = program.ForContext("Scope", new[] {"Main", "TextFormattingExample2()"});
program
.ForContext("Scope", new[] {"Main", "TextFormattingExample2()"})
.Information("HTTP {Method} {Path} responded {StatusCode} in {Elapsed:0.000} ms", "GET", "/api/hello", 200, 1.23);

scoped.Information("Hello, world!");
program.Warning("We've reached the end of the line");
}
}
}
2 changes: 1 addition & 1 deletion example/Sample/Sample.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>

Expand Down
2 changes: 2 additions & 0 deletions serilog-expressions.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Acerola/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Comparand/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=delim/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Enricher/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Evaluatable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Existentials/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=formattable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nblumhardt/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ogham/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reorderable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Serilog/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Subproperties/@EntryIndexedValue">True</s:Boolean>
Expand Down
16 changes: 15 additions & 1 deletion src/Serilog.Expressions/Expressions/Ast/AccessorExpression.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
using System;
// Copyright © 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;

namespace Serilog.Expressions.Ast
{
Expand Down
22 changes: 18 additions & 4 deletions src/Serilog.Expressions/Expressions/Ast/AmbientNameExpression.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
using System;
// Copyright © 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;

namespace Serilog.Expressions.Ast
{
class AmbientNameExpression : Expression
{
readonly bool _requiresEscape;

public AmbientNameExpression(string Name, bool isBuiltIn)
public AmbientNameExpression(string name, bool isBuiltIn)
{
PropertyName = Name ?? throw new ArgumentNullException(nameof(Name));
PropertyName = name ?? throw new ArgumentNullException(nameof(name));
IsBuiltIn = isBuiltIn;
_requiresEscape = !SerilogExpression.IsValidIdentifier(Name);
_requiresEscape = !SerilogExpression.IsValidIdentifier(name);
}

public string PropertyName { get; }
Expand Down
16 changes: 15 additions & 1 deletion src/Serilog.Expressions/Expressions/Ast/ArrayExpression.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
using System;
// Copyright © 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.Linq;

namespace Serilog.Expressions.Ast
Expand Down
16 changes: 15 additions & 1 deletion src/Serilog.Expressions/Expressions/Ast/CallExpression.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
using System;
// Copyright © 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.Linq;

namespace Serilog.Expressions.Ast
Expand Down
18 changes: 16 additions & 2 deletions src/Serilog.Expressions/Expressions/Ast/ConstantExpression.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
using System;
// Copyright © 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.Globalization;
using Serilog.Events;

Expand Down Expand Up @@ -28,7 +42,7 @@ public override string ToString()
case IFormattable formattable:
return formattable.ToString(null, CultureInfo.InvariantCulture);
default:
return (sv.Value ?? "null").ToString();
return (sv.Value ?? "null").ToString() ?? "<ToString() returned null>";
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/Serilog.Expressions/Expressions/Ast/Element.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
namespace Serilog.Expressions.Ast
// Copyright © 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.

namespace Serilog.Expressions.Ast
{
abstract class Element
{
Expand Down
16 changes: 15 additions & 1 deletion src/Serilog.Expressions/Expressions/Ast/Expression.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
namespace Serilog.Expressions.Ast
// Copyright © 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.

namespace Serilog.Expressions.Ast
{
abstract class Expression
{
Expand Down
14 changes: 14 additions & 0 deletions src/Serilog.Expressions/Expressions/Ast/IndexOfMatchExpression.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
// Copyright © 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.Text.RegularExpressions;

Expand Down
14 changes: 14 additions & 0 deletions src/Serilog.Expressions/Expressions/Ast/IndexerExpression.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
// Copyright © 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.

namespace Serilog.Expressions.Ast
{
class IndexerExpression : Expression
Expand Down
16 changes: 15 additions & 1 deletion src/Serilog.Expressions/Expressions/Ast/IndexerWildcard.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
namespace Serilog.Expressions.Ast
// Copyright © 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.

namespace Serilog.Expressions.Ast
{
enum IndexerWildcard { Undefined, Any, All }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
using System;
// Copyright © 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;

namespace Serilog.Expressions.Ast
{
Expand Down
Loading

0 comments on commit c6192d6

Please sign in to comment.