Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

An embeddable mini-language for filtering, enriching, and formatting Serilog events, ideal for use with JSON or XML configuration.

License

NotificationsYou must be signed in to change notification settings

nblumhardt/serilog-expressions

 
 

Repository files navigation

An embeddable mini-language for filtering, enriching, and formatting Serilogevents, ideal for use with JSON or XML configuration.

Getting started

Install the package from NuGet:

dotnet add package Serilog.Expressions

The package adds extension methods to Serilog'sFilter,WriteTo, andEnrich configuration objects, along with anExpressionTemplatetype that's compatible with Serilog sinks accepting anITextFormatter.

Filtering example

Serilog.Expressions addsByExcluding() andByIncludingOnly()overloads to theFilter configuration object that accept filterexpressions:

Log.Logger=newLoggerConfiguration().Filter.ByExcluding("RequestPath like '/health%'").CreateLogger();

Events with aRequestPath property that matches the expressionwill be excluded by the filter.

Note that if the expression syntax is invalid, anArgumentException willbe thrown from theByExcluding() method, and by similar methods elsewherein the package. To check expression syntax without throwing, see theTry*() methods in theSerilogExpression class.

AnappSettings.json JSON configuration example

InappSettings.json configurationthis is written as:

{"Serilog": {"Using": ["Serilog.Expressions"],"Filter": [      {"Name":"ByExcluding","Args": {"expression":"RequestPath like '/health%'"        }      }    ]  }}

An<appSettings> XML configuration example

InXML configuration files,this is written as:

  <appSettings>    <addkey="serilog:using:Expressions"value="Serilog.Expressions" />    <addkey="serilog:filter:ByExcluding.expression"value="RequestPath like '/health%'" />  </appSettings>

Supported configuration APIs

Serilog.Expressions adds a number of expression-based overloads and helper methods to the Serilog configuration syntax:

  • Filter.ByExcluding(),Filter.ByIncludingOnly() - use an expression to filter events passing through the Serilog pipeline
  • WriteTo.Conditional() - use an expression to select the events passed to a particular sink
  • Enrich.When() - conditionally enable an enricher when events match an expression
  • Enrich.WithComputed() - add or modify event properties using an expression

Formatting withExpressionTemplate

Serilog.Expressions includes theExpressionTemplate class for text formatting.ExpressionTemplate implementsITextFormatter, soit works with any text-based Serilog sink, includingConsole,File,Debug, andEmail:

// using Serilog.Templates;Log.Logger=newLoggerConfiguration().WriteTo.Console(newExpressionTemplate("[{@t:HH:mm:ss} {@l:u3} ({SourceContext})] {@m} (first item is {Cart[0]})\n{@x}")).CreateLogger();// Produces log events like:// [21:21:40 INF (Sample.Program)] Cart contains ["Tea","Coffee"] (first item is Tea)

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 complexexpressions over the first-class properties of the event, like{SourceContext} and{Cart[0]} in the example..

Templates support customizable color themes when used with theConsole sink:

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

Screenshot showing colored terminal output

Newline-delimited JSON (for example, replicating theCLEF format) can be generatedusing object literals:

.WriteTo.Console(newExpressionTemplate("{ {@t, @mt, @r, @l: if @l = 'Information' then undefined() else @l, @x, ..@p} }\n"))

Language reference

Properties

The following properties are available in expressions:

  • All first-class properties of the event - no special syntax:SourceContext andCart are used in the formatting examples above
  • @t - the event's timestamp, as aDateTimeOffset
  • @m - the rendered message
  • @mt - the raw message template
  • @l - the event's level, as aLogEventLevel
  • @x - the exception associated with the event, if any, as anException
  • @p - a dictionary containing all first-class properties; this supports properties with non-identifier names, for example@p['snake-case-name']
  • @i - event id; a 32-bit numeric hash of the event's message template
  • @r - renderings; if any tokens in the message template include .NET-specific formatting, an array of rendered values for each such token

The built-in properties mirror those available in the CLEF format.

Literals

Data typeDescriptionExamples
NullCorresponds to .NET'snull valuenull
NumberA number in decimal or hexadecimal notation, represented by .NETdecimal0,100,-12.34,0xC0FFEE
StringA single-quoted Unicode string literal; to escape', double it'pie','isn''t','😋'
BooleanA Boolean valuetrue,false
ArrayAn array of values, in square brackets[1, 'two', null]
ObjectA mapping of string keys to values; keys that are valid identifiers do not need to be quoted{a: 1, 'b c': 2, d}

