Showing preview only (583K chars total). Download the full file or copy to clipboard to get everything.
Repository: serilog/serilog-expressions
Branch: dev
Commit: 697c8fa89ec1
Files: 188
Total size: 526.8 KB
Directory structure:
gitextract_cw7ezsg_/
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── feature_request.md
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── Build.ps1
├── Directory.Build.props
├── Directory.Version.props
├── LICENSE
├── README.md
├── RunPerfTests.ps1
├── assets/
│ └── Serilog.snk
├── example/
│ └── Sample/
│ ├── Program.cs
│ └── Sample.csproj
├── global.json
├── serilog-expressions.sln
├── serilog-expressions.sln.DotSettings
├── src/
│ └── Serilog.Expressions/
│ ├── Expressions/
│ │ ├── Ast/
│ │ │ ├── AccessorExpression.cs
│ │ │ ├── AmbientNameExpression.cs
│ │ │ ├── ArrayExpression.cs
│ │ │ ├── CallExpression.cs
│ │ │ ├── ConstantExpression.cs
│ │ │ ├── Element.cs
│ │ │ ├── Expression.cs
│ │ │ ├── IndexOfMatchExpression.cs
│ │ │ ├── IndexerExpression.cs
│ │ │ ├── IndexerWildcard.cs
│ │ │ ├── IndexerWildcardExpression.cs
│ │ │ ├── ItemElement.cs
│ │ │ ├── LambdaExpression.cs
│ │ │ ├── LocalNameExpression.cs
│ │ │ ├── Member.cs
│ │ │ ├── ObjectExpression.cs
│ │ │ ├── ParameterExpression.cs
│ │ │ ├── PropertyMember.cs
│ │ │ ├── SpreadElement.cs
│ │ │ └── SpreadMember.cs
│ │ ├── BuiltInProperty.cs
│ │ ├── Compilation/
│ │ │ ├── Arrays/
│ │ │ │ └── ConstantArrayEvaluator.cs
│ │ │ ├── DefaultFunctionNameResolver.cs
│ │ │ ├── ExpressionCompiler.cs
│ │ │ ├── ExpressionValidationException.cs
│ │ │ ├── Linq/
│ │ │ │ ├── EventIdHash.cs
│ │ │ │ ├── ExpressionConstantMapper.cs
│ │ │ │ ├── Intrinsics.cs
│ │ │ │ ├── LinqExpressionCompiler.cs
│ │ │ │ └── ParameterReplacementVisitor.cs
│ │ │ ├── OrderedNameResolver.cs
│ │ │ ├── Pattern.cs
│ │ │ ├── Properties/
│ │ │ │ └── PropertiesObjectAccessorTransformer.cs
│ │ │ ├── Text/
│ │ │ │ ├── LikeSyntaxTransformer.cs
│ │ │ │ └── TextMatchingTransformer.cs
│ │ │ ├── Transformations/
│ │ │ │ ├── IdentityTransformer.cs
│ │ │ │ ├── NodeReplacer.cs
│ │ │ │ └── SerilogExpressionTransformer.cs
│ │ │ ├── Variadics/
│ │ │ │ └── VariadicCallRewriter.cs
│ │ │ └── Wildcards/
│ │ │ ├── WildcardComprehensionTransformer.cs
│ │ │ └── WildcardSearch.cs
│ │ ├── CompiledExpression.cs
│ │ ├── Evaluatable.cs
│ │ ├── EvaluationContext.cs
│ │ ├── ExpressionResult.cs
│ │ ├── Helpers.cs
│ │ ├── LoggingFilterSwitch.cs
│ │ ├── NameResolver.cs
│ │ ├── Operators.cs
│ │ ├── Parsing/
│ │ │ ├── Combinators.cs
│ │ │ ├── ExpressionKeyword.cs
│ │ │ ├── ExpressionParser.cs
│ │ │ ├── ExpressionTextParsers.cs
│ │ │ ├── ExpressionToken.cs
│ │ │ ├── ExpressionTokenParsers.cs
│ │ │ ├── ExpressionTokenizer.cs
│ │ │ └── ParserExtensions.cs
│ │ ├── Runtime/
│ │ │ ├── Coerce.cs
│ │ │ ├── Locals.cs
│ │ │ ├── RuntimeOperators.cs
│ │ │ └── Support/
│ │ │ └── UnflattenDottedPropertyNames.cs
│ │ ├── SerilogExpression.cs
│ │ └── StaticMemberNameResolver.cs
│ ├── LoggerEnrichmentConfigurationExtensions.cs
│ ├── LoggerFilterConfigurationExtensions.cs
│ ├── LoggerSinkConfigurationExtensions.cs
│ ├── ParserConstruction/
│ │ ├── Combinators.cs
│ │ ├── Display/
│ │ │ ├── Presentation.cs
│ │ │ └── TokenAttribute.cs
│ │ ├── Model/
│ │ │ ├── Position.cs
│ │ │ ├── Result.cs
│ │ │ ├── Result`1.cs
│ │ │ ├── TextSpan.cs
│ │ │ ├── TokenListParserResult.cs
│ │ │ ├── TokenListParserResult`2.cs
│ │ │ ├── TokenList`1.cs
│ │ │ ├── Token`1.cs
│ │ │ └── Unit.cs
│ │ ├── Parse.cs
│ │ ├── ParseException.cs
│ │ ├── ParserExtensions.cs
│ │ ├── Parsers/
│ │ │ ├── Character.cs
│ │ │ ├── Numerics.cs
│ │ │ ├── Span.cs
│ │ │ └── Token.cs
│ │ ├── README.md
│ │ ├── TextParser`1.cs
│ │ ├── TokenListParser`2.cs
│ │ ├── Tokenizer`1.cs
│ │ └── Util/
│ │ ├── CharInfo.cs
│ │ └── Friendly.cs
│ ├── Pipeline/
│ │ └── ComputedPropertyEnricher.cs
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── Serilog.Expressions.csproj
│ └── Templates/
│ ├── Ast/
│ │ ├── Conditional.cs
│ │ ├── FormattedExpression.cs
│ │ ├── LiteralText.cs
│ │ ├── Repetition.cs
│ │ ├── Template.cs
│ │ └── TemplateBlock.cs
│ ├── Compilation/
│ │ ├── CompiledConditional.cs
│ │ ├── CompiledExceptionToken.cs
│ │ ├── CompiledFormattedExpression.cs
│ │ ├── CompiledLevelToken.cs
│ │ ├── CompiledLiteralText.cs
│ │ ├── CompiledMessageToken.cs
│ │ ├── CompiledRepetition.cs
│ │ ├── CompiledTemplate.cs
│ │ ├── CompiledTemplateBlock.cs
│ │ ├── CompiledTimestampToken.cs
│ │ ├── NameResolution/
│ │ │ ├── ExpressionLocalNameBinder.cs
│ │ │ └── TemplateLocalNameBinder.cs
│ │ ├── TemplateCompiler.cs
│ │ ├── TemplateFunctionNameResolver.cs
│ │ ├── UnreferencedProperties/
│ │ │ ├── ExpressionReferencedPropertiesFinder.cs
│ │ │ ├── TemplateReferencedPropertiesFinder.cs
│ │ │ └── UnreferencedPropertiesFunction.cs
│ │ └── Unsafe/
│ │ └── UnsafeOutputFunction.cs
│ ├── Encoding/
│ │ ├── EncodedCompiledTemplate.cs
│ │ ├── EncodedTemplateFactory.cs
│ │ ├── EscapableEncodedCompiledFormattedExpression.cs
│ │ ├── PreEncodedValue.cs
│ │ └── TemplateOutputEncoder.cs
│ ├── ExpressionTemplate.cs
│ ├── Parsing/
│ │ ├── TemplateParser.cs
│ │ ├── TemplateTokenParsers.cs
│ │ └── TemplateTokenizer.cs
│ ├── Rendering/
│ │ ├── AlignmentExtensions.cs
│ │ ├── Casing.cs
│ │ ├── LevelRenderer.cs
│ │ └── Padding.cs
│ └── Themes/
│ ├── Style.cs
│ ├── StyleReset.cs
│ ├── TemplateTheme.cs
│ ├── TemplateThemeStyle.cs
│ ├── TemplateThemes.cs
│ └── ThemedJsonValueFormatter.cs
└── test/
├── Serilog.Expressions.PerformanceTests/
│ ├── ComparisonBenchmark.cs
│ ├── Harness.cs
│ ├── Serilog.Expressions.PerformanceTests.csproj
│ └── Support/
│ └── Some.cs
└── Serilog.Expressions.Tests/
├── Cases/
│ ├── expression-evaluation-cases.asv
│ ├── template-encoding-cases.asv
│ ├── template-evaluation-cases.asv
│ └── translation-cases.asv
├── ConfigurationTests.cs
├── ExpressionCompilerTests.cs
├── ExpressionEvaluationTests.cs
├── ExpressionParserTests.cs
├── ExpressionTranslationTests.cs
├── ExpressionValidationTests.cs
├── ExpressionValueTests.cs
├── Expressions/
│ ├── NameResolverTests.cs
│ └── Runtime/
│ ├── LocalsTests.cs
│ └── RuntimeOperatorsTests.cs
├── FormatParityTests.cs
├── LoggingFilterSwitchTests.cs
├── Properties/
│ └── launchSettings.json
├── Serilog.Expressions.Tests.csproj
├── Support/
│ ├── AsvCases.cs
│ ├── CollectingSink.cs
│ ├── ParenthesizingEncoder.cs
│ ├── Some.cs
│ ├── StringHashPrefixingTheme.cs
│ └── TestHelperNameResolver.cs
├── TemplateEncodingTests.cs
├── TemplateEvaluationTests.cs
├── TemplateParserTests.cs
├── TemplateTokenizerTests.cs
└── Templates/
└── UnreferencedPropertiesFunctionTests.cs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Report a bug and help us to improve Serilog.Expressions
title: ''
labels: bug
assignees: ''
---
The Serilog maintainers want you to have a great experience using Serilog.Expressions, and will happily track down and resolve bugs. We all have limited time, though, so please think through all of the factors that might be involved and include as much useful information as possible 😊.
ℹ If the problem is caused by a sink or other extension package, please track down the correct repository for that package and create the report there: this tracker is for the **Serilog.Expressions** package only.
**Description**
What's going wrong?
**Reproduction**
Please provide code samples showing how you're configuring and calling Serilog.Expressions to produce the behavior.
**Expected behavior**
A concise description of what you expected to happen.
**Relevant package, tooling and runtime versions**
What Serilog version are you using, on what platform?
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
contact_links:
- name: Ask for help
url: https://stackoverflow.com/tags/serilog
about: Ask the community for help on how to use Serilog.Expressions
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an improvement to Serilog.Expressions
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. For example, "I'd like to do _x_ but currently I can't because _y_ [...]".
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any workarounds or alternative solutions you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/workflows/ci.yml
================================================
# If this file is renamed, the incrementing run attempt number will be reset.
name: CI
on:
push:
branches: [ "dev", "main" ]
pull_request:
branches: [ "dev", "main" ]
env:
CI_BUILD_NUMBER_BASE: ${{ github.run_number }}
CI_TARGET_BRANCH: ${{ github.head_ref || github.ref_name }}
jobs:
build:
# The build must run on Windows so that .NET Framework targets can be built and tested.
runs-on: windows-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Setup
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Compute build number
shell: bash
run: |
echo "CI_BUILD_NUMBER=$(($CI_BUILD_NUMBER_BASE+2300))" >> $GITHUB_ENV
- name: Build and Publish
env:
DOTNET_CLI_TELEMETRY_OPTOUT: true
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: pwsh
run: |
./Build.ps1
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
.idea
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/
example/Sample/log.txt
BenchmarkDotNet.Artifacts/
================================================
FILE: Build.ps1
================================================
Write-Output "build: Tool versions follow"
dotnet --version
dotnet --list-sdks
Write-Output "build: Build started"
Push-Location $PSScriptRoot
try {
if(Test-Path .\artifacts) {
Write-Output "build: Cleaning ./artifacts"
Remove-Item ./artifacts -Force -Recurse
}
& dotnet restore --no-cache
$dbp = [Xml] (Get-Content .\Directory.Version.props)
$versionPrefix = $dbp.Project.PropertyGroup.VersionPrefix
Write-Output "build: Package version prefix is $versionPrefix"
$branch = @{ $true = $env:CI_TARGET_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$NULL -ne $env:CI_TARGET_BRANCH];
$revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:CI_BUILD_NUMBER, 10); $false = "local" }[$NULL -ne $env:CI_BUILD_NUMBER];
$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)) -replace '([^a-zA-Z0-9\-]*)', '')-$revision"}[$branch -eq "main" -and $revision -ne "local"]
$commitHash = $(git rev-parse --short HEAD)
$buildSuffix = @{ $true = "$($suffix)-$($commitHash)"; $false = "$($branch)-$($commitHash)" }[$suffix -ne ""]
Write-Output "build: Package version suffix is $suffix"
Write-Output "build: Build version suffix is $buildSuffix"
& dotnet build -c Release --version-suffix=$buildSuffix /p:ContinuousIntegrationBuild=true
if($LASTEXITCODE -ne 0) { throw "Build failed" }
foreach ($src in Get-ChildItem src/*) {
Push-Location $src
Write-Output "build: Packaging project in $src"
if ($suffix) {
& dotnet pack -c Release --no-build --no-restore -o ../../artifacts --version-suffix=$suffix
} else {
& dotnet pack -c Release --no-build --no-restore -o ../../artifacts
}
if($LASTEXITCODE -ne 0) { throw "Packaging failed" }
Pop-Location
}
foreach ($test in Get-ChildItem test/*.Tests) {
Push-Location $test
Write-Output "build: Testing project in $test"
& dotnet test -c Release --no-build --no-restore
if($LASTEXITCODE -ne 0) { throw "Testing failed" }
Pop-Location
}
if ($env:NUGET_API_KEY) {
# GitHub Actions will only supply this to branch builds and not PRs. We publish
# builds from any branch this action targets (i.e. main and dev).
Write-Output "build: Publishing NuGet packages"
foreach ($nupkg in Get-ChildItem artifacts/*.nupkg) {
& dotnet nuget push -k $env:NUGET_API_KEY -s https://api.nuget.org/v3/index.json "$nupkg"
if($LASTEXITCODE -ne 0) { throw "Publishing failed" }
}
if (!($suffix)) {
Write-Output "build: Creating release for version $versionPrefix"
iex "gh release create v$versionPrefix --title v$versionPrefix --generate-notes $(get-item ./artifacts/*.nupkg) $(get-item ./artifacts/*.snupkg)"
}
}
} finally {
Pop-Location
}
================================================
FILE: Directory.Build.props
================================================
<Project>
<!-- Properties in this file are expected to be identical for all Serilog organization projects. If
a property value is project-specific, please record it in the CSPROJ file instead. -->
<Import Project="$(MSBuildThisFileDirectory)Directory.Version.props" />
<PropertyGroup>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<!-- The condition is required to support BenchmarkDotNet -->
<SignAssembly Condition="Exists('$(MSBuildThisFileDirectory)assets/Serilog.snk')">true</SignAssembly>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)assets/Serilog.snk</AssemblyOriginatorKeyFile>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
</Project>
================================================
FILE: Directory.Version.props
================================================
<Project>
<PropertyGroup>
<VersionPrefix>5.1.0</VersionPrefix>
</PropertyGroup>
</Project>
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
================================================
FILE: README.md
================================================
# Serilog.Expressions [](https://github.com/serilog/serilog-expressions/actions) [](https://nuget.org/packages/serilog.expressions)
An embeddable mini-language for filtering, enriching, and formatting Serilog
events, ideal for use with JSON or XML configuration.
## Getting started
Install the package from NuGet:
```shell
dotnet add package Serilog.Expressions
```
The package adds extension methods to Serilog's `Filter`, `WriteTo`, and
`Enrich` configuration objects, along with an `ExpressionTemplate`
type that's compatible with Serilog sinks accepting an
`ITextFormatter`.
### Filtering example
_Serilog.Expressions_ adds `ByExcluding()` and `ByIncludingOnly()`
overloads to the `Filter` configuration object that accept filter
expressions:
```csharp
Log.Logger = new LoggerConfiguration()
.Filter.ByExcluding("RequestPath like '/health%'")
.CreateLogger();
```
Events with a `RequestPath` property that matches the expression
will be excluded by the filter.
> Note that if the expression syntax is invalid, an `ArgumentException` will
be thrown from the `ByExcluding()` method, and by similar methods elsewhere
in the package. To check expression syntax without throwing, see the
`Try*()` methods in the `SerilogExpression` class.
#### An `appSettings.json` JSON configuration example
In [`appSettings.json` configuration](https://github.com/serilog/serilog-settings-configuration)
this is written as:
```json
{
"Serilog": {
"Using": ["Serilog.Expressions"],
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "RequestPath like '/health%'"
}
}
]
}
}
```
#### An `<appSettings>` XML configuration example
In [XML configuration files](https://github.com/serilog/serilog-settings-appsettings),
this is written as:
```xml
<appSettings>
<add key="serilog:using:Expressions" value="Serilog.Expressions" />
<add key="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 with `ExpressionTemplate`
_Serilog.Expressions_ includes the `ExpressionTemplate` class for text formatting. `ExpressionTemplate` implements `ITextFormatter`, so
it works with any text-based Serilog sink, including `Console`, `File`, `Debug`, and `Email`:
```csharp
// using Serilog.Templates;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new ExpressionTemplate(
"[{@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 complex
expressions over the first-class properties of the event, like `{SourceContext}` 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))
```

