Skip to content

Disable theming when console output is redirected #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 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
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.
27 changes: 23 additions & 4 deletions src/Serilog.Expressions/Templates/ExpressionTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static bool TryParse(
[MaybeNullWhen(true)] out string error)
{
if (template == null) throw new ArgumentNullException(nameof(template));
return TryParse(template, null, null, null, out result, out error);
return TryParse(template, null, null, null, false, out result, out error);
}

/// <summary>
Expand All @@ -60,12 +60,15 @@ public static bool TryParse(
/// <param name="error">A description of the error, if unsuccessful.</param>
/// <param name="nameResolver">Optionally, a <see cref="NameResolver"/>
/// with which to resolve function names that appear in the template.</param>
/// <param name="applyThemeWhenOutputIsRedirected">Apply <paramref name="theme"/> even when
/// <see cref="System.Console.IsOutputRedirected"/> or <see cref="Console.IsErrorRedirected"/> returns <c>true</c>.</param>
/// <returns><c langword="true">true</c> if the template was well-formed.</returns>
public static bool TryParse(
string template,
IFormatProvider? formatProvider,
NameResolver? nameResolver,
TemplateTheme? theme,
bool applyThemeWhenOutputIsRedirected,
[MaybeNullWhen(false)] out ExpressionTemplate result,
[MaybeNullWhen(true)] out string error)
{
Expand All @@ -84,7 +87,7 @@ public static bool TryParse(
TemplateCompiler.Compile(
planned,
formatProvider, DefaultFunctionNameResolver.Build(nameResolver),
theme ?? TemplateTheme.None));
SelectTheme(theme, applyThemeWhenOutputIsRedirected)));

return true;
}
Expand All @@ -103,11 +106,14 @@ public static bool TryParse(
/// <param name="nameResolver">Optionally, a <see cref="NameResolver"/>
/// with which to resolve function names that appear in the template.</param>
/// <param name="theme">Optionally, an ANSI theme to apply to the template output.</param>
/// <param name="applyThemeWhenOutputIsRedirected">Apply <paramref name="theme"/> even when
/// <see cref="Console.IsOutputRedirected"/> or <see cref="Console.IsErrorRedirected"/> returns <c>true</c>.</param>
public ExpressionTemplate(
string template,
IFormatProvider? formatProvider = null,
NameResolver? nameResolver = null,
TemplateTheme? theme = null)
TemplateTheme? theme = null,
bool applyThemeWhenOutputIsRedirected = false)
{
if (template == null) throw new ArgumentNullException(nameof(template));

Expand All @@ -119,7 +125,20 @@ public ExpressionTemplate(

_compiled = TemplateCompiler.Compile(
planned,
formatProvider, DefaultFunctionNameResolver.Build(nameResolver), theme ?? TemplateTheme.None);
formatProvider,
DefaultFunctionNameResolver.Build(nameResolver),
SelectTheme(theme, applyThemeWhenOutputIsRedirected));
}

static TemplateTheme SelectTheme(TemplateTheme? supplied, bool applyThemeWhenOutputIsRedirected)
{
if (supplied == null ||
(Console.IsOutputRedirected || Console.IsErrorRedirected) && !applyThemeWhenOutputIsRedirected)
{
return TemplateTheme.None;
}

return supplied;
}

/// <inheritdoc />
Expand Down
2 changes: 1 addition & 1 deletion test/Serilog.Expressions.Tests/TemplateParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class TemplateParserTests
[InlineData("Empty {Align,} digits", "Syntax error (line 1, column 14): unexpected `}`, expected alignment and width.")]
public void ErrorsAreReported(string input, string error)
{
Assert.False(ExpressionTemplate.TryParse(input, null, null, null, out _, out var actual));
Assert.False(ExpressionTemplate.TryParse(input, null, null, null, false, out _, out var actual));
Assert.Equal(error, actual);
}

Expand Down