Array and object literals support the spread operator:[1, 2, ..others],{a: 1, ..others}. Specifying an undefinedproperty in an object literal will remove it from the result:{..User, Email: Undefined()}

Operators and conditionals

A typical set of operators is supported:

  • Equality= and inequality<>, including for arrays and objects
  • Booleanand,or,not
  • Arithmetic+,-,*,/,^,%
  • Numeric comparison<,<=,>,>=
  • Existenceis null andis not null
  • SQL-stylelike andnot like, with% and_ wildcards (double wildcards to escape them)
  • Array membership within andnot in
  • Accessorsa.b
  • Indexersa['b'] anda[0]
  • Wildcard indexing -a[?] any, anda[*] all
  • Conditionalif a then b else c (all branches required; see also the section below onconditional blocks)

Comparision operators that act on text all accept an optional postfixci modifier to select case-insensitive comparisons:

User.Name like 'n%' ci

Functions

Functions are called using typicalIdentifier(args) syntax.

Except for theIsDefined() function, the result ofcalling a function will be undefined if:

  • any argument is undefined, or
  • any argument is of an incompatible type.
FunctionDescription
Coalesce(p0, p1, [..pN])Returns the first defined, non-null argument.
Concat(s0, s1, [..sN])Concatenate two or more strings.
Contains(s, t)Tests whether the strings contains the substringt.
ElementAt(x, i)Retrieves a property ofx by namei, or array element ofx by numeric indexi.
EndsWith(s, t)Tests whether the strings ends with substringt.
IndexOf(s, t)Returns the first index of substringt in strings, or -1 if the substring does not appear.
IndexOfMatch(s, p)Returns the index of the first match of regular expressionp in strings, or -1 if the regular expression does not match.
IsMatch(s, p)Tests whether the regular expressionp matches within the strings.
IsDefined(x)Returnstrue if the expressionx has a value, includingnull, orfalse ifx is undefined.
LastIndexOf(s, t)Returns the last index of substringt in strings, or -1 if the substring does not appear.
Length(x)Returns the length of a string or array.
Now()ReturnsDateTimeOffset.Now.
Rest([deep])In anExpressionTemplate, returns an object containing the first-class event properties not otherwise referenced in the template. Ifdeep istrue, also excludes properties referenced in the event's message template.
Round(n, m)Round the numbern tom decimal places.
StartsWith(s, t)Tests whether the strings starts with substringt.
Substring(s, start, [length])Return the substring of strings fromstart to the end of the string, or oflength characters, if this argument is supplied.
TagOf(o)Returns theTypeTag field of a captured object (i.e. whereTypeOf(x) is'object').
ToString(x, [format])Convertx to a string, applying the format stringformat ifx isIFormattable.
TypeOf(x)Returns a string describing the type of expressionx: a .NET type name ifx is scalar and non-null, or,'array','object','dictionary','null', or'undefined'.
Undefined()Explicitly mark an undefined value.
UtcDateTime(x)Convert aDateTime orDateTimeOffset into a UTCDateTime.

Functions that compare text accept an optional postfixci modifier to select case-insensitive comparisons:

StartsWith(User.Name, 'n') ci

Template directives

Conditional blocks

Within anExpressionTemplate, a portion of the template can be conditionally evaluated using#if.

Log.Logger=newLoggerConfiguration().WriteTo.Console(newExpressionTemplate("[{@t:HH:mm:ss} {@l:u3}{#if SourceContext is not null} ({SourceContext}){#end}] {@m}\n{@x}")).CreateLogger();// Produces log events like:// [21:21:45 INF] Starting up// [21:21:46 INF (Sample.Program)] Firing engines