Newline-delimited JSON (for example, replicating the [CLEF format](https://github.com/serilog/serilog-formatting-compact)) can be generated
using object literals:
```csharp
.WriteTo.Console(new ExpressionTemplate(
"{ {@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` and `Cart` are used in the formatting examples above
* `@t` - the event's timestamp, as a `DateTimeOffset`
* `@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)
* `@mt` - the raw message template
* `@l` - the event's level, as a `LogEventLevel`
* `@x` - the exception associated with the event, if any, as an `Exception`
* `@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
* `@tr` - trace id; The id of the trace that was active when the event was created, if any
* `@sp` - span id; The id of the span that was active when the event was created, if any
The built-in properties mirror those available in the CLEF format.
The exception property `@x` is treated as a scalar and will appear as a string when formatted into text. The properties of
the underlying `Exception` object can be accessed using `Inspect()`, for example `Inspect(@x).Message`, and the type of the
exception retrieved using `TypeOf(@x)`.
### Literals
| Data type | Description | Examples |
| :--- | :--- | :--- |
| Null | Corresponds to .NET's `null` value | `null` |
| Number | A number in decimal or hexadecimal notation, represented by .NET `decimal` | `0`, `100`, `-12.34`, `0xC0FFEE` |
| String | A single-quoted Unicode string literal; to escape `'`, double it | `'pie'`, `'isn''t'`, `'😋'` |
| Boolean | A Boolean value | `true`, `false` |
| Array | An array of values, in square brackets | `[1, 'two', null]` |
| Object | A 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 undefined
property 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
* Boolean `and`, `or`, `not`
* Arithmetic `+`, `-`, `*`, `/`, `^`, `%`
* Numeric comparison `<`, `<=`, `>`, `>=`
* Existence `is null` and `is not null`
* SQL-style `like` and `not like`, with `%` and `_` wildcards (double wildcards to escape them)
* Array membership with `in` and `not in`
* Accessors `a.b`
* Indexers `a['b']` and `a[0]`
* Wildcard indexing - `a[?]` any, and `a[*]` all
* Conditional `if a then b else c` (all branches required; see also the section below on _conditional blocks_)
Comparision operators that act on text all accept an optional postfix `ci` modifier to select case-insensitive comparisons:
```
User.Name like 'n%' ci
```
### Functions
Functions are called using typical `Identifier(args)` syntax.
Except for the `IsDefined()` function, the result of
calling a function will be undefined if:
* any argument is undefined, or
* any argument is of an incompatible type.
| Function | Description |
|:--------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Coalesce(a0, a1, [..aN])` | Returns the first defined, non-null argument. |
| `Concat(s0, s1, [..sN])` | Concatenate two or more strings. |
| `Contains(s, p)` | Tests whether the string `s` contains the substring `p`. |
| `ElementAt(x, i)` | Retrieves a property of `x` by name `i`, or array element of `x` by numeric index `i`. |
| `EndsWith(s, p)` | Tests whether the string `s` ends with substring `p`. |
| `IndexOf(s, p)` | Returns the first index of substring `p` in string `s`, or -1 if the substring does not appear. |
| `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. |
| `Inspect(o, [deep])` | Read properties from an object captured as the scalar value `o`. |
| `IsMatch(s, p)` | Tests whether the regular expression `p` matches within the string `s`. |
| `IsDefined(x)` | Returns `true` if the expression `x` has a value, including `null`, or `false` if `x` is undefined. |
| `LastIndexOf(s, p)` | Returns the last index of substring `p` in string `s`, or -1 if the substring does not appear. |
| `Length(x)` | Returns the length of a string or array. |
| `Nest(o)` | Converts dotted (flattened) property names of object `o` into nested sub-objects. |
| `Now()` | Returns `DateTimeOffset.Now`. |
| `Replace(s, p, r)` | Replace occurrences of substring `p` in string `s` with replacement `r`. |
| `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. |
| `Round(n, m)` | Round the number `n` to `m` decimal places. |
| `StartsWith(s, p)` | Tests whether the string `s` starts with substring `p`. |
| `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. |
| `TagOf(o)` | Returns the `TypeTag` field of a captured object (i.e. where `TypeOf(x)` is `'object'`). |
| `ToString(x, [format])` | Convert `x` to a string, applying the format string `format` if `x` is `IFormattable`. |
| `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'`. |
| `Undefined()` | Explicitly mark an undefined value. |
| `UtcDateTime(x)` | Convert a `DateTime` or `DateTimeOffset` into a UTC `DateTime`. |
Functions that compare text accept an optional postfix `ci` modifier to select case-insensitive comparisons:
```
StartsWith(User.Name, 'n') ci
```
### Template directives
#### Conditional blocks
Within an `ExpressionTemplate`, a portion of the template can be conditionally evaluated using `#if`.
```csharp
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new ExpressionTemplate(
"[{@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>` is `true` - in the example, events with a `SourceContext` include this in parentheses, while those without, don't.
It's important to notice that the directive requires a Boolean `true` before the conditional block will be evaluated. It wouldn't be sufficient in this case to write `{#if SourceContext}`, since no values other than `true` 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 the `ExpressionTemplate` 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 the _names_ of the properties of the object.
To get to the _values_ 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 down `SourceContext` to a type name only:**
```
Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1)
```
This expression takes advantage of `LastIndexOf()` returning -1 when no `.` character appears in `SourceContext`, to yield a `startIndex` 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 that `User.Name` and `User['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 the `ci` 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 with `Timestamp` and
`Username` fields. The object will be formatted as JSON. The trailing `\n` is a C# or JSON newline literal (don't escape this any further, as
it's not part of the output template syntax).
## Working with the raw API
The package provides the class `SerilogExpression` in the `Serilog.Expressions` namespace
for working with expressions.
```csharp
if (SerilogExpression.TryCompile("RequestPath like '/health%'", out var compiled, out var error)
{
// `compiled` is a function that can be executed against `LogEvent`s:
var result = 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 (result is ScalarValue value &&
value.Value is bool matches &&
matches)
{
Console.WriteLine("The event matched.");
}
}
else
{
// `error` describes a syntax error.
Console.WriteLine($"Couldn't compile the expression; {error}.");
}
```
Compiled expression delegates return `LogEventPropertyValue` because this is the most
convenient type to work with in many Serilog scenarios (enrichers, sinks, ...). To
convert the result to plain-old-.NET-types like `string`, `bool`, `Dictionary<K,V>` and
`Array`, use the functions in the `Serilog.Expressions.ExpressionResult` class:
```csharp
var result = 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:
* Return `LogEventPropertyValue?`,
* Have arguments of type `LogEventPropertyValue?` or `LogEvent`,
* If the `ci` modifier is supported, accept a `StringComparison`, and
* If culture-specific formatting or comparisons are used, accepts an `IFormatProvider`.
For example:
```csharp
public static class MyFunctions
{
public static LogEventPropertyValue? IsHello(
StringComparison comparison,
LogEventPropertyValue? maybeHello)
{
if (maybeHello is ScalarValue sv && sv.Value is string s)
return new ScalarValue(s.Equals("Hello", comparison));
// Undefined - argument was not a string.
return null;
}
}
```
In the example, `IsHello('Hello')` will evaluate to `true`, `IsHello('HELLO')` will be `false`, `IsHello('HELLO') ci`
will be `true`, and `IsHello(42)` will be undefined.
User-defined functions are supplied through an instance of `NameResolver`:
```csharp
var myFunctions = new StaticMemberNameResolver(typeof(MyFunctions));
var expr = SerilogExpression.Compile("IsHello(User.Name)", nameResolver: 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.
================================================
FILE: RunPerfTests.ps1
================================================
Push-Location $PSScriptRoot
./Build.ps1
foreach ($test in ls test/*.PerformanceTests) {
Push-Location $test
echo "perf: Running performance test project in $test"
& dotnet test -c Release
if($LASTEXITCODE -ne 0) { exit 2 }
Pop-Location
}
Pop-Location
================================================
FILE: example/Sample/Program.cs
================================================
using Serilog;
using Serilog.Debugging;
using Serilog.Templates;
using Serilog.Templates.Themes;
SelfLog.Enable(Console.Error);
TextFormattingExample1();
JsonFormattingExample();
PipelineComponentExample();
TextFormattingExample2();
return;
static void TextFormattingExample1()
{
using var log = new LoggerConfiguration()
.Enrich.WithProperty("Application", "Sample")
.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>')}) {rest()}\n{@x}",
theme: TemplateTheme.Code))
.CreateLogger();
log.Information("Running {Example}", nameof(TextFormattingExample1));
log.ForContext<Program>()
.Information("Cart contains {@Items}", new[] { "Tea", "Coffee" });
log.ForContext<Program>()
.Information("Cart contains {@Items}", new[] { "Apricots" });
}
static void JsonFormattingExample()
{
using var log = new LoggerConfiguration()
.Enrich.WithProperty("Application", "Example")
.WriteTo.Console(new ExpressionTemplate(
"{ {@t: UtcDateTime(@t), @mt, @l: if @l = 'Information' then undefined() else @l, @x, ..@p} }\n"))
.CreateLogger();
log.Information("Running {Example}", nameof(JsonFormattingExample));
log.ForContext<Program>()
.Information("Cart contains {@Items}", new[] { "Tea", "Coffee" });
log.ForContext<Program>()
.Warning("Cart is empty");
}
static void PipelineComponentExample()
{
using var log = new LoggerConfiguration()
.Enrich.WithProperty("Application", "Example")
.Enrich.WithComputed("FirstItem", "coalesce(Items[0], '<empty>')")
.Enrich.WithComputed("SourceContext", "coalesce(Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1), '<no source>')")
.Filter.ByIncludingOnly("Items is null or Items[?] like 'C%'")
.WriteTo.Console(outputTemplate:
"[{Timestamp:HH:mm:ss} {Level:u3} ({SourceContext})] {Message:lj} (first item is {FirstItem}){NewLine}{Exception}")
.CreateLogger();
log.Information("Running {Example}", nameof(PipelineComponentExample));
log.ForContext<Program>()
.Information("Cart contains {@Items}", new[] { "Tea", "Coffee" });
log.ForContext<Program>()
.Information("Cart contains {@Items}", new[] { "Apricots" });
}
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}",
theme: melon))
.CreateLogger();
var program = log.ForContext<Program>();
program.Information("Host listening at {ListenUri}", "https://hello-world.local");
program
.ForContext("Scope", new[] {"Main", "TextFormattingExample2()"})
.Information("HTTP {Method} {Path} responded {StatusCode} in {Elapsed:0.000} ms", "GET", "/api/hello", 200, 1.23);
program.Warning("We've reached the end of the line");
}
================================================
FILE: example/Sample/Sample.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<OutputType>Exe</OutputType>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../src/Serilog.Expressions/Serilog.Expressions.csproj" />
</ItemGroup>
</Project>
================================================
FILE: global.json
================================================
{
"sdk": {
"version": "9.0.200",
"allowPrerelease": false,
"rollForward": "latestFeature"
}
}
================================================
FILE: serilog-expressions.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31410.223
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{91E482DE-E1E7-4CE1-9511-C0AF07F3648A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "global", "global", "{24B1126F-184C-469E-9F06-C1019DEF165A}"
ProjectSection(SolutionItems) = preProject
.gitattributes = .gitattributes
.gitignore = .gitignore
Build.ps1 = Build.ps1
Directory.Build.props = Directory.Build.props
LICENSE = LICENSE
README.md = README.md
RunPerfTests.ps1 = RunPerfTests.ps1
Directory.Version.props = Directory.Version.props
global.json = global.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "example", "example", "{BD94A77E-34B1-478E-B921-E87A5F71B574}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B03B3086-D197-4B32-9AE2-8536C345EA2D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "example\Sample\Sample.csproj", "{776EECAC-3C50-45EA-847D-0EBE5158E51E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Expressions", "src\Serilog.Expressions\Serilog.Expressions.csproj", "{A420C4E3-3A2D-4369-88EB-77E4DB1D0219}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Expressions.Tests", "test\Serilog.Expressions.Tests\Serilog.Expressions.Tests.csproj", "{3C2D8E01-5580-426A-BDD9-EC59CD98E618}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Expressions.PerformanceTests", "test\Serilog.Expressions.PerformanceTests\Serilog.Expressions.PerformanceTests.csproj", "{D7A37F73-BBA3-4DAE-9648-1A753A86F968}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{776EECAC-3C50-45EA-847D-0EBE5158E51E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{776EECAC-3C50-45EA-847D-0EBE5158E51E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{776EECAC-3C50-45EA-847D-0EBE5158E51E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{776EECAC-3C50-45EA-847D-0EBE5158E51E}.Release|Any CPU.Build.0 = Release|Any CPU
{A420C4E3-3A2D-4369-88EB-77E4DB1D0219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A420C4E3-3A2D-4369-88EB-77E4DB1D0219}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A420C4E3-3A2D-4369-88EB-77E4DB1D0219}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A420C4E3-3A2D-4369-88EB-77E4DB1D0219}.Release|Any CPU.Build.0 = Release|Any CPU
{3C2D8E01-5580-426A-BDD9-EC59CD98E618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C2D8E01-5580-426A-BDD9-EC59CD98E618}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C2D8E01-5580-426A-BDD9-EC59CD98E618}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3C2D8E01-5580-426A-BDD9-EC59CD98E618}.Release|Any CPU.Build.0 = Release|Any CPU
{D7A37F73-BBA3-4DAE-9648-1A753A86F968}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7A37F73-BBA3-4DAE-9648-1A753A86F968}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7A37F73-BBA3-4DAE-9648-1A753A86F968}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7A37F73-BBA3-4DAE-9648-1A753A86F968}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{776EECAC-3C50-45EA-847D-0EBE5158E51E} = {BD94A77E-34B1-478E-B921-E87A5F71B574}
{A420C4E3-3A2D-4369-88EB-77E4DB1D0219} = {91E482DE-E1E7-4CE1-9511-C0AF07F3648A}
{3C2D8E01-5580-426A-BDD9-EC59CD98E618} = {B03B3086-D197-4B32-9AE2-8536C345EA2D}
{D7A37F73-BBA3-4DAE-9648-1A753A86F968} = {B03B3086-D197-4B32-9AE2-8536C345EA2D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EB6672D6-318E-493E-8B60-77F5A7A90E66}
EndGlobalSection
EndGlobal
================================================
FILE: serilog-expressions.sln.DotSettings
================================================
<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:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CI/@EntryIndexedValue">CI</s:String>
<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>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Variadics/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/AccessorExpression.cs
================================================
// 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;
/// <summary>
/// An accessor retrieves a property from a (structured) object. For example, in the expression
/// <code>Headers.ContentType</code> the <code>.</code> operator forms an accessor expression that
/// retrieves the <code>ContentType</code> property from the <code>Headers</code> object.
/// </summary>
/// <remarks>Note that the AST type can represent accessors that cannot be validly written using
/// <code>.</code> notation. In these cases, if the accessor is formatted back out as an expression,
/// <see cref="IndexerExpression"/> notation will be used.</remarks>
class AccessorExpression : Expression
{
public AccessorExpression(Expression receiver, string memberName)
{
MemberName = memberName ?? throw new ArgumentNullException(nameof(memberName));
Receiver = receiver;
}
public string MemberName { get; }
public Expression Receiver { get; }
public override string ToString()
{
if (SerilogExpression.IsValidIdentifier(MemberName))
return Receiver + "." + MemberName;
return $"{Receiver}['{SerilogExpression.EscapeStringContent(MemberName)}']";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/AmbientNameExpression.cs
================================================
// 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;
/// <summary>
/// An ambient name is generally a property name or built-in that appears standalone in an expression. For example,
/// in <code>Headers.ContentType</code>, <code>Headers</code> is an ambient name that produces an
/// <see cref="AmbientNameExpression"/>. Built-ins like <code>@Level</code> are also parsed as ambient names.
/// </summary>
class AmbientNameExpression : Expression
{
readonly bool _requiresEscape;
public AmbientNameExpression(string name, bool isBuiltIn)
{
PropertyName = name ?? throw new ArgumentNullException(nameof(name));
IsBuiltIn = isBuiltIn;
_requiresEscape = !SerilogExpression.IsValidIdentifier(name);
}
public string PropertyName { get; }
public bool IsBuiltIn { get; }
public override string ToString()
{
if (_requiresEscape)
return $"@Properties['{SerilogExpression.EscapeStringContent(PropertyName)}']";
return (IsBuiltIn ? "@" : "") + PropertyName;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/ArrayExpression.cs
================================================
// 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;
/// <summary>
/// An array expression constructs an array from a list of elements. For example, <code>[1, 2, 3]</code> is an
/// array expression. The items in an array expression can be literal values or expressions, like in the
/// above example, or they can be spread expressions that describe zero or more elements to include in the
/// list. Whether included via regular elements or spread expressions, undefined values are ignored and won't
/// appear in the resulting array value.
/// </summary>
class ArrayExpression : Expression
{
public ArrayExpression(Element[] elements)
{
Elements = elements ?? throw new ArgumentNullException(nameof(elements));
}
public Element[] Elements { get; }
public override string ToString()
{
return "[" + string.Join(", ", Elements.Select(o => o.ToString())) + "]";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/CallExpression.cs
================================================
// 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;
/// <summary>
/// A <see cref="CallExpression"/> is a function call made up of the function name, parenthesised argument
/// list, and optional postfix <code>ci</code> modifier. For example, <code>Substring(RequestPath, 0, 5)</code>.
/// </summary>
class CallExpression : Expression
{
public CallExpression(bool ignoreCase, string operatorName, params Expression[] operands)
{
IgnoreCase = ignoreCase;
OperatorName = operatorName ?? throw new ArgumentNullException(nameof(operatorName));
Operands = operands ?? throw new ArgumentNullException(nameof(operands));
}
public bool IgnoreCase { get; }
public string OperatorName { get; }
public Expression[] Operands { get; }
public override string ToString()
{
return OperatorName
+ "(" + string.Join(", ", Operands.Select(o => o.ToString())) + ")"
+ (IgnoreCase ? " ci" : "");
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/ConstantExpression.cs
================================================
// 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.Globalization;
using Serilog.Events;
namespace Serilog.Expressions.Ast;
/// <summary>
/// A constant such as <code>'hello'</code>, <code>true</code>, <code>null</code>, or <code>123.45</code>.
/// </summary>
class ConstantExpression : Expression
{
public ConstantExpression(LogEventPropertyValue constant)
{
Constant = constant ?? throw new ArgumentNullException(nameof(constant));
}
public LogEventPropertyValue Constant { get; }
public override string ToString()
{
if (Constant is ScalarValue sv)
{
return sv.Value switch
{
string s => "'" + s.Replace("'", "''") + "'",
true => "true",
false => "false",
IFormattable formattable => formattable.ToString(null, CultureInfo.InvariantCulture),
_ => (sv.Value ?? "null").ToString() ?? "<ToString() returned null>"
};
}
return Constant.ToString();
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/Element.cs
================================================
// 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;
/// <summary>
/// An element in an <see cref="ArrayExpression"/>.
/// </summary>
abstract class Element;
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/Expression.cs
================================================
// 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;
/// <summary>
/// An AST node.
/// </summary>
abstract class Expression
{
/// <summary>
/// The <see cref="ToString"/> representation of an <see cref="Expression"/> is <strong>not</strong>
/// guaranteed to be syntactically valid: this is provided for debugging purposes only.
/// </summary>
/// <returns>A textual representation of the expression.</returns>
public abstract override string ToString();
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/IndexOfMatchExpression.cs
================================================
// 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.Text.RegularExpressions;
namespace Serilog.Expressions.Ast;
/// <summary>
/// A non-syntax expression tree node used when compiling the <see cref="Operators.OpIndexOfMatch"/>,
/// <see cref="Operators.OpIsMatch"/>, and SQL-style <code>like</code> expressions.
/// </summary>
class IndexOfMatchExpression : Expression
{
public Expression Corpus { get; }
public Regex Regex { get; }
public IndexOfMatchExpression(Expression corpus, Regex regex)
{
Corpus = corpus ?? throw new ArgumentNullException(nameof(corpus));
Regex = regex ?? throw new ArgumentNullException(nameof(regex));
}
public override string ToString()
{
return $"_Internal_IndexOfMatch({Corpus}, '{Regex.ToString().Replace("'", "''")}')";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/IndexerExpression.cs
================================================
// 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;
/// <summary>
/// An <see cref="IndexerExpression"/> retrieves a property from an object, by name, or an item from an array
/// by zero-based numeric index. For example, <code>Headers['Content-Type']</code> and <code>Items[2]</code> are
/// parsed as indexer expressions.
/// </summary>
class IndexerExpression : Expression
{
public Expression Receiver { get; }
public Expression Index { get; }
public IndexerExpression(Expression receiver, Expression index)
{
Receiver = receiver;
Index = index;
}
public override string ToString()
{
return $"{Receiver}[{Index}]";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/IndexerWildcard.cs
================================================
// 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;
/// <summary>
/// Describes the wildcard in a <see cref="IndexerWildcardExpression"/>.
/// </summary>
enum IndexerWildcard { Undefined, Any, All }
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/IndexerWildcardExpression.cs
================================================
// 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;
/// <summary>
/// An indexer wildcard is a placeholder in a property path expression. For example,
/// in <code>Headers[?] = 'test'</code>, the question-mark token is a wildcard that means "any property of
/// the <code>Headers</code> object". The other wildcard indexer is the asterisk, meaning "all".
/// </summary>
class IndexerWildcardExpression : Expression
{
public IndexerWildcardExpression(IndexerWildcard wildcard)
{
Wildcard = wildcard;
}
public IndexerWildcard Wildcard { get; }
public override string ToString()
{
switch (Wildcard)
{
case IndexerWildcard.Any:
return "?";
case IndexerWildcard.All:
return "*";
default:
throw new NotSupportedException("Unrecognized wildcard " + Wildcard);
}
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/ItemElement.cs
================================================
// 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;
/// <summary>
/// A single item in an <see cref="ArrayExpression"/>.
/// </summary>
class ItemElement : Element
{
public Expression Value { get; }
public ItemElement(Expression value)
{
Value = value;
}
public override string ToString()
{
return Value.ToString();
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/LambdaExpression.cs
================================================
// 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;
/// <summary>
/// A non-syntax expression tree node used in the compilation of <see cref="IndexerWildcardExpression"/>. Only
/// very limited support for lambda expressions is currently present.
/// </summary>
class LambdaExpression : Expression
{
public LambdaExpression(ParameterExpression[] parameters, Expression body)
{
Parameters = parameters;
Body = body;
}
public ParameterExpression[] Parameters { get; }
public Expression Body { get; }
public override string ToString()
{
return "|" + string.Join(", ", Parameters.Select(p => p.ToString())) + "| {" + Body + "}";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/LocalNameExpression.cs
================================================
// 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;
/// <summary>
/// Represents the iteration variable in template <code>#each</code> directives.
/// </summary>
class LocalNameExpression : Expression
{
public LocalNameExpression(string name)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
}
public string Name { get; }
public override string ToString()
{
// No unambiguous syntax for this right now, `$` will do to make these stand out when debugging,
// but the result won't round-trip parse.
return $"${Name}";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/Member.cs
================================================
// 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;
/// <summary>
/// A member in an <see cref="ObjectExpression"/>.
/// </summary>
abstract class Member;
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/ObjectExpression.cs
================================================
// 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;
/// <summary>
/// Constructs an object given a list of members. Members can be <code>name: value</code> pairs, or spread
/// expressions that include members from another object. Where names conflict, the rightmost appearance of
/// a name wins. Members that evaluate to an undefined value do not appear in the resulting object.
/// </summary>
class ObjectExpression : Expression
{
public ObjectExpression(Member[] members)
{
Members = members;
}
public Member[] Members { get; }
public override string ToString()
{
return "{" + string.Join(", ", Members.Select(m => m.ToString())) + "}";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/ParameterExpression.cs
================================================
// 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;
/// <summary>
/// Non-syntax expression type used to represent parameters in <see cref="LambdaExpression"/> bodies.
/// </summary>
class ParameterExpression : Expression
{
public ParameterExpression(string parameterName)
{
ParameterName = parameterName;
}
public string ParameterName { get; }
public override string ToString()
{
return "$$" + ParameterName;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/PropertyMember.cs
================================================
// 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 Serilog.Events;
namespace Serilog.Expressions.Ast;
/// <summary>
/// An <see cref="ObjectExpression"/> member comprising an optionally-quoted name and a value, for example
/// the object <code>{Username: 'alice'}</code> includes a single <see cref="PropertyMember"/> with name
/// <code>Username</code> and value <code>'alice'</code>.
/// </summary>
class PropertyMember : Member
{
public string Name { get; }
public Expression Value { get; }
public PropertyMember(string name, Expression value)
{
Name = name;
Value = value;
}
public override string ToString()
{
return $"{new ScalarValue(Name)}: {Value}";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/SpreadElement.cs
================================================
// 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;
/// <summary>
/// An element in an <see cref="ArrayExpression"/> that describes zero or more items to include in the array.
/// Spread elements are written with two dots preceding an expression that evaluates to an array of elements to
/// insert into the result array at the position of the spread element, for example, in <code>[1, 2, ..Others]</code>,
/// the <code>..Others</code> expression is a spread element. If the value of the array in the spread is
/// undefined, no items will be added to the list.
/// </summary>
class SpreadElement : Element
{
public Expression Content { get; }
public SpreadElement(Expression content)
{
Content = content;
}
public override string ToString()
{
return $"..{Content}";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Ast/SpreadMember.cs
================================================
// 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;
/// <summary>
/// An <see cref="ObjectExpression"/> member that designates another object from which to copy members into the
/// current object. Spread member expressions comprise two dots preceding an expression that is expected to
/// evaluate to an object.
/// </summary>
class SpreadMember : Member
{
public Expression Content { get; }
public SpreadMember(Expression content)
{
Content = content;
}
public override string ToString()
{
return $"..{Content}";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/BuiltInProperty.cs
================================================
// 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;
// See https://github.com/serilog/serilog-formatting-compact#reified-properties
static class BuiltInProperty
{
public const string Exception = "x";
public const string Level = "l";
public const string Timestamp = "t";
public const string Message = "m";
public const string MessageTemplate = "mt";
public const string Properties = "p";
public const string Renderings = "r";
public const string EventId = "i";
public const string TraceId = "tr";
public const string SpanId = "sp";
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Arrays/ConstantArrayEvaluator.cs
================================================
// 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 Serilog.Events;
using Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Transformations;
namespace Serilog.Expressions.Compilation.Arrays;
class ConstantArrayEvaluator : IdentityTransformer
{
static readonly ConstantArrayEvaluator Instance = new();
public static Expression Rewrite(Expression expression)
{
return Instance.Transform(expression);
}
protected override Expression Transform(ArrayExpression ax)
{
// This should probably go depth-first.
if (ax.Elements.All(el => el is ItemElement item &&
item.Value is ConstantExpression))
{
return new ConstantExpression(
new SequenceValue(ax.Elements
.Cast<ItemElement>()
.Select(item => ((ConstantExpression)item.Value).Constant)));
}
return base.Transform(ax);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/DefaultFunctionNameResolver.cs
================================================
// 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 Serilog.Expressions.Runtime;
namespace Serilog.Expressions.Compilation;
static class DefaultFunctionNameResolver
{
public static NameResolver Build(NameResolver? additionalNameResolver)
{
var defaultResolver = new StaticMemberNameResolver(typeof(RuntimeOperators));
return additionalNameResolver == null
? defaultResolver
: new OrderedNameResolver(new[] {defaultResolver, additionalNameResolver });
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/ExpressionCompiler.cs
================================================
// 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 Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Arrays;
using Serilog.Expressions.Compilation.Linq;
using Serilog.Expressions.Compilation.Properties;
using Serilog.Expressions.Compilation.Text;
using Serilog.Expressions.Compilation.Variadics;
using Serilog.Expressions.Compilation.Wildcards;
namespace Serilog.Expressions.Compilation;
static class ExpressionCompiler
{
public static Expression Translate(Expression expression)
{
var actual = expression;
actual = VariadicCallRewriter.Rewrite(actual);
actual = TextMatchingTransformer.Rewrite(actual);
actual = LikeSyntaxTransformer.Rewrite(actual);
actual = PropertiesObjectAccessorTransformer.Rewrite(actual);
actual = ConstantArrayEvaluator.Rewrite(actual);
actual = WildcardComprehensionTransformer.Rewrite(actual);
return actual;
}
public static Evaluatable Compile(Expression expression, IFormatProvider? formatProvider, NameResolver nameResolver)
{
var actual = Translate(expression);
return LinqExpressionCompiler.Compile(actual, formatProvider, nameResolver);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/ExpressionValidationException.cs
================================================
// 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.Compilation;
class ExpressionValidationException : ArgumentException
{
public ExpressionValidationException(string message) : base(message)
{
}
public ExpressionValidationException(string message, Exception innerException) : base(message, innerException)
{
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/EventIdHash.cs
================================================
// 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.
// ReSharper disable ForCanBeConvertedToForeach
namespace Serilog.Expressions.Compilation.Linq;
/// <summary>
/// Hash functions for message templates. See <see cref="Compute"/>.
/// </summary>
public static class EventIdHash
{
/// <summary>
/// Compute a 32-bit hash of the provided <paramref name="messageTemplate"/>. The
/// resulting hash value can be uses as an event id in lieu of transmitting the
/// full template string.
/// </summary>
/// <param name="messageTemplate">A message template.</param>
/// <returns>A 32-bit hash of the template.</returns>
[CLSCompliant(false)]
public static uint Compute(string messageTemplate)
{
if (messageTemplate == null) throw new ArgumentNullException(nameof(messageTemplate));
// Jenkins one-at-a-time https://en.wikipedia.org/wiki/Jenkins_hash_function
unchecked
{
uint hash = 0;
for (var i = 0; i < messageTemplate.Length; ++i)
{
hash += messageTemplate[i];
hash += hash << 10;
hash ^= hash >> 6;
}
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
return hash;
}
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/ExpressionConstantMapper.cs
================================================
// 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.Linq.Expressions;
using Serilog.Events;
namespace Serilog.Expressions.Compilation.Linq;
class ExpressionConstantMapper : ExpressionVisitor
{
readonly IDictionary<object, Expression> _mapping;
public ExpressionConstantMapper(IDictionary<object, Expression> mapping)
{
_mapping = mapping;
}
protected override Expression VisitConstant(ConstantExpression node)
{
if (node.Value is ScalarValue { Value: {} sv } &&
_mapping.TryGetValue(sv, out var substitute))
return substitute;
return base.VisitConstant(node);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/Intrinsics.cs
================================================
// 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.Collections.Specialized;
using System.Text.RegularExpressions;
using Serilog.Events;
using Serilog.Expressions.Runtime;
using Serilog.Parsing;
using Serilog.Templates.Compilation;
// ReSharper disable ParameterTypeCanBeEnumerable.Global
namespace Serilog.Expressions.Compilation.Linq;
static class Intrinsics
{
static readonly LogEventPropertyValue NegativeOne = new ScalarValue(-1);
static readonly LogEventPropertyValue Tombstone = new ScalarValue("😬 (if you see this you have found a bug.)");
public static List<LogEventPropertyValue?> CollectSequenceElements(LogEventPropertyValue?[] elements)
{
return elements.ToList();
}
public static List<LogEventPropertyValue?> ExtendSequenceValueWithItem(List<LogEventPropertyValue?> elements,
LogEventPropertyValue? element)
{
// Mutates the list; returned so we can nest calls instead of emitting a block.
if (element != null)
elements.Add(element);
return elements;
}
public static List<LogEventPropertyValue?> ExtendSequenceValueWithSpread(List<LogEventPropertyValue?> elements,
LogEventPropertyValue? content)
{
if (content is SequenceValue sequence)
foreach (var element in sequence.Elements)
elements.Add(element);
return elements;
}
public static LogEventPropertyValue ConstructSequenceValue(List<LogEventPropertyValue?> elements)
{
if (elements.Any(el => el == null))
return new SequenceValue(elements.Where(el => el != null)!);
return new SequenceValue(elements!);
}
public static List<LogEventProperty> CollectStructureProperties(string[] names, LogEventPropertyValue?[] values)
{
var properties = new List<LogEventProperty>();
for (var i = 0; i < names.Length; ++i)
{
var name = names[i];
var value = values[i];
properties.Add(new(name, value ?? Tombstone));
}
return properties;
}
public static LogEventPropertyValue ConstructStructureValue(List<LogEventProperty> properties)
{
if (properties.Any(p => p == null || p.Value == Tombstone))
return new StructureValue(properties.Where(p => p != null && p.Value != Tombstone));
return new StructureValue(properties);
}
public static List<LogEventProperty> ExtendStructureValueWithSpread(
List<LogEventProperty> properties,
LogEventPropertyValue? content)
{
if (content is StructureValue structure)
{
foreach (var property in structure.Properties)
if (property != null)
properties.Add(property);
}
return properties;
}
public static List<LogEventProperty> ExtendStructureValueWithProperty(
List<LogEventProperty> properties,
string name,
LogEventPropertyValue? value)
{
// Mutates the list; returned so we can nest calls instead of emitting a block.
properties.Add(new(name, value ?? Tombstone));
return properties;
}
public static LogEventPropertyValue CompleteStructureValue(List<LogEventProperty> properties)
{
var result = new OrderedDictionary();
foreach (var property in properties)
{
if (result.Contains(property.Name))
result.Remove(property.Name);
if (property.Value != Tombstone)
result.Add(property.Name, new LogEventProperty(property.Name, property.Value));
}
return new StructureValue(result.Values.Cast<LogEventProperty>().ToList());
}
public static bool CoerceToScalarBoolean(LogEventPropertyValue value)
{
if (value is ScalarValue sv && sv.Value is bool b)
return b;
return false;
}
public static LogEventPropertyValue? IndexOfMatch(LogEventPropertyValue value, Regex regex)
{
if (value is ScalarValue scalar &&
scalar.Value is string s)
{
var m = regex.Match(s);
if (m.Success)
return new ScalarValue(m.Index);
return NegativeOne;
}
return null;
}
public static LogEventPropertyValue? GetPropertyValue(EvaluationContext ctx, string propertyName)
{
if (!ctx.LogEvent.Properties.TryGetValue(propertyName, out var value))
return null;
return value;
}
public static LogEventPropertyValue? GetLocalValue(EvaluationContext ctx, string localName)
{
if (!Locals.TryGetValue(ctx.Locals, localName, out var value))
return null;
return value;
}
public static LogEventPropertyValue? TryGetStructurePropertyValue(StringComparison sc, LogEventPropertyValue maybeStructure, string name)
{
if (maybeStructure is StructureValue sv)
{
foreach (var prop in sv.Properties)
{
if (prop.Name.Equals(name, sc))
{
return prop.Value;
}
}
}
return null;
}
// Use of `CompiledMessageToken` is a layering violation here, but we want to ensure the formatting implementations
// line up exactly. Some refactoring here might be worthwhile, though with an eye on indirection costs.
public static string RenderMessage(CompiledMessageToken formatter, EvaluationContext ctx)
{
var sw = new StringWriter();
formatter.Evaluate(ctx, sw);
return sw.ToString();
}
public static LogEventPropertyValue? GetRenderings(LogEvent logEvent, IFormatProvider? formatProvider)
{
List<LogEventPropertyValue>? elements = null;
foreach (var token in logEvent.MessageTemplate.Tokens)
{
if (token is PropertyToken {Format: { }} pt)
{
elements ??= new();
var space = new StringWriter();
pt.Render(logEvent.Properties, space, formatProvider);
elements.Add(new ScalarValue(space.ToString()));
}
}
return elements == null ? null : new SequenceValue(elements);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs
================================================
// 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.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Transformations;
using Serilog.Templates.Compilation;
using Serilog.Templates.Themes;
using ConstantExpression = Serilog.Expressions.Ast.ConstantExpression;
using Expression = Serilog.Expressions.Ast.Expression;
using ParameterExpression = System.Linq.Expressions.ParameterExpression;
using LX = System.Linq.Expressions.Expression;
using ExpressionBody = System.Linq.Expressions.Expression;
// ReSharper disable UseIndexFromEndExpression
namespace Serilog.Expressions.Compilation.Linq;
class LinqExpressionCompiler : SerilogExpressionTransformer<ExpressionBody>
{
readonly NameResolver _nameResolver;
readonly IFormatProvider? _formatProvider;
static readonly MethodInfo CollectSequenceElementsMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.CollectSequenceElements), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo ExtendSequenceValueWithSpreadMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.ExtendSequenceValueWithSpread), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo ExtendSequenceValueWithItemMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.ExtendSequenceValueWithItem), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo ConstructSequenceValueMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.ConstructSequenceValue), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo CollectStructurePropertiesMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.CollectStructureProperties), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo ConstructStructureValueMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.ConstructStructureValue), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo CompleteStructureValueMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.CompleteStructureValue), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo ExtendStructureValueWithSpreadMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.ExtendStructureValueWithSpread), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo ExtendStructureValueWithPropertyMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.ExtendStructureValueWithProperty), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo CoerceToScalarBooleanMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.CoerceToScalarBoolean), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo IndexOfMatchMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.IndexOfMatch), BindingFlags.Static | BindingFlags.Public)!;
static readonly MethodInfo TryGetStructurePropertyValueMethod = typeof(Intrinsics)
.GetMethod(nameof(Intrinsics.TryGetStructurePropertyValue), BindingFlags.Static | BindingFlags.Public)!;
static readonly PropertyInfo EvaluationContextLogEventProperty = typeof(EvaluationContext)
.GetProperty(nameof(EvaluationContext.LogEvent), BindingFlags.Instance | BindingFlags.Public)!;
ParameterExpression Context { get; } = LX.Variable(typeof(EvaluationContext), "ctx");
LinqExpressionCompiler(IFormatProvider? formatProvider, NameResolver nameResolver)
{
_nameResolver = nameResolver;
_formatProvider = formatProvider;
}
public static Evaluatable Compile(Expression expression, IFormatProvider? formatProvider,
NameResolver nameResolver)
{
if (expression == null) throw new ArgumentNullException(nameof(expression));
var compiler = new LinqExpressionCompiler(formatProvider, nameResolver);
var body = compiler.Transform(expression);
return LX.Lambda<Evaluatable>(body, compiler.Context).Compile();
}
ExpressionBody Splice(Expression<Evaluatable> lambda)
{
return ParameterReplacementVisitor.ReplaceParameters(lambda, Context);
}
protected override ExpressionBody Transform(CallExpression call)
{
if (!_nameResolver.TryResolveFunctionName(call.OperatorName, out var m))
throw new ExpressionValidationException($"The function name `{call.OperatorName}` was not recognized.");
var methodParameters = m.GetParameters()
.Select(info => (pi: info, optional: info.GetCustomAttribute<OptionalAttribute>() != null))
.ToList();
// Log warning for CI modifier usage on functions that don't support it
// Note: We log a warning rather than throwing to maintain backward compatibility
// Previously, invalid CI usage was silently ignored
if (call.IgnoreCase)
{
var supportsStringComparison = methodParameters.Any(p => p.pi.ParameterType == typeof(StringComparison));
if (!supportsStringComparison)
{
SelfLog.WriteLine($"The function `{call.OperatorName}` does not support case-insensitive operation; the 'ci' modifier will be ignored.");
}
}
var allowedParameters = methodParameters.Where(info => info.pi.ParameterType == typeof(LogEventPropertyValue)).ToList();
var requiredParameterCount = allowedParameters.Count(info => !info.optional);
if (call.Operands.Length < requiredParameterCount || call.Operands.Length > allowedParameters.Count)
{
var requirements = DescribeRequirements(allowedParameters.Select(info => (info.pi.Name!, info.optional)).ToList());
throw new ArgumentException($"The function `{call.OperatorName}` {requirements}.");
}
var operands = new Queue<LX>(call.Operands.Select(Transform));
// `and` and `or` short-circuit to save execution time; unlike the earlier Serilog.Filters.Expressions, nothing else does.
if (Operators.SameOperator(call.OperatorName, Operators.RuntimeOpAnd))
return CompileLogical(LX.AndAlso, operands.Dequeue(), operands.Dequeue());
if (Operators.SameOperator(call.OperatorName, Operators.RuntimeOpOr))
return CompileLogical(LX.OrElse, operands.Dequeue(), operands.Dequeue());
var boundParameters = new List<LX>(methodParameters.Count);
foreach (var (pi, optional) in methodParameters)
{
if (pi.ParameterType == typeof(LogEventPropertyValue))
{
boundParameters.Add(operands.Count > 0
? operands.Dequeue()
: LX.Constant(null, typeof(LogEventPropertyValue)));
}
else if (pi.ParameterType == typeof(StringComparison))
boundParameters.Add(LX.Constant(call.IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal));
else if (pi.ParameterType == typeof(IFormatProvider))
boundParameters.Add(LX.Constant(_formatProvider, typeof(IFormatProvider)));
else if (pi.ParameterType == typeof(LogEvent))
boundParameters.Add(LX.Property(Context, EvaluationContextLogEventProperty));
else if (_nameResolver.TryBindFunctionParameter(pi, out var binding))
boundParameters.Add(LX.Constant(binding, pi.ParameterType));
else if (optional)
boundParameters.Add(LX.Constant(
pi.GetCustomAttribute<DefaultParameterValueAttribute>()?.Value, pi.ParameterType));
else
throw new ArgumentException($"The method `{m.Name}` implementing function `{call.OperatorName}` has argument `{pi.Name}` which could not be bound.");
}
return LX.Call(m, boundParameters);
}
static string DescribeRequirements(IReadOnlyList<(string name, bool optional)> parameters)
{
static string DescribeArgument((string name, bool optional) p) =>
$"`{p.name}`" + (p.optional ? " (optional)" : "");
if (parameters.Count == 0)
return "accepts no arguments";
if (parameters.Count == 1)
return $"accepts one argument, {DescribeArgument(parameters[0])}";
if (parameters.Count == 2)
return $"accepts two arguments, {DescribeArgument(parameters[0])} and {DescribeArgument(parameters[1])}";
var result = new StringBuilder("accepts arguments");
for (var i = 0; i < parameters.Count - 1; ++i)
result.Append($" {DescribeArgument(parameters[i])},");
result.Append($" and {DescribeArgument(parameters[parameters.Count - 1])}");
return result.ToString();
}
static ExpressionBody CompileLogical(Func<ExpressionBody, ExpressionBody, ExpressionBody> apply, ExpressionBody lhs, ExpressionBody rhs)
{
return LX.Convert(
LX.New(
typeof(ScalarValue).GetConstructor([typeof(object)])!,
LX.Convert(apply(
LX.Call(CoerceToScalarBooleanMethod, lhs),
LX.Call(CoerceToScalarBooleanMethod, rhs)), typeof(object))),
typeof(LogEventPropertyValue));
}
protected override ExpressionBody Transform(AccessorExpression spx)
{
var receiver = Transform(spx.Receiver);
return LX.Call(TryGetStructurePropertyValueMethod, LX.Constant(StringComparison.Ordinal), receiver, LX.Constant(spx.MemberName, typeof(string)));
}
protected override ExpressionBody Transform(ConstantExpression cx)
{
return LX.Constant(cx.Constant);
}
protected override ExpressionBody Transform(AmbientNameExpression px)
{
if (px.IsBuiltIn)
{
var formatter = new CompiledMessageToken(_formatProvider, null, TemplateTheme.None);
var formatProvider = _formatProvider;
return px.PropertyName switch
{
BuiltInProperty.Level => Splice(context => new ScalarValue(context.LogEvent.Level)),
BuiltInProperty.Message => Splice(context => new ScalarValue(Intrinsics.RenderMessage(formatter, context))),
BuiltInProperty.Exception => Splice(context =>
context.LogEvent.Exception == null ? null : new ScalarValue(context.LogEvent.Exception)),
BuiltInProperty.TraceId => Splice(context =>
context.LogEvent.TraceId == null ? null : new ScalarValue(context.LogEvent.TraceId.Value)),
BuiltInProperty.SpanId => Splice(context =>
context.LogEvent.SpanId == null ? null : new ScalarValue(context.LogEvent.SpanId.Value)),
BuiltInProperty.Timestamp => Splice(context => new ScalarValue(context.LogEvent.Timestamp)),
BuiltInProperty.MessageTemplate => Splice(context => new ScalarValue(context.LogEvent.MessageTemplate.Text)),
BuiltInProperty.Properties => Splice(context =>
new StructureValue(context.LogEvent.Properties.Select(kvp => new LogEventProperty(kvp.Key, kvp.Value)),
null)),
BuiltInProperty.Renderings => Splice(context => Intrinsics.GetRenderings(context.LogEvent, formatProvider)),
BuiltInProperty.EventId => Splice(context =>
new ScalarValue(EventIdHash.Compute(context.LogEvent.MessageTemplate.Text))),
var alias when _nameResolver.TryResolveBuiltInPropertyName(alias, out var target) =>
Transform(new AmbientNameExpression(target, true)),
_ => LX.Constant(null, typeof(LogEventPropertyValue))
};
}
// Don't close over the AST node.
var propertyName = px.PropertyName;
return Splice(context => Intrinsics.GetPropertyValue(context, propertyName));
}
protected override ExpressionBody Transform(LocalNameExpression nlx)
{
// Don't close over the AST node.
var name = nlx.Name;
return Splice(context => Intrinsics.GetLocalValue(context, name));
}
protected override ExpressionBody Transform(Ast.LambdaExpression lmx)
{
var parameters = lmx.Parameters.Select(px => Tuple.Create(px, LX.Parameter(typeof(LogEventPropertyValue), px.ParameterName))).ToList();
var paramSwitcher = new ExpressionConstantMapper(parameters.ToDictionary(px => (object)px.Item1, px => (System.Linq.Expressions.Expression)px.Item2));
var rewritten = paramSwitcher.Visit(Transform(lmx.Body));
Type delegateType;
if (lmx.Parameters.Length == 1)
delegateType = typeof(Func<LogEventPropertyValue, LogEventPropertyValue>);
else if (lmx.Parameters.Length == 2)
delegateType = typeof(Func<LogEventPropertyValue, LogEventPropertyValue, LogEventPropertyValue>);
else
throw new NotSupportedException("Unsupported lambda signature.");
var lambda = LX.Lambda(delegateType, rewritten!, parameters.Select(px => px.Item2).ToArray());
// Unfortunately, right now, functions need to be threaded through in constant scalar values :-D
return LX.New(typeof(ScalarValue).GetConstructor([typeof(object)])!,
LX.Convert(lambda, typeof(object)));
}
protected override ExpressionBody Transform(Ast.ParameterExpression prx)
{
// Will be within a lambda, which will subsequently sub-in the actual value.
// The `prx` placeholder needs to be wrapped in a `ScalarValue` so that eager
// typechecking doesn't fail before we've substituted the real value in.
return LX.Constant(new ScalarValue(prx), typeof(LogEventPropertyValue));
}
protected override ExpressionBody Transform(IndexerWildcardExpression wx)
{
return LX.Constant(null, typeof(LogEventPropertyValue));
}
protected override ExpressionBody Transform(ArrayExpression ax)
{
var elements = new List<ExpressionBody>(ax.Elements.Length);
var i = 0;
for (; i < ax.Elements.Length; ++i)
{
var element = ax.Elements[i];
if (element is ItemElement item)
elements.Add(Transform(item.Value));
else
break;
}
var arr = LX.NewArrayInit(typeof(LogEventPropertyValue), elements.ToArray());
var collected = LX.Call(CollectSequenceElementsMethod, arr);
for (; i < ax.Elements.Length; ++i)
{
var element = ax.Elements[i];
if (element is ItemElement item)
collected = LX.Call(ExtendSequenceValueWithItemMethod, collected, Transform(item.Value));
else
{
var spread = (SpreadElement) element;
collected = LX.Call(ExtendSequenceValueWithSpreadMethod, collected, Transform(spread.Content));
}
}
return LX.Call(ConstructSequenceValueMethod, collected);
}
protected override ExpressionBody Transform(ObjectExpression ox)
{
var names = new List<string>();
var values = new List<ExpressionBody>();
var i = 0;
for (; i < ox.Members.Length; ++i)
{
var member = ox.Members[i];
if (member is PropertyMember property)
{
if (names.Contains(property.Name))
{
var oldPos = names.IndexOf(property.Name);
values[oldPos] = Transform(property.Value);
}
else
{
names.Add(property.Name);
values.Add(Transform(property.Value));
}
}
else
{
break;
}
}
var namesConstant = LX.Constant(names.ToArray(), typeof(string[]));
var valuesArr = LX.NewArrayInit(typeof(LogEventPropertyValue), values.ToArray());
var properties = LX.Call(CollectStructurePropertiesMethod, namesConstant, valuesArr);
if (i == ox.Members.Length)
{
// No spreads; more efficient than `Complete*` because erasure is not required.
return LX.Call(ConstructStructureValueMethod, properties);
}
for (; i < ox.Members.Length; ++i)
{
var member = ox.Members[i];
if (member is PropertyMember property)
{
properties = LX.Call(
ExtendStructureValueWithPropertyMethod,
properties,
LX.Constant(property.Name),
Transform(property.Value));
}
else
{
var spread = (SpreadMember) member;
properties = LX.Call(
ExtendStructureValueWithSpreadMethod,
properties,
Transform(spread.Content));
}
}
return LX.Call(CompleteStructureValueMethod, properties);
}
protected override ExpressionBody Transform(IndexerExpression ix)
{
return Transform(new CallExpression(false, Operators.OpElementAt, ix.Receiver, ix.Index));
}
protected override ExpressionBody Transform(IndexOfMatchExpression mx)
{
var rx = LX.Constant(mx.Regex);
var target = Transform(mx.Corpus);
return LX.Call(IndexOfMatchMethod, target, rx);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/ParameterReplacementVisitor.cs
================================================
// 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.Linq.Expressions;
namespace Serilog.Expressions.Compilation.Linq;
class ParameterReplacementVisitor : ExpressionVisitor
{
readonly ParameterExpression[] _from, _to;
public static Expression ReplaceParameters(LambdaExpression lambda, params ParameterExpression[] newParameters)
{
var v = new ParameterReplacementVisitor(lambda.Parameters.ToArray(), newParameters);
return v.Visit(lambda.Body)!;
}
ParameterReplacementVisitor(ParameterExpression[] from, ParameterExpression[] to)
{
if (from == null) throw new ArgumentNullException(nameof(from));
if (to == null) throw new ArgumentNullException(nameof(to));
if (from.Length != to.Length) throw new InvalidOperationException("Mismatched parameter lists");
_from = from;
_to = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
for (var i = 0; i < _from.Length; i++)
{
if (node == _from[i]) return _to[i];
}
return node;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/OrderedNameResolver.cs
================================================
// 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.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace Serilog.Expressions.Compilation;
class OrderedNameResolver : NameResolver
{
readonly NameResolver[] _orderedResolvers;
public OrderedNameResolver(IEnumerable<NameResolver> orderedResolvers)
{
_orderedResolvers = orderedResolvers.ToArray();
}
public override bool TryResolveFunctionName(string name, [MaybeNullWhen(false)] out MethodInfo implementation)
{
foreach (var resolver in _orderedResolvers)
{
if (resolver.TryResolveFunctionName(name, out implementation))
return true;
}
implementation = null;
return false;
}
public override bool TryBindFunctionParameter(ParameterInfo parameter, [MaybeNullWhen(false)] out object boundValue)
{
foreach (var resolver in _orderedResolvers)
{
if (resolver.TryBindFunctionParameter(parameter, out boundValue))
return true;
}
boundValue = null;
return false;
}
public override bool TryResolveBuiltInPropertyName(string alias, [NotNullWhen(true)] out string? target)
{
foreach (var resolver in _orderedResolvers)
{
if (resolver.TryResolveBuiltInPropertyName(alias, out target))
return true;
}
target = null;
return false;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Pattern.cs
================================================
// 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.Diagnostics.CodeAnalysis;
using Serilog.Events;
using Serilog.Expressions.Ast;
namespace Serilog.Expressions.Compilation;
static class Pattern
{
public static bool IsAmbientProperty(Expression expression, string name, bool isBuiltIn)
{
return expression is AmbientNameExpression px &&
px.PropertyName == name &&
px.IsBuiltIn == isBuiltIn;
}
public static bool IsStringConstant(Expression expression, [MaybeNullWhen(false)] out string value)
{
if (expression is ConstantExpression cx &&
cx.Constant is ScalarValue sv &&
sv.Value is string s)
{
value = s;
return true;
}
value = null;
return false;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Properties/PropertiesObjectAccessorTransformer.cs
================================================
// 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 Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Transformations;
namespace Serilog.Expressions.Compilation.Properties;
class PropertiesObjectAccessorTransformer : IdentityTransformer
{
public static Expression Rewrite(Expression actual)
{
return new PropertiesObjectAccessorTransformer().Transform(actual);
}
protected override Expression Transform(AccessorExpression ax)
{
if (!Pattern.IsAmbientProperty(ax.Receiver, BuiltInProperty.Properties, true))
return base.Transform(ax);
return new AmbientNameExpression(ax.MemberName, false);
}
protected override Expression Transform(IndexerExpression ix)
{
if (!Pattern.IsAmbientProperty(ix.Receiver, BuiltInProperty.Properties, true) ||
!Pattern.IsStringConstant(ix.Index, out var name))
return base.Transform(ix);
return new AmbientNameExpression(name, false);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Text/LikeSyntaxTransformer.cs
================================================
// 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.Text.RegularExpressions;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Transformations;
namespace Serilog.Expressions.Compilation.Text;
class LikeSyntaxTransformer: IdentityTransformer
{
static readonly LikeSyntaxTransformer Instance = new();
public static Expression Rewrite(Expression expression)
{
return Instance.Transform(expression);
}
protected override Expression Transform(CallExpression call)
{
if (call.Operands.Length != 2)
return base.Transform(call);
if (Operators.SameOperator(call.OperatorName, Operators.IntermediateOpLike))
return TryCompileLikeExpression(call.IgnoreCase, call.Operands[0], call.Operands[1]);
if (Operators.SameOperator(call.OperatorName, Operators.IntermediateOpNotLike))
return new CallExpression(
false,
Operators.RuntimeOpStrictNot,
TryCompileLikeExpression(call.IgnoreCase, call.Operands[0], call.Operands[1]));
return base.Transform(call);
}
Expression TryCompileLikeExpression(bool ignoreCase, Expression corpus, Expression like)
{
if (like is ConstantExpression { Constant: ScalarValue { Value: string s } })
{
var regex = LikeToRegex(s);
var opts = RegexOptions.Compiled | RegexOptions.ExplicitCapture;
if (ignoreCase)
opts |= RegexOptions.IgnoreCase;
var compiled = new Regex(regex, opts, TimeSpan.FromMilliseconds(100));
var indexof = new IndexOfMatchExpression(Transform(corpus), compiled);
return new CallExpression(ignoreCase, Operators.RuntimeOpNotEqual, indexof, new ConstantExpression(new ScalarValue(-1)));
}
SelfLog.WriteLine($"Serilog.Expressions: `like` requires a constant string argument; found ${like}.");
return new CallExpression(false, Operators.OpUndefined);
}
static string LikeToRegex(string like)
{
var begin = "^";
var regex = "";
var end = "$";
for (var i = 0; i < like.Length; ++i)
{
var ch = like[i];
var following = i == like.Length - 1 ? (char?)null : like[i + 1];
if (ch == '%')
{
if (following == '%')
{
regex += '%';
++i;
}
else
{
if (i == 0)
begin = "";
if (i == like.Length - 1)
end = "";
if (i == 0 && i == like.Length - 1)
regex += ".*";
if (i != 0 && i != like.Length - 1)
regex += "(?:.|\\r|\\n)*"; // ~= RegexOptions.Singleline
}
}
else if (ch == '_')
{
if (following == '_')
{
regex += '_';
++i;
}
else
{
regex += '.'; // Newlines aren't considered matches for _
}
}
else
regex += Regex.Escape(ch.ToString());
}
return begin + regex + end;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Text/TextMatchingTransformer.cs
================================================
// 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.Text.RegularExpressions;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Transformations;
namespace Serilog.Expressions.Compilation.Text;
class TextMatchingTransformer: IdentityTransformer
{
static readonly TextMatchingTransformer Instance = new();
public static Expression Rewrite(Expression expression)
{
return Instance.Transform(expression);
}
protected override Expression Transform(CallExpression call)
{
if (call.Operands.Length != 2)
return base.Transform(call);
if (Operators.SameOperator(call.OperatorName, Operators.OpIndexOfMatch))
return TryCompileIndexOfMatch(call.IgnoreCase, call.Operands[0], call.Operands[1]);
if (Operators.SameOperator(call.OperatorName, Operators.OpIsMatch))
return new CallExpression(
false,
Operators.RuntimeOpNotEqual,
TryCompileIndexOfMatch(call.IgnoreCase, call.Operands[0], call.Operands[1]),
new ConstantExpression(new ScalarValue(-1)));
return base.Transform(call);
}
Expression TryCompileIndexOfMatch(bool ignoreCase, Expression corpus, Expression regex)
{
if (regex is ConstantExpression { Constant: ScalarValue { Value: string s } })
{
try
{
var opts = RegexOptions.Compiled | RegexOptions.ExplicitCapture;
if (ignoreCase)
opts |= RegexOptions.IgnoreCase;
var compiled = new Regex(s, opts, TimeSpan.FromMilliseconds(100));
return new IndexOfMatchExpression(Transform(corpus), compiled);
}
catch (ArgumentException ex)
{
throw new ExpressionValidationException($"Invalid regular expression in IndexOfMatch: {ex.Message}", ex);
}
}
SelfLog.WriteLine($"Serilog.Expressions: `IndexOfMatch()` requires a constant string regular expression argument; found {regex}.");
return new CallExpression(false, Operators.OpUndefined);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Transformations/IdentityTransformer.cs
================================================
// 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 Serilog.Expressions.Ast;
namespace Serilog.Expressions.Compilation.Transformations;
class IdentityTransformer : SerilogExpressionTransformer<Expression>
{
bool TryTransform(Expression expr, out Expression result)
{
result = Transform(expr);
return !ReferenceEquals(expr, result);
}
protected override Expression Transform(CallExpression call)
{
var any = false;
var operands = new List<Expression>();
foreach (var op in call.Operands)
{
if (TryTransform(op, out var result))
any = true;
operands.Add(result);
}
if (!any)
return call;
return new CallExpression(call.IgnoreCase, call.OperatorName, operands.ToArray());
}
protected override Expression Transform(ConstantExpression cx)
{
return cx;
}
protected override Expression Transform(AmbientNameExpression px)
{
return px;
}
protected override Expression Transform(LocalNameExpression nlx)
{
return nlx;
}
protected override Expression Transform(AccessorExpression spx)
{
if (!TryTransform(spx.Receiver, out var recv))
return spx;
return new AccessorExpression(recv, spx.MemberName);
}
protected override Expression Transform(LambdaExpression lmx)
{
if (!TryTransform(lmx.Body, out var body))
return lmx;
// By default we maintain the parameters available in the body
return new LambdaExpression(lmx.Parameters, body);
}
// Only touches uses of the parameters, not decls
protected override Expression Transform(ParameterExpression prx)
{
return prx;
}
protected override Expression Transform(IndexerWildcardExpression wx)
{
return wx;
}
protected override Expression Transform(ArrayExpression ax)
{
var any = false;
var elements = new List<Element>();
foreach (var el in ax.Elements)
{
if (el is ItemElement item)
{
if (TryTransform(item.Value, out var result))
any = true;
elements.Add(new ItemElement(result));
}
else
{
var spread = (SpreadElement) el;
if (TryTransform(spread.Content, out var result))
any = true;
elements.Add(new SpreadElement(result));
}
}
if (!any)
return ax;
return new ArrayExpression(elements.ToArray());
}
protected override Expression Transform(ObjectExpression ox)
{
var any = false;
var members = new List<Member>();
foreach (var m in ox.Members)
{
if (m is PropertyMember p)
{
if (TryTransform(p.Value, out var result))
any = true;
members.Add(new PropertyMember(p.Name, result));
}
else
{
var s = (SpreadMember) m;
if (TryTransform(s.Content, out var result))
any = true;
members.Add(new SpreadMember(result));
}
}
if (!any)
return ox;
return new ObjectExpression(members.ToArray());
}
protected override Expression Transform(IndexerExpression ix)
{
var transformedRecv = TryTransform(ix.Receiver, out var recv);
if (!TryTransform(ix.Index, out var index) && !transformedRecv)
return ix;
return new IndexerExpression(recv, index);
}
protected override Expression Transform(IndexOfMatchExpression mx)
{
if (!TryTransform(mx.Corpus, out var corpus))
return mx;
return new IndexOfMatchExpression(corpus, mx.Regex);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Transformations/NodeReplacer.cs
================================================
// 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 Serilog.Expressions.Ast;
namespace Serilog.Expressions.Compilation.Transformations;
class NodeReplacer : IdentityTransformer
{
readonly Expression _source;
readonly Expression _dest;
public static Expression Replace(Expression expr, Expression source, Expression dest)
{
var replacer = new NodeReplacer(source, dest);
return replacer.Transform(expr);
}
NodeReplacer(Expression source, Expression dest)
{
_source = source;
_dest = dest;
}
protected override Expression Transform(Expression x)
{
if (x == _source)
return _dest;
return base.Transform(x);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Transformations/SerilogExpressionTransformer.cs
================================================
// 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 Serilog.Expressions.Ast;
namespace Serilog.Expressions.Compilation.Transformations;
abstract class SerilogExpressionTransformer<TResult>
{
protected virtual TResult Transform(Expression expression)
{
return expression switch
{
CallExpression call => Transform(call),
ConstantExpression constant => Transform(constant),
AccessorExpression accessor => Transform(accessor),
AmbientNameExpression property => Transform(property),
LocalNameExpression local => Transform(local),
LambdaExpression lambda => Transform(lambda),
ParameterExpression parameter => Transform(parameter),
IndexerWildcardExpression wildcard => Transform(wildcard),
ArrayExpression array => Transform(array),
ObjectExpression obj => Transform(obj),
IndexerExpression indexer => Transform(indexer),
IndexOfMatchExpression match => Transform(match),
null => throw new ArgumentNullException(nameof(expression)),
// Non-exhaustive because `InternalsVisibleTo` is applied to the assembly.
_ => throw new NotSupportedException($"{expression} is not supported.")
};
}
protected abstract TResult Transform(CallExpression call);
protected abstract TResult Transform(ConstantExpression cx);
protected abstract TResult Transform(AmbientNameExpression px);
protected abstract TResult Transform(LocalNameExpression nlx);
protected abstract TResult Transform(AccessorExpression spx);
protected abstract TResult Transform(LambdaExpression lmx);
protected abstract TResult Transform(ParameterExpression prx);
protected abstract TResult Transform(IndexerWildcardExpression wx);
protected abstract TResult Transform(ArrayExpression ax);
protected abstract TResult Transform(ObjectExpression ox);
protected abstract TResult Transform(IndexerExpression ix);
protected abstract TResult Transform(IndexOfMatchExpression mx);
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Variadics/VariadicCallRewriter.cs
================================================
// 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 Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Transformations;
namespace Serilog.Expressions.Compilation.Variadics;
// Handles variadic `coalesce()` and `concat()`, as well as optional arguments for other functions.
class VariadicCallRewriter : IdentityTransformer
{
static readonly VariadicCallRewriter Instance = new();
public static Expression Rewrite(Expression expression)
{
return Instance.Transform(expression);
}
protected override Expression Transform(CallExpression call)
{
if (Operators.SameOperator(call.OperatorName, Operators.OpCoalesce) ||
Operators.SameOperator(call.OperatorName, Operators.OpConcat))
{
if (call.Operands.Length == 0)
return new CallExpression(false, Operators.OpUndefined);
if (call.Operands.Length == 1)
return Transform(call.Operands.Single());
if (call.Operands.Length > 2)
{
var first = Transform(call.Operands.First());
return new CallExpression(call.IgnoreCase, call.OperatorName, first,
Transform(new CallExpression(call.IgnoreCase, call.OperatorName, call.Operands.Skip(1).ToArray())));
}
}
return base.Transform(call);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Wildcards/WildcardComprehensionTransformer.cs
================================================
// 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 Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Transformations;
namespace Serilog.Expressions.Compilation.Wildcards;
class WildcardComprehensionTransformer : IdentityTransformer
{
int _nextParameter;
public static Expression Rewrite(Expression root)
{
var wc = new WildcardComprehensionTransformer();
return wc.Transform(root);
}
// This matches expression fragments such as `A[?] = 'test'` and
// transforms them into `any(A, |p| p = 'test)`.
//
// As the comparand in such expressions can be complex, e.g.
// `Substring(A[?], 0, 4) = 'test')`, the search for `?` and `*` wildcards
// is deep, but, it terminates upon reaching any other wildcard-compatible
// comparison. Thus `(A[?] = 'test') = true` will result in `any(A, |p| p = 'test') = true` and
// not `any(A, |p| (p = 'test') = true)`, which is important because short-circuiting when the first
// argument to `any()` is undefined will change the semantics of the resulting expression, otherwise.
protected override Expression Transform(CallExpression lx)
{
if (!Operators.WildcardComparators.Contains(lx.OperatorName))
return base.Transform(lx);
IndexerExpression? indexer = null;
Expression? wildcardPath = null;
var indexerOperand = -1;
for (var i = 0; i < lx.Operands.Length; ++i)
{
indexer = WildcardSearch.FindWildcardIndexer(lx.Operands[i]);
if (indexer != null)
{
indexerOperand = i;
wildcardPath = lx.Operands[i];
break;
}
}
if (indexer == null || wildcardPath == null)
return base.Transform(lx); // N/A, or invalid
var px = new ParameterExpression("p" + _nextParameter++);
var nestedComparand = NodeReplacer.Replace(wildcardPath, indexer, px);
var coll = indexer.Receiver;
var wc = ((IndexerWildcardExpression)indexer.Index).Wildcard;
var comparisonArgs = lx.Operands.ToArray();
comparisonArgs[indexerOperand] = nestedComparand;
var body = new CallExpression(lx.IgnoreCase, lx.OperatorName, comparisonArgs);
var lambda = new LambdaExpression([px], body);
var op = Operators.ToRuntimeWildcardOperator(wc);
var call = new CallExpression(false, op, coll, lambda);
return Transform(call);
}
// Detects and transforms standalone `A[?]` fragments that are not part of a comparision; these
// are effectively Boolean tests.
protected override Expression Transform(IndexerExpression ix)
{
if (ix.Index is not IndexerWildcardExpression wx)
return base.Transform(ix);
var px = new ParameterExpression("p" + _nextParameter++);
var coll = Transform(ix.Receiver);
var lambda = new LambdaExpression([px], px);
var op = Operators.ToRuntimeWildcardOperator(wx.Wildcard);
return new CallExpression(false, op, coll, lambda);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Compilation/Wildcards/WildcardSearch.cs
================================================
// 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 Serilog.Expressions.Ast;
using Serilog.Expressions.Compilation.Transformations;
namespace Serilog.Expressions.Compilation.Wildcards;
class WildcardSearch : SerilogExpressionTransformer<IndexerExpression?>
{
static readonly WildcardSearch Instance = new();
public static IndexerExpression? FindWildcardIndexer(Expression fx)
{
return Instance.Transform(fx);
}
protected override IndexerExpression? Transform(IndexerExpression ix)
{
if (ix.Index is IndexerWildcardExpression)
return ix;
return Transform(ix.Receiver);
}
protected override IndexerExpression? Transform(ConstantExpression cx)
{
return null;
}
protected override IndexerExpression? Transform(AmbientNameExpression px)
{
return null;
}
protected override IndexerExpression? Transform(LocalNameExpression nlx)
{
return null;
}
protected override IndexerExpression? Transform(AccessorExpression spx)
{
return Transform(spx.Receiver);
}
protected override IndexerExpression? Transform(LambdaExpression lmx)
{
return null;
}
protected override IndexerExpression? Transform(ParameterExpression prx)
{
return null;
}
protected override IndexerExpression? Transform(IndexerWildcardExpression wx)
{
// Must be within an indexer
return null;
}
protected override IndexerExpression? Transform(ArrayExpression ax)
{
return null;
}
protected override IndexerExpression? Transform(CallExpression call)
{
// If we hit a wildcard-compatible operation, then any wildcards within its operands "belong" to
// it and can't be the result of this search.
if (Operators.WildcardComparators.Contains(call.OperatorName))
return null;
return call.Operands.Select(Transform).FirstOrDefault(e => e != null);
}
protected override IndexerExpression? Transform(IndexOfMatchExpression mx)
{
return Transform(mx.Corpus);
}
protected override IndexerExpression? Transform(ObjectExpression ox)
{
return null;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/CompiledExpression.cs
================================================
// 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 Serilog.Events;
namespace Serilog.Expressions;
/// <summary>
/// A compiled expression evaluated against a <see cref="LogEvent"/>.
/// </summary>
/// <param name="logEvent"></param>
/// <returns>The result of evaluating the expression, represented as a <see cref="LogEventPropertyValue"/>,
/// or <c langword="null">null</c> if the result is undefined.</returns>
public delegate LogEventPropertyValue? CompiledExpression(LogEvent logEvent);
================================================
FILE: src/Serilog.Expressions/Expressions/Evaluatable.cs
================================================
// 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 Serilog.Events;
namespace Serilog.Expressions;
delegate LogEventPropertyValue? Evaluatable(EvaluationContext ctx);
================================================
FILE: src/Serilog.Expressions/Expressions/EvaluationContext.cs
================================================
// 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 Serilog.Events;
using Serilog.Expressions.Runtime;
namespace Serilog.Expressions;
readonly struct EvaluationContext
{
public LogEvent LogEvent { get; }
public Locals? Locals { get; }
public EvaluationContext(LogEvent logEvent, Locals? locals = null)
{
LogEvent = logEvent ?? throw new ArgumentNullException(nameof(logEvent));
Locals = locals;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/ExpressionResult.cs
================================================
// 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 Serilog.Events;
using Serilog.Expressions.Runtime;
namespace Serilog.Expressions;
/// <summary>
/// Helper functions for working with the results of evaluating expressions.
/// </summary>
public static class ExpressionResult
{
/// <summary>
/// Test whether <paramref name="value"/> is <c langword="true">true</c>.
/// </summary>
/// <param name="value">The value to test, which may be <c langword="null">null</c>
/// if the result of evaluating an expression was undefined.</param>
/// <returns>Returns <c langword="true">true</c> if and only if the
/// <paramref name="value"/> is a scalar Boolean with the
/// value <c langword="true">true</c>. Returns <c langword="false">false</c>, otherwise.</returns>
public static bool IsTrue(LogEventPropertyValue? value)
{
return Coerce.IsTrue(value);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Helpers.cs
================================================
// 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.Text.RegularExpressions;
#if NO_CI_STRING_CONTAINS
namespace Serilog.Expressions
{
/// <summary>
/// Helper methods.
/// </summary>
static class Helpers
{
/// <summary>
/// Backport .NET Standard 2.1 additions to maintain .NET Standard 2.0 compatibility.
/// Returns a value indicating whether a specified string occurs within this string, using the specified comparison rules.
///
/// From;
/// https://github.com/dotnet/runtime/issues/22198
/// https://stackoverflow.com/questions/444798/case-insensitive-containsstring/444818#444818
/// </summary>
/// <param name="this">input string</param>
/// <param name="value">The string to seek.</param>
/// <param name="comparisonType">Specifies the rule to use in the comparison.</param>
/// <returns></returns>
public static bool Contains(this string @this, string value, StringComparison comparisonType)
{
return @this.IndexOf(value, comparisonType) >= 0;
}
public static string Replace(this string @this, string oldValue, string newValue, StringComparison comparisonType)
{
if ("a".Equals("A", comparisonType))
{
return Regex.Replace(
@this,
Regex.Escape(oldValue),
newValue.Replace("$", "$$"),
RegexOptions.IgnoreCase);
}
return @this.Replace(oldValue, newValue);
}
}
}
#endif
================================================
FILE: src/Serilog.Expressions/Expressions/LoggingFilterSwitch.cs
================================================
// 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 Serilog.Core;
using Serilog.Events;
using Serilog.Expressions.Runtime;
namespace Serilog.Expressions;
/// <summary>
/// A log event filter that can be modified at runtime.
/// </summary>
public class LoggingFilterSwitch : ILogEventFilter
{
// Reference assignments are atomic. While this class makes
// no attempt to synchronize Expression, ToString(), and IsIncluded(),
// for any observer, this at least ensures they won't be permanently out-of-sync for
// all observers.
volatile Tuple<string, CompiledExpression>? _filter;
/// <summary>
/// Construct a <see cref="LoggingFilterSwitch"/>, optionally initialized
/// with the <paramref name="expression"/>.
/// </summary>
/// <param name="expression">A filter expression against which log events will be tested.
/// Only expressions that evaluate to <c>true</c> are included
/// by the filter. A <c>null</c> expression will accept all
/// events.</param>
public LoggingFilterSwitch(string? expression = null)
{
Expression = expression;
}
/// <summary>
/// A filter expression against which log events will be tested.
/// Only expressions that evaluate to <c>true</c> are included
/// by the filter. A <c>null</c> expression will accept all
/// events.
/// </summary>
public string? Expression
{
// ReSharper disable once UnusedMember.Global
get
{
var filter = _filter;
return filter?.Item1;
}
set
{
if (value == null)
{
_filter = null;
}
else
{
_filter = new(
value,
SerilogExpression.Compile(value));
}
}
}
/// <inheritdoc/>
public bool IsEnabled(LogEvent logEvent)
{
if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
var filter = _filter;
if (filter == null)
return true;
return Coerce.IsTrue(filter.Item2(logEvent));
}
/// <inheritdoc/>
public override string ToString()
{
var filter = _filter;
return filter?.Item1 ?? "";
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/NameResolver.cs
================================================
// 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.Diagnostics.CodeAnalysis;
using System.Reflection;
using Serilog.Events;
namespace Serilog.Expressions;
/// <summary>
/// Looks up the implementations of functions that appear in expressions.
/// </summary>
public abstract class NameResolver
{
/// <summary>
/// Match a function name to a method that implements it.
/// </summary>
/// <param name="name">The function name as it appears in the expression source. Names are not case-sensitive.</param>
/// <param name="implementation">A <see cref="MethodInfo"/> implementing the function.</param>
/// <returns><c>True</c> if the name could be resolved; otherwise, <c>false</c>.</returns>
/// <remarks>The method implementing a function should be <c>static</c>, return <see cref="LogEventPropertyValue"/>,
/// and accept parameters of type <see cref="LogEventPropertyValue"/>. If the <c>ci</c> modifier is supported,
/// a <see cref="StringComparison"/> should be included in the argument list. If the function is culture-specific,
/// an <see cref="IFormatProvider"/> should be included in the argument list.</remarks>
public virtual bool TryResolveFunctionName(string name, [MaybeNullWhen(false)] out MethodInfo implementation)
{
implementation = null;
return false;
}
/// <summary>
/// Provide a value for a non-<see cref="LogEventPropertyValue"/> parameter. This allows user-defined state to
/// be threaded through user-defined functions.
/// </summary>
/// <param name="parameter">A parameter of a method implementing a user-defined function, which could not be
/// bound to any of the standard runtime-provided values or operands.</param>
/// <param name="boundValue">The value that should be provided when the method is called.</param>
/// <returns><c>True</c> if the parameter could be bound; otherwise, <c>false</c>.</returns>
public virtual bool TryBindFunctionParameter(ParameterInfo parameter, [MaybeNullWhen(false)] out object boundValue)
{
boundValue = null;
return false;
}
/// <summary>
/// Map an unrecognized built-in property name to a recognised one.
/// </summary>
/// <remarks>Intended predominantly to support migration from <em>Serilog.Filters.Expressions</em>.</remarks>
/// <param name="alias">The unrecognized name, for example, <code>"Message"</code>; the <code>@</code> prefix is
/// not included.</param>
/// <param name="target">If the name could be resolved, the target property name, without any prefix; for
/// example, <code>"m"</code>.</param>
/// <returns>True if the alias was mapped to a built-in property; otherwise, false.</returns>
public virtual bool TryResolveBuiltInPropertyName(string alias, [NotNullWhen(true)] out string? target)
{
target = null;
return false;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Operators.cs
================================================
// 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 Serilog.Expressions.Ast;
// ReSharper disable InconsistentNaming, MemberCanBePrivate.Global
namespace Serilog.Expressions;
static class Operators
{
static StringComparer OperatorComparer { get; } = StringComparer.OrdinalIgnoreCase;
// Core filter language
// Op* means usable in expressions _and_ runtime executable.
// RuntimeOp* means runtime only.
public const string OpCoalesce = "Coalesce";
public const string OpConcat = "Concat";
public const string OpContains = "Contains";
public const string OpElementAt = "ElementAt";
public const string OpEndsWith = "EndsWith";
public const string OpIndexOf = "IndexOf";
public const string OpIndexOfMatch = "IndexOfMatch";
public const string OpInspect = "Inspect";
public const string OpIsMatch = "IsMatch";
public const string OpIsDefined = "IsDefined";
public const string OpLastIndexOf = "LastIndexOf";
public const string OpLength = "Length";
public const string OpNest = "Nest";
public const string OpNow = "Now";
public const string OpReplace = "Replace";
public const string OpRound = "Round";
public const string OpStartsWith = "StartsWith";
public const string OpSubstring = "Substring";
public const string OpTagOf = "TagOf";
public const string OpToString = "ToString";
public const string OpTypeOf = "TypeOf";
public const string OpUndefined = "Undefined";
public const string OpUtcDateTime = "UtcDateTime";
public const string IntermediateOpLike = "_Internal_Like";
public const string IntermediateOpNotLike = "_Internal_NotLike";
public const string RuntimeOpAdd = "_Internal_Add";
public const string RuntimeOpSubtract = "_Internal_Subtract";
public const string RuntimeOpMultiply = "_Internal_Multiply";
public const string RuntimeOpDivide = "_Internal_Divide";
public const string RuntimeOpModulo = "_Internal_Modulo";
public const string RuntimeOpPower = "_Internal_Power";
public const string RuntimeOpAnd = "_Internal_And";
public const string RuntimeOpOr = "_Internal_Or";
public const string RuntimeOpLessThanOrEqual = "_Internal_LessThanOrEqual";
public const string RuntimeOpLessThan = "_Internal_LessThan";
public const string RuntimeOpGreaterThan = "_Internal_GreaterThan";
public const string RuntimeOpGreaterThanOrEqual = "_Internal_GreaterThanOrEqual";
public const string RuntimeOpEqual = "_Internal_Equal";
public const string RuntimeOpNotEqual = "_Internal_NotEqual";
public const string RuntimeOpNegate = "_Internal_Negate";
public const string RuntimeOpNot = "_Internal_Not";
public const string RuntimeOpAny = "_Internal_Any";
public const string RuntimeOpAll = "_Internal_All";
public const string RuntimeOpIsNull = "_Internal_IsNull";
public const string RuntimeOpIsNotNull = "_Internal_IsNotNull";
public const string RuntimeOpIn = "_Internal_In";
public const string RuntimeOpNotIn = "_Internal_NotIn";
public const string RuntimeOpStrictNot = "_Internal_StrictNot";
public const string RuntimeOpIfThenElse = "_Internal_IfThenElse";
public static readonly HashSet<string> WildcardComparators = new(OperatorComparer)
{
OpContains,
OpStartsWith,
OpEndsWith,
RuntimeOpNotEqual,
RuntimeOpEqual,
RuntimeOpLessThan,
RuntimeOpLessThanOrEqual,
RuntimeOpGreaterThan,
RuntimeOpGreaterThanOrEqual,
IntermediateOpLike,
IntermediateOpNotLike,
RuntimeOpIn,
RuntimeOpNotIn,
OpIsMatch,
OpIsDefined,
RuntimeOpIsNull,
RuntimeOpIsNotNull,
RuntimeOpAny,
RuntimeOpAll
};
public static bool SameOperator(string op1, string op2)
{
if (op1 == null) throw new ArgumentNullException(nameof(op1));
if (op2 == null) throw new ArgumentNullException(nameof(op2));
return OperatorComparer.Equals(op1, op2);
}
public static string ToRuntimeWildcardOperator(IndexerWildcard wildcard)
{
return wildcard switch
{
IndexerWildcard.All => RuntimeOpAll,
IndexerWildcard.Any => RuntimeOpAny,
_ => throw new ArgumentException("Unsupported wildcard.")
};
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Parsing/Combinators.cs
================================================
// 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 Serilog.ParserConstruction;
using Serilog.ParserConstruction.Model;
namespace Serilog.Expressions.Parsing;
static class Combinators
{
public static TokenListParser<TKind, TResult> ChainModified<TKind, TResult, TOperator, TModifier>(
TokenListParser<TKind, TOperator> @operator,
TokenListParser<TKind, TResult> operand,
TokenListParser<TKind, TModifier> modify,
Func<TOperator, TResult, TResult, TModifier, TResult> apply)
{
if (@operator == null)
throw new ArgumentNullException(nameof (@operator));
if (operand == null)
throw new ArgumentNullException(nameof (operand));
if (modify == null) throw new ArgumentNullException(nameof(modify));
if (apply == null)
throw new ArgumentNullException(nameof (apply));
return input =>
{
var parseResult = operand(input);
if (!parseResult.HasValue )
return parseResult;
var result = parseResult.Value;
var remainder = parseResult.Remainder;
var operatorResult = @operator(remainder);
while (operatorResult.HasValue || operatorResult.SubTokenErrorPosition.HasValue || remainder != operatorResult.Remainder)
{
// If operator read any input, but failed to read complete input, we return error
if (!operatorResult.HasValue)
return TokenListParserResult.CastEmpty<TKind, TOperator, TResult>(operatorResult);
var operandResult = operand(operatorResult.Remainder);
remainder = operandResult.Remainder;
if (!operandResult.HasValue)
return operandResult;
var modifierResult = modify(remainder);
remainder = modifierResult.Remainder;
if (!modifierResult.HasValue)
return TokenListParserResult.CastEmpty<TKind, TModifier, TResult>(modifierResult);
result = apply(operatorResult.Value, result, operandResult.Value, modifierResult.Value);
operatorResult = @operator(remainder);
}
return TokenListParserResult.Value(result, input, remainder);
};
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionKeyword.cs
================================================
// 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.Parsing;
readonly struct ExpressionKeyword
{
public string Text { get; }
public ExpressionToken Token { get; }
public ExpressionKeyword(string text, ExpressionToken token)
{
Text = text ?? throw new ArgumentNullException(nameof(text));
Token = token;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionParser.cs
================================================
// 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.Diagnostics.CodeAnalysis;
using Serilog.Expressions.Ast;
namespace Serilog.Expressions.Parsing;
class ExpressionParser
{
readonly ExpressionTokenizer _tokenizer = new();
public Expression Parse(string expression)
{
if (!TryParse(expression, out var root, out var error))
throw new ArgumentException(error);
return root;
}
public bool TryParse(string filterExpression,
[MaybeNullWhen(false)] out Expression root, [MaybeNullWhen(true)] out string error)
{
if (filterExpression == null) throw new ArgumentNullException(nameof(filterExpression));
var tokenList = _tokenizer.TryTokenize(filterExpression);
if (!tokenList.HasValue)
{
error = tokenList.ToString();
root = null;
return false;
}
var result = ExpressionTokenParsers.TryParse(tokenList.Value);
if (!result.HasValue)
{
error = result.ToString();
root = null;
return false;
}
root = result.Value;
error = null;
return true;
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionTextParsers.cs
================================================
// 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 Serilog.ParserConstruction;
using Serilog.ParserConstruction.Model;
using Serilog.ParserConstruction.Parsers;
namespace Serilog.Expressions.Parsing;
static class ExpressionTextParsers
{
static readonly TextParser<ExpressionToken> LessOrEqual = Span.EqualTo("<=").Value(ExpressionToken.LessThanOrEqual);
static readonly TextParser<ExpressionToken> GreaterOrEqual = Span.EqualTo(">=").Value(ExpressionToken.GreaterThanOrEqual);
static readonly TextParser<ExpressionToken> NotEqual = Span.EqualTo("<>").Value(ExpressionToken.NotEqual);
static readonly TextParser<ExpressionToken> Spread = Span.EqualTo("..").Value(ExpressionToken.Spread);
public static readonly TextParser<ExpressionToken> CompoundOperator = GreaterOrEqual.Or(LessOrEqual.Try().Or(NotEqual)).Or(Spread);
public static readonly TextParser<string> HexInteger =
Span.EqualTo("0x")
.IgnoreThen(Character.Digit.Or(Character.Matching(ch => ch is >= 'a' and <= 'f' or >= 'A' and <= 'F', "a-f"))
.Named("hex digit")
.AtLeastOnce())
.Select(chars => new string(chars));
static readonly TextParser<char> StringContentChar =
Span.EqualTo("''").Value('\'').Try().Or(Character.Except('\''));
public static readonly TextParser<string> String =
Character.EqualTo('\'')
.IgnoreThen(StringContentChar.Many())
.Then(s => Character.EqualTo('\'').Value(new string(s)));
public static readonly TextParser<TextSpan> Real =
Numerics.Integer
.Then(n => Character.EqualTo('.').IgnoreThen(Numerics.Integer).OptionalOrDefault()
.Select(f => f == TextSpan.None ? n : new(n.Source!, n.Position, n.Length + f.Length + 1)));
}
================================================
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionToken.cs
================================================
// 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 Serilog.ParserConstruction.Display;
namespace Serilog.Expressions.Parsing;
enum ExpressionToken
{
None,
Identifier,
[Token(Description = "built-in identifier")]
BuiltInIdentifier,
String,
Number,
[Token(Description = "hexadecimal number")]
HexNumber,
[Token(Example = ",")]
Comma,
[Token(Example = ".")]
Period,
[Token(Example = "..")]
Spread,
[Token(Example = "[")]
LBracket,
[Token(Example = "]")]
RBracket,
[Token(Example = "(")]
LParen,
[Token(Example = ")")]
RParen,
[Token(Example = "{")]
LBrace,
[Token(Example = "}")]
RBrace,
[Token(Example = ":")]
Colon,
[Token(Example = "?")]
QuestionMark,
[Token(Category = "operator", Example = "+")]
Plus,
[Token(Category = "operator", Example = "-")]
Minus,
[Token(Example = "*")]
Asterisk,
[Token(Category = "operator", Example = "/")]
ForwardSlash,
[Token(Category = "operator", Example = "%")]
Percent,
[Token(Category = "operator", Example = "^")]
Caret,
[Token(Category = "operator", Example = "<")]
LessThan,
[Token(Category = "operator", Example = "<=")]
LessThanOrEqual,
[Token(Category = "operator", Example = ">")]
GreaterThan,
[Token(Category = "operator", Example = ">=")]
GreaterThanOrEqual,
[Token(Category = "operator", Example = "=")]
Equal,
[Token(Category = "operator", Example = "<>")]
NotEqual,
[Token(Category = "keyword", Example = "and")]
And,
[Token(Category = "keyword", Example = "in")]
In,
[Token(Category = "keyword", Example = "is")]
Is,
[Token(Category = "keyword", Example = "like")]
Like,
[Token(Category = "keyword", Example = "not")]
Not,
[Token(Category = "keyword", Example = "or")]
Or,
[Token(Category = "keyword", Example = "true")]
True,
[Token(Category = "keyword", Example = "false")]
False,
[Token(Category = "keyword", Example = "null")]
Null,
[Token(Category = "keyword", Example = "if")]
If,
[Token(Category = "keyword", Example = "then")]
Then,
[Token(Category = "keyword", Example = "else")]
Else,
[Token(Category = "keyword", Example = "ci")]
CI,
// Template syntax
[Token(Description = "text")]
Text,
[Token(Example = "{{")]
DoubleLBrace,
[Token(Example = "}}")]
DoubleRBrace,
[Token(Example = "{#")]
LBraceHash,
[Token(Description = "format specifier")]
Format,
[Token(Category = "keyword", Example = "end")]
End,
[Token(Category = "keyword", Example = "each")]
Each,
[Token(Category = "keyword", Example = "delimit")]
Delimit,
}
================================================
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionTokenParsers.cs
================================================
// 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.Globalization;
using Serilog.Events;
using Serilog.Expressions.Ast;
using Serilog.ParserConstruction;
using Serilog.ParserConstruction.Model;
using Serilog.ParserConstruction.Parsers;
namespace Serilog.Expressions.Parsing;
static class ExpressionTokenParsers
{
public static TokenListParserResult<ExpressionToken, Expression> TryParse(
TokenList<ExpressionToken> input)
{
return Expr.AtEnd().TryParse(input);
}
public static TokenListParserResult<ExpressionToken, Expression> TryPartialParse(
TokenList<ExpressionToken> input)
{
return Expr.TryParse(input);
}
static readonly TokenListParser<ExpressionToken, string> Add = Token.EqualTo(ExpressionToken.Plus).Value(Operators.RuntimeOpAdd);
static readonly TokenListParser<ExpressionToken, string> Subtract = Token.EqualTo(ExpressionToken.Minus).Value(Operators.RuntimeOpSubtract);
static readonly TokenListParser<ExpressionToken, string> Multiply = Token.EqualTo(ExpressionToken.Asterisk).Value(Operators.RuntimeOpMultiply);
static readonly TokenListParser<ExpressionToken, string> Divide = Token.EqualTo(ExpressionToken.ForwardSlash).Value(Operators.RuntimeOpDivide);
static readonly TokenListParser<ExpressionToken, string> Modulo = Token.EqualTo(ExpressionToken.Percent).Value(Operators.RuntimeOpModulo);
static readonly TokenListParser<ExpressionToken, string> Power = Token.EqualTo(ExpressionToken.Caret).Value(Operators.RuntimeOpPower);
static readonly TokenListParser<ExpressionToken, string> And = Token.EqualTo(ExpressionToken.And).Value(Operators.RuntimeOpAnd);
static readonly TokenListParser<ExpressionToken, string> Or = Token.EqualTo(ExpressionToken.Or).Value(Operators.RuntimeOpOr);
static readonly TokenListParser<ExpressionToken, string> Lte = Token.EqualTo(ExpressionToken.LessThanOrEqual).Value(Operators.RuntimeOpLessThanOrEqual);
static readonly TokenListParser<ExpressionToken, string> Lt = Token.EqualTo(ExpressionToken.LessThan).Value(Operators.RuntimeOpLessThan);
static readonly TokenListParser<ExpressionToken, string> Gt = Token.EqualTo(ExpressionToken.GreaterThan).Value(Operators.RuntimeOpGreaterThan);
static readonly TokenListParser<ExpressionToken, string> Gte = Token.EqualTo(ExpressionToken.GreaterThanOrEqual).Value(Operators.RuntimeOpGreaterThanOrEqual);
static readonly TokenListParser<ExpressionToken, string> Eq = Token.EqualTo(ExpressionToken.Equal).Value(Operators.RuntimeOpEqual);
static readonly TokenListParser<ExpressionToken, string> Neq = Token.EqualTo(ExpressionToken.NotEqual).Value(Operators.RuntimeOpNotEqual);
static readonly TokenListParser<ExpressionToken, string> Negate = Token.EqualTo(ExpressionToken.Minus).Value(Operators.RuntimeOpNegate);
static readonly TokenListParser<ExpressionToken, string> Not = Token.EqualTo(ExpressionToken.Not).Value(Operators.RuntimeOpNot);
static readonly TokenListParser<ExpressionToken, string> Like = Token.EqualTo(ExpressionToken.Like).Value(Operators.IntermediateOpLike);
static readonly TokenListParser<ExpressionToken, string> NotLike =
Token.EqualTo(ExpressionToken.Not)
.IgnoreThen(Token.EqualTo(ExpressionToken.Like))
.Value(Operators.IntermediateOpNotLike);
static readonly TokenListParser<ExpressionToken, string> In = Token.EqualTo(ExpressionToken.In).Value(Operators.RuntimeOpIn);
static readonly TokenListParser<ExpressionToken, string> NotIn =
Token.EqualTo(ExpressionToken.Not)
.IgnoreThen(Token.EqualTo(ExpressionToken.In))
.Value(Operators.RuntimeOpNotIn);
static readonly TokenListParser<ExpressionToken, Func<Expression, Expression>> PropertyPathStep =
Token.EqualTo(ExpressionToken.Period)
.IgnoreThen(Token.EqualTo(ExpressionToken.Identifier))
.Then(n => Parse.Return<ExpressionToken, Func<Expression, Expression>>(r => new AccessorExpression(r, n.ToStringValue())));
static readonly TokenListParser<ExpressionToken, Expression> Wildcard =
Token.EqualTo(ExpressionToken.QuestionMark).Value((Expression)new IndexerWildcardExpression(IndexerWildcard.Any))
.Or(Token.EqualTo(ExpressionToken.Asterisk).Value((Expression)new IndexerWildcardExpression(IndexerWildcard.All)));
static readonly TokenListParser<ExpressionToken, Func<Expression, Expression>> PropertyPathIndexerStep =
from open in Token.EqualTo(ExpressionToken.LBracket)
from indexer in Wildcard.Or(Parse.Ref(() => Expr!))
from close in Token.EqualTo(ExpressionToken.RBracket)
select new Func<Expression, Expression>(r => new IndexerExpression(r, indexer));
static readonly TokenListParser<ExpressionToken, Expression> Function =
(from name in Token.EqualTo(ExpressionToken.Identifier)
from lparen in Token.EqualTo(ExpressionToken.LParen)
from expr in Parse.Ref(() => Expr!).ManyDelimitedBy(Token.EqualTo(ExpressionToken.Comma))
from rparen in Token.EqualTo(ExpressionToken.RParen)
from ci in Token.EqualTo(ExpressionToken.CI).Value(true).OptionalOrDefault()
select (Expression)new CallExpression(ci, name.ToStringValue(), expr)).Named("function");
static readonly TokenListParser<ExpressionToken, Element> ArrayElement =
Token.EqualTo(ExpressionToken.Spread)
.IgnoreThen(Parse.Ref(() => Expr!))
.Select(content => (Element)new SpreadElement(content))
.Or(Parse.Ref(() => Expr!).Select(item => (Element) new ItemElement(item)));
static readonly TokenListParser<ExpressionToken, Expression> ArrayLiteral =
(from lbracket in Token.EqualTo(ExpressionToken.LBracket)
from elements in ArrayElement.ManyDelimitedBy(Token.EqualTo(ExpressionToken.Comma))
from rbracket in Token.EqualTo(ExpressionToken.RBracket)
select (Expression)new ArrayExpression(elements)).Named("array");
static readonly TokenListParser<ExpressionToken, Member> IdentifierMember =
from key in Token.EqualTo(ExpressionToken.Identifier).Or(Token.EqualTo(ExpressionToken.BuiltInIdentifier))
from value in Token.EqualTo(ExpressionToken.Colon)
.IgnoreThen(Parse.Ref(() => Expr!))
.Cast<ExpressionToken, Expression, Expression?>()
.OptionalOrDefault()
select (Member) new PropertyMember(
key.ToStringValue(),
value ?? (key.Kind == ExpressionToken.BuiltInIdentifier ?
new AmbientNameExpression(key.ToStringValue().Substring(1), true) :
new AmbientNameExpression(key.ToStringValue(), false)));
static readonly TokenListParser<ExpressionToken, Member> StringMember =
from key in Token.EqualTo(ExpressionToken.String).Apply(ExpressionTextParsers.String)
from colon in Token.EqualTo(ExpressionToken.Colon)
from value in Parse.Ref(() => Expr!)
select (Member)new PropertyMember(key, value);
static readonly TokenListParser<ExpressionToken, Member> SpreadMember =
from spread in Token.EqualTo(ExpressionToken.Spread)
from content in Parse.Ref(() => Expr!)
select (Member) new SpreadMember(content);
static readonly TokenListParser<ExpressionToken, Member> ObjectMember =
IdentifierMember.Or(StringMember).Or(SpreadMember).Named("object member");
static readonly TokenListParser<ExpressionToken, Expression> ObjectLiteral =
(from lbrace in Token.EqualTo(ExpressionToken.LBrace)
from members in ObjectMember.ManyDelimitedBy(Token.EqualTo(ExpressionToken.Comma))
from rbrace in Token.EqualTo(ExpressionToken.RBrace)
select (Expression)new ObjectExpression(members)).Named("object");
static readonly TokenListParser<ExpressionToken, Expression> RootProperty =
(from notFunction in Parse.Not(Token.EqualTo(ExpressionToken.Identifier).IgnoreThen(Token.EqualTo(ExpressionToken.LParen)))
from p in Token.EqualTo(ExpressionToken.BuiltInIdentifier).Select(b => (Expression) new AmbientNameExpression(b.ToStringValue().Substring(1), true))
.Or(Token.EqualTo(ExpressionToken.Identifier).Select(t => (Expression) new AmbientNameExpression(t.ToStringValue(), false)))
select p).Named("property");
static readonly TokenListParser<ExpressionToken, Expression> String =
Token.EqualTo(ExpressionToken.String)
.Apply(ExpressionTextParsers.String)
.Select(s => (Expression)new ConstantExpression(new ScalarValue(s)));
static readonly TokenListParser<ExpressionToken, Expression> HexNumber =
Token.EqualTo(ExpressionToken.HexNumber)
.Apply(ExpressionTextParsers.HexInteger)
.SelectCatch(n => ulong.Parse(n, NumberStyles.HexNumber, CultureInfo.InvariantCulture), "the numeric literal is too large")
.Select(u => (Expression)new ConstantExpression(new ScalarValue((decimal)u)));
static readonly TokenListParser<ExpressionToken, Expression> Number =
Token.EqualTo(ExpressionToken.Number)
.Apply(ExpressionTextParsers.Real)
.SelectCatch(n => decimal.Parse(n.ToStringValue(), CultureInfo.InvariantCulture), "the numeric literal is too large")
.Select(d => (Expression)new ConstantExpression(new ScalarValue(d)));
static readonly TokenListParser<ExpressionToken, Expression> Conditional =
from _ in Token.EqualTo(ExpressionToken.If)
from condition in Parse.Ref(() => Expr!)
from __ in Token.EqualTo(ExpressionToken.Then)
from consequent in Parse.Ref(() => Expr!)
from ___ in Token.EqualTo(ExpressionToken.Else)
from alternative in Parse.Ref(() => Expr!)
select (Expression)new CallExpression(false, Operators.RuntimeOpIfThenElse, condition, consequent, alternative);
static readonly TokenListParser<ExpressionToken, Expression> Literal =
String
.Or(Number)
.Or(HexNumber)
.Or(Token.EqualTo(ExpressionToken.True).Value((Expression)new ConstantExpression(new ScalarValue(true))))
.Or(Token.EqualTo(ExpressionToken.False).Value((Expression)new ConstantExpression(new ScalarValue(false))))
.Or(Token.EqualTo(ExpressionToken.Null).Value((Expression)new ConstantExpression(new ScalarValue(null))))
.Named("literal");
static readonly TokenListParser<ExpressionToken, Expression> Item =
Literal
.Or(RootProperty)
.Or(Function)
.Or(ArrayLiteral)
.Or(ObjectLiteral)
.Or(Conditional);
static readonly TokenListParser<ExpressionToken, Expression> Factor =
(from lparen in Token.EqualTo(ExpressionToken.LParen)
from expr in Parse.Ref(() => Expr!)
from rparen in Token.EqualTo(ExpressionToken.RParen)
select expr)
.Or(Item);
static readonly TokenListParser<ExpressionToken, Expression> Path =
from root in Factor
from path in PropertyPathStep.Or(PropertyPathIndexerStep).Many()
select path.Aggregate(root, (o, f) => f(o));
static readonly TokenListParser<ExpressionToken, Expression> Operand =
(from op in Negate.Or(Not)
from path in Path
select MakeUnary(op, path))
.Or(Path)
.Then(operand => Token.EqualTo(ExpressionToken.Is).Try()
.IgnoreThen(
Token.EqualTo(ExpressionToken.Null).Value(Operators.RuntimeOpIsNull)
.Or(Token.EqualTo(ExpressionToken.Not).IgnoreThen(Token.EqualTo(ExpressionToken.Null)).Value(Operators.RuntimeOpIsNotNull)))
.Select(op => (Expression)new CallExpression(false, op, operand))
.OptionalOrDefault(operand))
.Named("expression");
static readonly TokenListParser<ExpressionToken, Expression> InnerTerm = Parse.Chain(Power, Operand, MakeBinary);
static readonly TokenListParser<ExpressionToken, Expression> Term = Parse.Chain(Multiply.Or(Divide).Or(Modulo), InnerTerm, MakeBinary);
static readonly TokenListParser<ExpressionToken, Expression> Comparand = Parse.Chain(Add.Or(Subtract), Term, MakeBinary);
static readonly TokenListParser<ExpressionToken, Expression> Comparison = Combinators.ChainModified(
NotLike.Try().Or(Like)
.Or(NotIn.Try().Or(In))
.Or(Lte.Or(Neq).Or(Lt))
.Or(Gte.Or(Gt))
.Or(Eq),
Comparand,
Token.EqualTo(ExpressionToken.CI).Value(true).OptionalOrDefault(),
(o, l, r, ci) => new CallExpression(ci, o, l, r));
static readonly TokenListParser<ExpressionToken, Expression> Conjunction = Parse.Chain(And, Comparison, MakeBinary);
static readonly TokenListParser<ExpressionToken, Expression> Disjunction = Parse.Chain(Or, Conjunction, MakeBinary);
public static readonly TokenListParser<ExpressionToken, Expression> Expr = Disjunction;
static Expression MakeBinary(string operatorName, Expression leftOperand, Expression rightOperand)
{
return new CallExpression(false, operatorName, leftOperand, rightOperand);
}
static Expression MakeUnary(string operatorName, Expression operand)
{
return new CallExpression(false, operatorName, operand);
}
}
================================================
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionTokenizer.cs
================================================
// 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 Serilog.ParserConstruction;
using Serilog.ParserConstruction.Model;
namespace Serilog.Expressions.Parsing;
class ExpressionTokenizer : Tokenizer<ExpressionToken>
{
readonly ExpressionToken[] _singleCharOps = new ExpressionToken[128];
readonly ExpressionKeyword[] _keywords =
[
new("and", ExpressionToken.And),
new("in", ExpressionToken.In),
new("is", ExpressionToken.Is),
new("like", ExpressionToken.Like),
new("not", ExpressionToken.Not),
new("or", ExpressionToken.Or),
new("true", ExpressionToken.True),
new("false", ExpressionToken.False),
new("null", ExpressionToken.Null),
new("if", ExpressionToken.If),
new("then", ExpressionToken.Then),
new("else", ExpressionToken.Else),
new("end", ExpressionToken.End),
new("ci", ExpressionToken.CI),
new("each", ExpressionToken.Each),
new("delimit", ExpressionToken.Delimit)
];
public ExpressionTokenizer()
{
_singleCharOps['+'] = ExpressionToken.Plus;
_singleCharOps['-'] = ExpressionToken.Minus;
_singleCharOps['*'] = ExpressionToken.Asterisk;
_singleCharOps['/'] = ExpressionToken.ForwardSlash;
_singleCharOps['%'] = ExpressionToken.Percent;
_singleCharOps['^'] = ExpressionToken.Caret;
_singleCharOps['<'] = ExpressionToken.LessTh
gitextract_cw7ezsg_/
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── feature_request.md
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── Build.ps1
├── Directory.Build.props
├── Directory.Version.props
├── LICENSE
├── README.md
├── RunPerfTests.ps1
├── assets/
│ └── Serilog.snk
├── example/
│ └── Sample/
│ ├── Program.cs
│ └── Sample.csproj
├── global.json
├── serilog-expressions.sln
├── serilog-expressions.sln.DotSettings
├── src/
│ └── Serilog.Expressions/
│ ├── Expressions/
│ │ ├── Ast/
│ │ │ ├── AccessorExpression.cs
│ │ │ ├── AmbientNameExpression.cs
│ │ │ ├── ArrayExpression.cs
│ │ │ ├── CallExpression.cs
│ │ │ ├── ConstantExpression.cs
│ │ │ ├── Element.cs
│ │ │ ├── Expression.cs
│ │ │ ├── IndexOfMatchExpression.cs
│ │ │ ├── IndexerExpression.cs
│ │ │ ├── IndexerWildcard.cs
│ │ │ ├── IndexerWildcardExpression.cs
│ │ │ ├── ItemElement.cs
│ │ │ ├── LambdaExpression.cs
│ │ │ ├── LocalNameExpression.cs
│ │ │ ├── Member.cs
│ │ │ ├── ObjectExpression.cs
│ │ │ ├── ParameterExpression.cs
│ │ │ ├── PropertyMember.cs
│ │ │ ├── SpreadElement.cs
│ │ │ └── SpreadMember.cs
│ │ ├── BuiltInProperty.cs
│ │ ├── Compilation/
│ │ │ ├── Arrays/
│ │ │ │ └── ConstantArrayEvaluator.cs
│ │ │ ├── DefaultFunctionNameResolver.cs
│ │ │ ├── ExpressionCompiler.cs
│ │ │ ├── ExpressionValidationException.cs
│ │ │ ├── Linq/
│ │ │ │ ├── EventIdHash.cs
│ │ │ │ ├── ExpressionConstantMapper.cs
│ │ │ │ ├── Intrinsics.cs
│ │ │ │ ├── LinqExpressionCompiler.cs
│ │ │ │ └── ParameterReplacementVisitor.cs
│ │ │ ├── OrderedNameResolver.cs
│ │ │ ├── Pattern.cs
│ │ │ ├── Properties/
│ │ │ │ └── PropertiesObjectAccessorTransformer.cs
│ │ │ ├── Text/
│ │ │ │ ├── LikeSyntaxTransformer.cs
│ │ │ │ └── TextMatchingTransformer.cs
│ │ │ ├── Transformations/
│ │ │ │ ├── IdentityTransformer.cs
│ │ │ │ ├── NodeReplacer.cs
│ │ │ │ └── SerilogExpressionTransformer.cs
│ │ │ ├── Variadics/
│ │ │ │ └── VariadicCallRewriter.cs
│ │ │ └── Wildcards/
│ │ │ ├── WildcardComprehensionTransformer.cs
│ │ │ └── WildcardSearch.cs
│ │ ├── CompiledExpression.cs
│ │ ├── Evaluatable.cs
│ │ ├── EvaluationContext.cs
│ │ ├── ExpressionResult.cs
│ │ ├── Helpers.cs
│ │ ├── LoggingFilterSwitch.cs
│ │ ├── NameResolver.cs
│ │ ├── Operators.cs
│ │ ├── Parsing/
│ │ │ ├── Combinators.cs
│ │ │ ├── ExpressionKeyword.cs
│ │ │ ├── ExpressionParser.cs
│ │ │ ├── ExpressionTextParsers.cs
│ │ │ ├── ExpressionToken.cs
│ │ │ ├── ExpressionTokenParsers.cs
│ │ │ ├── ExpressionTokenizer.cs
│ │ │ └── ParserExtensions.cs
│ │ ├── Runtime/
│ │ │ ├── Coerce.cs
│ │ │ ├── Locals.cs
│ │ │ ├── RuntimeOperators.cs
│ │ │ └── Support/
│ │ │ └── UnflattenDottedPropertyNames.cs
│ │ ├── SerilogExpression.cs
│ │ └── StaticMemberNameResolver.cs
│ ├── LoggerEnrichmentConfigurationExtensions.cs
│ ├── LoggerFilterConfigurationExtensions.cs
│ ├── LoggerSinkConfigurationExtensions.cs
│ ├── ParserConstruction/
│ │ ├── Combinators.cs
│ │ ├── Display/
│ │ │ ├── Presentation.cs
│ │ │ └── TokenAttribute.cs
│ │ ├── Model/
│ │ │ ├── Position.cs
│ │ │ ├── Result.cs
│ │ │ ├── Result`1.cs
│ │ │ ├── TextSpan.cs
│ │ │ ├── TokenListParserResult.cs
│ │ │ ├── TokenListParserResult`2.cs
│ │ │ ├── TokenList`1.cs
│ │ │ ├── Token`1.cs
│ │ │ └── Unit.cs
│ │ ├── Parse.cs
│ │ ├── ParseException.cs
│ │ ├── ParserExtensions.cs
│ │ ├── Parsers/
│ │ │ ├── Character.cs
│ │ │ ├── Numerics.cs
│ │ │ ├── Span.cs
│ │ │ └── Token.cs
│ │ ├── README.md
│ │ ├── TextParser`1.cs
│ │ ├── TokenListParser`2.cs
│ │ ├── Tokenizer`1.cs
│ │ └── Util/
│ │ ├── CharInfo.cs
│ │ └── Friendly.cs
│ ├── Pipeline/
│ │ └── ComputedPropertyEnricher.cs
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── Serilog.Expressions.csproj
│ └── Templates/
│ ├── Ast/
│ │ ├── Conditional.cs
│ │ ├── FormattedExpression.cs
│ │ ├── LiteralText.cs
│ │ ├── Repetition.cs
│ │ ├── Template.cs
│ │ └── TemplateBlock.cs
│ ├── Compilation/
│ │ ├── CompiledConditional.cs
│ │ ├── CompiledExceptionToken.cs
│ │ ├── CompiledFormattedExpression.cs
│ │ ├── CompiledLevelToken.cs
│ │ ├── CompiledLiteralText.cs
│ │ ├── CompiledMessageToken.cs
│ │ ├── CompiledRepetition.cs
│ │ ├── CompiledTemplate.cs
│ │ ├── CompiledTemplateBlock.cs
│ │ ├── CompiledTimestampToken.cs
│ │ ├── NameResolution/
│ │ │ ├── ExpressionLocalNameBinder.cs
│ │ │ └── TemplateLocalNameBinder.cs
│ │ ├── TemplateCompiler.cs
│ │ ├── TemplateFunctionNameResolver.cs
│ │ ├── UnreferencedProperties/
│ │ │ ├── ExpressionReferencedPropertiesFinder.cs
│ │ │ ├── TemplateReferencedPropertiesFinder.cs
│ │ │ └── UnreferencedPropertiesFunction.cs
│ │ └── Unsafe/
│ │ └── UnsafeOutputFunction.cs
│ ├── Encoding/
│ │ ├── EncodedCompiledTemplate.cs
│ │ ├── EncodedTemplateFactory.cs
│ │ ├── EscapableEncodedCompiledFormattedExpression.cs
│ │ ├── PreEncodedValue.cs
│ │ └── TemplateOutputEncoder.cs
│ ├── ExpressionTemplate.cs
│ ├── Parsing/
│ │ ├── TemplateParser.cs
│ │ ├── TemplateTokenParsers.cs
│ │ └── TemplateTokenizer.cs
│ ├── Rendering/
│ │ ├── AlignmentExtensions.cs
│ │ ├── Casing.cs
│ │ ├── LevelRenderer.cs
│ │ └── Padding.cs
│ └── Themes/
│ ├── Style.cs
│ ├── StyleReset.cs
│ ├── TemplateTheme.cs
│ ├── TemplateThemeStyle.cs
│ ├── TemplateThemes.cs
│ └── ThemedJsonValueFormatter.cs
└── test/
├── Serilog.Expressions.PerformanceTests/
│ ├── ComparisonBenchmark.cs
│ ├── Harness.cs
│ ├── Serilog.Expressions.PerformanceTests.csproj
│ └── Support/
│ └── Some.cs
└── Serilog.Expressions.Tests/
├── Cases/
│ ├── expression-evaluation-cases.asv
│ ├── template-encoding-cases.asv
│ ├── template-evaluation-cases.asv
│ └── translation-cases.asv
├── ConfigurationTests.cs
├── ExpressionCompilerTests.cs
├── ExpressionEvaluationTests.cs
├── ExpressionParserTests.cs
├── ExpressionTranslationTests.cs
├── ExpressionValidationTests.cs
├── ExpressionValueTests.cs
├── Expressions/
│ ├── NameResolverTests.cs
│ └── Runtime/
│ ├── LocalsTests.cs
│ └── RuntimeOperatorsTests.cs
├── FormatParityTests.cs
├── LoggingFilterSwitchTests.cs
├── Properties/
│ └── launchSettings.json
├── Serilog.Expressions.Tests.csproj
├── Support/
│ ├── AsvCases.cs
│ ├── CollectingSink.cs
│ ├── ParenthesizingEncoder.cs
│ ├── Some.cs
│ ├── StringHashPrefixingTheme.cs
│ └── TestHelperNameResolver.cs
├── TemplateEncodingTests.cs
├── TemplateEvaluationTests.cs
├── TemplateParserTests.cs
├── TemplateTokenizerTests.cs
└── Templates/
└── UnreferencedPropertiesFunctionTests.cs
SYMBOL INDEX (712 symbols across 156 files)
FILE: src/Serilog.Expressions/Expressions/Ast/AccessorExpression.cs
class AccessorExpression (line 25) | class AccessorExpression : Expression
method AccessorExpression (line 27) | public AccessorExpression(Expression receiver, string memberName)
method ToString (line 37) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/AmbientNameExpression.cs
class AmbientNameExpression (line 22) | class AmbientNameExpression : Expression
method AmbientNameExpression (line 26) | public AmbientNameExpression(string name, bool isBuiltIn)
method ToString (line 37) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/ArrayExpression.cs
class ArrayExpression (line 24) | class ArrayExpression : Expression
method ArrayExpression (line 26) | public ArrayExpression(Element[] elements)
method ToString (line 33) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/CallExpression.cs
class CallExpression (line 21) | class CallExpression : Expression
method CallExpression (line 23) | public CallExpression(bool ignoreCase, string operatorName, params Exp...
method ToString (line 36) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/ConstantExpression.cs
class ConstantExpression (line 23) | class ConstantExpression : Expression
method ConstantExpression (line 25) | public ConstantExpression(LogEventPropertyValue constant)
method ToString (line 32) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/Element.cs
class Element (line 20) | abstract class Element;
FILE: src/Serilog.Expressions/Expressions/Ast/Expression.cs
class Expression (line 20) | abstract class Expression
method ToString (line 27) | public abstract override string ToString();
FILE: src/Serilog.Expressions/Expressions/Ast/IndexOfMatchExpression.cs
class IndexOfMatchExpression (line 23) | class IndexOfMatchExpression : Expression
method IndexOfMatchExpression (line 28) | public IndexOfMatchExpression(Expression corpus, Regex regex)
method ToString (line 34) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/IndexerExpression.cs
class IndexerExpression (line 22) | class IndexerExpression : Expression
method IndexerExpression (line 27) | public IndexerExpression(Expression receiver, Expression index)
method ToString (line 33) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/IndexerWildcard.cs
type IndexerWildcard (line 20) | enum IndexerWildcard { Undefined, Any, All }
FILE: src/Serilog.Expressions/Expressions/Ast/IndexerWildcardExpression.cs
class IndexerWildcardExpression (line 22) | class IndexerWildcardExpression : Expression
method IndexerWildcardExpression (line 24) | public IndexerWildcardExpression(IndexerWildcard wildcard)
method ToString (line 31) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/ItemElement.cs
class ItemElement (line 20) | class ItemElement : Element
method ItemElement (line 24) | public ItemElement(Expression value)
method ToString (line 29) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/LambdaExpression.cs
class LambdaExpression (line 21) | class LambdaExpression : Expression
method LambdaExpression (line 23) | public LambdaExpression(ParameterExpression[] parameters, Expression b...
method ToString (line 33) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/LocalNameExpression.cs
class LocalNameExpression (line 20) | class LocalNameExpression : Expression
method LocalNameExpression (line 22) | public LocalNameExpression(string name)
method ToString (line 29) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/Member.cs
class Member (line 20) | abstract class Member;
FILE: src/Serilog.Expressions/Expressions/Ast/ObjectExpression.cs
class ObjectExpression (line 22) | class ObjectExpression : Expression
method ObjectExpression (line 24) | public ObjectExpression(Member[] members)
method ToString (line 31) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/ParameterExpression.cs
class ParameterExpression (line 20) | class ParameterExpression : Expression
method ParameterExpression (line 22) | public ParameterExpression(string parameterName)
method ToString (line 29) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/PropertyMember.cs
class PropertyMember (line 24) | class PropertyMember : Member
method PropertyMember (line 29) | public PropertyMember(string name, Expression value)
method ToString (line 35) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/SpreadElement.cs
class SpreadElement (line 24) | class SpreadElement : Element
method SpreadElement (line 28) | public SpreadElement(Expression content)
method ToString (line 33) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/Ast/SpreadMember.cs
class SpreadMember (line 22) | class SpreadMember : Member
method SpreadMember (line 26) | public SpreadMember(Expression content)
method ToString (line 31) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/BuiltInProperty.cs
class BuiltInProperty (line 18) | static class BuiltInProperty
FILE: src/Serilog.Expressions/Expressions/Compilation/Arrays/ConstantArrayEvaluator.cs
class ConstantArrayEvaluator (line 21) | class ConstantArrayEvaluator : IdentityTransformer
method Rewrite (line 25) | public static Expression Rewrite(Expression expression)
method Transform (line 30) | protected override Expression Transform(ArrayExpression ax)
FILE: src/Serilog.Expressions/Expressions/Compilation/DefaultFunctionNameResolver.cs
class DefaultFunctionNameResolver (line 19) | static class DefaultFunctionNameResolver
method Build (line 21) | public static NameResolver Build(NameResolver? additionalNameResolver)
FILE: src/Serilog.Expressions/Expressions/Compilation/ExpressionCompiler.cs
class ExpressionCompiler (line 25) | static class ExpressionCompiler
method Translate (line 27) | public static Expression Translate(Expression expression)
method Compile (line 39) | public static Evaluatable Compile(Expression expression, IFormatProvid...
FILE: src/Serilog.Expressions/Expressions/Compilation/ExpressionValidationException.cs
class ExpressionValidationException (line 17) | class ExpressionValidationException : ArgumentException
method ExpressionValidationException (line 19) | public ExpressionValidationException(string message) : base(message)
method ExpressionValidationException (line 23) | public ExpressionValidationException(string message, Exception innerEx...
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/EventIdHash.cs
class EventIdHash (line 22) | public static class EventIdHash
method Compute (line 31) | [CLSCompliant(false)]
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/ExpressionConstantMapper.cs
class ExpressionConstantMapper (line 20) | class ExpressionConstantMapper : ExpressionVisitor
method ExpressionConstantMapper (line 24) | public ExpressionConstantMapper(IDictionary<object, Expression> mapping)
method VisitConstant (line 29) | protected override Expression VisitConstant(ConstantExpression node)
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/Intrinsics.cs
class Intrinsics (line 26) | static class Intrinsics
method CollectSequenceElements (line 31) | public static List<LogEventPropertyValue?> CollectSequenceElements(Log...
method ExtendSequenceValueWithItem (line 36) | public static List<LogEventPropertyValue?> ExtendSequenceValueWithItem...
method ExtendSequenceValueWithSpread (line 45) | public static List<LogEventPropertyValue?> ExtendSequenceValueWithSpre...
method ConstructSequenceValue (line 55) | public static LogEventPropertyValue ConstructSequenceValue(List<LogEve...
method CollectStructureProperties (line 63) | public static List<LogEventProperty> CollectStructureProperties(string...
method ConstructStructureValue (line 76) | public static LogEventPropertyValue ConstructStructureValue(List<LogEv...
method ExtendStructureValueWithSpread (line 84) | public static List<LogEventProperty> ExtendStructureValueWithSpread(
method ExtendStructureValueWithProperty (line 98) | public static List<LogEventProperty> ExtendStructureValueWithProperty(
method CompleteStructureValue (line 108) | public static LogEventPropertyValue CompleteStructureValue(List<LogEve...
method CoerceToScalarBoolean (line 121) | public static bool CoerceToScalarBoolean(LogEventPropertyValue value)
method IndexOfMatch (line 128) | public static LogEventPropertyValue? IndexOfMatch(LogEventPropertyValu...
method GetPropertyValue (line 142) | public static LogEventPropertyValue? GetPropertyValue(EvaluationContex...
method GetLocalValue (line 150) | public static LogEventPropertyValue? GetLocalValue(EvaluationContext c...
method TryGetStructurePropertyValue (line 158) | public static LogEventPropertyValue? TryGetStructurePropertyValue(Stri...
method RenderMessage (line 176) | public static string RenderMessage(CompiledMessageToken formatter, Eva...
method GetRenderings (line 183) | public static LogEventPropertyValue? GetRenderings(LogEvent logEvent, ...
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs
class LinqExpressionCompiler (line 34) | class LinqExpressionCompiler : SerilogExpressionTransformer<ExpressionBody>
method LinqExpressionCompiler (line 80) | LinqExpressionCompiler(IFormatProvider? formatProvider, NameResolver n...
method Compile (line 86) | public static Evaluatable Compile(Expression expression, IFormatProvid...
method Splice (line 95) | ExpressionBody Splice(Expression<Evaluatable> lambda)
method Transform (line 100) | protected override ExpressionBody Transform(CallExpression call)
method DescribeRequirements (line 166) | static string DescribeRequirements(IReadOnlyList<(string name, bool op...
method CompileLogical (line 188) | static ExpressionBody CompileLogical(Func<ExpressionBody, ExpressionBo...
method Transform (line 199) | protected override ExpressionBody Transform(AccessorExpression spx)
method Transform (line 204) | protected override ExpressionBody Transform(ConstantExpression cx)
method Transform (line 209) | protected override ExpressionBody Transform(AmbientNameExpression px)
method Transform (line 245) | protected override ExpressionBody Transform(LocalNameExpression nlx)
method Transform (line 252) | protected override ExpressionBody Transform(Ast.LambdaExpression lmx)
method Transform (line 273) | protected override ExpressionBody Transform(Ast.ParameterExpression prx)
method Transform (line 281) | protected override ExpressionBody Transform(IndexerWildcardExpression wx)
method Transform (line 286) | protected override ExpressionBody Transform(ArrayExpression ax)
method Transform (line 317) | protected override ExpressionBody Transform(ObjectExpression ox)
method Transform (line 379) | protected override ExpressionBody Transform(IndexerExpression ix)
method Transform (line 384) | protected override ExpressionBody Transform(IndexOfMatchExpression mx)
FILE: src/Serilog.Expressions/Expressions/Compilation/Linq/ParameterReplacementVisitor.cs
class ParameterReplacementVisitor (line 19) | class ParameterReplacementVisitor : ExpressionVisitor
method ReplaceParameters (line 23) | public static Expression ReplaceParameters(LambdaExpression lambda, pa...
method ParameterReplacementVisitor (line 29) | ParameterReplacementVisitor(ParameterExpression[] from, ParameterExpre...
method VisitParameter (line 38) | protected override Expression VisitParameter(ParameterExpression node)
FILE: src/Serilog.Expressions/Expressions/Compilation/OrderedNameResolver.cs
class OrderedNameResolver (line 20) | class OrderedNameResolver : NameResolver
method OrderedNameResolver (line 24) | public OrderedNameResolver(IEnumerable<NameResolver> orderedResolvers)
method TryResolveFunctionName (line 29) | public override bool TryResolveFunctionName(string name, [MaybeNullWhe...
method TryBindFunctionParameter (line 41) | public override bool TryBindFunctionParameter(ParameterInfo parameter,...
method TryResolveBuiltInPropertyName (line 53) | public override bool TryResolveBuiltInPropertyName(string alias, [NotN...
FILE: src/Serilog.Expressions/Expressions/Compilation/Pattern.cs
class Pattern (line 21) | static class Pattern
method IsAmbientProperty (line 23) | public static bool IsAmbientProperty(Expression expression, string nam...
method IsStringConstant (line 30) | public static bool IsStringConstant(Expression expression, [MaybeNullW...
FILE: src/Serilog.Expressions/Expressions/Compilation/Properties/PropertiesObjectAccessorTransformer.cs
class PropertiesObjectAccessorTransformer (line 20) | class PropertiesObjectAccessorTransformer : IdentityTransformer
method Rewrite (line 22) | public static Expression Rewrite(Expression actual)
method Transform (line 27) | protected override Expression Transform(AccessorExpression ax)
method Transform (line 35) | protected override Expression Transform(IndexerExpression ix)
FILE: src/Serilog.Expressions/Expressions/Compilation/Text/LikeSyntaxTransformer.cs
class LikeSyntaxTransformer (line 23) | class LikeSyntaxTransformer: IdentityTransformer
method Rewrite (line 27) | public static Expression Rewrite(Expression expression)
method Transform (line 32) | protected override Expression Transform(CallExpression call)
method TryCompileLikeExpression (line 49) | Expression TryCompileLikeExpression(bool ignoreCase, Expression corpus...
method LikeToRegex (line 66) | static string LikeToRegex(string like)
FILE: src/Serilog.Expressions/Expressions/Compilation/Text/TextMatchingTransformer.cs
class TextMatchingTransformer (line 23) | class TextMatchingTransformer: IdentityTransformer
method Rewrite (line 27) | public static Expression Rewrite(Expression expression)
method Transform (line 32) | protected override Expression Transform(CallExpression call)
method TryCompileIndexOfMatch (line 50) | Expression TryCompileIndexOfMatch(bool ignoreCase, Expression corpus, ...
FILE: src/Serilog.Expressions/Expressions/Compilation/Transformations/IdentityTransformer.cs
class IdentityTransformer (line 19) | class IdentityTransformer : SerilogExpressionTransformer<Expression>
method TryTransform (line 21) | bool TryTransform(Expression expr, out Expression result)
method Transform (line 27) | protected override Expression Transform(CallExpression call)
method Transform (line 44) | protected override Expression Transform(ConstantExpression cx)
method Transform (line 49) | protected override Expression Transform(AmbientNameExpression px)
method Transform (line 54) | protected override Expression Transform(LocalNameExpression nlx)
method Transform (line 59) | protected override Expression Transform(AccessorExpression spx)
method Transform (line 67) | protected override Expression Transform(LambdaExpression lmx)
method Transform (line 77) | protected override Expression Transform(ParameterExpression prx)
method Transform (line 82) | protected override Expression Transform(IndexerWildcardExpression wx)
method Transform (line 87) | protected override Expression Transform(ArrayExpression ax)
method Transform (line 114) | protected override Expression Transform(ObjectExpression ox)
method Transform (line 141) | protected override Expression Transform(IndexerExpression ix)
method Transform (line 151) | protected override Expression Transform(IndexOfMatchExpression mx)
FILE: src/Serilog.Expressions/Expressions/Compilation/Transformations/NodeReplacer.cs
class NodeReplacer (line 19) | class NodeReplacer : IdentityTransformer
method Replace (line 24) | public static Expression Replace(Expression expr, Expression source, E...
method NodeReplacer (line 30) | NodeReplacer(Expression source, Expression dest)
method Transform (line 36) | protected override Expression Transform(Expression x)
FILE: src/Serilog.Expressions/Expressions/Compilation/Transformations/SerilogExpressionTransformer.cs
class SerilogExpressionTransformer (line 19) | abstract class SerilogExpressionTransformer<TResult>
method Transform (line 21) | protected virtual TResult Transform(Expression expression)
method Transform (line 43) | protected abstract TResult Transform(CallExpression call);
method Transform (line 44) | protected abstract TResult Transform(ConstantExpression cx);
method Transform (line 45) | protected abstract TResult Transform(AmbientNameExpression px);
method Transform (line 46) | protected abstract TResult Transform(LocalNameExpression nlx);
method Transform (line 47) | protected abstract TResult Transform(AccessorExpression spx);
method Transform (line 48) | protected abstract TResult Transform(LambdaExpression lmx);
method Transform (line 49) | protected abstract TResult Transform(ParameterExpression prx);
method Transform (line 50) | protected abstract TResult Transform(IndexerWildcardExpression wx);
method Transform (line 51) | protected abstract TResult Transform(ArrayExpression ax);
method Transform (line 52) | protected abstract TResult Transform(ObjectExpression ox);
method Transform (line 53) | protected abstract TResult Transform(IndexerExpression ix);
method Transform (line 54) | protected abstract TResult Transform(IndexOfMatchExpression mx);
FILE: src/Serilog.Expressions/Expressions/Compilation/Variadics/VariadicCallRewriter.cs
class VariadicCallRewriter (line 21) | class VariadicCallRewriter : IdentityTransformer
method Rewrite (line 25) | public static Expression Rewrite(Expression expression)
method Transform (line 30) | protected override Expression Transform(CallExpression call)
FILE: src/Serilog.Expressions/Expressions/Compilation/Wildcards/WildcardComprehensionTransformer.cs
class WildcardComprehensionTransformer (line 20) | class WildcardComprehensionTransformer : IdentityTransformer
method Rewrite (line 24) | public static Expression Rewrite(Expression root)
method Transform (line 39) | protected override Expression Transform(CallExpression lx)
method Transform (line 80) | protected override Expression Transform(IndexerExpression ix)
FILE: src/Serilog.Expressions/Expressions/Compilation/Wildcards/WildcardSearch.cs
class WildcardSearch (line 20) | class WildcardSearch : SerilogExpressionTransformer<IndexerExpression?>
method FindWildcardIndexer (line 24) | public static IndexerExpression? FindWildcardIndexer(Expression fx)
method Transform (line 29) | protected override IndexerExpression? Transform(IndexerExpression ix)
method Transform (line 37) | protected override IndexerExpression? Transform(ConstantExpression cx)
method Transform (line 42) | protected override IndexerExpression? Transform(AmbientNameExpression px)
method Transform (line 47) | protected override IndexerExpression? Transform(LocalNameExpression nlx)
method Transform (line 52) | protected override IndexerExpression? Transform(AccessorExpression spx)
method Transform (line 57) | protected override IndexerExpression? Transform(LambdaExpression lmx)
method Transform (line 62) | protected override IndexerExpression? Transform(ParameterExpression prx)
method Transform (line 67) | protected override IndexerExpression? Transform(IndexerWildcardExpress...
method Transform (line 73) | protected override IndexerExpression? Transform(ArrayExpression ax)
method Transform (line 78) | protected override IndexerExpression? Transform(CallExpression call)
method Transform (line 88) | protected override IndexerExpression? Transform(IndexOfMatchExpression...
method Transform (line 93) | protected override IndexerExpression? Transform(ObjectExpression ox)
FILE: src/Serilog.Expressions/Expressions/EvaluationContext.cs
type EvaluationContext (line 20) | readonly struct EvaluationContext
method EvaluationContext (line 25) | public EvaluationContext(LogEvent logEvent, Locals? locals = null)
FILE: src/Serilog.Expressions/Expressions/ExpressionResult.cs
class ExpressionResult (line 23) | public static class ExpressionResult
method IsTrue (line 33) | public static bool IsTrue(LogEventPropertyValue? value)
FILE: src/Serilog.Expressions/Expressions/Helpers.cs
class Helpers (line 24) | static class Helpers
method Contains (line 38) | public static bool Contains(this string @this, string value, StringCom...
method Replace (line 43) | public static string Replace(this string @this, string oldValue, strin...
FILE: src/Serilog.Expressions/Expressions/LoggingFilterSwitch.cs
class LoggingFilterSwitch (line 24) | public class LoggingFilterSwitch : ILogEventFilter
method LoggingFilterSwitch (line 40) | public LoggingFilterSwitch(string? expression = null)
method IsEnabled (line 75) | public bool IsEnabled(LogEvent logEvent)
method ToString (line 88) | public override string ToString()
FILE: src/Serilog.Expressions/Expressions/NameResolver.cs
class NameResolver (line 24) | public abstract class NameResolver
method TryResolveFunctionName (line 36) | public virtual bool TryResolveFunctionName(string name, [MaybeNullWhen...
method TryBindFunctionParameter (line 50) | public virtual bool TryBindFunctionParameter(ParameterInfo parameter, ...
method TryResolveBuiltInPropertyName (line 65) | public virtual bool TryResolveBuiltInPropertyName(string alias, [NotNu...
FILE: src/Serilog.Expressions/Expressions/Operators.cs
class Operators (line 21) | static class Operators
method SameOperator (line 104) | public static bool SameOperator(string op1, string op2)
method ToRuntimeWildcardOperator (line 112) | public static string ToRuntimeWildcardOperator(IndexerWildcard wildcard)
FILE: src/Serilog.Expressions/Expressions/Parsing/Combinators.cs
class Combinators (line 20) | static class Combinators
method ChainModified (line 22) | public static TokenListParser<TKind, TResult> ChainModified<TKind, TRe...
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionKeyword.cs
type ExpressionKeyword (line 17) | readonly struct ExpressionKeyword
method ExpressionKeyword (line 22) | public ExpressionKeyword(string text, ExpressionToken token)
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionParser.cs
class ExpressionParser (line 20) | class ExpressionParser
method Parse (line 24) | public Expression Parse(string expression)
method TryParse (line 32) | public bool TryParse(string filterExpression,
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionTextParsers.cs
class ExpressionTextParsers (line 21) | static class ExpressionTextParsers
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionToken.cs
type ExpressionToken (line 19) | enum ExpressionToken
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionTokenParsers.cs
class ExpressionTokenParsers (line 24) | static class ExpressionTokenParsers
method TryParse (line 26) | public static TokenListParserResult<ExpressionToken, Expression> TryPa...
method TryPartialParse (line 32) | public static TokenListParserResult<ExpressionToken, Expression> TryPa...
method MakeBinary (line 232) | static Expression MakeBinary(string operatorName, Expression leftOpera...
method MakeUnary (line 237) | static Expression MakeUnary(string operatorName, Expression operand)
FILE: src/Serilog.Expressions/Expressions/Parsing/ExpressionTokenizer.cs
class ExpressionTokenizer (line 20) | class ExpressionTokenizer : Tokenizer<ExpressionToken>
method ExpressionTokenizer (line 44) | public ExpressionTokenizer()
method GreedyTokenize (line 68) | public TokenList<ExpressionToken> GreedyTokenize(TextSpan textSpan)
method LazyTokenize (line 78) | public IEnumerable<Result<ExpressionToken>> LazyTokenize(TextSpan span)
method Tokenize (line 83) | protected override IEnumerable<Result<ExpressionToken>> Tokenize(TextS...
method IsDelimiter (line 186) | bool IsDelimiter(Result<char> next)
method TryGetKeyword (line 193) | bool TryGetKeyword(TextSpan span, out ExpressionToken keyword)
FILE: src/Serilog.Expressions/Expressions/Parsing/ParserExtensions.cs
class ParserExtensions (line 20) | static class ParserExtensions
method SelectCatch (line 22) | public static TokenListParser<TTokenKind, TResult> SelectCatch<TTokenK...
FILE: src/Serilog.Expressions/Expressions/Runtime/Coerce.cs
class Coerce (line 21) | static class Coerce
method Numeric (line 31) | public static bool Numeric(LogEventPropertyValue? value, out decimal n...
method Boolean (line 45) | public static bool Boolean(LogEventPropertyValue? value, out bool bool...
method IsTrue (line 58) | public static bool IsTrue(LogEventPropertyValue? value)
method String (line 63) | public static bool String(LogEventPropertyValue? value, [NotNullWhen(t...
method Predicate (line 102) | public static bool Predicate(LogEventPropertyValue? value,
FILE: src/Serilog.Expressions/Expressions/Runtime/Locals.cs
class Locals (line 25) | class Locals
method Locals (line 31) | Locals(Locals? others, string name, LogEventPropertyValue value)
method Set (line 38) | public static Locals Set(Locals? others, string name, LogEventProperty...
method TryGetValue (line 43) | public static bool TryGetValue(Locals? locals, string name, [MaybeNull...
FILE: src/Serilog.Expressions/Expressions/Runtime/RuntimeOperators.cs
class RuntimeOperators (line 26) | static class RuntimeOperators
method ScalarBoolean (line 31) | internal static LogEventPropertyValue ScalarBoolean(bool value)
method Undefined (line 36) | public static LogEventPropertyValue? Undefined()
method _Internal_Add (line 41) | public static LogEventPropertyValue? _Internal_Add(LogEventPropertyVal...
method _Internal_Subtract (line 50) | public static LogEventPropertyValue? _Internal_Subtract(LogEventProper...
method _Internal_Multiply (line 59) | public static LogEventPropertyValue? _Internal_Multiply(LogEventProper...
method _Internal_Divide (line 68) | public static LogEventPropertyValue? _Internal_Divide(LogEventProperty...
method _Internal_Modulo (line 78) | public static LogEventPropertyValue? _Internal_Modulo(LogEventProperty...
method _Internal_Power (line 88) | public static LogEventPropertyValue? _Internal_Power(LogEventPropertyV...
method _Internal_And (line 98) | public static LogEventPropertyValue? _Internal_And(LogEventPropertyVal...
method _Internal_Or (line 104) | public static LogEventPropertyValue? _Internal_Or(LogEventPropertyValu...
method _Internal_LessThanOrEqual (line 109) | public static LogEventPropertyValue? _Internal_LessThanOrEqual(LogEven...
method _Internal_LessThan (line 118) | public static LogEventPropertyValue? _Internal_LessThan(LogEventProper...
method _Internal_GreaterThan (line 127) | public static LogEventPropertyValue? _Internal_GreaterThan(LogEventPro...
method _Internal_GreaterThanOrEqual (line 136) | public static LogEventPropertyValue? _Internal_GreaterThanOrEqual(LogE...
method _Internal_Equal (line 145) | public static LogEventPropertyValue? _Internal_Equal(StringComparison ...
method UnboxedEqualHelper (line 155) | static bool UnboxedEqualHelper(StringComparison sc, LogEventPropertyVa...
method _Internal_In (line 200) | public static LogEventPropertyValue? _Internal_In(StringComparison sc,...
method _Internal_NotIn (line 221) | public static LogEventPropertyValue? _Internal_NotIn(StringComparison ...
method _Internal_NotEqual (line 226) | public static LogEventPropertyValue? _Internal_NotEqual(StringComparis...
method _Internal_Negate (line 234) | public static LogEventPropertyValue? _Internal_Negate(LogEventProperty...
method Round (line 241) | public static LogEventPropertyValue? Round(LogEventPropertyValue? valu...
method _Internal_Not (line 253) | public static LogEventPropertyValue? _Internal_Not(LogEventPropertyVal...
method _Internal_StrictNot (line 263) | public static LogEventPropertyValue? _Internal_StrictNot(LogEventPrope...
method Contains (line 270) | public static LogEventPropertyValue? Contains(StringComparison sc, Log...
method IndexOf (line 279) | public static LogEventPropertyValue? IndexOf(StringComparison sc, LogE...
method LastIndexOf (line 288) | public static LogEventPropertyValue? LastIndexOf(StringComparison sc, ...
method Length (line 297) | public static LogEventPropertyValue? Length(LogEventPropertyValue? value)
method StartsWith (line 308) | public static LogEventPropertyValue? StartsWith(StringComparison sc, L...
method EndsWith (line 317) | public static LogEventPropertyValue? EndsWith(StringComparison sc, Log...
method IsDefined (line 326) | public static LogEventPropertyValue IsDefined(LogEventPropertyValue? v...
method ElementAt (line 331) | public static LogEventPropertyValue? ElementAt(StringComparison sc, Lo...
method _Internal_Any (line 363) | public static LogEventPropertyValue? _Internal_Any(LogEventPropertyVal...
method _Internal_All (line 386) | public static LogEventPropertyValue? _Internal_All(LogEventPropertyVal...
method TagOf (line 409) | public static LogEventPropertyValue? TagOf(LogEventPropertyValue? value)
method TypeOf (line 417) | public static LogEventPropertyValue TypeOf(LogEventPropertyValue? value)
method _Internal_IsNull (line 436) | public static LogEventPropertyValue _Internal_IsNull(LogEventPropertyV...
method _Internal_IsNotNull (line 441) | public static LogEventPropertyValue _Internal_IsNotNull(LogEventProper...
method Coalesce (line 447) | public static LogEventPropertyValue? Coalesce(LogEventPropertyValue? v...
method Substring (line 455) | public static LogEventPropertyValue? Substring(LogEventPropertyValue? ...
method Concat (line 476) | public static LogEventPropertyValue? Concat(LogEventPropertyValue? str...
method Replace (line 486) | public static LogEventPropertyValue? Replace(StringComparison sc, LogE...
method IndexOfMatch (line 497) | public static LogEventPropertyValue? IndexOfMatch(StringComparison sc,...
method IsMatch (line 503) | public static LogEventPropertyValue? IsMatch(StringComparison sc, LogE...
method _Internal_IfThenElse (line 509) | public static LogEventPropertyValue? _Internal_IfThenElse(
method ToString (line 517) | public static LogEventPropertyValue? ToString(IFormatProvider? formatP...
method UtcDateTime (line 536) | public static LogEventPropertyValue? UtcDateTime(LogEventPropertyValue...
method Now (line 551) | public static LogEventPropertyValue? Now()
method Inspect (line 557) | public static LogEventPropertyValue? Inspect(LogEventPropertyValue? va...
method Nest (line 594) | public static LogEventPropertyValue? Nest(LogEventPropertyValue? maybe...
FILE: src/Serilog.Expressions/Expressions/Runtime/Support/UnflattenDottedPropertyNames.cs
class UnflattenDottedPropertyNames (line 25) | static class UnflattenDottedPropertyNames
method ProcessDottedPropertyNames (line 29) | public static IReadOnlyDictionary<string, LogEventPropertyValue> Proce...
method DottedToNestedRecursive (line 34) | static IReadOnlyDictionary<string, LogEventPropertyValue> DottedToNest...
method MakeStructureValue (line 101) | static StructureValue MakeStructureValue(IReadOnlyDictionary<string,Lo...
method IsDottedIdentifier (line 106) | static bool IsDottedIdentifier(string key) =>
method IsIdentifier (line 112) | static bool IsIdentifier(string s) => s.Length != 0 &&
method TakeFirstIdentifier (line 116) | static (string, string) TakeFirstIdentifier(string dottedIdentifier)
FILE: src/Serilog.Expressions/Expressions/SerilogExpression.cs
class SerilogExpression (line 27) | public static class SerilogExpression
method Compile (line 38) | public static CompiledExpression Compile(string expression,
method TryCompile (line 58) | public static bool TryCompile(
method TryCompile (line 80) | public static bool TryCompile(string expression,
method TryCompileImpl (line 91) | static bool TryCompileImpl(string expression,
method EscapeLikeExpressionContent (line 127) | public static string EscapeLikeExpressionContent(string text)
method EscapeStringContent (line 140) | public static string EscapeStringContent(string text)
method IsValidIdentifier (line 151) | public static bool IsValidIdentifier(string identifier)
FILE: src/Serilog.Expressions/Expressions/StaticMemberNameResolver.cs
class StaticMemberNameResolver (line 23) | public class StaticMemberNameResolver : NameResolver
method StaticMemberNameResolver (line 31) | public StaticMemberNameResolver(
method TryResolveFunctionName (line 46) | public override bool TryResolveFunctionName(string name, [MaybeNullWhe...
FILE: src/Serilog.Expressions/LoggerEnrichmentConfigurationExtensions.cs
class LoggerEnrichmentConfigurationExtensions (line 25) | public static class LoggerEnrichmentConfigurationExtensions
method When (line 35) | public static LoggerConfiguration When(
method WithComputed (line 58) | public static LoggerConfiguration WithComputed(
FILE: src/Serilog.Expressions/LoggerFilterConfigurationExtensions.cs
class LoggerFilterConfigurationExtensions (line 26) | public static class LoggerFilterConfigurationExtensions
method ByIncludingOnly (line 34) | public static LoggerConfiguration ByIncludingOnly(this LoggerFilterCon...
method ByExcluding (line 49) | public static LoggerConfiguration ByExcluding(this LoggerFilterConfigu...
method ControlledBy (line 65) | public static LoggerConfiguration ControlledBy(this LoggerFilterConfig...
FILE: src/Serilog.Expressions/LoggerSinkConfigurationExtensions.cs
class LoggerSinkConfigurationExtensions (line 24) | public static class LoggerSinkConfigurationExtensions
method Conditional (line 36) | public static LoggerConfiguration Conditional(
FILE: src/Serilog.Expressions/ParserConstruction/Combinators.cs
class Combinators (line 26) | static class Combinators
method Apply (line 36) | public static TokenListParser<TKind, U> Apply<TKind, U>(this TokenList...
method AtEnd (line 65) | public static TextParser<T> AtEnd<T>(this TextParser<T> parser)
method AtEnd (line 89) | public static TokenListParser<TKind, T> AtEnd<TKind, T>(this TokenList...
method AtLeastOnce (line 112) | public static TextParser<T[]> AtLeastOnce<T>(this TextParser<T> parser)
method AtLeastOnceDelimitedBy (line 127) | public static TokenListParser<TKind, T[]> AtLeastOnceDelimitedBy<TKind...
method IgnoreThen (line 144) | public static TokenListParser<TKind, U> IgnoreThen<TKind, T, U>(this T...
method IgnoreThen (line 171) | public static TextParser<U> IgnoreThen<T, U>(this TextParser<T> first,...
method Many (line 198) | public static TokenListParser<TKind, T[]> Many<TKind, T>(this TokenLis...
method Many (line 231) | public static TextParser<T[]> Many<T>(this TextParser<T> parser)
method ManyDelimitedBy (line 269) | public static TokenListParser<TKind, T[]> ManyDelimitedBy<TKind, T, U>(
method Named (line 298) | public static TokenListParser<TKind, T> Named<TKind, T>(this TokenList...
method Named (line 320) | public static TextParser<T> Named<T>(this TextParser<T> parser, string...
method OptionalOrDefault (line 344) | public static TokenListParser<TKind, T> OptionalOrDefault<TKind, T>(th...
method OptionalOrDefault (line 359) | public static TextParser<T> OptionalOrDefault<T>(this TextParser<T> pa...
method Or (line 375) | public static TokenListParser<TKind, T> Or<TKind, T>(this TokenListPar...
method Or (line 402) | public static TextParser<T> Or<T>(this TextParser<T> lhs, TextParser<T...
method Select (line 430) | public static TokenListParser<TKind, U> Select<TKind, T, U>(this Token...
method Select (line 455) | public static TextParser<U> Select<T, U>(this TextParser<T> parser, Fu...
method Cast (line 480) | public static TokenListParser<TKind, U> Cast<TKind, T, U>(this TokenLi...
method SelectMany (line 499) | public static TokenListParser<TKind, V> SelectMany<TKind, T, U, V>(
method Then (line 520) | public static TokenListParser<TKind, U> Then<TKind, T, U>(this TokenLi...
method Then (line 547) | public static TextParser<U> Then<T, U>(this TextParser<T> first, Func<...
method Try (line 574) | public static TokenListParser<TKind, T> Try<TKind, T>(this TokenListPa...
method Try (line 596) | public static TextParser<T> Try<T>(this TextParser<T> parser)
method Value (line 620) | public static TokenListParser<TKind, U> Value<TKind, T, U>(this TokenL...
method Value (line 635) | public static TextParser<U> Value<T, U>(this TextParser<T> parser, U v...
method Chain (line 654) | public static TokenListParser<TKind, TResult> Chain<TKind, TResult, TO...
FILE: src/Serilog.Expressions/ParserConstruction/Display/Presentation.cs
class Presentation (line 20) | static class Presentation
method FormatKind (line 22) | static string FormatKind(object kind)
method TryGetTokenAttribute (line 27) | static TokenAttribute? TryGetTokenAttribute(Type type)
method TryGetTokenAttribute (line 32) | static TokenAttribute? TryGetTokenAttribute<TKind>(TKind kind)
method FormatExpectation (line 47) | public static string FormatExpectation<TKind>(TKind kind)
method FormatAppearance (line 61) | public static string FormatAppearance<TKind>(TKind kind, string value)
method FormatLiteral (line 77) | public static string FormatLiteral(char literal)
method FormatLiteral (line 145) | public static string FormatLiteral(string literal)
FILE: src/Serilog.Expressions/ParserConstruction/Display/TokenAttribute.cs
class TokenAttribute (line 24) | [AttributeUsage(AttributeTargets.Field|AttributeTargets.Class)]
FILE: src/Serilog.Expressions/ParserConstruction/Model/Position.cs
type Position (line 20) | readonly struct Position
method Position (line 43) | Position(int absolute, int line, int column)
method Advance (line 76) | public Position Advance(char overChar)
method ToString (line 85) | public override string ToString()
FILE: src/Serilog.Expressions/ParserConstruction/Model/Result.cs
class Result (line 22) | static class Result
method Empty (line 30) | public static Result<T> Empty<T>(TextSpan remainder)
method Empty (line 42) | public static Result<T> Empty<T>(TextSpan remainder, string[] expectat...
method Value (line 55) | public static Result<T> Value<T>(T value, TextSpan location, TextSpan ...
method CastEmpty (line 67) | public static Result<U> CastEmpty<T, U>(Result<T> result)
method CombineEmpty (line 79) | public static Result<T> CombineEmpty<T>(Result<T> first, Result<T> sec...
FILE: src/Serilog.Expressions/ParserConstruction/Model/Result`1.cs
type Result (line 23) | struct Result<T>
method IsPartial (line 58) | internal bool IsPartial(TextSpan from) => from != Remainder;
method Result (line 75) | internal Result(T value, TextSpan location, TextSpan remainder, bool b...
method Result (line 86) | internal Result(TextSpan remainder, string? errorMessage, string[]? ex...
method ToString (line 97) | public override string ToString()
method FormatErrorMessageFragment (line 119) | public string FormatErrorMessageFragment()
FILE: src/Serilog.Expressions/ParserConstruction/Model/TextSpan.cs
type TextSpan (line 20) | readonly struct TextSpan : IEquatable<TextSpan>
method TextSpan (line 41) | public TextSpan(string source)
method TextSpan (line 52) | public TextSpan(string source, Position position, int length)
method EnsureHasValue (line 84) | void EnsureHasValue()
method ConsumeChar (line 94) | public Result<char> ConsumeChar()
method Equals (line 106) | public override bool Equals(object? obj)
method GetHashCode (line 115) | public override int GetHashCode()
method Equals (line 129) | public bool Equals(TextSpan other)
method Until (line 163) | public TextSpan Until(TextSpan next)
method First (line 178) | TextSpan First(int length)
method ToString (line 189) | public override string ToString()
method ToStringValue (line 201) | public string ToStringValue()
method EqualsValueIgnoreCase (line 212) | public bool EqualsValueIgnoreCase(string otherValue)
FILE: src/Serilog.Expressions/ParserConstruction/Model/TokenListParserResult.cs
class TokenListParserResult (line 20) | static class TokenListParserResult
method Empty (line 29) | public static TokenListParserResult<TKind, T> Empty<TKind, T>(TokenLis...
method Empty (line 42) | public static TokenListParserResult<TKind, T> Empty<TKind, T>(TokenLis...
method Empty (line 55) | public static TokenListParserResult<TKind, T> Empty<TKind, T>(TokenLis...
method Value (line 69) | public static TokenListParserResult<TKind, T> Value<TKind, T>(T value,...
method CastEmpty (line 82) | public static TokenListParserResult<TKind,U> CastEmpty<TKind, T, U>(To...
method CombineEmpty (line 95) | public static TokenListParserResult<TKind, T> CombineEmpty<TKind, T>(T...
FILE: src/Serilog.Expressions/ParserConstruction/Model/TokenListParserResult`2.cs
type TokenListParserResult (line 25) | struct TokenListParserResult<TKind, T>
method IsPartial (line 93) | internal bool IsPartial(TokenList<TKind> from) => SubTokenErrorPositio...
method TokenListParserResult (line 97) | internal TokenListParserResult(T value, TokenList<TKind> location, Tok...
method TokenListParserResult (line 109) | internal TokenListParserResult(TokenList<TKind> location, TokenList<TK...
method TokenListParserResult (line 121) | internal TokenListParserResult(TokenList<TKind> remainder, Position er...
method ToString (line 133) | public override string ToString()
method FormatErrorMessageFragment (line 157) | string FormatErrorMessageFragment()
FILE: src/Serilog.Expressions/ParserConstruction/Model/TokenList`1.cs
type TokenList (line 23) | readonly struct TokenList<TKind> : IEquatable<TokenList<TKind>>, IEnumer...
method TokenList (line 36) | public TokenList(Token<TKind>[] tokens)
method TokenList (line 42) | TokenList(Token<TKind>[] tokens, int position)
method EnsureHasValue (line 70) | void EnsureHasValue()
method ConsumeToken (line 80) | public TokenListParserResult<TKind, Token<TKind>> ConsumeToken()
method GetEnumerator (line 92) | public IEnumerator<Token<TKind>> GetEnumerator()
method GetEnumerator (line 100) | IEnumerator IEnumerable.GetEnumerator()
method Equals (line 106) | public override bool Equals(object? obj)
method GetHashCode (line 115) | public override int GetHashCode()
method Equals (line 128) | public bool Equals(TokenList<TKind> other)
method ToString (line 156) | public override string ToString()
method ComputeEndOfInputPosition (line 165) | internal Position ComputeEndOfInputPosition()
FILE: src/Serilog.Expressions/ParserConstruction/Model/Token`1.cs
type Token (line 21) | readonly struct Token<TKind>
method ToStringValue (line 37) | public string ToStringValue() => Span.ToStringValue();
method Token (line 54) | public Token(TKind kind, TextSpan span)
method ToString (line 61) | public override string ToString()
FILE: src/Serilog.Expressions/ParserConstruction/Model/Unit.cs
type Unit (line 20) | struct Unit
FILE: src/Serilog.Expressions/ParserConstruction/Parse.cs
class Parse (line 24) | static class Parse
method Chain (line 37) | public static TokenListParser<TKind, T> Chain<TKind, T, TOperator>(
method Not (line 54) | public static TokenListParser<TKind, Unit> Not<TKind, T>(TokenListPars...
method Ref (line 91) | public static TokenListParser<TKind, T> Ref<TKind, T>(Func<TokenListPa...
method Return (line 111) | public static TextParser<T> Return<T>(T value)
method Return (line 123) | public static TokenListParser<TKind, T> Return<TKind, T>(T value)
FILE: src/Serilog.Expressions/ParserConstruction/ParseException.cs
class ParseException (line 24) | class ParseException : Exception
method ParseException (line 31) | public ParseException(string message, Position errorPosition) : this(m...
method ParseException (line 39) | public ParseException(string message, Position errorPosition, Exceptio...
FILE: src/Serilog.Expressions/ParserConstruction/ParserExtensions.cs
class ParserExtensions (line 22) | static class ParserExtensions
method TryParse (line 33) | public static TokenListParserResult<TKind, T> TryParse<TKind, T>(this ...
FILE: src/Serilog.Expressions/ParserConstruction/Parsers/Character.cs
class Character (line 23) | static class Character
method Matching (line 25) | static TextParser<char> Matching(Func<char, bool> predicate, string[] ...
method Matching (line 43) | public static TextParser<char> Matching(Func<char, bool> predicate, st...
method Except (line 57) | static TextParser<char> Except(Func<char, bool> predicate, string desc...
method EqualTo (line 68) | public static TextParser<char> EqualTo(char ch)
method Except (line 76) | public static TextParser<char> Except(char ch)
FILE: src/Serilog.Expressions/ParserConstruction/Parsers/Numerics.cs
class Numerics (line 25) | static class Numerics
FILE: src/Serilog.Expressions/ParserConstruction/Parsers/Span.cs
class Span (line 23) | static class Span
method EqualTo (line 30) | public static TextParser<TextSpan> EqualTo(string text)
FILE: src/Serilog.Expressions/ParserConstruction/Parsers/Token.cs
class Token (line 23) | static class Token
method EqualTo (line 32) | public static TokenListParser<TKind, Token<TKind>> EqualTo<TKind>(TKin...
method Sequence (line 52) | public static TokenListParser<TKind, Token<TKind>[]> Sequence<TKind>(p...
FILE: src/Serilog.Expressions/ParserConstruction/Tokenizer`1.cs
class Tokenizer (line 24) | abstract class Tokenizer<TKind>
method Tokenize (line 32) | public TokenList<TKind> Tokenize(string source)
method TryTokenize (line 48) | public Result<TokenList<TKind>> TryTokenize(string source)
method Tokenize (line 77) | protected abstract IEnumerable<Result<TKind>> Tokenize(TextSpan span);
method SkipWhiteSpace (line 84) | protected static Result<char> SkipWhiteSpace(TextSpan span)
FILE: src/Serilog.Expressions/ParserConstruction/Util/CharInfo.cs
class CharInfo (line 17) | static class CharInfo
method IsLatinDigit (line 19) | public static bool IsLatinDigit(char ch)
FILE: src/Serilog.Expressions/ParserConstruction/Util/Friendly.cs
class Friendly (line 17) | static class Friendly
method List (line 19) | public static string List(IEnumerable<string> items)
method Clip (line 42) | public static string Clip(string value, int maxLength)
FILE: src/Serilog.Expressions/Pipeline/ComputedPropertyEnricher.cs
class ComputedPropertyEnricher (line 21) | class ComputedPropertyEnricher : ILogEventEnricher
method ComputedPropertyEnricher (line 26) | public ComputedPropertyEnricher(string propertyName, CompiledExpressio...
method Enrich (line 32) | public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propert...
FILE: src/Serilog.Expressions/Templates/Ast/Conditional.cs
class Conditional (line 19) | class Conditional : Template
method Conditional (line 25) | public Conditional(Expression condition, Template consequent, Template...
FILE: src/Serilog.Expressions/Templates/Ast/FormattedExpression.cs
class FormattedExpression (line 20) | class FormattedExpression : Template
method FormattedExpression (line 26) | public FormattedExpression(Expression expression, string? format, Alig...
FILE: src/Serilog.Expressions/Templates/Ast/LiteralText.cs
class LiteralText (line 17) | class LiteralText : Template
method LiteralText (line 21) | public LiteralText(string text)
FILE: src/Serilog.Expressions/Templates/Ast/Repetition.cs
class Repetition (line 19) | class Repetition: Template
method Repetition (line 27) | public Repetition(
FILE: src/Serilog.Expressions/Templates/Ast/Template.cs
class Template (line 17) | abstract class Template;
FILE: src/Serilog.Expressions/Templates/Ast/TemplateBlock.cs
class TemplateBlock (line 17) | class TemplateBlock : Template
method TemplateBlock (line 21) | public TemplateBlock(Template[] elements)
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledConditional.cs
class CompiledConditional (line 19) | class CompiledConditional : CompiledTemplate
method CompiledConditional (line 25) | public CompiledConditional(Evaluatable condition, CompiledTemplate con...
method Evaluate (line 32) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledExceptionToken.cs
class CompiledExceptionToken (line 20) | class CompiledExceptionToken : CompiledTemplate
method CompiledExceptionToken (line 26) | public CompiledExceptionToken(TemplateTheme theme)
method Evaluate (line 32) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledFormattedExpression.cs
class CompiledFormattedExpression (line 23) | class CompiledFormattedExpression : CompiledTemplate
method CompiledFormattedExpression (line 32) | public CompiledFormattedExpression(Evaluatable expression, string? for...
method Evaluate (line 42) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
method EvaluateUnaligned (line 58) | void EvaluateUnaligned(EvaluationContext ctx, TextWriter output, IForm...
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledLevelToken.cs
class CompiledLevelToken (line 22) | class CompiledLevelToken : CompiledTemplate
method CompiledLevelToken (line 28) | public CompiledLevelToken(string? format, Alignment? alignment, Templa...
method Evaluate (line 43) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
method EvaluateUnaligned (line 59) | void EvaluateUnaligned(EvaluationContext ctx, TextWriter output, ref i...
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledLiteralText.cs
class CompiledLiteralText (line 20) | class CompiledLiteralText : CompiledTemplate
method CompiledLiteralText (line 25) | public CompiledLiteralText(string text, TemplateTheme theme)
method Evaluate (line 31) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledMessageToken.cs
class CompiledMessageToken (line 23) | class CompiledMessageToken : CompiledTemplate
method CompiledMessageToken (line 30) | public CompiledMessageToken(IFormatProvider? formatProvider, Alignment...
method Evaluate (line 44) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
method EvaluateUnaligned (line 60) | void EvaluateUnaligned(EvaluationContext ctx, TextWriter output, ref i...
method EvaluateProperty (line 86) | void EvaluateProperty(IReadOnlyDictionary<string,LogEventPropertyValue...
method EvaluatePropertyUnaligned (line 115) | void EvaluatePropertyUnaligned(LogEventPropertyValue propertyValue, Te...
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledRepetition.cs
class CompiledRepetition (line 21) | class CompiledRepetition : CompiledTemplate
method CompiledRepetition (line 30) | public CompiledRepetition(
method Evaluate (line 46) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledTemplate.cs
class CompiledTemplate (line 19) | abstract class CompiledTemplate
method Evaluate (line 21) | public abstract void Evaluate(EvaluationContext ctx, TextWriter output);
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledTemplateBlock.cs
class CompiledTemplateBlock (line 19) | class CompiledTemplateBlock : CompiledTemplate
method CompiledTemplateBlock (line 23) | public CompiledTemplateBlock(CompiledTemplate[] elements)
method Evaluate (line 28) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
FILE: src/Serilog.Expressions/Templates/Compilation/CompiledTimestampToken.cs
class CompiledTimestampToken (line 22) | class CompiledTimestampToken : CompiledTemplate
method CompiledTimestampToken (line 29) | public CompiledTimestampToken(string? format, Alignment? alignment, IF...
method Evaluate (line 37) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
method EvaluateUnaligned (line 53) | void EvaluateUnaligned(EvaluationContext ctx, TextWriter output, IForm...
FILE: src/Serilog.Expressions/Templates/Compilation/NameResolution/ExpressionLocalNameBinder.cs
class ExpressionLocalNameBinder (line 20) | class ExpressionLocalNameBinder : IdentityTransformer
method BindLocalValueNames (line 24) | public static Expression BindLocalValueNames(Expression expression, IR...
method ExpressionLocalNameBinder (line 30) | ExpressionLocalNameBinder(IReadOnlyCollection<string> localNames)
method Transform (line 35) | protected override Expression Transform(AmbientNameExpression px)
FILE: src/Serilog.Expressions/Templates/Compilation/NameResolution/TemplateLocalNameBinder.cs
class TemplateLocalNameBinder (line 21) | class TemplateLocalNameBinder
method BindLocalValueNames (line 23) | public static Template BindLocalValueNames(Template template)
method Transform (line 29) | Template Transform(Template template, Stack<string> locals)
method Transform (line 42) | Template Transform(TemplateBlock block, Stack<string> locals)
method Transform (line 49) | Template Transform(FormattedExpression fx, Stack<string> locals)
method Transform (line 60) | Template Transform(Conditional cond, Stack<string> locals)
method Transform (line 68) | Template Transform(Repetition rep, Stack<string> locals)
FILE: src/Serilog.Expressions/Templates/Compilation/TemplateCompiler.cs
class TemplateCompiler (line 24) | static class TemplateCompiler
method Compile (line 26) | public static CompiledTemplate Compile(Template template,
FILE: src/Serilog.Expressions/Templates/Compilation/TemplateFunctionNameResolver.cs
class TemplateFunctionNameResolver (line 24) | static class TemplateFunctionNameResolver
method Build (line 26) | public static NameResolver Build(NameResolver? additionalNameResolver,...
FILE: src/Serilog.Expressions/Templates/Compilation/UnreferencedProperties/ExpressionReferencedPropertiesFinder.cs
class ExpressionReferencedPropertiesFinder (line 22) | class ExpressionReferencedPropertiesFinder : SerilogExpressionTransforme...
method FindReferencedProperties (line 24) | public IEnumerable<string> FindReferencedProperties(Expression express...
method Transform (line 29) | protected override IEnumerable<string> Transform(CallExpression call)
method Transform (line 34) | protected override IEnumerable<string> Transform(ConstantExpression cx)
method Transform (line 39) | protected override IEnumerable<string> Transform(AmbientNameExpression...
method Transform (line 45) | protected override IEnumerable<string> Transform(LocalNameExpression nlx)
method Transform (line 50) | protected override IEnumerable<string> Transform(AccessorExpression spx)
method Transform (line 59) | protected override IEnumerable<string> Transform(LambdaExpression lmx)
method Transform (line 64) | protected override IEnumerable<string> Transform(ParameterExpression prx)
method Transform (line 69) | protected override IEnumerable<string> Transform(IndexerWildcardExpres...
method Transform (line 74) | protected override IEnumerable<string> Transform(ArrayExpression ax)
method Transform (line 80) | protected override IEnumerable<string> Transform(ObjectExpression ox)
method Transform (line 86) | protected override IEnumerable<string> Transform(IndexerExpression ix)
method Transform (line 102) | protected override IEnumerable<string> Transform(IndexOfMatchExpressio...
FILE: src/Serilog.Expressions/Templates/Compilation/UnreferencedProperties/TemplateReferencedPropertiesFinder.cs
class TemplateReferencedPropertiesFinder (line 19) | class TemplateReferencedPropertiesFinder
method FindReferencedProperties (line 23) | public IEnumerable<string> FindReferencedProperties(Template template)
FILE: src/Serilog.Expressions/Templates/Compilation/UnreferencedProperties/UnreferencedPropertiesFunction.cs
class UnreferencedPropertiesFunction (line 36) | class UnreferencedPropertiesFunction : NameResolver
method UnreferencedPropertiesFunction (line 42) | public UnreferencedPropertiesFunction(Template template)
method TryBindFunctionParameter (line 48) | public override bool TryBindFunctionParameter(ParameterInfo parameter,...
method TryResolveFunctionName (line 60) | public override bool TryResolveFunctionName(string name, [MaybeNullWhe...
method Implementation (line 75) | public static LogEventPropertyValue? Implementation(UnreferencedProper...
method TemplateContainsPropertyName (line 84) | static bool TemplateContainsPropertyName(MessageTemplate messageTempla...
FILE: src/Serilog.Expressions/Templates/Compilation/Unsafe/UnsafeOutputFunction.cs
class UnsafeOutputFunction (line 26) | class UnsafeOutputFunction : NameResolver
method TryResolveFunctionName (line 30) | public override bool TryResolveFunctionName(string name, [MaybeNullWhe...
method Implementation (line 45) | public static LogEventPropertyValue? Implementation(LogEventPropertyVa...
FILE: src/Serilog.Expressions/Templates/Encoding/EncodedCompiledTemplate.cs
class EncodedCompiledTemplate (line 6) | class EncodedCompiledTemplate : CompiledTemplate
method EncodedCompiledTemplate (line 11) | public EncodedCompiledTemplate(CompiledTemplate inner, TemplateOutputE...
method Evaluate (line 17) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
FILE: src/Serilog.Expressions/Templates/Encoding/EncodedTemplateFactory.cs
class EncodedTemplateFactory (line 8) | class EncodedTemplateFactory
method EncodedTemplateFactory (line 12) | public EncodedTemplateFactory(TemplateOutputEncoder? encoder)
method Wrap (line 17) | public CompiledTemplate Wrap(CompiledTemplate inner)
method MakeCompiledFormattedExpression (line 25) | public CompiledTemplate MakeCompiledFormattedExpression(Evaluatable ex...
FILE: src/Serilog.Expressions/Templates/Encoding/EscapableEncodedCompiledFormattedExpression.cs
class EscapableEncodedCompiledFormattedExpression (line 10) | class EscapableEncodedCompiledFormattedExpression : CompiledTemplate
method EscapableEncodedCompiledFormattedExpression (line 18) | public EscapableEncodedCompiledFormattedExpression(Evaluatable express...
method GetSubstituteLocalValue (line 29) | LogEventPropertyValue? GetSubstituteLocalValue(EvaluationContext context)
method Evaluate (line 36) | public override void Evaluate(EvaluationContext ctx, TextWriter output)
FILE: src/Serilog.Expressions/Templates/Encoding/PreEncodedValue.cs
class PreEncodedValue (line 5) | class PreEncodedValue
method PreEncodedValue (line 9) | public PreEncodedValue(LogEventPropertyValue? inner)
method ToString (line 14) | public override string ToString()
FILE: src/Serilog.Expressions/Templates/Encoding/TemplateOutputEncoder.cs
class TemplateOutputEncoder (line 6) | public abstract class TemplateOutputEncoder
method Encode (line 13) | public abstract string Encode(string value);
FILE: src/Serilog.Expressions/Templates/ExpressionTemplate.cs
class ExpressionTemplate (line 30) | public class ExpressionTemplate : ITextFormatter
method TryParse (line 41) | public static bool TryParse(
method TryParse (line 65) | public static bool TryParse(
method ExpressionTemplate (line 97) | ExpressionTemplate(CompiledTemplate compiled)
method ExpressionTemplate (line 114) | public ExpressionTemplate(
method SelectTheme (line 138) | static TemplateTheme SelectTheme(TemplateTheme? supplied, bool applyTh...
method Format (line 150) | public void Format(LogEvent logEvent, TextWriter output)
FILE: src/Serilog.Expressions/Templates/Parsing/TemplateParser.cs
class TemplateParser (line 20) | class TemplateParser
method TryParse (line 25) | public bool TryParse(
FILE: src/Serilog.Expressions/Templates/Parsing/TemplateTokenParsers.cs
class TemplateTokenParsers (line 28) | class TemplateTokenParsers
method TemplateTokenParsers (line 32) | public TemplateTokenParsers()
method LeftReduceConditional (line 70) | static Template? LeftReduceConditional((Expression?, Template)[] first...
method AtEnd (line 136) | _template = block.AtEnd();
FILE: src/Serilog.Expressions/Templates/Parsing/TemplateTokenizer.cs
class TemplateTokenizer (line 21) | class TemplateTokenizer : Tokenizer<ExpressionToken>
method Tokenize (line 25) | protected override IEnumerable<Result<ExpressionToken>> Tokenize(TextS...
method TokenizeHole (line 95) | IEnumerable<Result<ExpressionToken>> TokenizeHole(TextSpan span)
FILE: src/Serilog.Expressions/Templates/Rendering/AlignmentExtensions.cs
class AlignmentExtensions (line 19) | static class AlignmentExtensions
method Widen (line 21) | public static Alignment Widen(this Alignment alignment, int amount)
FILE: src/Serilog.Expressions/Templates/Rendering/Casing.cs
class Casing (line 17) | static class Casing
method Format (line 26) | public static string Format(string value, string? format = null)
FILE: src/Serilog.Expressions/Templates/Rendering/LevelRenderer.cs
class LevelRenderer (line 27) | static class LevelRenderer
method GetLevelMoniker (line 59) | public static string GetLevelMoniker(LogEventLevel value, string? format)
FILE: src/Serilog.Expressions/Templates/Rendering/Padding.cs
class Padding (line 19) | static class Padding
method Apply (line 26) | public static void Apply(TextWriter output, string value, Alignment al...
FILE: src/Serilog.Expressions/Templates/Themes/Style.cs
type Style (line 17) | readonly struct Style
method Style (line 21) | public Style(string ansiStyle)
method Set (line 26) | internal StyleReset Set(TextWriter output, ref int invisibleCharacterC...
method GetAnsiStyle (line 40) | public string? GetAnsiStyle()
FILE: src/Serilog.Expressions/Templates/Themes/StyleReset.cs
type StyleReset (line 17) | readonly struct StyleReset : IDisposable
method StyleReset (line 24) | public StyleReset(TextWriter output)
method Dispose (line 29) | public void Dispose()
FILE: src/Serilog.Expressions/Templates/Themes/TemplateTheme.cs
class TemplateTheme (line 20) | public class TemplateTheme
method TemplateTheme (line 52) | public TemplateTheme(IReadOnlyDictionary<TemplateThemeStyle, string> a...
method TemplateTheme (line 65) | public TemplateTheme(TemplateTheme baseTheme, IReadOnlyDictionary<Temp...
method GetStyle (line 74) | internal Style GetStyle(TemplateThemeStyle templateThemeStyle)
FILE: src/Serilog.Expressions/Templates/Themes/TemplateThemeStyle.cs
type TemplateThemeStyle (line 20) | public enum TemplateThemeStyle
FILE: src/Serilog.Expressions/Templates/Themes/TemplateThemes.cs
class TemplateThemes (line 17) | static class TemplateThemes
FILE: src/Serilog.Expressions/Templates/Themes/ThemedJsonValueFormatter.cs
class ThemedJsonValueFormatter (line 24) | class ThemedJsonValueFormatter : LogEventPropertyValueVisitor<TextWriter...
method ThemedJsonValueFormatter (line 30) | public ThemedJsonValueFormatter(TemplateTheme theme)
method Format (line 41) | public int Format(LogEventPropertyValue value, TextWriter output)
method VisitScalarValue (line 46) | protected override int VisitScalarValue(TextWriter state, ScalarValue ...
method VisitSequenceValue (line 51) | protected override int VisitSequenceValue(TextWriter state, SequenceVa...
method VisitStructureValue (line 78) | protected override int VisitStructureValue(TextWriter state, Structure...
method VisitDictionaryValue (line 128) | protected override int VisitDictionaryValue(TextWriter state, Dictiona...
method FormatLiteralValue (line 167) | int FormatLiteralValue(ScalarValue scalar, TextWriter output)
FILE: test/Serilog.Expressions.PerformanceTests/ComparisonBenchmark.cs
class ComparisonBenchmark (line 11) | public class ComparisonBenchmark
method ComparisonBenchmark (line 16) | public ComparisonBenchmark()
method TrivialFilter (line 40) | [Benchmark]
method HandwrittenFilter (line 46) | [Benchmark(Baseline = true)]
method ExpressionFilter (line 52) | [Benchmark]
FILE: test/Serilog.Expressions.PerformanceTests/Harness.cs
class Harness (line 22) | public class Harness
method ComparisonBenchmark (line 24) | [Fact]
FILE: test/Serilog.Expressions.PerformanceTests/Support/Some.cs
class Some (line 6) | static class Some
method InformationEvent (line 8) | public static LogEvent InformationEvent(string messageTemplate = "Hell...
method WarningEvent (line 13) | public static LogEvent WarningEvent(string messageTemplate = "Hello, w...
method LogEvent (line 18) | public static LogEvent LogEvent(LogEventLevel level, string messageTem...
FILE: test/Serilog.Expressions.Tests/ConfigurationTests.cs
class ConfigurationTests (line 6) | public class ConfigurationTests
method ExpressionsControlConditionalSinks (line 8) | [Fact]
method ExpressionsControlConditionalEnrichment (line 22) | [Fact]
FILE: test/Serilog.Expressions.Tests/ExpressionCompilerTests.cs
class ExpressionCompilerTests (line 9) | public class ExpressionCompilerTests
method ExpressionsEvaluateStringEquality (line 11) | [Fact]
method ComparisonsAreCaseSensitive (line 20) | [Fact]
method ExpressionsEvaluateStringContent (line 28) | [Fact]
method ExpressionsEvaluateStringPrefix (line 36) | [Fact]
method ExpressionsEvaluateStringSuffix (line 44) | [Fact]
method LikeIsCaseSensitive (line 52) | [Fact]
method ExpressionsEvaluateNumericComparisons (line 60) | [Fact]
method ExpressionsEvaluateWildcardsOnCollectionItems (line 68) | [Fact]
method ExpressionsEvaluateBuiltInProperties (line 76) | [Fact]
method ExpressionsEvaluateExistentials (line 84) | [Fact]
method ExpressionsLogicalOperations (line 93) | [Fact]
method ExpressionsEvaluateSubproperties (line 102) | [Fact]
method SequenceLengthCanBeDetermined (line 111) | [Fact]
method InMatchesLiterals (line 119) | [Fact]
method InExaminesSequenceValues (line 127) | [Fact]
method ReportsArityMismatches (line 136) | [Theory]
method AssertEvaluation (line 149) | static void AssertEvaluation(string expression, LogEvent match, params...
FILE: test/Serilog.Expressions.Tests/ExpressionEvaluationTests.cs
class ExpressionEvaluationTests (line 11) | public class ExpressionEvaluationTests
method ExpressionsAreCorrectlyEvaluated (line 16) | [Theory]
method Display (line 52) | static string Display(LogEventPropertyValue? value)
FILE: test/Serilog.Expressions.Tests/ExpressionParserTests.cs
class ExpressionParserTests (line 6) | public class ExpressionParserTests
method ValidSyntaxIsAccepted (line 8) | [Theory]
method InvalidSyntaxIsRejected (line 49) | [Theory]
method PreciseErrorsAreReported (line 66) | [Theory]
FILE: test/Serilog.Expressions.Tests/ExpressionTranslationTests.cs
class ExpressionTranslationTests (line 8) | public class ExpressionTranslationTests
method ExpressionsAreCorrectlyTranslated (line 13) | [Theory]
FILE: test/Serilog.Expressions.Tests/ExpressionValidationTests.cs
class ExpressionValidationTests (line 5) | public class ExpressionValidationTests
method InvalidRegularExpressionsAreReportedGracefully (line 7) | [Theory]
method UnknownFunctionNamesAreReportedGracefully (line 21) | [Theory]
method InvalidCiModifierUsageCompilesWithWarning (line 34) | [Theory]
method ValidCiModifierUsageCompiles (line 48) | [Theory]
method FirstErrorIsReportedInComplexExpressions (line 66) | [Fact]
method ValidExpressionsStillCompileWithoutErrors (line 80) | [Fact]
method CompileMethodStillThrowsForInvalidExpressions (line 104) | [Fact]
method NonConstantRegexPatternsHandledGracefully (line 122) | [Theory]
method RegexTimeoutIsRespected (line 136) | [Fact]
method ComplexExpressionsReportFirstError (line 149) | [Fact]
method BackwardCompatibilityPreservedForInvalidCiUsage (line 163) | [Fact]
FILE: test/Serilog.Expressions.Tests/ExpressionValueTests.cs
class ExpressionValueTests (line 6) | public class ExpressionValueTests
method UndefinedResultsAreFalse (line 8) | [Fact]
method NonBooleanResultsAreFalse (line 14) | [Fact]
method TrueIsTrue (line 20) | [Fact]
method FalseIsNotTrue (line 26) | [Fact]
FILE: test/Serilog.Expressions.Tests/Expressions/NameResolverTests.cs
class NameResolverTests (line 10) | public class NameResolverTests
method Magic (line 13) | public static LogEventPropertyValue? Magic(LogEventPropertyValue? number)
method SecretWordAt (line 22) | public static LogEventPropertyValue? SecretWordAt(string word, LogEven...
class SecretWordResolver (line 30) | class SecretWordResolver : NameResolver
method SecretWordResolver (line 35) | public SecretWordResolver(NameResolver inner, string word)
method TryResolveFunctionName (line 41) | public override bool TryResolveFunctionName(string name, [MaybeNullW...
method TryBindFunctionParameter (line 44) | public override bool TryBindFunctionParameter(ParameterInfo paramete...
class LegacyLevelPropertyNameResolver (line 57) | class LegacyLevelPropertyNameResolver: NameResolver
method TryResolveBuiltInPropertyName (line 59) | public override bool TryResolveBuiltInPropertyName(string alias, [No...
method UserDefinedFunctionsAreCallableInExpressions (line 72) | [Fact]
method UserDefinedFunctionsCanReceiveUserProvidedParameters (line 81) | [Fact]
method BuiltInPropertiesCanBeAliased (line 90) | [Fact]
FILE: test/Serilog.Expressions.Tests/Expressions/Runtime/LocalsTests.cs
class LocalsTests (line 7) | public class LocalsTests
method NoValueIsDefinedInNoLocals (line 9) | [Fact]
method ASetValueIsRetrieved (line 15) | [Fact]
method ASetValueIsRetrievedFromMany (line 24) | [Fact]
method TheTopmostValueIsRetrievedForAName (line 34) | [Fact]
FILE: test/Serilog.Expressions.Tests/Expressions/Runtime/RuntimeOperatorsTests.cs
class RuntimeOperatorsTests (line 9) | public class RuntimeOperatorsTests
method InspectReadsPublicPropertiesFromScalarValue (line 11) | [Fact]
method DeepInspectionReadsSubproperties (line 26) | [Fact]
FILE: test/Serilog.Expressions.Tests/FormatParityTests.cs
class FormatParityTests (line 17) | public class FormatParityTests
method ClefEscape (line 21) | public static LogEventPropertyValue? ClefEscape(LogEventPropertyValue?...
method ClassicRender (line 50) | public static LogEventPropertyValue? ClassicRender(LogEventPropertyVal...
method ClassicRenderings (line 66) | public static LogEventPropertyValue? ClassicRenderings(LogEventPropert...
method Render (line 125) | static string Render(
method AssertWriteParity (line 134) | void AssertWriteParity(
method ParityIsMaintained (line 162) | [Fact]
FILE: test/Serilog.Expressions.Tests/LoggingFilterSwitchTests.cs
class LoggingFilterSwitchTests (line 6) | public class LoggingFilterSwitchTests
method WhenTheFilterExpressionIsModifiedTheFilterChanges (line 8) | [Fact]
FILE: test/Serilog.Expressions.Tests/Support/AsvCases.cs
class AsvCases (line 9) | static class AsvCases
method ReadCases (line 13) | public static IEnumerable<object[]> ReadCases(string filename)
FILE: test/Serilog.Expressions.Tests/Support/CollectingSink.cs
class CollectingSink (line 6) | class CollectingSink : ILogEventSink
method Emit (line 14) | public void Emit(LogEvent logEvent)
FILE: test/Serilog.Expressions.Tests/Support/ParenthesizingEncoder.cs
class ParenthesizingEncoder (line 5) | public class ParenthesizingEncoder : TemplateOutputEncoder
method Encode (line 7) | public override string Encode(string value)
FILE: test/Serilog.Expressions.Tests/Support/Some.cs
class Some (line 6) | static class Some
method InformationEvent (line 10) | public static LogEvent InformationEvent(string messageTemplate = "Hell...
method InformationEvent (line 15) | public static LogEvent InformationEvent(DateTimeOffset timestamp, stri...
method WarningEvent (line 20) | public static LogEvent WarningEvent(string messageTemplate = "Hello, w...
method LogEvent (line 25) | public static LogEvent LogEvent(LogEventLevel level, string messageTem...
method LogEvent (line 30) | public static LogEvent LogEvent(DateTimeOffset timestamp, LogEventLeve...
method AnonymousObject (line 42) | public static object AnonymousObject()
method LogEventPropertyValue (line 47) | public static LogEventPropertyValue LogEventPropertyValue()
method Int (line 52) | static int Int()
method String (line 57) | public static string String()
FILE: test/Serilog.Expressions.Tests/Support/StringHashPrefixingTheme.cs
class StringHashPrefixingTheme (line 5) | static class StringHashPrefixingTheme
FILE: test/Serilog.Expressions.Tests/Support/TestHelperNameResolver.cs
class TestHelperNameResolver (line 7) | public class TestHelperNameResolver: NameResolver
method TryResolveFunctionName (line 9) | public override bool TryResolveFunctionName(string name, [MaybeNullWhe...
method TestDict (line 21) | public static LogEventPropertyValue? TestDict(LogEventPropertyValue? v...
FILE: test/Serilog.Expressions.Tests/TemplateEncodingTests.cs
class TemplateEncodingTests (line 7) | public class TemplateEncodingTests
method TemplatesAreCorrectlyEvaluated (line 12) | [Theory]
method EncodingAppliesToThemedOutput (line 27) | [Fact]
FILE: test/Serilog.Expressions.Tests/TemplateEvaluationTests.cs
class TemplateEvaluationTests (line 9) | public class TemplateEvaluationTests
method TemplatesAreCorrectlyEvaluated (line 17) | [Theory]
FILE: test/Serilog.Expressions.Tests/TemplateParserTests.cs
class TemplateParserTests (line 8) | public class TemplateParserTests
method ErrorsAreReported (line 10) | [Theory]
method DefaultAlignmentIsNull (line 26) | [Fact]
FILE: test/Serilog.Expressions.Tests/TemplateTokenizerTests.cs
class TemplateTokenizerTests (line 9) | public class TemplateTokenizerTests
method ValidTemplatesAreTokenized (line 46) | [Theory]
method InvalidTemplatesAreReported (line 56) | [Theory]
FILE: test/Serilog.Expressions.Tests/Templates/UnreferencedPropertiesFunctionTests.cs
class UnreferencedPropertiesFunctionTests (line 10) | public class UnreferencedPropertiesFunctionTests
method UnreferencedPropertiesFunctionIsNamedRest (line 12) | [Fact]
method UnreferencedPropertiesExcludeThoseInMessageAndTemplate (line 19) | [Fact]
Condensed preview — 188 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (575K chars).
[
{
"path": ".gitattributes",
"chars": 67,
"preview": "# Auto detect text files and perform LF normalization\n\n* text=auto\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 1052,
"preview": "---\nname: Bug report\nabout: Report a bug and help us to improve Serilog.Expressions\ntitle: ''\nlabels: bug\nassignees: ''\n"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 158,
"preview": "contact_links:\n - name: Ask for help\n url: https://stackoverflow.com/tags/serilog\n about: Ask the community for h"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 658,
"preview": "---\nname: Feature request\nabout: Suggest an improvement to Serilog.Expressions\ntitle: ''\nlabels: enhancement\nassignees: "
},
{
"path": ".github/workflows/ci.yml",
"chars": 1023,
"preview": "# If this file is renamed, the incrementing run attempt number will be reset.\n\nname: CI\n\non:\n push:\n branches: [ \"de"
},
{
"path": ".gitignore",
"chars": 3798,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
},
{
"path": "Build.ps1",
"chars": 2948,
"preview": "Write-Output \"build: Tool versions follow\"\n\ndotnet --version\ndotnet --list-sdks\n\nWrite-Output \"build: Build started\"\n\nPu"
},
{
"path": "Directory.Build.props",
"chars": 1313,
"preview": "<Project>\n <!-- Properties in this file are expected to be identical for all Serilog organization projects. If\n a pro"
},
{
"path": "Directory.Version.props",
"chars": 99,
"preview": "<Project>\n <PropertyGroup>\n <VersionPrefix>5.1.0</VersionPrefix>\n </PropertyGroup>\n</Project>\n"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 21388,
"preview": "# Serilog.Expressions [ {\n Push-Location $test\n\n\techo"
},
{
"path": "example/Sample/Program.cs",
"chars": 3722,
"preview": "using Serilog;\nusing Serilog.Debugging;\nusing Serilog.Templates;\nusing Serilog.Templates.Themes;\n\nSelfLog.Enable(Consol"
},
{
"path": "example/Sample/Sample.csproj",
"chars": 454,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>net9.0</TargetFramework>\n <OutputType>Exe<"
},
{
"path": "global.json",
"chars": 110,
"preview": "{\n \"sdk\": {\n \"version\": \"9.0.200\",\n \"allowPrerelease\": false,\n \"rollForward\": \"latestFeature\"\n }\n}\n"
},
{
"path": "serilog-expressions.sln",
"chars": 3939,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.3141"
},
{
"path": "serilog-expressions.sln.DotSettings",
"chars": 1674,
"preview": "<wpf:ResourceDictionary xml:space=\"preserve\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:s=\"clr-namesp"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/AccessorExpression.cs",
"chars": 1779,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/AmbientNameExpression.cs",
"chars": 1622,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/ArrayExpression.cs",
"chars": 1487,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/CallExpression.cs",
"chars": 1560,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/ConstantExpression.cs",
"chars": 1595,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/Element.cs",
"chars": 736,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/Expression.cs",
"chars": 1060,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/IndexOfMatchExpression.cs",
"chars": 1372,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/IndexerExpression.cs",
"chars": 1258,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/IndexerWildcard.cs",
"chars": 778,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/IndexerWildcardExpression.cs",
"chars": 1484,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/ItemElement.cs",
"chars": 945,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/LambdaExpression.cs",
"chars": 1266,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/LocalNameExpression.cs",
"chars": 1176,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/Member.cs",
"chars": 734,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/ObjectExpression.cs",
"chars": 1269,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/ParameterExpression.cs",
"chars": 1038,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/PropertyMember.cs",
"chars": 1273,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/SpreadElement.cs",
"chars": 1397,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Ast/SpreadMember.cs",
"chars": 1144,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/BuiltInProperty.cs",
"chars": 1147,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Arrays/ConstantArrayEvaluator.cs",
"chars": 1514,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/DefaultFunctionNameResolver.cs",
"chars": 1058,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/ExpressionCompiler.cs",
"chars": 1745,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/ExpressionValidationException.cs",
"chars": 911,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Linq/EventIdHash.cs",
"chars": 1851,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Linq/ExpressionConstantMapper.cs",
"chars": 1202,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Linq/Intrinsics.cs",
"chars": 6825,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs",
"chars": 18155,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Linq/ParameterReplacementVisitor.cs",
"chars": 1652,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/OrderedNameResolver.cs",
"chars": 2005,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Pattern.cs",
"chars": 1362,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Properties/PropertiesObjectAccessorTransformer.cs",
"chars": 1546,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Text/LikeSyntaxTransformer.cs",
"chars": 3971,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Text/TextMatchingTransformer.cs",
"chars": 2747,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Transformations/IdentityTransformer.cs",
"chars": 4499,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Transformations/NodeReplacer.cs",
"chars": 1267,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Transformations/SerilogExpressionTransformer.cs",
"chars": 2640,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Variadics/VariadicCallRewriter.cs",
"chars": 1912,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Wildcards/WildcardComprehensionTransformer.cs",
"chars": 3643,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Compilation/Wildcards/WildcardSearch.cs",
"chars": 2786,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/CompiledExpression.cs",
"chars": 1042,
"preview": "// Copyright Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
},
{
"path": "src/Serilog.Expressions/Expressions/Evaluatable.cs",
"chars": 718,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/EvaluationContext.cs",
"chars": 987,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/ExpressionResult.cs",
"chars": 1452,
"preview": "// Copyright Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
},
{
"path": "src/Serilog.Expressions/Expressions/Helpers.cs",
"chars": 2160,
"preview": "// Copyright Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
},
{
"path": "src/Serilog.Expressions/Expressions/LoggingFilterSwitch.cs",
"chars": 2837,
"preview": "// Copyright Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
},
{
"path": "src/Serilog.Expressions/Expressions/NameResolver.cs",
"chars": 3465,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Operators.cs",
"chars": 4900,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Parsing/Combinators.cs",
"chars": 2868,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Parsing/ExpressionKeyword.cs",
"chars": 918,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Parsing/ExpressionParser.cs",
"chars": 1730,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Parsing/ExpressionTextParsers.cs",
"chars": 2344,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Parsing/ExpressionToken.cs",
"chars": 3369,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Parsing/ExpressionTokenParsers.cs",
"chars": 13936,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Parsing/ExpressionTokenizer.cs",
"chars": 7828,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Parsing/ParserExtensions.cs",
"chars": 1706,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Runtime/Coerce.cs",
"chars": 3147,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/Runtime/Locals.cs",
"chars": 1776,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Runtime/RuntimeOperators.cs",
"chars": 21276,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Expressions/Runtime/Support/UnflattenDottedPropertyNames.cs",
"chars": 5007,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Expressions/SerilogExpression.cs",
"chars": 7074,
"preview": "// Copyright Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
},
{
"path": "src/Serilog.Expressions/Expressions/StaticMemberNameResolver.cs",
"chars": 1856,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/LoggerEnrichmentConfigurationExtensions.cs",
"chars": 3502,
"preview": "// Copyright 2019 Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may"
},
{
"path": "src/Serilog.Expressions/LoggerFilterConfigurationExtensions.cs",
"chars": 3369,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/LoggerSinkConfigurationExtensions.cs",
"chars": 2181,
"preview": "// Copyright 2019 Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Combinators.cs",
"chars": 30636,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Display/Presentation.cs",
"chars": 5810,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Display/TokenAttribute.cs",
"chars": 1481,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/Position.cs",
"chars": 2831,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/Result.cs",
"chars": 3722,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/Result`1.cs",
"chars": 4220,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/TextSpan.cs",
"chars": 7021,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/TokenListParserResult.cs",
"chars": 5285,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/TokenListParserResult`2.cs",
"chars": 5895,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/TokenList`1.cs",
"chars": 5415,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/Token`1.cs",
"chars": 1978,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Model/Unit.cs",
"chars": 896,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Parse.cs",
"chars": 5543,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/ParseException.cs",
"chars": 2156,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/ParserExtensions.cs",
"chars": 1575,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Parsers/Character.cs",
"chars": 3127,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Parsers/Numerics.cs",
"chars": 2578,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Parsers/Span.cs",
"chars": 1974,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Parsers/Token.cs",
"chars": 2557,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/README.md",
"chars": 11426,
"preview": "# Superpower\n\nThe classes in this namespace are from [Superpower](https://github.com/datalust/superpower).\n\nThey are in"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/TextParser`1.cs",
"chars": 1071,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/TokenListParser`2.cs",
"chars": 1195,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Versi"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Tokenizer`1.cs",
"chars": 3776,
"preview": "// Copyright 2016-2018 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, "
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Util/CharInfo.cs",
"chars": 800,
"preview": "// Copyright 2018 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/ParserConstruction/Util/Friendly.cs",
"chars": 1624,
"preview": "// Copyright 2016 Datalust, Superpower Contributors, Sprache Contributors\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/Serilog.Expressions/Pipeline/ComputedPropertyEnricher.cs",
"chars": 1361,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Properties/AssemblyInfo.cs",
"chars": 640,
"preview": "using System.Runtime.CompilerServices;\n\n[assembly: CLSCompliant(true)]\n\n[assembly: InternalsVisibleTo(\"Serilog.Expressi"
},
{
"path": "src/Serilog.Expressions/Serilog.Expressions.csproj",
"chars": 1934,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <Description>An embeddable mini-language for filtering, enrichi"
},
{
"path": "src/Serilog.Expressions/Templates/Ast/Conditional.cs",
"chars": 1127,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Ast/FormattedExpression.cs",
"chars": 1091,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Ast/LiteralText.cs",
"chars": 812,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Ast/Repetition.cs",
"chars": 1334,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Ast/Template.cs",
"chars": 653,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Ast/TemplateBlock.cs",
"chars": 844,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledConditional.cs",
"chars": 1436,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledExceptionToken.cs",
"chars": 1910,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledFormattedExpression.cs",
"chars": 2872,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledLevelToken.cs",
"chars": 2404,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledLiteralText.cs",
"chars": 1197,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledMessageToken.cs",
"chars": 6156,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledRepetition.cs",
"chars": 4666,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledTemplate.cs",
"chars": 777,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledTemplateBlock.cs",
"chars": 1091,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/CompiledTimestampToken.cs",
"chars": 2409,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/NameResolution/ExpressionLocalNameBinder.cs",
"chars": 1535,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/NameResolution/TemplateLocalNameBinder.cs",
"chars": 2879,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/TemplateCompiler.cs",
"chars": 3837,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/TemplateFunctionNameResolver.cs",
"chars": 1405,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/UnreferencedProperties/ExpressionReferencedPropertiesFinder.cs",
"chars": 3371,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/UnreferencedProperties/TemplateReferencedPropertiesFinder.cs",
"chars": 2156,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/UnreferencedProperties/UnreferencedPropertiesFunction.cs",
"chars": 3880,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Compilation/Unsafe/UnsafeOutputFunction.cs",
"chars": 1739,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Encoding/EncodedCompiledTemplate.cs",
"chars": 743,
"preview": "using Serilog.Expressions;\nusing Serilog.Templates.Compilation;\n\nnamespace Serilog.Templates.Encoding\n{\n class Encod"
},
{
"path": "src/Serilog.Expressions/Templates/Encoding/EncodedTemplateFactory.cs",
"chars": 1097,
"preview": "using Serilog.Expressions;\nusing Serilog.Parsing;\nusing Serilog.Templates.Compilation;\nusing Serilog.Templates.Themes;\n"
},
{
"path": "src/Serilog.Expressions/Templates/Encoding/EscapableEncodedCompiledFormattedExpression.cs",
"chars": 2639,
"preview": "using Serilog.Events;\nusing Serilog.Expressions;\nusing Serilog.Expressions.Runtime;\nusing Serilog.Parsing;\nusing Serilo"
},
{
"path": "src/Serilog.Expressions/Templates/Encoding/PreEncodedValue.cs",
"chars": 585,
"preview": "using Serilog.Events;\n\nnamespace Serilog.Templates.Encoding\n{\n class PreEncodedValue\n {\n public LogEventPr"
},
{
"path": "src/Serilog.Expressions/Templates/Encoding/TemplateOutputEncoder.cs",
"chars": 483,
"preview": "namespace Serilog.Templates.Encoding\n{\n /// <summary>\n /// An encoder applied to the output substituted into temp"
},
{
"path": "src/Serilog.Expressions/Templates/ExpressionTemplate.cs",
"chars": 6428,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Parsing/TemplateParser.cs",
"chars": 1583,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Parsing/TemplateTokenParsers.cs",
"chars": 5840,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Parsing/TemplateTokenizer.cs",
"chars": 6315,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Rendering/AlignmentExtensions.cs",
"chars": 847,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Rendering/Casing.cs",
"chars": 1407,
"preview": "// Copyright Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
},
{
"path": "src/Serilog.Expressions/Templates/Rendering/LevelRenderer.cs",
"chars": 3240,
"preview": "// Copyright 2017 Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may"
},
{
"path": "src/Serilog.Expressions/Templates/Rendering/Padding.cs",
"chars": 1582,
"preview": "// Copyright 2013-2020 Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// yo"
},
{
"path": "src/Serilog.Expressions/Templates/Themes/Style.cs",
"chars": 1210,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Themes/StyleReset.cs",
"chars": 973,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Themes/TemplateTheme.cs",
"chars": 3419,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Themes/TemplateThemeStyle.cs",
"chars": 2346,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "src/Serilog.Expressions/Templates/Themes/TemplateThemes.cs",
"chars": 5178,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not"
},
{
"path": "src/Serilog.Expressions/Templates/Themes/ThemedJsonValueFormatter.cs",
"chars": 7740,
"preview": "// Copyright © Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may no"
},
{
"path": "test/Serilog.Expressions.PerformanceTests/ComparisonBenchmark.cs",
"chars": 1559,
"preview": "using BenchmarkDotNet.Attributes;\nusing Serilog.Events;\nusing Serilog.Expressions.PerformanceTests.Support;\nusing Xunit;"
},
{
"path": "test/Serilog.Expressions.PerformanceTests/Harness.cs",
"chars": 867,
"preview": "\n// Copyright 2013-2016 Serilog Contributors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// yo"
},
{
"path": "test/Serilog.Expressions.PerformanceTests/Serilog.Expressions.PerformanceTests.csproj",
"chars": 870,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>net9.0</TargetFramework>\n <GenerateRuntimeC"
},
{
"path": "test/Serilog.Expressions.PerformanceTests/Support/Some.cs",
"chars": 1165,
"preview": "using Serilog.Events;\nusing Xunit.Sdk;\n\nnamespace Serilog.Expressions.PerformanceTests.Support;\n\nstatic class Some\n{\n "
},
{
"path": "test/Serilog.Expressions.Tests/Cases/expression-evaluation-cases.asv",
"chars": 12957,
"preview": "// Primitives\nnull ⇶ null\ntrue ⇶ true\nfalse "
},
{
"path": "test/Serilog.Expressions.Tests/Cases/template-encoding-cases.asv",
"chars": 399,
"preview": "{@m} ⇶ (Hello, nblumhardt!)\n{'world'}! ⇶ (world)!\n{unsafe('world')}!"
},
{
"path": "test/Serilog.Expressions.Tests/Cases/template-evaluation-cases.asv",
"chars": 2421,
"preview": "Hello, {'world'}! ⇶ Hello, world!\n{@l} ⇶ Information\n{@l:u3} "
},
{
"path": "test/Serilog.Expressions.Tests/Cases/translation-cases.asv",
"chars": 1480,
"preview": "// Like\nA like 'a' ⇶ _Internal_NotEqual(_Internal_IndexOfMatch(A, '^a$'), -1)\nA like"
},
{
"path": "test/Serilog.Expressions.Tests/ConfigurationTests.cs",
"chars": 1009,
"preview": "using Serilog.Expressions.Tests.Support;\nusing Xunit;\n\nnamespace Serilog.Expressions.Tests;\n\npublic class Configuration"
},
{
"path": "test/Serilog.Expressions.Tests/ExpressionCompilerTests.cs",
"chars": 5421,
"preview": "using Serilog.Events;\nusing Serilog.Expressions.Tests.Support;\nusing Xunit;\n\n// ReSharper disable CoVariantArrayConvers"
},
{
"path": "test/Serilog.Expressions.Tests/ExpressionEvaluationTests.cs",
"chars": 2244,
"preview": "using System.Diagnostics;\nusing System.Globalization;\nusing Serilog.Events;\nusing Serilog.Expressions.Runtime;\nusing Ser"
},
{
"path": "test/Serilog.Expressions.Tests/ExpressionParserTests.cs",
"chars": 4111,
"preview": "using Serilog.Expressions.Parsing;\nusing Xunit;\n\nnamespace Serilog.Expressions.Tests;\n\npublic class ExpressionParserTes"
},
{
"path": "test/Serilog.Expressions.Tests/ExpressionTranslationTests.cs",
"chars": 696,
"preview": "using Serilog.Expressions.Compilation;\nusing Serilog.Expressions.Parsing;\nusing Serilog.Expressions.Tests.Support;\nusing"
},
{
"path": "test/Serilog.Expressions.Tests/ExpressionValidationTests.cs",
"chars": 6881,
"preview": "using Xunit;\n\nnamespace Serilog.Expressions.Tests;\n\npublic class ExpressionValidationTests\n{\n [Theory]\n [InlineDat"
},
{
"path": "test/Serilog.Expressions.Tests/ExpressionValueTests.cs",
"chars": 617,
"preview": "using Serilog.Events;\nusing Xunit;\n\nnamespace Serilog.Expressions.Tests;\n\npublic class ExpressionValueTests\n{\n [Fact"
},
{
"path": "test/Serilog.Expressions.Tests/Expressions/NameResolverTests.cs",
"chars": 2971,
"preview": "using System.Diagnostics.CodeAnalysis;\nusing System.Reflection;\nusing Serilog.Events;\nusing Serilog.Expressions.Runtime"
},
{
"path": "test/Serilog.Expressions.Tests/Expressions/Runtime/LocalsTests.cs",
"chars": 1380,
"preview": "using Serilog.Expressions.Runtime;\nusing Serilog.Expressions.Tests.Support;\nusing Xunit;\n\nnamespace Serilog.Expressions"
},
{
"path": "test/Serilog.Expressions.Tests/Expressions/Runtime/RuntimeOperatorsTests.cs",
"chars": 1642,
"preview": "using System.Reflection;\nusing Serilog.Events;\nusing Serilog.Expressions.Runtime;\nusing Serilog.Expressions.Tests.Suppor"
},
{
"path": "test/Serilog.Expressions.Tests/FormatParityTests.cs",
"chars": 6705,
"preview": "using Serilog.Events;\nusing Serilog.Expressions.Tests.Support;\nusing Serilog.Formatting;\nusing Serilog.Formatting.Compa"
},
{
"path": "test/Serilog.Expressions.Tests/LoggingFilterSwitchTests.cs",
"chars": 982,
"preview": "using Serilog.Expressions.Tests.Support;\nusing Xunit;\n\nnamespace Serilog.Expressions.Tests;\n\npublic class LoggingFilter"
},
{
"path": "test/Serilog.Expressions.Tests/Properties/launchSettings.json",
"chars": 189,
"preview": "{\n \"profiles\": {\n \"test\": {\n \"commandName\": \"test\"\n },\n \"test-dnxcore50\": {\n \"commandName\": \"test\",\n"
},
{
"path": "test/Serilog.Expressions.Tests/Serilog.Expressions.Tests.csproj",
"chars": 1024,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n <PropertyGroup>\n <TargetFramework>net9.0</TargetFramework>\n <GenerateRuntimeC"
},
{
"path": "test/Serilog.Expressions.Tests/Support/AsvCases.cs",
"chars": 945,
"preview": "namespace Serilog.Expressions.Tests.Support;\n\n// \"Arrow-separated values ;-) ... convenient because the Unicode `⇶` cha"
},
{
"path": "test/Serilog.Expressions.Tests/Support/CollectingSink.cs",
"chars": 391,
"preview": "using Serilog.Core;\nusing Serilog.Events;\n\nnamespace Serilog.Expressions.Tests.Support;\n\nclass CollectingSink : ILogEve"
},
{
"path": "test/Serilog.Expressions.Tests/Support/ParenthesizingEncoder.cs",
"chars": 234,
"preview": "using Serilog.Templates.Encoding;\n\nnamespace Serilog.Expressions.Tests.Support;\n\npublic class ParenthesizingEncoder : T"
},
{
"path": "test/Serilog.Expressions.Tests/Support/Some.cs",
"chars": 2061,
"preview": "using Serilog.Events;\nusing Xunit.Sdk;\n\nnamespace Serilog.Expressions.Tests.Support;\n\nstatic class Some\n{\n static in"
},
{
"path": "test/Serilog.Expressions.Tests/Support/StringHashPrefixingTheme.cs",
"chars": 275,
"preview": "using Serilog.Templates.Themes;\n\nnamespace Serilog.Expressions.Tests.Support;\n\nstatic class StringHashPrefixingTheme\n{\n "
},
{
"path": "test/Serilog.Expressions.Tests/Support/TestHelperNameResolver.cs",
"chars": 811,
"preview": "using System.Diagnostics.CodeAnalysis;\nusing System.Reflection;\nusing Serilog.Events;\n\nnamespace Serilog.Expressions.Tes"
},
{
"path": "test/Serilog.Expressions.Tests/TemplateEncodingTests.cs",
"chars": 1747,
"preview": "using Serilog.Expressions.Tests.Support;\nusing Serilog.Templates;\nusing Xunit;\n\nnamespace Serilog.Expressions.Tests;\n\npu"
},
{
"path": "test/Serilog.Expressions.Tests/TemplateEvaluationTests.cs",
"chars": 1013,
"preview": "using System.Globalization;\nusing Serilog.Events;\nusing Serilog.Expressions.Tests.Support;\nusing Serilog.Templates;\nusin"
},
{
"path": "test/Serilog.Expressions.Tests/TemplateParserTests.cs",
"chars": 1700,
"preview": "using Serilog.Templates;\nusing Serilog.Templates.Ast;\nusing Serilog.Templates.Parsing;\nusing Xunit;\n\nnamespace Serilog."
},
{
"path": "test/Serilog.Expressions.Tests/TemplateTokenizerTests.cs",
"chars": 2032,
"preview": "using Serilog.Expressions.Parsing;\nusing Serilog.Templates.Parsing;\nusing Xunit;\n\nusing static Serilog.Expressions.Pars"
},
{
"path": "test/Serilog.Expressions.Tests/Templates/UnreferencedPropertiesFunctionTests.cs",
"chars": 1940,
"preview": "using Serilog.Events;\nusing Serilog.Parsing;\nusing Serilog.Templates.Ast;\nusing Serilog.Templates.Compilation.Unreferen"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the serilog/serilog-expressions GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 188 files (526.8 KB), approximately 122.8k tokens, and a symbol index with 712 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.