Ostatnio w moim jednym pet projekcie (pisany w ASP.NET Core 3.1.) wymyśliłem sobie tak, aby do bazy zapisywane były tylko te logi, które:

  • W polu SourceContext zawieraja się namespace aplikacji lub
  • Pole @Exception nie jest puste.

Chciałem do bazy zapisywać tylko błędy oraz moje logi z aplikacji, żeby widzieć jak aplikacja działa. Zapisuję tylko to, bo do tych błędów będą miał zrobioną na stronie oddzielną podstronę do ich przeglądania. Chciałem aby na tej podstronie były tylko logi, które mnie interesują, żebym nie musiał przeszukiwać dużej liczby.

Jak to zrobić?

Trzeba doinstalować nugeta Serilog.Filters.Expression:

dotnet add package Serilog.Filters.Expressions

I już można korzystać z filtrów. Są dwie opcje filtrowania:

  • ByIncludingOnly
  • ByExcluding

Pewnie znasz angielski, więc możesz się domyślić, że ByIncludingOnly uwzględnia te logi i przekazuje je do odpowiedniego zlewu :-) , a ByExcluding wyklucza i nie zapisuje do loga.

Składnia pisania warunków jest bardzo podobna do składni SQL.

Category Examples
Literals 123, 123.4, 'Hello', true, false, null
Properties A, A.B, @Level, @Timestamp, @Exception, @Message, @MessageTemplate, @Properties['A-b-c']
Comparisons A = B, A <> B, A > B, A >= B, A is null, A is not null, A in [1, 2]
Text A like 'H%', A not like 'H%', A like 'Hel_o', Contains(A, 'H'), StartsWith(A, 'H'), EndsWith(A, 'H'), IndexOf(A, 'H'), Length(A)
Regular expressions A = /H.*o/, Contains(A, /[lL]/), other string functions
Collections A[0] = 'Hello', A[?] = 'Hello' (any), StartsWith(A[*], 'H') (all), Length(A)
Maths A + 2, A - 2, A * 2, A % 2
Logic not A, A and B, A or B
Grouping A * (B + C)
Other Has(A), TypeOf(A)

Tabelkę “zakosiłem” z oficjalnej dokumentacji :-)

Przykład

Jak to wygląda u mnie? A no tak:

StartsWith(@Properties['SourceContext'] , 'MyNamespace') or @Exception is not null

A tutaj wklejam kawałek mojego pliku kofiguracyjnego:

[...]

"WriteTo": [
  {
    "Name": "MSSqlServer",
    "Args": {
      "connectionString": "MyConnectionString",
      "tableName": "Log"
    }
  }
],
"Filter": [
  {
    "Name": "ByIncludingOnly",
    "Args": { "expression": "StartsWith(@Properties['SourceContext'] , 'MyNamespace') or @Exception is not null" }
  }
]

[...]

Podsumowanie

I to tyle :-) Zapytanie podobne do zapytań SQL wystarczy, aby filtrować jakie informacje mają być zapisywane do loga.

Źródła: https://github.com/serilog/serilog-filters-expressions