The block between the{#if <expr>} and{#end} directives will only appear in the output if<expr> istrue - in the example, events with aSourceContext include this in parentheses, while those without, don't.

It's important to notice that the directive requires a Booleantrue before the conditional block will be evaluated. It wouldn't be sufficient in this case to write{#if SourceContext}, since no values other thantrue are considered "truthy".

The syntax supports{#if <expr>}, chained{#else if <expr>},{#else}, and{#end}, with arbitrary nesting.

Repetition

If a log event includes structured data in arrays or objects, a template block can be repeated for each element or member using#each/in (newlines, double quotes and construction of theExpressionTemplate omitted for clarity):

{@l:w4}: {SourceContext}      {#each s in Scope}=> {s}{#delimit} {#end}      {@m}{@x}

This example uses the optional#delimit to add a space between each element, producing output like:

info: Sample.Program      => Main => TextFormattingExample      Hello, world!

When using{#each <name> in <expr>} over an object, such as the built-in@p (properties) object,<name> will be bound to thenames of the properties of the object.

To get to thevalues of the properties, use a second binding:

{#each k, v in @p}{k} = {v}{#delimit},{#end}

This example, if an event has three properties, will produce output like:

Account = "nblumhardt", Cart = ["Tea", "Coffee"], Powerup = 42

The syntax supports{#each <name>[, <name>] in <expr>}, an optional{#delimit} block, and finally an optional{#else} block, which will be evaluated if the array or object is empty.

Recipes

Trim downSourceContext to a type name only:

Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1)

This expression takes advantage ofLastIndexOf() returning -1 when no. character appears inSourceContext, to yield astartIndex of 0 in that case.

Write not-referenced context properties (only if there are any):

{#if rest(true) <> {}} <Context: {rest(true)}>{#end}

Access a property with a non-identifier name:

@p['some name']

Any structured value, including the built-in@p, can be indexed by string key. This means thatUser.Name andUser['Name'] are equivalent, for example.

Access a property with inconsistent casing:

ElementAt(@p, 'someName') ci

ElementAt() is a function-call version of the[] indexer notation, which means it can accept theci case-insensitivity modifier.

Format events as newline-delimited JSON (template, embedded in C# or JSON):

{ {Timestamp: @t, Username: User.Name} }\n

This output template shows the use of a space between the opening{ of a hole, and the enclosed object literal withTimestamp andUsername fields. The object will be formatted as JSON. The trailing\n is a C# or JSON newline literal (don't escape this any further, asit's not part of the output template syntax).

Working with the raw API

The package provides the classSerilogExpression in theSerilog.Expressions namespacefor working with expressions.

if(SerilogExpression.TryCompile("RequestPath like '/health%'",outvarcompiled,outvarerror){// `compiled` is a function that can be executed against `LogEvent`s:varresult= compiled(someEvent);// `result` will contain a `LogEventPropertyValue`, or `null` if the result of evaluating the// expression is undefined (for example if the event has no `RequestPath` property).if(resultis ScalarValue value&&        value.Valueisboolmatches&&        matches){Console.WriteLine("The event matched.");}}else{// `error` describes a syntax error.Console.WriteLine($"Couldn't compile the expression;{error}.");}

Compiled expression delegates returnLogEventPropertyValue because this is the mostconvenient type to work with in many Serilog scenarios (enrichers, sinks, ...). Toconvert the result to plain-old-.NET-types likestring,bool,Dictionary<K,V> andArray, use the functions in theSerilog.Expressions.ExpressionResult class:

varresult=compiled(someEvent);// `true` only if `result` is a scalar Boolean `true`; `false` otherwise:if(ExpressionResult.IsTrue(result)){Console.WriteLine("The event matched.");}

Implementing user-defined functions

User-defined functions can be plugged in by implementing static methods that:

  • ReturnLogEventPropertyValue?,
  • Have arguments of typeLogEventPropertyValue? orLogEvent,
  • If theci modifier is supported, accept aStringComparison, and
  • If culture-specific formatting or comparisons are used, accepts anIFormatProvider.

For example:

publicstaticclassMyFunctions{publicstaticLogEventPropertyValue?IsHello(StringComparisoncomparison,LogEventPropertyValue?maybeHello){if(maybeHelloisScalarValuesv&&sv.Valueisstrings)returnnewScalarValue(s.Equals("Hello",comparison));// Undefined - argument was not a string.returnnull;}}

In the example,IsHello('Hello') will evaluate totrue,IsHello('HELLO') will befalse,IsHello('HELLO') ciwill betrue, andIsHello(42) will be undefined.

User-defined functions are supplied through an instance ofNameResolver:

varmyFunctions=newStaticMemberNameResolver(typeof(MyFunctions));varexpr=SerilogExpression.Compile("IsHello(User.Name)",nameResolver:myFunctions);// Filter events based on whether `User.Name` is `'Hello'` :-)

Acknowledgements

Includes the parser combinator implementation fromSuperpower, copyright Datalust,Superpower Contributors, and Sprache Contributors; licensed under the Apache License, 2.0.

About

An embeddable mini-language for filtering, enriching, and formatting Serilog events, ideal for use with JSON or XML configuration.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C#99.5%
  • PowerShell0.5%

[8]ページ先頭

©2009-2025 Movatter.jp