Skip to content

Commit a2a6ea7

Browse files
authored
Merge pull request #111 from serilog/dev
5.0.0 Release
2 parents 63f621d + 3198122 commit a2a6ea7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+353
-189
lines changed

README.md

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,22 @@ The following properties are available in expressions:
125125

126126
* **All first-class properties of the event** - no special syntax: `SourceContext` and `Cart` are used in the formatting examples above
127127
* `@t` - the event's timestamp, as a `DateTimeOffset`
128-
* `@m` - the rendered message
128+
* `@m` - the rendered message (Note: do not add format specifiers like `:lj` or you'll lose theme color rendering. These format specifiers are not supported as they've become the default and only option - [see the discussion here](https://github.com/serilog/serilog-expressions/issues/56#issuecomment-1146472988)
129129
* `@mt` - the raw message template
130130
* `@l` - the event's level, as a `LogEventLevel`
131131
* `@x` - the exception associated with the event, if any, as an `Exception`
132132
* `@p` - a dictionary containing all first-class properties; this supports properties with non-identifier names, for example `@p['snake-case-name']`
133133
* `@i` - event id; a 32-bit numeric hash of the event's message template
134134
* `@r` - renderings; if any tokens in the message template include .NET-specific formatting, an array of rendered values for each such token
135+
* `@tr` - trace id; The id of the trace that was active when the event was created, if any
136+
* `@sp` - span id; The id of the span that was active when the event was created, if any
135137

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

140+
The exception property `@x` is treated as a scalar and will appear as a string when formatted into text. The properties of
141+
the underlying `Exception` object can be accessed using `Inspect()`, for example `Inspect(@x).Message`, and the type of the
142+
exception retrieved using `TypeOf(@x)`.
143+
138144
### Literals
139145

140146
| Data type | Description | Examples |
@@ -181,29 +187,30 @@ calling a function will be undefined if:
181187
* any argument is undefined, or
182188
* any argument is of an incompatible type.
183189

184-
| Function | Description |
185-
| :--- | :--- |
186-
| `Coalesce(p0, p1, [..pN])` | Returns the first defined, non-null argument. |
187-
| `Concat(s0, s1, [..sN])` | Concatenate two or more strings. |
188-
| `Contains(s, t)` | Tests whether the string `s` contains the substring `t`. |
189-
| `ElementAt(x, i)` | Retrieves a property of `x` by name `i`, or array element of `x` by numeric index `i`. |
190-
| `EndsWith(s, t)` | Tests whether the string `s` ends with substring `t`. |
191-
| `IndexOf(s, t)` | Returns the first index of substring `t` in string `s`, or -1 if the substring does not appear. |
192-
| `IndexOfMatch(s, p)` | Returns the index of the first match of regular expression `p` in string `s`, or -1 if the regular expression does not match. |
193-
| `IsMatch(s, p)` | Tests whether the regular expression `p` matches within the string `s`. |
194-
| `IsDefined(x)` | Returns `true` if the expression `x` has a value, including `null`, or `false` if `x` is undefined. |
195-
| `LastIndexOf(s, t)` | Returns the last index of substring `t` in string `s`, or -1 if the substring does not appear. |
196-
| `Length(x)` | Returns the length of a string or array. |
197-
| `Now()` | Returns `DateTimeOffset.Now`. |
198-
| `Rest([deep])` | In an `ExpressionTemplate`, returns an object containing the first-class event properties not otherwise referenced in the template. If `deep` is `true`, also excludes properties referenced in the event's message template. |
199-
| `Round(n, m)` | Round the number `n` to `m` decimal places. |
200-
| `StartsWith(s, t)` | Tests whether the string `s` starts with substring `t`. |
201-
| `Substring(s, start, [length])` | Return the substring of string `s` from `start` to the end of the string, or of `length` characters, if this argument is supplied. |
202-
| `TagOf(o)` | Returns the `TypeTag` field of a captured object (i.e. where `TypeOf(x)` is `'object'`). |
203-
| `ToString(x, [format])` | Convert `x` to a string, applying the format string `format` if `x` is `IFormattable`. |
204-
| `TypeOf(x)` | Returns a string describing the type of expression `x`: a .NET type name if `x` is scalar and non-null, or, `'array'`, `'object'`, `'dictionary'`, `'null'`, or `'undefined'`. |
205-
| `Undefined()` | Explicitly mark an undefined value. |
206-
| `UtcDateTime(x)` | Convert a `DateTime` or `DateTimeOffset` into a UTC `DateTime`. |
190+
| Function | Description |
191+
|:--------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
192+
| `Coalesce(p0, p1, [..pN])` | Returns the first defined, non-null argument. |
193+
| `Concat(s0, s1, [..sN])` | Concatenate two or more strings. |
194+
| `Contains(s, t)` | Tests whether the string `s` contains the substring `t`. |
195+
| `ElementAt(x, i)` | Retrieves a property of `x` by name `i`, or array element of `x` by numeric index `i`. |
196+
| `EndsWith(s, t)` | Tests whether the string `s` ends with substring `t`. |
197+
| `IndexOf(s, t)` | Returns the first index of substring `t` in string `s`, or -1 if the substring does not appear. |
198+
| `IndexOfMatch(s, p)` | Returns the index of the first match of regular expression `p` in string `s`, or -1 if the regular expression does not match. |
199+
| `Inspect(o, [deep])` | Read properties from an object captured as the scalar value `o`. |
200+
| `IsMatch(s, p)` | Tests whether the regular expression `p` matches within the string `s`. |
201+
| `IsDefined(x)` | Returns `true` if the expression `x` has a value, including `null`, or `false` if `x` is undefined. |
202+
| `LastIndexOf(s, t)` | Returns the last index of substring `t` in string `s`, or -1 if the substring does not appear. |
203+
| `Length(x)` | Returns the length of a string or array. |
204+
| `Now()` | Returns `DateTimeOffset.Now`. |
205+
| `Rest([deep])` | In an `ExpressionTemplate`, returns an object containing the first-class event properties not otherwise referenced in the template. If `deep` is `true`, also excludes properties referenced in the event's message template. |
206+
| `Round(n, m)` | Round the number `n` to `m` decimal places. |
207+
| `StartsWith(s, t)` | Tests whether the string `s` starts with substring `t`. |
208+
| `Substring(s, start, [length])` | Return the substring of string `s` from `start` to the end of the string, or of `length` characters, if this argument is supplied. |
209+
| `TagOf(o)` | Returns the `TypeTag` field of a captured object (i.e. where `TypeOf(x)` is `'object'`). |
210+
| `ToString(x, [format])` | Convert `x` to a string, applying the format string `format` if `x` is `IFormattable`. |
211+
| `TypeOf(x)` | Returns a string describing the type of expression `x`: a .NET type name if `x` is scalar and non-null, or, `'array'`, `'object'`, `'dictionary'`, `'null'`, or `'undefined'`. |
212+
| `Undefined()` | Explicitly mark an undefined value. |
213+
| `UtcDateTime(x)` | Convert a `DateTime` or `DateTimeOffset` into a UTC `DateTime`. |
207214

208215
Functions that compare text accept an optional postfix `ci` modifier to select case-insensitive comparisons:
209216

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ artifacts:
88
deploy:
99
- provider: NuGet
1010
api_key:
11-
secure: AcMGMnsJdQe1+SQwf+9VpRqcKNw93zr96OlxAEmPob52vqxDNH844SmdYidGX0cL
11+
secure: ZCEcKeB0btSRWVPgGPqQKphQeTcljBBsA4GKGW0Gmjw+UfXvS0LCcWzYdPXUWo5N
1212
skip_symbols: true
1313
on:
1414
branch: /^(main|dev)$/

serilog-expressions.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<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">
2+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CI/@EntryIndexedValue">CI</s:String>
23
<s:Boolean x:Key="/Default/UserDictionary/Words/=Acerola/@EntryIndexedValue">True</s:Boolean>
34
<s:Boolean x:Key="/Default/UserDictionary/Words/=Comparand/@EntryIndexedValue">True</s:Boolean>
45
<s:Boolean x:Key="/Default/UserDictionary/Words/=delim/@EntryIndexedValue">True</s:Boolean>

src/Serilog.Expressions/Expressions/Ast/AccessorExpression.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// An accessor retrieves a property from a (structured) object. For example, in the expression
19+
/// <code>Headers.ContentType</code> the <code>.</code> operator forms an accessor expression that
20+
/// retrieves the <code>ContentType</code> property from the <code>Headers</code> object.
21+
/// </summary>
22+
/// <remarks>Note that the AST type can represent accessors that cannot be validly written using
23+
/// <code>.</code> notation. In these cases, if the accessor is formatted back out as an expression,
24+
/// <see cref="IndexerExpression"/> notation will be used.</remarks>
1725
class AccessorExpression : Expression
1826
{
1927
public AccessorExpression(Expression receiver, string memberName)

src/Serilog.Expressions/Expressions/Ast/AmbientNameExpression.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// An ambient name is generally a property name or built-in that appears standalone in an expression. For example,
19+
/// in <code>Headers.ContentType</code>, <code>Headers</code> is an ambient name that produces an
20+
/// <see cref="AmbientNameExpression"/>. Built-ins like <code>@Level</code> are also parsed as ambient names.
21+
/// </summary>
1722
class AmbientNameExpression : Expression
1823
{
1924
readonly bool _requiresEscape;

src/Serilog.Expressions/Expressions/Ast/ArrayExpression.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// An array expression constructs an array from a list of elements. For example, <code>[1, 2, 3]</code> is an
19+
/// array expression. The items in an array expression can be literal values or expressions, like in the
20+
/// above example, or they can be spread expressions that describe zero or more elements to include in the
21+
/// list. Whether included via regular elements or spread expressions, undefined values are ignored and won't
22+
/// appear in the resulting array value.
23+
/// </summary>
1724
class ArrayExpression : Expression
1825
{
1926
public ArrayExpression(Element[] elements)

src/Serilog.Expressions/Expressions/Ast/CallExpression.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// A <see cref="CallExpression"/> is a function call made up of the function name, parenthesised argument
19+
/// list, and optional postfix <code>ci</code> modifier. For example, <code>Substring(RequestPath, 0, 5)</code>.
20+
/// </summary>
1721
class CallExpression : Expression
1822
{
1923
public CallExpression(bool ignoreCase, string operatorName, params Expression[] operands)

src/Serilog.Expressions/Expressions/Ast/ConstantExpression.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
namespace Serilog.Expressions.Ast;
1919

20+
/// <summary>
21+
/// A constant such as <code>'hello'</code>, <code>true</code>, <code>null</code>, or <code>123.45</code>.
22+
/// </summary>
2023
class ConstantExpression : Expression
2124
{
2225
public ConstantExpression(LogEventPropertyValue constant)
@@ -30,19 +33,14 @@ public override string ToString()
3033
{
3134
if (Constant is ScalarValue sv)
3235
{
33-
switch (sv.Value)
36+
return sv.Value switch
3437
{
35-
case string s:
36-
return "'" + s.Replace("'", "''") + "'";
37-
case true:
38-
return "true";
39-
case false:
40-
return "false";
41-
case IFormattable formattable:
42-
return formattable.ToString(null, CultureInfo.InvariantCulture);
43-
default:
44-
return (sv.Value ?? "null").ToString() ?? "<ToString() returned null>";
45-
}
38+
string s => "'" + s.Replace("'", "''") + "'",
39+
true => "true",
40+
false => "false",
41+
IFormattable formattable => formattable.ToString(null, CultureInfo.InvariantCulture),
42+
_ => (sv.Value ?? "null").ToString() ?? "<ToString() returned null>"
43+
};
4644
}
4745

4846
return Constant.ToString();

src/Serilog.Expressions/Expressions/Ast/Element.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17-
abstract class Element
18-
{
19-
}
17+
/// <summary>
18+
/// An element in an <see cref="ArrayExpression"/>.
19+
/// </summary>
20+
abstract class Element;

src/Serilog.Expressions/Expressions/Ast/Expression.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,15 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// An AST node.
19+
/// </summary>
1720
abstract class Expression
1821
{
19-
// Used only as an enabler for testing and debugging.
22+
/// <summary>
23+
/// The <see cref="ToString"/> representation of an <see cref="Expression"/> is <strong>not</strong>
24+
/// guaranteed to be syntactically valid: this is provided for debugging purposes only.
25+
/// </summary>
26+
/// <returns>A textual representation of the expression.</returns>
2027
public abstract override string ToString();
2128
}

src/Serilog.Expressions/Expressions/Ast/IndexOfMatchExpression.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
namespace Serilog.Expressions.Ast;
1818

19+
/// <summary>
20+
/// A non-syntax expression tree node used when compiling the <see cref="Operators.OpIndexOfMatch"/>,
21+
/// <see cref="Operators.OpIsMatch"/>, and SQL-style <code>like</code> expressions.
22+
/// </summary>
1923
class IndexOfMatchExpression : Expression
2024
{
2125
public Expression Corpus { get; }

src/Serilog.Expressions/Expressions/Ast/IndexerExpression.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// An <see cref="IndexerExpression"/> retrieves a property from an object, by name, or an item from an array
19+
/// by zero-based numeric index. For example, <code>Headers['Content-Type']</code> and <code>Items[2]</code> are
20+
/// parsed as indexer expressions.
21+
/// </summary>
1722
class IndexerExpression : Expression
1823
{
1924
public Expression Receiver { get; }

src/Serilog.Expressions/Expressions/Ast/IndexerWildcard.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// Describes the wildcard in a <see cref="IndexerWildcardExpression"/>.
19+
/// </summary>
1720
enum IndexerWildcard { Undefined, Any, All }

src/Serilog.Expressions/Expressions/Ast/IndexerWildcardExpression.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// An indexer wildcard is a placeholder in a property path expression. For example,
19+
/// in <code>Headers[?] = 'test'</code>, the question-mark token is a wildcard that means "any property of
20+
/// the <code>Headers</code> object". The other wildcard indexer is the asterisk, meaning "all".
21+
/// </summary>
1722
class IndexerWildcardExpression : Expression
1823
{
1924
public IndexerWildcardExpression(IndexerWildcard wildcard)

src/Serilog.Expressions/Expressions/Ast/ItemElement.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// A single item in an <see cref="ArrayExpression"/>.
19+
/// </summary>
1720
class ItemElement : Element
1821
{
1922
public Expression Value { get; }

src/Serilog.Expressions/Expressions/Ast/LambdaExpression.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// A non-syntax expression tree node used in the compilation of <see cref="IndexerWildcardExpression"/>. Only
19+
/// very limited support for lambda expressions is currently present.
20+
/// </summary>
1721
class LambdaExpression : Expression
1822
{
1923
public LambdaExpression(ParameterExpression[] parameters, Expression body)

src/Serilog.Expressions/Expressions/Ast/LocalNameExpression.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// Represents the iteration variable in template <code>#each</code> directives.
19+
/// </summary>
1720
class LocalNameExpression : Expression
1821
{
1922
public LocalNameExpression(string name)

src/Serilog.Expressions/Expressions/Ast/Member.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17-
abstract class Member
18-
{
19-
}
17+
/// <summary>
18+
/// A member in an <see cref="ObjectExpression"/>.
19+
/// </summary>
20+
abstract class Member;

src/Serilog.Expressions/Expressions/Ast/ObjectExpression.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// Constructs an object given a list of members. Members can be <code>name: value</code> pairs, or spread
19+
/// expressions that include members from another object. Where names conflict, the rightmost appearance of
20+
/// a name wins. Members that evaluate to an undefined value do not appear in the resulting object.
21+
/// </summary>
1722
class ObjectExpression : Expression
1823
{
1924
public ObjectExpression(Member[] members)

src/Serilog.Expressions/Expressions/Ast/ParameterExpression.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
namespace Serilog.Expressions.Ast;
1616

17+
/// <summary>
18+
/// Non-syntax expression type used to represent parameters in <see cref="LambdaExpression"/> bodies.
19+
/// </summary>
1720
class ParameterExpression : Expression
1821
{
1922
public ParameterExpression(string parameterName)

src/Serilog.Expressions/Expressions/Ast/PropertyMember.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616

1717
namespace Serilog.Expressions.Ast;
1818

19+
/// <summary>
20+
/// An <see cref="ObjectExpression"/> member comprising an optionally-quoted name and a value, for example
21+
/// the object <code>{Username: 'alice'}</code> includes a single <see cref="PropertyMember"/> with name
22+
/// <code>Username</code> and value <code>'alice'</code>.
23+
/// </summary>
1924
class PropertyMember : Member
2025
{
2126
public string Name { get; }

0 commit comments

Comments
 (0)