Reorganize source code in preparation to move into aspnet/AspNetCore

Prior to reorganization, this source code was found in 082d505977
This commit is contained in:
Nate McMaster 2018-11-21 16:21:23 -08:00
commit cb198d727b
No known key found for this signature in database
GPG Key ID: A778D9601BD78810
281 changed files with 290 additions and 12686 deletions

View File

@ -1,17 +0,0 @@
init:
- git config --global core.autocrlf true
branches:
only:
- master
- /^release\/.*$/
- /^(.*\/)?ci-.*$/
build_script:
- ps: .\run.ps1 default-build
clone_depth: 1
environment:
global:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_CLI_TELEMETRY_OPTOUT: 1
test: 'off'
deploy: 'off'
os: Visual Studio 2017

52
.gitattributes vendored
View File

@ -1,52 +0,0 @@
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text=auto diff=csharp
*.vb text=auto
*.resx text=auto
*.c text=auto
*.cpp text=auto
*.cxx text=auto
*.h text=auto
*.hxx text=auto
*.py text=auto
*.rb text=auto
*.java text=auto
*.html text=auto
*.htm text=auto
*.css text=auto
*.scss text=auto
*.sass text=auto
*.less text=auto
*.js text=auto
*.lisp text=auto
*.clj text=auto
*.sql text=auto
*.php text=auto
*.lua text=auto
*.m text=auto
*.asm text=auto
*.erl text=auto
*.fs text=auto
*.fsx text=auto
*.hs text=auto
*.csproj text=auto
*.vbproj text=auto
*.fsproj text=auto
*.dbproj text=auto
*.sln text=auto eol=crlf
*.sh eol=lf

38
.gitignore vendored
View File

@ -1,38 +0,0 @@
[Oo]bj/
[Bb]in/
TestResults/
.nuget/
_ReSharper.*/
packages/
artifacts/
PublishProfiles/
*.user
*.suo
*.cache
*.docstates
_ReSharper.*
nuget.exe
*net45.csproj
*net451.csproj
*k10.csproj
*.psess
*.vsp
*.pidb
*.userprefs
*DS_Store
*.ncrunchsolution
*.*sdf
*.ipch
*.sln.ide
node_modules
*.sln.ide
project.lock.json
.vs/
.vscode/
launchSettings.json
.build/
.testPublish/
global.json
# Rider and friends
.idea/

View File

@ -1,27 +0,0 @@
language: csharp
sudo: false
dist: trusty
env:
global:
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- DOTNET_CLI_TELEMETRY_OPTOUT: 1
mono: none
os:
- linux
- osx
osx_image: xcode8.2
addons:
apt:
packages:
- libunwind8
branches:
only:
- master
- /^release\/.*$/
- /^(.*\/)?ci-.*$/
before_install:
- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s
/usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
/usr/local/lib/; fi
script:
- ./build.sh

View File

@ -1,13 +0,0 @@
trigger:
- master
- release/*
resources:
repositories:
- repository: buildtools
type: git
name: aspnet-BuildTools
ref: refs/heads/master
phases:
- template: .vsts-pipelines/templates/project-ci.yml@buildtools

View File

@ -1,28 +0,0 @@
trigger:
- master
- release/*
# See https://github.com/aspnet/BuildTools
resources:
repositories:
- repository: buildtools
type: github
endpoint: DotNet-Bot GitHub Connection
name: aspnet/BuildTools
ref: refs/heads/master
phases:
- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
parameters:
agentOs: Windows
beforeBuild:
- script: sqllocaldb start
displayName: Start LocalDB
- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
parameters:
agentOs: macOS
- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools
parameters:
agentOs: Linux

View File

@ -1,4 +0,0 @@
Contributing
======
Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/AspNetCore/blob/master/CONTRIBUTING.md) in the AspNetCore repo.

View File

@ -1,410 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26923.0
MinimumVisualStudioVersion = 15.0.26730.03
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{509A6F36-AD80-4A18-B5B1-717D38DFF29D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{ACAA0157-A8C4-4152-93DE-90CCDF304087}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WelcomePageSample", "samples\WelcomePageSample\WelcomePageSample.csproj", "{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics", "src\Microsoft.AspNetCore.Diagnostics\Microsoft.AspNetCore.Diagnostics.csproj", "{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeveloperExceptionPageSample", "samples\DeveloperExceptionPageSample\DeveloperExceptionPageSample.csproj", "{589AC17F-9455-4764-8F82-FCD2AE58DA14}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2AF90579-B118-4583-AE88-672EFACB5BC4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics.Tests", "test\Microsoft.AspNetCore.Diagnostics.Tests\Microsoft.AspNetCore.Diagnostics.Tests.csproj", "{994351B4-7B2A-4139-8B72-72C5BB5CC618}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExceptionHandlerSample", "samples\ExceptionHandlerSample\ExceptionHandlerSample.csproj", "{427CDB36-78B0-4583-9EBC-7F283DE60355}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore", "src\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj", "{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests", "test\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.csproj", "{5486117B-A742-49E0-94FC-12B76F061803}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics.Elm", "src\Microsoft.AspNetCore.Diagnostics.Elm\Microsoft.AspNetCore.Diagnostics.Elm.csproj", "{624B0019-956A-4157-B008-270C5B229553}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StatusCodePagesSample", "samples\StatusCodePagesSample\StatusCodePagesSample.csproj", "{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics.Abstractions", "src\Microsoft.AspNetCore.Diagnostics.Abstractions\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj", "{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ElmPageSample", "samples\ElmPageSample\ElmPageSample.csproj", "{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabaseErrorPageSample", "samples\DatabaseErrorPageSample\DatabaseErrorPageSample.csproj", "{FF7F11A1-14E7-4948-A853-2487D99DE0C6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.MiddlewareAnalysis", "src\Microsoft.AspNetCore.MiddlewareAnalysis\Microsoft.AspNetCore.MiddlewareAnalysis.csproj", "{C2DEDD37-D1EB-4819-9A9C-475E37A52358}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiddlewareAnalysisSample", "samples\MiddlewareAnalysisSample\MiddlewareAnalysisSample.csproj", "{95981429-F212-44E1-83AA-32DA9E2A517C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.MiddlewareAnalysis.Tests", "test\Microsoft.AspNetCore.MiddlewareAnalysis.Tests\Microsoft.AspNetCore.MiddlewareAnalysis.Tests.csproj", "{B0166AED-738F-42EE-AF4D-C487C8B21521}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClassLibraryWithPortablePdbs", "test\ClassLibraryWithPortablePdbs\ClassLibraryWithPortablePdbs.csproj", "{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Diagnostics.EFCore.FunctionalTests", "test\Diagnostics.EFCore.FunctionalTests\Diagnostics.EFCore.FunctionalTests.csproj", "{043C5272-D7F7-4DB1-830F-5DC93CC0878E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Diagnostics.FunctionalTests", "test\Diagnostics.FunctionalTests\Diagnostics.FunctionalTests.csproj", "{C142A666-D932-4E0D-8D18-5B08944C1077}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "src\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.csproj", "{0D103C24-B9E8-468A-B113-509FCFEF7B45}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks", "src\Microsoft.Extensions.Diagnostics.HealthChecks\Microsoft.Extensions.Diagnostics.HealthChecks.csproj", "{F285F000-9342-4A01-9706-BAB2B97B4F97}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Diagnostics.HealthChecks", "src\Microsoft.AspNetCore.Diagnostics.HealthChecks\Microsoft.AspNetCore.Diagnostics.HealthChecks.csproj", "{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecksSample", "samples\HealthChecksSample\HealthChecksSample.csproj", "{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Diagnostics.HealthChecks.Tests", "test\Microsoft.AspNetCore.Diagnostics.HealthChecks.Tests\Microsoft.AspNetCore.Diagnostics.HealthChecks.Tests.csproj", "{E718CE19-23CC-427F-B06E-B866E9A35924}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks.Tests", "test\Microsoft.Extensions.Diagnostics.HealthChecks.Tests\Microsoft.Extensions.Diagnostics.HealthChecks.Tests.csproj", "{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore", "src\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.csproj", "{61F8B71C-4BDA-431C-9485-743D619ACF9A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.Tests", "test\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.Tests\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.Tests.csproj", "{4416D921-0E43-496D-9156-D7EAA9CB8DD3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Debug|x86.ActiveCfg = Debug|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Release|Any CPU.Build.0 = Release|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416}.Release|x86.ActiveCfg = Release|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Debug|x86.ActiveCfg = Debug|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Release|Any CPU.Build.0 = Release|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE}.Release|x86.ActiveCfg = Release|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Debug|Any CPU.Build.0 = Debug|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Debug|x86.ActiveCfg = Debug|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Release|Any CPU.ActiveCfg = Release|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Release|Any CPU.Build.0 = Release|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{589AC17F-9455-4764-8F82-FCD2AE58DA14}.Release|x86.ActiveCfg = Release|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Debug|Any CPU.Build.0 = Debug|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Debug|x86.ActiveCfg = Debug|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Release|Any CPU.ActiveCfg = Release|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Release|Any CPU.Build.0 = Release|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{994351B4-7B2A-4139-8B72-72C5BB5CC618}.Release|x86.ActiveCfg = Release|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Debug|Any CPU.Build.0 = Debug|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Debug|x86.ActiveCfg = Debug|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|Any CPU.ActiveCfg = Release|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|Any CPU.Build.0 = Release|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|x86.ActiveCfg = Release|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|x86.ActiveCfg = Debug|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|x86.Build.0 = Debug|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|Any CPU.Build.0 = Release|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|x86.ActiveCfg = Release|Any CPU
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|x86.Build.0 = Release|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Debug|x86.ActiveCfg = Debug|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Debug|x86.Build.0 = Debug|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Release|Any CPU.Build.0 = Release|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Release|x86.ActiveCfg = Release|Any CPU
{5486117B-A742-49E0-94FC-12B76F061803}.Release|x86.Build.0 = Release|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Debug|Any CPU.Build.0 = Debug|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Debug|x86.ActiveCfg = Debug|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Debug|x86.Build.0 = Debug|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Release|Any CPU.ActiveCfg = Release|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Release|Any CPU.Build.0 = Release|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Release|x86.ActiveCfg = Release|Any CPU
{624B0019-956A-4157-B008-270C5B229553}.Release|x86.Build.0 = Release|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Debug|x86.ActiveCfg = Debug|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Debug|x86.Build.0 = Debug|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Release|Any CPU.Build.0 = Release|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Release|x86.ActiveCfg = Release|Any CPU
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F}.Release|x86.Build.0 = Release|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Debug|x86.ActiveCfg = Debug|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Debug|x86.Build.0 = Debug|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Release|Any CPU.Build.0 = Release|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Release|x86.ActiveCfg = Release|Any CPU
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3}.Release|x86.Build.0 = Release|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Debug|x86.ActiveCfg = Debug|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Debug|x86.Build.0 = Debug|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Release|Any CPU.Build.0 = Release|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Release|x86.ActiveCfg = Release|Any CPU
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129}.Release|x86.Build.0 = Release|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Debug|x86.ActiveCfg = Debug|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Debug|x86.Build.0 = Debug|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Release|Any CPU.Build.0 = Release|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Release|x86.ActiveCfg = Release|Any CPU
{FF7F11A1-14E7-4948-A853-2487D99DE0C6}.Release|x86.Build.0 = Release|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Debug|x86.ActiveCfg = Debug|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Debug|x86.Build.0 = Debug|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Release|Any CPU.Build.0 = Release|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Release|x86.ActiveCfg = Release|Any CPU
{C2DEDD37-D1EB-4819-9A9C-475E37A52358}.Release|x86.Build.0 = Release|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Debug|x86.ActiveCfg = Debug|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Debug|x86.Build.0 = Debug|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Release|Any CPU.Build.0 = Release|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Release|x86.ActiveCfg = Release|Any CPU
{95981429-F212-44E1-83AA-32DA9E2A517C}.Release|x86.Build.0 = Release|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Debug|x86.ActiveCfg = Debug|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Debug|x86.Build.0 = Debug|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Release|Any CPU.Build.0 = Release|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Release|x86.ActiveCfg = Release|Any CPU
{B0166AED-738F-42EE-AF4D-C487C8B21521}.Release|x86.Build.0 = Release|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|x86.ActiveCfg = Debug|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|x86.Build.0 = Debug|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|Any CPU.Build.0 = Release|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|x86.ActiveCfg = Release|Any CPU
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|x86.Build.0 = Release|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Debug|x86.ActiveCfg = Debug|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Debug|x86.Build.0 = Debug|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Release|Any CPU.Build.0 = Release|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Release|x86.ActiveCfg = Release|Any CPU
{043C5272-D7F7-4DB1-830F-5DC93CC0878E}.Release|x86.Build.0 = Release|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Debug|x86.ActiveCfg = Debug|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Debug|x86.Build.0 = Debug|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Release|Any CPU.Build.0 = Release|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Release|x86.ActiveCfg = Release|Any CPU
{C142A666-D932-4E0D-8D18-5B08944C1077}.Release|x86.Build.0 = Release|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Debug|x86.ActiveCfg = Debug|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Debug|x86.Build.0 = Debug|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Release|Any CPU.Build.0 = Release|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Release|x86.ActiveCfg = Release|Any CPU
{0D103C24-B9E8-468A-B113-509FCFEF7B45}.Release|x86.Build.0 = Release|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Debug|x86.ActiveCfg = Debug|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Debug|x86.Build.0 = Debug|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Release|Any CPU.Build.0 = Release|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Release|x86.ActiveCfg = Release|Any CPU
{F285F000-9342-4A01-9706-BAB2B97B4F97}.Release|x86.Build.0 = Release|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Debug|x86.ActiveCfg = Debug|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Debug|x86.Build.0 = Debug|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Release|Any CPU.Build.0 = Release|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Release|x86.ActiveCfg = Release|Any CPU
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C}.Release|x86.Build.0 = Release|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Debug|x86.ActiveCfg = Debug|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Debug|x86.Build.0 = Debug|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Release|Any CPU.Build.0 = Release|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Release|x86.ActiveCfg = Release|Any CPU
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7}.Release|x86.Build.0 = Release|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Debug|x86.ActiveCfg = Debug|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Debug|x86.Build.0 = Debug|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Release|Any CPU.Build.0 = Release|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Release|x86.ActiveCfg = Release|Any CPU
{E718CE19-23CC-427F-B06E-B866E9A35924}.Release|x86.Build.0 = Release|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Debug|x86.ActiveCfg = Debug|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Debug|x86.Build.0 = Debug|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Release|Any CPU.Build.0 = Release|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Release|x86.ActiveCfg = Release|Any CPU
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1}.Release|x86.Build.0 = Release|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Debug|x86.ActiveCfg = Debug|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Debug|x86.Build.0 = Debug|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Release|Any CPU.Build.0 = Release|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Release|x86.ActiveCfg = Release|Any CPU
{61F8B71C-4BDA-431C-9485-743D619ACF9A}.Release|x86.Build.0 = Release|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Debug|x86.ActiveCfg = Debug|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Debug|x86.Build.0 = Debug|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Release|Any CPU.Build.0 = Release|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Release|x86.ActiveCfg = Release|Any CPU
{4416D921-0E43-496D-9156-D7EAA9CB8DD3}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C5F59CBA-DF2D-4983-8CBB-11B6AF21B416} = {ACAA0157-A8C4-4152-93DE-90CCDF304087}
{68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{589AC17F-9455-4764-8F82-FCD2AE58DA14} = {ACAA0157-A8C4-4152-93DE-90CCDF304087}
{994351B4-7B2A-4139-8B72-72C5BB5CC618} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
{427CDB36-78B0-4583-9EBC-7F283DE60355} = {ACAA0157-A8C4-4152-93DE-90CCDF304087}
{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{5486117B-A742-49E0-94FC-12B76F061803} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
{624B0019-956A-4157-B008-270C5B229553} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{CC1F5841-FE10-4DDB-8477-C4DE92BA759F} = {ACAA0157-A8C4-4152-93DE-90CCDF304087}
{83FFB65A-97B1-45AA-BCB8-3F43966BC8A3} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{FFD28DCF-C24F-4C59-9B6B-F3B74CE13129} = {ACAA0157-A8C4-4152-93DE-90CCDF304087}
{FF7F11A1-14E7-4948-A853-2487D99DE0C6} = {ACAA0157-A8C4-4152-93DE-90CCDF304087}
{C2DEDD37-D1EB-4819-9A9C-475E37A52358} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{95981429-F212-44E1-83AA-32DA9E2A517C} = {ACAA0157-A8C4-4152-93DE-90CCDF304087}
{B0166AED-738F-42EE-AF4D-C487C8B21521} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
{043C5272-D7F7-4DB1-830F-5DC93CC0878E} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
{C142A666-D932-4E0D-8D18-5B08944C1077} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
{0D103C24-B9E8-468A-B113-509FCFEF7B45} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{F285F000-9342-4A01-9706-BAB2B97B4F97} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{1B2B1EF4-9066-4F38-ADCF-D05C6423E21C} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{3B4E60F6-E42D-496E-B96F-71A11DABAEE7} = {ACAA0157-A8C4-4152-93DE-90CCDF304087}
{E718CE19-23CC-427F-B06E-B866E9A35924} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
{3783E8E4-2E96-4987-A83A-0CCCAF4891C1} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
{61F8B71C-4BDA-431C-9485-743D619ACF9A} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D}
{4416D921-0E43-496D-9156-D7EAA9CB8DD3} = {2AF90579-B118-4583-AE88-672EFACB5BC4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D915AA7B-4ADE-4BAC-AF65-1E800D3F3580}
EndGlobalSection
EndGlobal

View File

@ -1,20 +0,0 @@
<Project>
<Import
Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))\AspNetCoreSettings.props"
Condition=" '$(CI)' != 'true' AND '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))' != '' " />
<Import Project="version.props" />
<Import Project="build\dependencies.props" />
<Import Project="build\sources.props" />
<PropertyGroup>
<Product>Microsoft ASP.NET Core</Product>
<RepositoryUrl>https://github.com/aspnet/Diagnostics</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\Key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
</Project>

View File

@ -1,6 +0,0 @@
<Project>
<PropertyGroup>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.0' ">$(MicrosoftNETCoreAppPackageVersion)</RuntimeFrameworkVersion>
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
</PropertyGroup>
</Project>

View File

@ -1,201 +0,0 @@
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 (c) .NET Foundation and 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.

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<!-- Restore sources should be defined in build/sources.props. -->
</packageSources>
</configuration>

View File

@ -1,7 +0,0 @@
{
"Default": {
"rules": [
"DefaultCompositeRule"
]
}
}

View File

@ -1,11 +0,0 @@
ASP.NET Core Diagnostics
================
AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/5224cefq6y78aq21/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/Diagnostics/branch/dev)
Travis: [![Travis](https://travis-ci.org/aspnet/Diagnostics.svg?branch=dev)](https://travis-ci.org/aspnet/Diagnostics)
Diagnostics middleware for reporting info and handling exceptions and errors in ASP.NET Core, and diagnosing Entity Framework Core migrations errors.
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.

View File

@ -1,2 +0,0 @@
@ECHO OFF
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE"

View File

@ -1,8 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs)
chmod +x "$DIR/run.sh"; sync
"$DIR/run.sh" default-build "$@"

Binary file not shown.

View File

@ -1,51 +0,0 @@
<Project>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<PropertyGroup Label="Package Versions">
<InternalAspNetCoreSdkPackageVersion>3.0.0-build-20181116.1</InternalAspNetCoreSdkPackageVersion>
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreStaticFilesPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreStaticFilesPackageVersion>
<MicrosoftAspNetCoreTestHostPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreTestHostPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview-181113-11</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-preview-181109-02</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-preview-181109-02</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-preview-181109-02</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsHostingAbstractionsPackageVersion>3.0.0-alpha1-10742</MicrosoftExtensionsHostingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsRazorViewsSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsRazorViewsSourcesPackageVersion>
<MicrosoftExtensionsStackTraceSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsStackTraceSourcesPackageVersion>
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
<MicrosoftNETCoreAppPackageVersion>3.0.0-preview1-26907-05</MicrosoftNETCoreAppPackageVersion>
<MicrosoftNetHttpHeadersPackageVersion>3.0.0-alpha1-10742</MicrosoftNetHttpHeadersPackageVersion>
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
<MoqPackageVersion>4.10.0</MoqPackageVersion>
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
<SystemDataSqlClientPackageVersion>4.6.0-preview1-26907-04</SystemDataSqlClientPackageVersion>
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.6.0-preview1-26907-04</SystemDiagnosticsDiagnosticSourcePackageVersion>
<SystemReflectionMetadataPackageVersion>1.7.0-preview1-26907-04</SystemReflectionMetadataPackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
</PropertyGroup>
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
<PropertyGroup Label="Package Versions: Pinned" />
</Project>

View File

@ -1,13 +0,0 @@
<Project>
<Import Project="dependencies.props" />
<PropertyGroup>
<!-- These properties are use by the automation that updates dependencies.props -->
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
</PropertyGroup>
<ItemGroup>
<DotNetCoreRuntime Include="$(MicrosoftNETCoreAppPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,17 +0,0 @@
<Project>
<Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
<PropertyGroup Label="RestoreSources">
<RestoreSources>$(DotNetRestoreSources)</RestoreSources>
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' ">
$(RestoreSources);
https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
</RestoreSources>
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true'">
$(RestoreSources);
https://api.nuget.org/v3/index.json;
</RestoreSources>
</PropertyGroup>
</Project>

View File

@ -1,2 +0,0 @@
version:3.0.0-build-20181116.1
commithash:9be7d79a8f7e0668f66e584aca1e962f45975511

View File

@ -1,4 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json",
"channel": "master"
}

View File

@ -1,2 +0,0 @@
@ECHO OFF
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE"

209
run.ps1
View File

@ -1,209 +0,0 @@
#!/usr/bin/env powershell
#requires -version 4
<#
.SYNOPSIS
Executes KoreBuild commands.
.DESCRIPTION
Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`.
.PARAMETER Command
The KoreBuild command to run.
.PARAMETER Path
The folder to build. Defaults to the folder containing this script.
.PARAMETER Channel
The channel of KoreBuild to download. Overrides the value from the config file.
.PARAMETER DotNetHome
The directory where .NET Core tools will be stored.
.PARAMETER ToolsSource
The base url where build tools can be downloaded. Overrides the value from the config file.
.PARAMETER Update
Updates KoreBuild to the latest version even if a lock file is present.
.PARAMETER Reinstall
Re-installs KoreBuild
.PARAMETER ConfigFile
The path to the configuration file that stores values. Defaults to korebuild.json.
.PARAMETER ToolsSourceSuffix
The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores.
.PARAMETER CI
Sets up CI specific settings and variables.
.PARAMETER Arguments
Arguments to be passed to the command
.NOTES
This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.
When the lockfile is not present, KoreBuild will create one using latest available version from $Channel.
The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set
in the file are overridden by command line parameters.
.EXAMPLE
Example config file:
```json
{
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json",
"channel": "master",
"toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools"
}
```
#>
[CmdletBinding(PositionalBinding = $false)]
param(
[Parameter(Mandatory = $true, Position = 0)]
[string]$Command,
[string]$Path = $PSScriptRoot,
[Alias('c')]
[string]$Channel,
[Alias('d')]
[string]$DotNetHome,
[Alias('s')]
[string]$ToolsSource,
[Alias('u')]
[switch]$Update,
[switch]$Reinstall,
[string]$ToolsSourceSuffix,
[string]$ConfigFile = $null,
[switch]$CI,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$Arguments
)
Set-StrictMode -Version 2
$ErrorActionPreference = 'Stop'
#
# Functions
#
function Get-KoreBuild {
$lockFile = Join-Path $Path 'korebuild-lock.txt'
if (!(Test-Path $lockFile) -or $Update) {
Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix
}
$version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1
if (!$version) {
Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'"
}
$version = $version.TrimStart('version:').Trim()
$korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)
if ($Reinstall -and (Test-Path $korebuildPath)) {
Remove-Item -Force -Recurse $korebuildPath
}
if (!(Test-Path $korebuildPath)) {
Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version"
New-Item -ItemType Directory -Path $korebuildPath | Out-Null
$remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip"
try {
$tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix
if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) {
# Use built-in commands where possible as they are cross-plat compatible
Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
}
else {
# Fallback to old approach for old installations of PowerShell
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)
}
}
catch {
Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
throw
}
finally {
Remove-Item $tmpfile -ErrorAction Ignore
}
}
return $korebuildPath
}
function Join-Paths([string]$path, [string[]]$childPaths) {
$childPaths | ForEach-Object { $path = Join-Path $path $_ }
return $path
}
function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) {
if ($RemotePath -notlike 'http*') {
Copy-Item $RemotePath $LocalPath
return
}
$retries = 10
while ($retries -gt 0) {
$retries -= 1
try {
Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath
return
}
catch {
Write-Verbose "Request failed. $retries retries remaining"
}
}
Write-Error "Download failed: '$RemotePath'."
}
#
# Main
#
# Load configuration or set defaults
$Path = Resolve-Path $Path
if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' }
if (Test-Path $ConfigFile) {
try {
$config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json
if ($config) {
if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }
if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}
}
}
catch {
Write-Host -ForegroundColor Red $Error[0]
Write-Error "$ConfigFile contains invalid JSON."
exit 1
}
}
if (!$DotNetHome) {
$DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `
elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `
elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`
else { Join-Path $PSScriptRoot '.dotnet'}
}
if (!$Channel) { $Channel = 'master' }
if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
# Execute
$korebuildPath = Get-KoreBuild
Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')
try {
Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI
Invoke-KoreBuildCommand $Command @Arguments
}
finally {
Remove-Module 'KoreBuild' -ErrorAction Ignore
}

256
run.sh
View File

@ -1,256 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
#
# variables
#
RESET="\033[0m"
RED="\033[0;31m"
YELLOW="\033[0;33m"
MAGENTA="\033[0;95m"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet"
verbose=false
update=false
reinstall=false
repo_path="$DIR"
channel=''
tools_source=''
tools_source_suffix=''
ci=false
#
# Functions
#
__usage() {
echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] <Arguments>...]"
echo ""
echo "Arguments:"
echo " command The command to be run."
echo " <Arguments>... Arguments passed to the command. Variable number of arguments allowed."
echo ""
echo "Options:"
echo " --verbose Show verbose output."
echo " -c|--channel <CHANNEL> The channel of KoreBuild to download. Overrides the value from the config file.."
echo " --config-file <FILE> The path to the configuration file that stores values. Defaults to korebuild.json."
echo " -d|--dotnet-home <DIR> The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet."
echo " --path <PATH> The directory to build. Defaults to the directory containing the script."
echo " -s|--tools-source|-ToolsSource <URL> The base url where build tools can be downloaded. Overrides the value from the config file."
echo " --tools-source-suffix|-ToolsSourceSuffix <SUFFIX> The suffix to append to tools-source. Useful for query strings."
echo " -u|--update Update to the latest KoreBuild even if the lock file is present."
echo " --reinstall Reinstall KoreBuild."
echo " --ci Apply CI specific settings and environment variables."
echo ""
echo "Description:"
echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be."
echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel."
if [[ "${1:-}" != '--no-exit' ]]; then
exit 2
fi
}
get_korebuild() {
local version
local lock_file="$repo_path/korebuild-lock.txt"
if [ ! -f "$lock_file" ] || [ "$update" = true ]; then
__get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix"
fi
version="$(grep 'version:*' -m 1 "$lock_file")"
if [[ "$version" == '' ]]; then
__error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'"
return 1
fi
version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version"
if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then
rm -rf "$korebuild_path"
fi
{
if [ ! -d "$korebuild_path" ]; then
mkdir -p "$korebuild_path"
local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip"
tmpfile="$(mktemp)"
echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}"
if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then
unzip -q -d "$korebuild_path" "$tmpfile"
fi
rm "$tmpfile" || true
fi
source "$korebuild_path/KoreBuild.sh"
} || {
if [ -d "$korebuild_path" ]; then
echo "Cleaning up after failed installation"
rm -rf "$korebuild_path" || true
fi
return 1
}
}
__error() {
echo -e "${RED}error: $*${RESET}" 1>&2
}
__warn() {
echo -e "${YELLOW}warning: $*${RESET}"
}
__machine_has() {
hash "$1" > /dev/null 2>&1
return $?
}
__get_remote_file() {
local remote_path=$1
local local_path=$2
local remote_path_suffix=$3
if [[ "$remote_path" != 'http'* ]]; then
cp "$remote_path" "$local_path"
return 0
fi
local failed=false
if __machine_has wget; then
wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true
else
failed=true
fi
if [ "$failed" = true ] && __machine_has curl; then
failed=false
curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true
fi
if [ "$failed" = true ]; then
__error "Download failed: $remote_path" 1>&2
return 1
fi
}
#
# main
#
command="${1:-}"
shift
while [[ $# -gt 0 ]]; do
case $1 in
-\?|-h|--help)
__usage --no-exit
exit 0
;;
-c|--channel|-Channel)
shift
channel="${1:-}"
[ -z "$channel" ] && __usage
;;
--config-file|-ConfigFile)
shift
config_file="${1:-}"
[ -z "$config_file" ] && __usage
if [ ! -f "$config_file" ]; then
__error "Invalid value for --config-file. $config_file does not exist."
exit 1
fi
;;
-d|--dotnet-home|-DotNetHome)
shift
DOTNET_HOME="${1:-}"
[ -z "$DOTNET_HOME" ] && __usage
;;
--path|-Path)
shift
repo_path="${1:-}"
[ -z "$repo_path" ] && __usage
;;
-s|--tools-source|-ToolsSource)
shift
tools_source="${1:-}"
[ -z "$tools_source" ] && __usage
;;
--tools-source-suffix|-ToolsSourceSuffix)
shift
tools_source_suffix="${1:-}"
[ -z "$tools_source_suffix" ] && __usage
;;
-u|--update|-Update)
update=true
;;
--reinstall|-[Rr]einstall)
reinstall=true
;;
--ci|-[Cc][Ii])
ci=true
;;
--verbose|-Verbose)
verbose=true
;;
--)
shift
break
;;
*)
break
;;
esac
shift
done
if ! __machine_has unzip; then
__error 'Missing required command: unzip'
exit 1
fi
if ! __machine_has curl && ! __machine_has wget; then
__error 'Missing required command. Either wget or curl is required.'
exit 1
fi
[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json"
if [ -f "$config_file" ]; then
if __machine_has jq ; then
if jq '.' "$config_file" >/dev/null ; then
config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")"
config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")"
else
__error "$config_file contains invalid JSON."
exit 1
fi
elif __machine_has python ; then
if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then
config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
else
__error "$config_file contains invalid JSON."
exit 1
fi
elif __machine_has python3 ; then
if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then
config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
else
__error "$config_file contains invalid JSON."
exit 1
fi
else
__error 'Missing required command: jq or python. Could not parse the JSON file.'
exit 1
fi
[ ! -z "${config_channel:-}" ] && channel="$config_channel"
[ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source"
fi
[ -z "$channel" ] && channel='master'
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
get_korebuild
set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci"
invoke_korebuild_command "$command" "$@"

View File

@ -1,18 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics\Microsoft.AspNetCore.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics\Microsoft.AspNetCore.Diagnostics.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics.Elm\Microsoft.AspNetCore.Diagnostics.Elm.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,34 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace ElmPageSample
{
public class HelloWorldMiddleware
{
private readonly ILogger _logger;
private readonly RequestDelegate _next;
public HelloWorldMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<HelloWorldMiddleware>();
}
public async Task Invoke(HttpContext httpContext)
{
using (_logger.BeginScope("Scope1"))
{
_logger.LogDebug("Getting message");
httpContext.Response.ContentType = "text/html; charset=utf-8";
await httpContext.Response.WriteAsync(
"<html><body><h2>Hello World!</h2><a href=\"/Elm\">Elm Logs</a></body></html>");
}
}
}
}

View File

@ -1,42 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace ElmPageSample
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddElm(elmOptions =>
{
elmOptions.Filter = (loggerName, loglevel) => loglevel == LogLevel.Debug;
});
}
public void Configure(IApplicationBuilder app)
{
app.UseElmPage();
app.UseElmCapture();
app.UseMiddleware<HelloWorldMiddleware>();
}
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}

View File

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics\Microsoft.AspNetCore.Diagnostics.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
You've reached the static error page.<br /><br />
<a href="/">Home</a><br />
</body>
</html>

View File

@ -1,24 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<!-- Used in our tests -->
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="$(MicrosoftExtensionsConfigurationCommandLinePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftExtensionsConfigurationJsonPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
<PackageReference Include="System.Data.SqlClient" Version="$(SystemDataSqlClientPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics.HealthChecks\Microsoft.AspNetCore.Diagnostics.HealthChecks.csproj" />
<ProjectReference Include="..\..\src\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.csproj" />
</ItemGroup>
</Project>

View File

@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics\Microsoft.AspNetCore.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.MiddlewareAnalysis\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="$(MicrosoftExtensionsDiagnosticAdapterPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics\Microsoft.AspNetCore.Diagnostics.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics\Microsoft.AspNetCore.Diagnostics.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,7 +0,0 @@
<Project>
<Import Project="..\Directory.Build.props" />
<ItemGroup>
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
public class ActivityContext
{
public Guid Id { get; set; }
public HttpInfo HttpInfo { get; set; }
public ScopeNode Root { get; set; }
public DateTimeOffset Time { get; set; }
public bool IsCollapsed { get; set; }
public bool RepresentsScope { get; set; }
}
}

View File

@ -1,71 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
/// <summary>
/// Enables the Elm logging service.
/// </summary>
public class ElmCaptureMiddleware
{
private readonly RequestDelegate _next;
private readonly ElmOptions _options;
private readonly ILogger _logger;
public ElmCaptureMiddleware(RequestDelegate next, ILoggerFactory factory, IOptions<ElmOptions> options)
{
_next = next;
_options = options.Value;
_logger = factory.CreateLogger<ElmCaptureMiddleware>();
}
public async Task Invoke(HttpContext context)
{
using (RequestIdentifier.Ensure(context))
{
var requestId = context.Features.Get<IHttpRequestIdentifierFeature>().TraceIdentifier;
using (_logger.BeginScope("Request: {RequestId}", requestId))
{
try
{
ElmScope.Current.Context.HttpInfo = GetHttpInfo(context);
await _next(context);
}
finally
{
ElmScope.Current.Context.HttpInfo.StatusCode = context.Response.StatusCode;
}
}
}
}
/// <summary>
/// Takes the info from the given HttpContext and copies it to an HttpInfo object
/// </summary>
/// <returns>The HttpInfo for the current elm context</returns>
private static HttpInfo GetHttpInfo(HttpContext context)
{
return new HttpInfo()
{
RequestID = context.Features.Get<IHttpRequestIdentifierFeature>().TraceIdentifier,
Host = context.Request.Host,
ContentType = context.Request.ContentType,
Path = context.Request.Path,
Scheme = context.Request.Scheme,
StatusCode = context.Response.StatusCode,
User = context.User,
Method = context.Request.Method,
Protocol = context.Request.Protocol,
Headers = context.Request.Headers,
Query = context.Request.QueryString,
Cookies = context.Request.Cookies
};
}
}
}

View File

@ -1,47 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Diagnostics.Elm;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Builder
{
public static class ElmExtensions
{
/// <summary>
/// Enables the Elm logging service, which can be accessed via the <see cref="ElmPageMiddleware"/>.
/// </summary>
public static IApplicationBuilder UseElmCapture(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
// add the elm provider to the factory here so the logger can start capturing logs immediately
var factory = app.ApplicationServices.GetRequiredService<ILoggerFactory>() as LoggerFactory;
if (factory != null)
{
var provider = app.ApplicationServices.GetRequiredService<ElmLoggerProvider>();
factory.AddProvider(provider);
}
return app.UseMiddleware<ElmCaptureMiddleware>();
}
/// <summary>
/// Enables viewing logs captured by the <see cref="ElmCaptureMiddleware"/>.
/// </summary>
public static IApplicationBuilder UseElmPage(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<ElmPageMiddleware>();
}
}
}

View File

@ -1,82 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
public class ElmLogger : ILogger
{
private readonly string _name;
private readonly ElmOptions _options;
private readonly ElmStore _store;
public ElmLogger(string name, ElmOptions options, ElmStore store)
{
_name = name;
_options = options;
_store = store;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
Func<TState, Exception, string> formatter)
{
if (!IsEnabled(logLevel) || (state == null && exception == null))
{
return;
}
LogInfo info = new LogInfo()
{
ActivityContext = GetCurrentActivityContext(),
Name = _name,
EventID = eventId.Id,
Severity = logLevel,
Exception = exception,
State = state,
Message = formatter == null ? state.ToString() : formatter(state, exception),
Time = DateTimeOffset.UtcNow
};
if (ElmScope.Current != null)
{
ElmScope.Current.Node.Messages.Add(info);
}
// The log does not belong to any scope - create a new context for it
else
{
var context = GetNewActivityContext();
context.RepresentsScope = false; // mark as a non-scope log
context.Root = new ScopeNode();
context.Root.Messages.Add(info);
_store.AddActivity(context);
}
}
public bool IsEnabled(LogLevel logLevel)
{
return _options.Filter(_name, logLevel);
}
public IDisposable BeginScope<TState>(TState state)
{
var scope = new ElmScope(_name, state);
scope.Context = ElmScope.Current?.Context ?? GetNewActivityContext();
return ElmScope.Push(scope, _store);
}
private ActivityContext GetNewActivityContext()
{
return new ActivityContext()
{
Id = Guid.NewGuid(),
Time = DateTimeOffset.UtcNow,
RepresentsScope = true
};
}
private ActivityContext GetCurrentActivityContext()
{
return ElmScope.Current?.Context ?? GetNewActivityContext();
}
}
}

View File

@ -1,40 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
public class ElmLoggerProvider : ILoggerProvider
{
private readonly ElmStore _store;
private readonly ElmOptions _options;
public ElmLoggerProvider(ElmStore store, IOptions<ElmOptions> options)
{
if (store == null)
{
throw new ArgumentNullException(nameof(store));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
_store = store;
_options = options.Value;
}
public ILogger CreateLogger(string name)
{
return new ElmLogger(name, _options, _store);
}
public void Dispose()
{
}
}
}

View File

@ -1,26 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
/// <summary>
/// Options for ElmMiddleware
/// </summary>
public class ElmOptions
{
/// <summary>
/// Specifies the path to view the logs.
/// </summary>
public PathString Path { get; set; } = new PathString("/Elm");
/// <summary>
/// Determines whether log statements should be logged based on the name of the logger
/// and the <see cref="M:LogLevel"/> of the message.
/// </summary>
public Func<string, LogLevel, bool> Filter { get; set; } = (name, level) => true;
}
}

View File

@ -1,127 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Linq;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
/// <summary>
/// Enables viewing logs captured by the <see cref="ElmCaptureMiddleware"/>.
/// </summary>
public class ElmPageMiddleware
{
private readonly RequestDelegate _next;
private readonly ElmOptions _options;
private readonly ElmStore _store;
public ElmPageMiddleware(RequestDelegate next, IOptions<ElmOptions> options, ElmStore store)
{
_next = next;
_options = options.Value;
_store = store;
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Path.StartsWithSegments(_options.Path))
{
await _next(context);
return;
}
var t = await ParseParams(context);
var options = t.Item1;
var redirect = t.Item2;
if (redirect)
{
return;
}
if (context.Request.Path == _options.Path)
{
RenderMainLogPage(options, context);
}
else
{
RenderDetailsPage(options, context);
}
}
private async void RenderMainLogPage(ViewOptions options, HttpContext context)
{
var model = new LogPageModel()
{
Activities = _store.GetActivities(),
Options = options,
Path = _options.Path
};
var logPage = new LogPage(model);
await logPage.ExecuteAsync(context);
}
private async void RenderDetailsPage(ViewOptions options, HttpContext context)
{
var parts = context.Request.Path.Value.Split('/');
var id = Guid.Empty;
if (!Guid.TryParse(parts[parts.Length - 1], out id))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Invalid Id");
return;
}
var model = new DetailsPageModel()
{
Activity = _store.GetActivities().Where(a => a.Id == id).FirstOrDefault(),
Options = options
};
var detailsPage = new DetailsPage(model);
await detailsPage.ExecuteAsync(context);
}
private async Task<Tuple<ViewOptions, bool>> ParseParams(HttpContext context)
{
var options = new ViewOptions()
{
MinLevel = LogLevel.Debug,
NamePrefix = string.Empty
};
var isRedirect = false;
IFormCollection form = null;
if (context.Request.HasFormContentType)
{
form = await context.Request.ReadFormAsync();
}
if (form != null && form.ContainsKey("clear"))
{
_store.Clear();
context.Response.Redirect(context.Request.PathBase.Add(_options.Path).ToString());
isRedirect = true;
}
else
{
if (context.Request.Query.ContainsKey("level"))
{
var minLevel = options.MinLevel;
if (Enum.TryParse<LogLevel>(context.Request.Query["level"], out minLevel))
{
options.MinLevel = minLevel;
}
}
if (context.Request.Query.ContainsKey("name"))
{
var namePrefix = context.Request.Query["name"];
options.NamePrefix = namePrefix;
}
}
return Tuple.Create(options, isRedirect);
}
}
}

View File

@ -1,96 +0,0 @@
using System;
using System.Threading;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
public class ElmScope
{
private readonly string _name;
private readonly object _state;
public ElmScope(string name, object state)
{
_name = name;
_state = state;
}
public ActivityContext Context { get; set; }
public ElmScope Parent { get; set; }
public ScopeNode Node { get; set; }
private static AsyncLocal<ElmScope> _value = new AsyncLocal<ElmScope>();
public static ElmScope Current
{
set
{
_value.Value = value;
}
get
{
return _value.Value;
}
}
public static IDisposable Push(ElmScope scope, ElmStore store)
{
if (scope == null)
{
throw new ArgumentNullException(nameof(scope));
}
if (store == null)
{
throw new ArgumentNullException(nameof(store));
}
var temp = Current;
Current = scope;
Current.Parent = temp;
Current.Node = new ScopeNode()
{
StartTime = DateTimeOffset.UtcNow,
State = Current._state,
Name = Current._name
};
if (Current.Parent != null)
{
Current.Node.Parent = Current.Parent.Node;
Current.Parent.Node.Children.Add(Current.Node);
}
else
{
Current.Context.Root = Current.Node;
store.AddActivity(Current.Context);
}
return new DisposableAction(() =>
{
Current.Node.EndTime = DateTimeOffset.UtcNow;
Current = Current.Parent;
});
}
private class DisposableAction : IDisposable
{
private Action _action;
public DisposableAction(Action action)
{
_action = action;
}
public void Dispose()
{
if (_action != null)
{
_action.Invoke();
_action = null;
}
}
}
}
}

View File

@ -1,58 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Diagnostics.Elm;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for setting up Elm services in an <see cref="IServiceCollection" />.
/// </summary>
public static class ElmServiceCollectionExtensions
{
/// <summary>
/// Adds error logging middleware services to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection AddElm(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddOptions();
services.TryAddSingleton<ElmStore>();
services.TryAddSingleton<ElmLoggerProvider>();
return services;
}
/// <summary>
/// Adds error logging middleware services to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <param name="setupAction">An <see cref="Action{ElmOptions}"/> to configure the provided <see cref="ElmOptions"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection AddElm(this IServiceCollection services, Action<ElmOptions> setupAction)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
if (setupAction == null)
{
throw new ArgumentNullException(nameof(setupAction));
}
services.AddElm();
services.Configure(setupAction);
return services;
}
}
}

View File

@ -1,119 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
public class ElmStore
{
private const int Capacity = 200;
private LinkedList<ActivityContext> Activities { get; set; } = new LinkedList<ActivityContext>();
/// <summary>
/// Returns an IEnumerable of the contexts of the logs.
/// </summary>
/// <returns>An IEnumerable of <see cref="ActivityContext"/> objects where each context stores
/// information about a top level scope.</returns>
public IEnumerable<ActivityContext> GetActivities()
{
for (var context = Activities.First; context != null; context = context.Next)
{
if (!context.Value.IsCollapsed && CollapseActivityContext(context.Value))
{
Activities.Remove(context);
}
}
return Activities;
}
/// <summary>
/// Adds a new <see cref="ActivityContext"/> to the store.
/// </summary>
/// <param name="activity">The <see cref="ActivityContext"/> to be added to the store.</param>
public void AddActivity(ActivityContext activity)
{
if (activity == null)
{
throw new ArgumentNullException(nameof(activity));
}
lock (Activities)
{
Activities.AddLast(activity);
while (Count() > Capacity)
{
Activities.RemoveFirst();
}
}
}
/// <summary>
/// Removes all activity contexts that have been stored.
/// </summary>
public void Clear()
{
Activities.Clear();
}
/// <summary>
/// Returns the total number of logs in all activities in the store
/// </summary>
/// <returns>The total log count</returns>
public int Count()
{
return Activities.Sum(a => Count(a.Root));
}
private int Count(ScopeNode node)
{
if (node == null)
{
return 0;
}
var sum = node.Messages.Count;
foreach (var child in node.Children)
{
sum += Count(child);
}
return sum;
}
/// <summary>
/// Removes any nodes on the context's scope tree that doesn't have any logs
/// This may occur as a result of the filters turned on
/// </summary>
/// <param name="context">The context who's node should be condensed</param>
/// <returns>true if the node has been condensed to null, false otherwise</returns>
private bool CollapseActivityContext(ActivityContext context)
{
context.Root = CollapseHelper(context.Root);
context.IsCollapsed = true;
return context.Root == null;
}
private ScopeNode CollapseHelper(ScopeNode node)
{
if (node == null)
{
return node;
}
for (int i = 0; i < node.Children.Count; i++)
{
node.Children[i] = CollapseHelper(node.Children[i]);
}
node.Children.RemoveAll(c => c == null);
if (node.Children.Count == 0 && node.Messages.Count == 0)
{
return null;
}
else
{
return node;
}
}
}
}

View File

@ -1,36 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
public class HttpInfo
{
public string RequestID { get; set; }
public HostString Host { get; set; }
public PathString Path { get; set; }
public string ContentType { get; set; }
public string Scheme { get; set; }
public int StatusCode { get; set; }
public ClaimsPrincipal User { get; set; }
public string Method { get; set; }
public string Protocol { get; set; }
public IHeaderDictionary Headers { get; set; }
public QueryString Query { get; set; }
public IRequestCookieCollection Cookies { get; set; }
}
}

View File

@ -1,12 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
internal class HttpRequestIdentifierFeature : IHttpRequestIdentifierFeature
{
public string TraceIdentifier { get; set; }
}
}

View File

@ -1,27 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
public class LogInfo
{
public ActivityContext ActivityContext { get; set; }
public string Name { get; set; }
public object State { get; set; }
public Exception Exception { get; set; }
public string Message { get; set; }
public LogLevel Severity { get; set; }
public int EventID { get; set; }
public DateTimeOffset Time { get; set; }
}
}

View File

@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core Error Logging Middleware (ELM) to capture and display request logs.</Description>
<VersionPrefix Condition="'$(ExperimentalVersionPrefix)' != ''">$(ExperimentalVersionPrefix)</VersionPrefix>
<VersionSuffix Condition="'$(ExperimentalVersionSuffix)' != ''">$(ExperimentalVersionSuffix)</VersionSuffix>
<VerifyVersion Condition="'$(ExperimentalVersionPrefix)' != ''">false</VerifyVersion>
<PackageVersion Condition="'$(ExperimentalPackageVersion)' != ''">$(ExperimentalPackageVersion)</PackageVersion>
<TargetFramework>netcoreapp3.0</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;diagnostics</PackageTags>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\shared\**\*.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="$(MicrosoftAspNetCoreHttpAbstractionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsOptionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.RazorViews.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsRazorViewsSourcesPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,57 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
internal class RequestIdentifier : IDisposable
{
private readonly bool _addedFeature;
private readonly bool _updatedIdentifier;
private readonly string _originalIdentifierValue;
private readonly HttpContext _context;
private readonly IHttpRequestIdentifierFeature _feature;
private RequestIdentifier(HttpContext context)
{
_context = context;
_feature = context.Features.Get<IHttpRequestIdentifierFeature>();
if (_feature == null)
{
_feature = new HttpRequestIdentifierFeature()
{
TraceIdentifier = Guid.NewGuid().ToString()
};
context.Features.Set(_feature);
_addedFeature = true;
}
else if (string.IsNullOrEmpty(_feature.TraceIdentifier))
{
_originalIdentifierValue = _feature.TraceIdentifier;
_feature.TraceIdentifier = Guid.NewGuid().ToString();
_updatedIdentifier = true;
}
}
public static IDisposable Ensure(HttpContext context)
{
return new RequestIdentifier(context);
}
public void Dispose()
{
if (_addedFeature)
{
_context.Features.Set<IHttpRequestIdentifierFeature>(null);
}
else if (_updatedIdentifier)
{
_feature.TraceIdentifier = _originalIdentifierValue;
}
}
}
}

View File

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
public class ScopeNode
{
public ScopeNode Parent { get; set; }
public List<ScopeNode> Children { get; private set; } = new List<ScopeNode>();
public List<LogInfo> Messages { get; private set; } = new List<LogInfo>();
public DateTimeOffset StartTime { get; set; }
public DateTimeOffset EndTime { get; set; }
public object State { get; set; }
public string Name { get; set; }
}
}

View File

@ -1,23 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Diagnostics.Elm
{
/// <summary>
/// Options for viewing elm logs.
/// </summary>
public class ViewOptions
{
/// <summary>
/// The minimum <see cref="LogLevel"/> of logs shown on the elm page.
/// </summary>
public LogLevel MinLevel { get; set; }
/// <summary>
/// The prefix for the logger names of logs shown on the elm page.
/// </summary>
public string NamePrefix { get; set; }
}
}

View File

@ -1,541 +0,0 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews
{
#line hidden
#line 1 "DetailsPage.cshtml"
using System;
#line default
#line hidden
using System.Threading.Tasks;
#line 2 "DetailsPage.cshtml"
using System.Globalization;
#line default
#line hidden
#line 3 "DetailsPage.cshtml"
using System.Linq;
#line default
#line hidden
#line 4 "DetailsPage.cshtml"
using Microsoft.AspNetCore.Diagnostics.Elm;
#line default
#line hidden
#line 5 "DetailsPage.cshtml"
using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews;
#line default
#line hidden
#line 6 "DetailsPage.cshtml"
using Microsoft.Extensions.RazorViews;
#line default
#line hidden
#line 7 "DetailsPage.cshtml"
using Microsoft.Extensions.Logging;
#line default
#line hidden
internal class DetailsPage : Microsoft.Extensions.RazorViews.BaseView
{
#pragma warning disable 1998
public async override global::System.Threading.Tasks.Task ExecuteAsync()
{
WriteLiteral("\r\n");
#line 86 "DetailsPage.cshtml"
Response.ContentType = "text/html; charset=utf-8";
#line default
#line hidden
WriteLiteral(@"<!DOCTYPE html>
<html>
<head>
<meta charset=""utf-8"" />
<title>ASP.NET Core Logs</title>
<script src=""http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js""></script>
<style>
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif;
line-height: 1.4em;
}
h1 {
font-family: 'Segoe UI', Helvetica, sans-serif;
font-size: 2.5em;
}
td {
text-overflow: ellipsis;
overflow: hidden;
}
tr:nth-child(2n) {
background-color: #F6F6F6;
}
.critical {
background-color: red;
color: white;
}
.error {
color: red;
}
.information {
color: blue;
}
.debug {
color: black;
}
.warning {
color: orange;
} body {
font-size: 0.9em;
width: 90%;
margin: 0px auto;
}
h1 {
padding-bottom: 10px;
}
h2 {
font-weight: normal;
}
table {
border-spacing: 0px;
width: 100%;
border-collapse: collapse;
border: 1px solid black;
white-space: pre-wrap;
}
");
WriteLiteral(@"
th {
font-family: Arial;
}
td, th {
padding: 8px;
}
#headerTable, #cookieTable {
border: none;
height: 100%;
}
#headerTd {
white-space: normal;
}
#label {
width: 20%;
border-right: 1px solid black;
}
#logs{
margin-top: 10px;
margin-bottom: 20px;
}
#logs>tbody>tr>td {
border-right: 1px dashed lightgray;
}
#logs>thead>tr>th {
border: 1px solid black;
}
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
");
#line 194 "DetailsPage.cshtml"
var context = Model.Activity?.HttpInfo;
#line default
#line hidden
WriteLiteral(" ");
#line 197 "DetailsPage.cshtml"
if (context != null)
{
#line default
#line hidden
WriteLiteral(" <h2 id=\"requestHeader\">Request Details</h2>\r\n <table id=\"requestDetails\">\r\n <colgroup><col id=\"label\" /><col /></colgroup>\r\n\r\n <tr>\r\n <th>Path</th>\r\n <td>");
#line 205 "DetailsPage.cshtml"
Write(context.Path);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Host</th>\r\n <td>");
#line 209 "DetailsPage.cshtml"
Write(context.Host);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Content Type</th>\r\n <td>");
#line 213 "DetailsPage.cshtml"
Write(context.ContentType);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Method</th>\r\n <td>");
#line 217 "DetailsPage.cshtml"
Write(context.Method);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Protocol</th>\r\n <td>");
#line 221 "DetailsPage.cshtml"
Write(context.Protocol);
#line default
#line hidden
WriteLiteral(@"</td>
</tr>
<tr>
<th>Headers</th>
<td id=""headerTd"">
<table id=""headerTable"">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 234 "DetailsPage.cshtml"
foreach (var header in context.Headers)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 237 "DetailsPage.cshtml"
Write(header.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 238 "DetailsPage.cshtml"
Write(string.Join(";", header.Value));
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 240 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n </td>\r\n </tr>\r\n <tr>\r\n <th>Status Code</th>\r\n <td>");
#line 247 "DetailsPage.cshtml"
Write(context.StatusCode);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>User</th>\r\n <td>");
#line 251 "DetailsPage.cshtml"
Write(context.User.Identity.Name);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Claims</th>\r\n <td>\r\n");
#line 256 "DetailsPage.cshtml"
if (context.User.Claims.Any())
{
#line default
#line hidden
WriteLiteral(@" <table id=""claimsTable"">
<thead>
<tr>
<th>Issuer</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 266 "DetailsPage.cshtml"
foreach (var claim in context.User.Claims)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 269 "DetailsPage.cshtml"
Write(claim.Issuer);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 270 "DetailsPage.cshtml"
Write(claim.Value);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 272 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n");
#line 275 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </td>\r\n </tr>\r\n <tr>\r\n <th>Scheme</th>\r\n <td>");
#line 280 "DetailsPage.cshtml"
Write(context.Scheme);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Query</th>\r\n <td>");
#line 284 "DetailsPage.cshtml"
Write(context.Query.Value);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Cookies</th>\r\n <td>\r\n");
#line 289 "DetailsPage.cshtml"
if (context.Cookies.Any())
{
#line default
#line hidden
WriteLiteral(@" <table id=""cookieTable"">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 299 "DetailsPage.cshtml"
foreach (var cookie in context.Cookies)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 302 "DetailsPage.cshtml"
Write(cookie.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 303 "DetailsPage.cshtml"
Write(string.Join(";", cookie.Value));
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 305 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n");
#line 308 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </td>\r\n </tr>\r\n </table>\r\n");
#line 312 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" <h2>Logs</h2>\r\n <form method=\"get\">\r\n <select name=\"level\">\r\n");
#line 316 "DetailsPage.cshtml"
foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 8857, "\"", 8877, 1);
#line 321 "DetailsPage.cshtml"
WriteAttributeValue("", 8865, severityInt, 8865, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" selected=\"selected\">");
#line 321 "DetailsPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 322 "DetailsPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 9006, "\"", 9026, 1);
#line 325 "DetailsPage.cshtml"
WriteAttributeValue("", 9014, severityInt, 9014, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 325 "DetailsPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 326 "DetailsPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </select>\r\n <input type=\"text\" name=\"name\"");
BeginWriteAttribute("value", " value=\"", 9139, "\"", 9172, 1);
#line 329 "DetailsPage.cshtml"
WriteAttributeValue("", 9147, Model.Options.NamePrefix, 9147, 25, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" />
<input type=""submit"" value=""filter"" />
</form>
<table id=""logs"">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Severity</th>
<th>Name</th>
<th>State</th>
<th>Error</th>
</tr>
</thead>
");
#line 343 "DetailsPage.cshtml"
Write(Traverse(Model.Activity.Root));
#line default
#line hidden
WriteLiteral(@"
</table>
<script type=""text/javascript"">
$(document).ready(function () {
$(""#requestHeader"").click(function () {
$(""#requestDetails"").toggle();
});
});
</script>
</body>
</html>");
}
#pragma warning restore 1998
#line 10 "DetailsPage.cshtml"
public DetailsPage(DetailsPageModel model)
{
Model = model;
}
public DetailsPageModel Model { get; set; }
public HelperResult LogRow(LogInfo log)
{
return new HelperResult((writer) =>
{
if (log.Severity >= Model.Options.MinLevel &&
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
{
PushWriter(writer);
WriteLiteral(" <tr>\r\n <td>");
Write(string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteral("</td>\r\n <td>");
Write(string.Format("{0:H:mm:ss}", log.Time));
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteral($"</td>\r\n <td class=\"{severity}\">");
Write(log.Severity);
WriteLiteral($"</td>\r\n <td title=\"{log.Name}\">");
Write(log.Name);
WriteLiteral($"</td>\r\n <td title=\"{log.Message}\""+
"class=\"logState\" width=\"100px\">");
Write(log.Message);
WriteLiteral($"</td>\r\n <td title=\"{log.Exception}\">");
Write(log.Exception);
WriteLiteral("</td>\r\n </tr>\r\n");
PopWriter();
}
});
}
public HelperResult Traverse(ScopeNode node)
{
return new HelperResult((writer) =>
{
var messageIndex = 0;
var childIndex = 0;
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
{
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
{
LogRow(node.Messages[messageIndex]);
messageIndex++;
}
else
{
Traverse(node.Children[childIndex]);
childIndex++;
}
}
if (messageIndex < node.Messages.Count)
{
for (var i = messageIndex; i < node.Messages.Count; i++)
{
LogRow(node.Messages[i]);
}
}
else
{
for (var i = childIndex; i < node.Children.Count; i++)
{
Traverse(node.Children[i]);
}
}
});
}
#line default
#line hidden
}
}
#pragma warning restore 1591

View File

@ -1,260 +0,0 @@
@using System
@using System.Globalization
@using System.Linq
@using Microsoft.AspNetCore.Diagnostics.Elm
@using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews
@using Microsoft.Extensions.RazorViews
@using Microsoft.Extensions.Logging
@functions
{
public DetailsPage(DetailsPageModel model)
{
Model = model;
}
public DetailsPageModel Model { get; set; }
public HelperResult LogRow(LogInfo log)
{
return new HelperResult((writer) =>
{
if (log.Severity >= Model.Options.MinLevel &&
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
{
PushWriter(writer);
WriteLiteral(" <tr>\r\n <td>");
Write(string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteral("</td>\r\n <td>");
Write(string.Format("{0:H:mm:ss}", log.Time));
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteral($"</td>\r\n <td class=\"{severity}\">");
Write(log.Severity);
WriteLiteral($"</td>\r\n <td title=\"{log.Name}\">");
Write(log.Name);
WriteLiteral($"</td>\r\n <td title=\"{log.Message}\""+
"class=\"logState\" width=\"100px\">");
Write(log.Message);
WriteLiteral($"</td>\r\n <td title=\"{log.Exception}\">");
Write(log.Exception);
WriteLiteral("</td>\r\n </tr>\r\n");
PopWriter();
}
});
}
public HelperResult Traverse(ScopeNode node)
{
return new HelperResult((writer) =>
{
var messageIndex = 0;
var childIndex = 0;
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
{
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
{
LogRow(node.Messages[messageIndex]);
messageIndex++;
}
else
{
Traverse(node.Children[childIndex]);
childIndex++;
}
}
if (messageIndex < node.Messages.Count)
{
for (var i = messageIndex; i < node.Messages.Count; i++)
{
LogRow(node.Messages[i]);
}
}
else
{
for (var i = childIndex; i < node.Children.Count; i++)
{
Traverse(node.Children[i]);
}
}
});
}
}
@{
Response.ContentType = "text/html; charset=utf-8";
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core Logs</title>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js"></script>
<style>
<%$ include: Shared.css %> <%$ include: DetailsPage.css %>
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
@{
var context = Model.Activity?.HttpInfo;
}
@if (context != null)
{
<h2 id="requestHeader">Request Details</h2>
<table id="requestDetails">
<colgroup><col id="label" /><col /></colgroup>
<tr>
<th>Path</th>
<td>@context.Path</td>
</tr>
<tr>
<th>Host</th>
<td>@context.Host</td>
</tr>
<tr>
<th>Content Type</th>
<td>@context.ContentType</td>
</tr>
<tr>
<th>Method</th>
<td>@context.Method</td>
</tr>
<tr>
<th>Protocol</th>
<td>@context.Protocol</td>
</tr>
<tr>
<th>Headers</th>
<td id="headerTd">
<table id="headerTable">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var header in context.Headers)
{
<tr>
<td>@header.Key</td>
<td>@string.Join(";", header.Value)</td>
</tr>
}
</tbody>
</table>
</td>
</tr>
<tr>
<th>Status Code</th>
<td>@context.StatusCode</td>
</tr>
<tr>
<th>User</th>
<td>@context.User.Identity.Name</td>
</tr>
<tr>
<th>Claims</th>
<td>
@if (context.User.Claims.Any())
{
<table id="claimsTable">
<thead>
<tr>
<th>Issuer</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var claim in context.User.Claims)
{
<tr>
<td>@claim.Issuer</td>
<td>@claim.Value</td>
</tr>
}
</tbody>
</table>
}
</td>
</tr>
<tr>
<th>Scheme</th>
<td>@context.Scheme</td>
</tr>
<tr>
<th>Query</th>
<td>@context.Query.Value</td>
</tr>
<tr>
<th>Cookies</th>
<td>
@if (context.Cookies.Any())
{
<table id="cookieTable">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var cookie in context.Cookies)
{
<tr>
<td>@cookie.Key</td>
<td>@string.Join(";", cookie.Value)</td>
</tr>
}
</tbody>
</table>
}
</td>
</tr>
</table>
}
<h2>Logs</h2>
<form method="get">
<select name="level">
@foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
<option value="@severityInt" selected="selected">@severity</option>
}
else
{
<option value="@severityInt">@severity</option>
}
}
</select>
<input type="text" name="name" value="@Model.Options.NamePrefix" />
<input type="submit" value="filter" />
</form>
<table id="logs">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Severity</th>
<th>Name</th>
<th>State</th>
<th>Error</th>
</tr>
</thead>
@Traverse(Model.Activity.Root)
</table>
<script type="text/javascript">
$(document).ready(function () {
$("#requestHeader").click(function () {
$("#requestDetails").toggle();
});
});
</script>
</body>
</html>

View File

@ -1,56 +0,0 @@
body {
font-size: 0.9em;
width: 90%;
margin: 0px auto;
}
h1 {
padding-bottom: 10px;
}
h2 {
font-weight: normal;
}
table {
border-spacing: 0px;
width: 100%;
border-collapse: collapse;
border: 1px solid black;
white-space: pre-wrap;
}
th {
font-family: Arial;
}
td, th {
padding: 8px;
}
#headerTable, #cookieTable {
border: none;
height: 100%;
}
#headerTd {
white-space: normal;
}
#label {
width: 20%;
border-right: 1px solid black;
}
#logs{
margin-top: 10px;
margin-bottom: 20px;
}
#logs>tbody>tr>td {
border-right: 1px dashed lightgray;
}
#logs>thead>tr>th {
border: 1px solid black;
}

View File

@ -1,11 +0,0 @@
using System;
namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews
{
public class DetailsPageModel
{
public ActivityContext Activity { get; set; }
public ViewOptions Options { get; set; }
}
}

View File

@ -1,651 +0,0 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews
{
#line hidden
#line 1 "LogPage.cshtml"
using System;
#line default
#line hidden
using System.Threading.Tasks;
#line 2 "LogPage.cshtml"
using System.Collections.Generic;
#line default
#line hidden
#line 3 "LogPage.cshtml"
using System.Globalization;
#line default
#line hidden
#line 4 "LogPage.cshtml"
using System.Linq;
#line default
#line hidden
#line 5 "LogPage.cshtml"
using Microsoft.AspNetCore.Diagnostics.Elm;
#line default
#line hidden
#line 6 "LogPage.cshtml"
using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews;
#line default
#line hidden
#line 7 "LogPage.cshtml"
using Microsoft.Extensions.RazorViews;
#line default
#line hidden
#line 8 "LogPage.cshtml"
using Microsoft.Extensions.Logging;
#line default
#line hidden
internal class LogPage : Microsoft.Extensions.RazorViews.BaseView
{
#pragma warning disable 1998
public async override global::System.Threading.Tasks.Task ExecuteAsync()
{
WriteLiteral("\r\n");
#line 118 "LogPage.cshtml"
Response.ContentType = "text/html; charset=utf-8";
#line default
#line hidden
WriteLiteral(@"
<!DOCTYPE html>
<html>
<head>
<meta charset=""utf-8"" />
<title>ASP.NET Core Logs</title>
<script src=""//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js""></script>
<style>
body {
font-size: .813em;
white-space: nowrap;
margin: 20px;
}
col:nth-child(2n) {
background-color: #FAFAFA;
}
form {
display: inline-block;
}
h1 {
margin-left: 25px;
}
table {
margin: 0px auto;
border-collapse: collapse;
border-spacing: 0px;
table-layout: fixed;
width: 100%;
}
td, th {
padding: 4px;
}
thead {
font-size: 1em;
font-family: Arial;
}
tr {
height: 23px;
}
#requestHeader {
border-bottom: solid 1px gray;
border-top: solid 1px gray;
margin-bottom: 2px;
font-size: 1em;
line-height: 2em;
}
.collapse {
color: black;
float: right;
font-weight: normal;
width: 1em;
}
.date, .time {
width: 70px;
}
.logHeader {
border-bottom: 1px ");
WriteLiteral(@"solid lightgray;
color: gray;
text-align: left;
}
.logState {
text-overflow: ellipsis;
overflow: hidden;
}
.logTd {
border-left: 1px solid gray;
padding: 0px;
}
.logs {
width: 80%;
}
.logRow:hover {
background-color: #D6F5FF;
}
.requestRow>td {
border-bottom: solid 1px gray;
}
.severity {
width: 80px;
}
.summary {
color: black;
line-height: 1.8em;
}
.summary>th {
font-weight: normal;
}
.tab {
margin-left: 30px;
}
#viewOptions {
margin: 20px;
}
#viewOptions > * {
margin: 5px;
}
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif;
line-height: 1.4em;
}
h1 {
font-family: 'Segoe UI', Helvetica, sans-serif;
font-size: 2.5em;
}
td {
text-overflow: ellipsis;
overflow: hidden;
}
tr:nth-child(2n) {
background-color: #F6F6F6;
}
.critical {
background-color: red;
color: white;
}
.error {
color: red;
}
");
WriteLiteral("\r\n.information {\r\n color: blue;\r\n}\r\n\r\n.debug {\r\n color: black;\r\n}\r\n\r\n.warning {\r\n color: orange;\r\n}\r\n </style>\r\n</head>\r\n<body>\r\n <h1>ASP.NET Core Logs</h1>\r\n <form id=\"viewOptions\" method=\"get\">\r\n <select name=\"level\">\r\n");
#line 284 "LogPage.cshtml"
foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 6741, "\"", 6761, 1);
#line 289 "LogPage.cshtml"
WriteAttributeValue("", 6749, severityInt, 6749, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" selected=\"selected\">");
#line 289 "LogPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 290 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 6890, "\"", 6910, 1);
#line 293 "LogPage.cshtml"
WriteAttributeValue("", 6898, severityInt, 6898, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 293 "LogPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 294 "LogPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </select>\r\n <input type=\"text\" name=\"name\"");
BeginWriteAttribute("value", " value=\"", 7023, "\"", 7056, 1);
#line 297 "LogPage.cshtml"
WriteAttributeValue("", 7031, Model.Options.NamePrefix, 7031, 25, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" />
<input type=""submit"" value=""filter"" />
</form>
<form id=""clear"" method=""post"" action="""">
<button type=""submit"" name=""clear"" value=""1"">Clear Logs</button>
</form>
<table id=""requestTable"">
<thead id=""requestHeader"">
<tr>
<th class=""path"">Path</th>
<th class=""method"">Method</th>
<th class=""host"">Host</th>
<th class=""statusCode"">Status Code</th>
<th class=""logs"">Logs</th>
</tr>
</thead>
<colgroup>
<col />
<col />
<col />
<col />
<col />
</colgroup>
");
#line 321 "LogPage.cshtml"
foreach (var activity in Model.Activities.Reverse())
{
#line default
#line hidden
WriteLiteral(" <tbody>\r\n <tr class=\"requestRow\">\r\n");
#line 325 "LogPage.cshtml"
var activityPath = Model.Path.Value + "/" + activity.Id;
if (activity.HttpInfo != null)
{
#line default
#line hidden
WriteLiteral(" \t<td><a");
BeginWriteAttribute("href", " href=\"", 8120, "\"", 8140, 1);
#line 329 "LogPage.cshtml"
WriteAttributeValue("", 8127, activityPath, 8127, 13, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 8141, "\"", 8172, 1);
#line 329 "LogPage.cshtml"
WriteAttributeValue("", 8149, activity.HttpInfo.Path, 8149, 23, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 329 "LogPage.cshtml"
Write(activity.HttpInfo.Path);
#line default
#line hidden
WriteLiteral("</a></td>\r\n <td>");
#line 330 "LogPage.cshtml"
Write(activity.HttpInfo.Method);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 331 "LogPage.cshtml"
Write(activity.HttpInfo.Host);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 332 "LogPage.cshtml"
Write(activity.HttpInfo.StatusCode);
#line default
#line hidden
WriteLiteral("</td>\r\n");
#line 333 "LogPage.cshtml"
}
else if (activity.RepresentsScope)
{
#line default
#line hidden
WriteLiteral(" <td colspan=\"4\"><a");
BeginWriteAttribute("href", " href=\"", 8562, "\"", 8582, 1);
#line 336 "LogPage.cshtml"
WriteAttributeValue("", 8569, activityPath, 8569, 13, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 8583, "\"", 8611, 1);
#line 336 "LogPage.cshtml"
WriteAttributeValue("", 8591, activity.Root.State, 8591, 20, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 336 "LogPage.cshtml"
Write(activity.Root.State);
#line default
#line hidden
WriteLiteral("</a></td>\r\n");
#line 337 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <td colspan=\"4\"><a");
BeginWriteAttribute("href", " href=\"", 8774, "\"", 8794, 1);
#line 340 "LogPage.cshtml"
WriteAttributeValue("", 8781, activityPath, 8781, 13, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">Non-scope Log</a></td>\r\n");
#line 341 "LogPage.cshtml"
}
#line default
#line hidden
WriteLiteral(@" <td class=""logTd"">
<table class=""logTable"">
<thead class=""logHeader"">
<tr class=""headerRow"">
<th class=""date"">Date</th>
<th class=""time"">Time</th>
<th class=""name"">Name</th>
<th class=""severity"">Severity</th>
<th class=""state"">State</th>
<th>Error<span class=""collapse"">^</span></th>
</tr>
</thead>
");
#line 355 "LogPage.cshtml"
var counts = new Dictionary<string, int>();
counts["Critical"] = 0;
counts["Error"] = 0;
counts["Warning"] = 0;
counts["Information"] = 0;
counts["Debug"] = 0;
#line default
#line hidden
WriteLiteral(" <tbody class=\"logBody\">\r\n");
#line 364 "LogPage.cshtml"
if (!activity.RepresentsScope)
{
// message not within a scope
var logInfo = activity.Root.Messages.FirstOrDefault();
#line default
#line hidden
#line 368 "LogPage.cshtml"
Write(LogRow(logInfo, 0));
#line default
#line hidden
#line 368 "LogPage.cshtml"
counts[logInfo.Severity.ToString()] = 1;
}
else
{
#line default
#line hidden
#line 373 "LogPage.cshtml"
Write(Traverse(activity.Root, 0, counts));
#line default
#line hidden
#line 373 "LogPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n <tbody class=\"summary\">\r\n <tr class=\"logRow\">\r\n <td>");
#line 378 "LogPage.cshtml"
Write(activity.Time.ToString("MM-dd-yyyy HH:mm:ss"));
#line default
#line hidden
WriteLiteral("</td>\r\n");
#line 379 "LogPage.cshtml"
foreach (var kvp in counts)
{
if (string.Equals("Debug", kvp.Key)) {
#line default
#line hidden
WriteLiteral(" <td>");
#line 382 "LogPage.cshtml"
Write(kvp.Value);
#line default
#line hidden
WriteLiteral(" ");
#line 382 "LogPage.cshtml"
Write(kvp.Key);
#line default
#line hidden
WriteLiteral("<span class=\"collapse\">v</span></td>\r\n");
#line 383 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <td>");
#line 386 "LogPage.cshtml"
Write(kvp.Value);
#line default
#line hidden
WriteLiteral(" ");
#line 386 "LogPage.cshtml"
Write(kvp.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n");
#line 387 "LogPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </tr>\r\n </tbody>\r\n </table>\r\n </td>\r\n </tr>\r\n </tbody>\r\n");
#line 395 "LogPage.cshtml"
}
#line default
#line hidden
WriteLiteral(@" </table>
<script type=""text/javascript"">
$(document).ready(function () {
$("".logBody"").hide();
$("".logTable > thead"").hide();
$("".logTable > thead"").click(function () {
$(this).closest("".logTable"").find(""tbody"").hide();
$(this).closest("".logTable"").find("".summary"").show();
$(this).hide();
});
$("".logTable > .summary"").click(function () {
$(this).closest("".logTable"").find(""tbody"").show();
$(this).closest("".logTable"").find(""thead"").show();
$(this).hide();
});
});
</script>
</body>
</html>");
}
#pragma warning restore 1998
#line 11 "LogPage.cshtml"
public LogPage(LogPageModel model)
{
Model = model;
}
public LogPageModel Model { get; set; }
public HelperResult LogRow(LogInfo log, int level)
{
return new HelperResult((writer) =>
{
if (log.Severity >= Model.Options.MinLevel &&
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
{
PushWriter(writer);
WriteLiteral(" <tr class=\"logRow\">\r\n <td>");
Write(string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteral("</td>\r\n <td>");
Write(string.Format("{0:H:mm:ss}", log.Time));
WriteLiteral($"</td>\r\n <td title=\"{log.Name}\">");
Write(log.Name);
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteral($"</td>\r\n <td class=\"{severity}\">");
Write(log.Severity);
WriteLiteral($"</td>\r\n <td title=\"{log.Message}\"> \r\n");
for (var i = 0; i < level; i++)
{
WriteLiteral(" <span class=\"tab\"></span>\r\n");
}
WriteLiteral(" ");
Write(log.Message);
WriteLiteral($"\r\n </td>\r\n <td title=\"{log.Exception}\">");
Write(log.Exception);
WriteLiteral("</td>\r\n </tr>\r\n");
PopWriter();
}
});
}
public HelperResult Traverse(ScopeNode node, int level, Dictionary<string, int> counts)
{
return new HelperResult((writer) => {
PushWriter(writer);
// print start of scope
Write(LogRow(new LogInfo()
{
Name = node.Name,
Time = node.StartTime,
Severity = LogLevel.Debug,
Message = "Beginning " + node.State,
}, level));
var messageIndex = 0;
var childIndex = 0;
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
{
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
{
Write(LogRow(node.Messages[messageIndex], level));
counts[node.Messages[messageIndex].Severity.ToString()]++;
messageIndex++;
}
else
{
Write(Traverse(node.Children[childIndex], level + 1, counts));
childIndex++;
}
}
if (messageIndex < node.Messages.Count)
{
for (var i = messageIndex; i < node.Messages.Count; i++)
{
Write(LogRow(node.Messages[i], level));
counts[node.Messages[i].Severity.ToString()]++;
}
}
else
{
for (var i = childIndex; i < node.Children.Count; i++)
{
Write(Traverse(node.Children[i], level + 1, counts));
}
}
// print end of scope
Write(LogRow(new LogInfo()
{
Name = node.Name,
Time = node.EndTime,
Severity = LogLevel.Debug,
Message = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime)
}, level));
PopWriter();
});
}
#line default
#line hidden
}
}
#pragma warning restore 1591

View File

@ -1,267 +0,0 @@
@using System
@using System.Collections.Generic
@using System.Globalization
@using System.Linq
@using Microsoft.AspNetCore.Diagnostics.Elm
@using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews
@using Microsoft.Extensions.RazorViews
@using Microsoft.Extensions.Logging
@functions
{
public LogPage(LogPageModel model)
{
Model = model;
}
public LogPageModel Model { get; set; }
public HelperResult LogRow(LogInfo log, int level)
{
return new HelperResult((writer) =>
{
if (log.Severity >= Model.Options.MinLevel &&
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
{
PushWriter(writer);
WriteLiteral(" <tr class=\"logRow\">\r\n <td>");
Write(string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteral("</td>\r\n <td>");
Write(string.Format("{0:H:mm:ss}", log.Time));
WriteLiteral($"</td>\r\n <td title=\"{log.Name}\">");
Write(log.Name);
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteral($"</td>\r\n <td class=\"{severity}\">");
Write(log.Severity);
WriteLiteral($"</td>\r\n <td title=\"{log.Message}\"> \r\n");
for (var i = 0; i < level; i++)
{
WriteLiteral(" <span class=\"tab\"></span>\r\n");
}
WriteLiteral(" ");
Write(log.Message);
WriteLiteral($"\r\n </td>\r\n <td title=\"{log.Exception}\">");
Write(log.Exception);
WriteLiteral("</td>\r\n </tr>\r\n");
PopWriter();
}
});
}
public HelperResult Traverse(ScopeNode node, int level, Dictionary<string, int> counts)
{
return new HelperResult((writer) => {
PushWriter(writer);
// print start of scope
Write(LogRow(new LogInfo()
{
Name = node.Name,
Time = node.StartTime,
Severity = LogLevel.Debug,
Message = "Beginning " + node.State,
}, level));
var messageIndex = 0;
var childIndex = 0;
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
{
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
{
Write(LogRow(node.Messages[messageIndex], level));
counts[node.Messages[messageIndex].Severity.ToString()]++;
messageIndex++;
}
else
{
Write(Traverse(node.Children[childIndex], level + 1, counts));
childIndex++;
}
}
if (messageIndex < node.Messages.Count)
{
for (var i = messageIndex; i < node.Messages.Count; i++)
{
Write(LogRow(node.Messages[i], level));
counts[node.Messages[i].Severity.ToString()]++;
}
}
else
{
for (var i = childIndex; i < node.Children.Count; i++)
{
Write(Traverse(node.Children[i], level + 1, counts));
}
}
// print end of scope
Write(LogRow(new LogInfo()
{
Name = node.Name,
Time = node.EndTime,
Severity = LogLevel.Debug,
Message = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime)
}, level));
PopWriter();
});
}
}
@{
Response.ContentType = "text/html; charset=utf-8";
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core Logs</title>
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js"></script>
<style>
<%$ include: LogPage.css %>
<%$ include: Shared.css %>
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
<form id="viewOptions" method="get">
<select name="level">
@foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
<option value="@severityInt" selected="selected">@severity</option>
}
else
{
<option value="@severityInt">@severity</option>
}
}
</select>
<input type="text" name="name" value="@Model.Options.NamePrefix" />
<input type="submit" value="filter" />
</form>
<form id="clear" method="post" action="">
<button type="submit" name="clear" value="1">Clear Logs</button>
</form>
<table id="requestTable">
<thead id="requestHeader">
<tr>
<th class="path">Path</th>
<th class="method">Method</th>
<th class="host">Host</th>
<th class="statusCode">Status Code</th>
<th class="logs">Logs</th>
</tr>
</thead>
<colgroup>
<col />
<col />
<col />
<col />
<col />
</colgroup>
@foreach (var activity in Model.Activities.Reverse())
{
<tbody>
<tr class="requestRow">
@{
var activityPath = Model.Path.Value + "/" + activity.Id;
if (activity.HttpInfo != null)
{
<td><a href="@activityPath" title="@activity.HttpInfo.Path">@activity.HttpInfo.Path</a></td>
<td>@activity.HttpInfo.Method</td>
<td>@activity.HttpInfo.Host</td>
<td>@activity.HttpInfo.StatusCode</td>
}
else if (activity.RepresentsScope)
{
<td colspan="4"><a href="@activityPath" title="@activity.Root.State">@activity.Root.State</a></td>
}
else
{
<td colspan="4"><a href="@activityPath">Non-scope Log</a></td>
}
}
<td class="logTd">
<table class="logTable">
<thead class="logHeader">
<tr class="headerRow">
<th class="date">Date</th>
<th class="time">Time</th>
<th class="name">Name</th>
<th class="severity">Severity</th>
<th class="state">State</th>
<th>Error<span class="collapse">^</span></th>
</tr>
</thead>
@{
var counts = new Dictionary<string, int>();
counts["Critical"] = 0;
counts["Error"] = 0;
counts["Warning"] = 0;
counts["Information"] = 0;
counts["Debug"] = 0;
}
<tbody class="logBody">
@if (!activity.RepresentsScope)
{
// message not within a scope
var logInfo = activity.Root.Messages.FirstOrDefault();
@LogRow(logInfo, 0)
counts[logInfo.Severity.ToString()] = 1;
}
else
{
@Traverse(activity.Root, 0, counts)
}
</tbody>
<tbody class="summary">
<tr class="logRow">
<td>@activity.Time.ToString("MM-dd-yyyy HH:mm:ss")</td>
@foreach (var kvp in counts)
{
if (string.Equals("Debug", kvp.Key)) {
<td>@kvp.Value @kvp.Key<span class="collapse">v</span></td>
}
else
{
<td>@kvp.Value @kvp.Key</td>
}
}
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
}
</table>
<script type="text/javascript">
$(document).ready(function () {
$(".logBody").hide();
$(".logTable > thead").hide();
$(".logTable > thead").click(function () {
$(this).closest(".logTable").find("tbody").hide();
$(this).closest(".logTable").find(".summary").show();
$(this).hide();
});
$(".logTable > .summary").click(function () {
$(this).closest(".logTable").find("tbody").show();
$(this).closest(".logTable").find("thead").show();
$(this).hide();
});
});
</script>
</body>
</html>

View File

@ -1,110 +0,0 @@
body {
font-size: .813em;
white-space: nowrap;
margin: 20px;
}
col:nth-child(2n) {
background-color: #FAFAFA;
}
form {
display: inline-block;
}
h1 {
margin-left: 25px;
}
table {
margin: 0px auto;
border-collapse: collapse;
border-spacing: 0px;
table-layout: fixed;
width: 100%;
}
td, th {
padding: 4px;
}
thead {
font-size: 1em;
font-family: Arial;
}
tr {
height: 23px;
}
#requestHeader {
border-bottom: solid 1px gray;
border-top: solid 1px gray;
margin-bottom: 2px;
font-size: 1em;
line-height: 2em;
}
.collapse {
color: black;
float: right;
font-weight: normal;
width: 1em;
}
.date, .time {
width: 70px;
}
.logHeader {
border-bottom: 1px solid lightgray;
color: gray;
text-align: left;
}
.logState {
text-overflow: ellipsis;
overflow: hidden;
}
.logTd {
border-left: 1px solid gray;
padding: 0px;
}
.logs {
width: 80%;
}
.logRow:hover {
background-color: #D6F5FF;
}
.requestRow>td {
border-bottom: solid 1px gray;
}
.severity {
width: 80px;
}
.summary {
color: black;
line-height: 1.8em;
}
.summary>th {
font-weight: normal;
}
.tab {
margin-left: 30px;
}
#viewOptions {
margin: 20px;
}
#viewOptions > * {
margin: 5px;
}

View File

@ -1,14 +0,0 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews
{
public class LogPageModel
{
public IEnumerable<ActivityContext> Activities { get; set; }
public ViewOptions Options { get; set; }
public PathString Path { get; set; }
}
}

View File

@ -1,512 +0,0 @@
namespace Microsoft.AspNetCore.Diagnostics.Elm.Views
{
#line 1 "DetailsPage.cshtml"
using System
#line default
#line hidden
;
#line 2 "DetailsPage.cshtml"
using System.Globalization
#line default
#line hidden
;
#line 3 "DetailsPage.cshtml"
using System.Linq
#line default
#line hidden
;
#line 4 "DetailsPage.cshtml"
using Microsoft.AspNetCore.Diagnostics.Elm
#line default
#line hidden
;
#line 5 "DetailsPage.cshtml"
using Microsoft.AspNetCore.Diagnostics.Elm.Views
#line default
#line hidden
;
#line 6 "DetailsPage.cshtml"
using Microsoft.AspNetCore.DiagnosticsViewPage.Views
#line default
#line hidden
;
#line 7 "DetailsPage.cshtml"
using Microsoft.Extensions.Logging
#line default
#line hidden
;
using System.Threading.Tasks;
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class DetailsPage : Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView
{
#line 10 "DetailsPage.cshtml"
public DetailsPage(DetailsPageModel model)
{
Model = model;
}
public DetailsPageModel Model { get; set; }
public HelperResult LogRow(LogInfo log)
{
return new HelperResult((writer) =>
{
if (log.Severity >= Model.Options.MinLevel &&
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
{
WriteLiteralTo(writer, " <tr>\r\n <td>");
WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteralTo(writer, "</td>\r\n <td>");
WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time));
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteralTo(writer, $"</td>\r\n <td class=\"{severity}\">");
WriteTo(writer, log.Severity);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Name}\">");
WriteTo(writer, log.Name);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Message}\""+
"class=\"logState\" width=\"100px\">");
WriteTo(writer, log.Message);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Exception}\">");
WriteTo(writer, log.Exception);
WriteLiteralTo(writer, "</td>\r\n </tr>\r\n");
}
});
}
public HelperResult Traverse(ScopeNode node)
{
return new HelperResult((writer) =>
{
var messageIndex = 0;
var childIndex = 0;
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
{
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
{
LogRow(node.Messages[messageIndex]);
messageIndex++;
}
else
{
Traverse(node.Children[childIndex]);
childIndex++;
}
}
if (messageIndex < node.Messages.Count)
{
for (var i = messageIndex; i < node.Messages.Count; i++)
{
LogRow(node.Messages[i]);
}
}
else
{
for (var i = childIndex; i < node.Children.Count; i++)
{
Traverse(node.Children[i]);
}
}
});
}
#line default
#line hidden
#line hidden
public DetailsPage()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
WriteLiteral("\r\n");
#line 84 "DetailsPage.cshtml"
Response.ContentType = "text/html";
#line default
#line hidden
WriteLiteral(@"<!DOCTYPE html>
<html>
<head>
<meta charset=""utf-8"" />
<title>ASP.NET Core Logs</title>
<script src=""http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js""></script>
<style>
<%$ include: Shared.css % > <%$ include: DetailsPage.css % >
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
");
#line 99 "DetailsPage.cshtml"
#line default
#line hidden
#line 99 "DetailsPage.cshtml"
var context = Model.Activity?.HttpInfo;
#line default
#line hidden
WriteLiteral(" ");
#line 102 "DetailsPage.cshtml"
if (context != null)
{
#line default
#line hidden
WriteLiteral(" <h2 id=\"requestHeader\">Request Details</h2>\r\n <table id=\"requestDetails\">\r\n <colgroup><col id=\"label\" /><col /></colgroup>\r\n\r\n <tr>\r\n <th>Path</th>\r\n <td>");
#line 110 "DetailsPage.cshtml"
Write(context.Path);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Host</th>\r\n <td>");
#line 114 "DetailsPage.cshtml"
Write(context.Host);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Content Type</th>\r\n <td>");
#line 118 "DetailsPage.cshtml"
Write(context.ContentType);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Method</th>\r\n <td>");
#line 122 "DetailsPage.cshtml"
Write(context.Method);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Protocol</th>\r\n <td>");
#line 126 "DetailsPage.cshtml"
Write(context.Protocol);
#line default
#line hidden
WriteLiteral(@"</td>
</tr>
<tr>
<th>Headers</th>
<td id=""headerTd"">
<table id=""headerTable"">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 139 "DetailsPage.cshtml"
#line default
#line hidden
#line 139 "DetailsPage.cshtml"
foreach (var header in context.Headers)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 142 "DetailsPage.cshtml"
Write(header.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 143 "DetailsPage.cshtml"
Write(string.Join(";", header.Value));
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 145 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n </td>\r\n </tr>\r\n <tr>\r\n <th>Status Code</th>\r\n <td>");
#line 152 "DetailsPage.cshtml"
Write(context.StatusCode);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>User</th>\r\n <td>");
#line 156 "DetailsPage.cshtml"
Write(context.User.Identity.Name);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Claims</th>\r\n <td>\r\n");
#line 161 "DetailsPage.cshtml"
#line default
#line hidden
#line 161 "DetailsPage.cshtml"
if (context.User.Claims.Any())
{
#line default
#line hidden
WriteLiteral(@" <table id=""claimsTable"">
<thead>
<tr>
<th>Issuer</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 171 "DetailsPage.cshtml"
#line default
#line hidden
#line 171 "DetailsPage.cshtml"
foreach (var claim in context.User.Claims)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 174 "DetailsPage.cshtml"
Write(claim.Issuer);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 175 "DetailsPage.cshtml"
Write(claim.Value);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 177 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n");
#line 180 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </td>\r\n </tr>\r\n <tr>\r\n <th>Scheme</th>\r\n <td>");
#line 185 "DetailsPage.cshtml"
Write(context.Scheme);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Query</th>\r\n <td>");
#line 189 "DetailsPage.cshtml"
Write(context.Query.Value);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Cookies</th>\r\n <td>\r\n");
#line 194 "DetailsPage.cshtml"
#line default
#line hidden
#line 194 "DetailsPage.cshtml"
if (context.Cookies.Any())
{
#line default
#line hidden
WriteLiteral(@" <table id=""cookieTable"">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 204 "DetailsPage.cshtml"
#line default
#line hidden
#line 204 "DetailsPage.cshtml"
foreach (var cookie in context.Cookies)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 207 "DetailsPage.cshtml"
Write(cookie.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 208 "DetailsPage.cshtml"
Write(string.Join(";", cookie.Value));
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 210 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n");
#line 213 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </td>\r\n </tr>\r\n </table>\r\n");
#line 217 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" <h2>Logs</h2>\r\n <form method=\"get\">\r\n <select name=\"level\">\r\n");
#line 221 "DetailsPage.cshtml"
#line default
#line hidden
#line 221 "DetailsPage.cshtml"
foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 7723, "\"", 7743, 1);
#line 226 "DetailsPage.cshtml"
WriteAttributeValue("", 7731, severityInt, 7731, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" selected=\"selected\">");
#line 226 "DetailsPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 227 "DetailsPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 7872, "\"", 7892, 1);
#line 230 "DetailsPage.cshtml"
WriteAttributeValue("", 7880, severityInt, 7880, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 230 "DetailsPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 231 "DetailsPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </select>\r\n <input type=\"text\" name=\"name\"");
BeginWriteAttribute("value", " value=\"", 8005, "\"", 8038, 1);
#line 234 "DetailsPage.cshtml"
WriteAttributeValue("", 8013, Model.Options.NamePrefix, 8013, 25, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" />
<input type=""submit"" value=""filter"" />
</form>
<table id=""logs"">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Severity</th>
<th>Name</th>
<th>State</th>
<th>Error</th>
</tr>
</thead>
");
#line 248 "DetailsPage.cshtml"
Write(Traverse(Model.Activity.Root));
#line default
#line hidden
WriteLiteral(@"
</table>
<script type=""text/javascript"">
$(document).ready(function () {
$(""#requestHeader"").click(function () {
$(""#requestDetails"").toggle();
});
});
</script>
</body>
</html>");
}
#pragma warning restore 1998
}
}

View File

@ -1,258 +0,0 @@
@using System
@using System.Globalization
@using System.Linq
@using Microsoft.AspNetCore.Diagnostics.Elm
@using Microsoft.AspNetCore.Diagnostics.Elm.Views
@using Microsoft.AspNetCore.DiagnosticsViewPage.Views
@using Microsoft.Extensions.Logging
@functions
{
public DetailsPage(DetailsPageModel model)
{
Model = model;
}
public DetailsPageModel Model { get; set; }
public HelperResult LogRow(LogInfo log)
{
return new HelperResult((writer) =>
{
if (log.Severity >= Model.Options.MinLevel &&
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
{
WriteLiteralTo(writer, " <tr>\r\n <td>");
WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteralTo(writer, "</td>\r\n <td>");
WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time));
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteralTo(writer, $"</td>\r\n <td class=\"{severity}\">");
WriteTo(writer, log.Severity);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Name}\">");
WriteTo(writer, log.Name);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Message}\""+
"class=\"logState\" width=\"100px\">");
WriteTo(writer, log.Message);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Exception}\">");
WriteTo(writer, log.Exception);
WriteLiteralTo(writer, "</td>\r\n </tr>\r\n");
}
});
}
public HelperResult Traverse(ScopeNode node)
{
return new HelperResult((writer) =>
{
var messageIndex = 0;
var childIndex = 0;
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
{
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
{
LogRow(node.Messages[messageIndex]);
messageIndex++;
}
else
{
Traverse(node.Children[childIndex]);
childIndex++;
}
}
if (messageIndex < node.Messages.Count)
{
for (var i = messageIndex; i < node.Messages.Count; i++)
{
LogRow(node.Messages[i]);
}
}
else
{
for (var i = childIndex; i < node.Children.Count; i++)
{
Traverse(node.Children[i]);
}
}
});
}
}
@{
Response.ContentType = "text/html";
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core Logs</title>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js"></script>
<style>
<%$ include: Shared.css % > <%$ include: DetailsPage.css % >
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
@{
var context = Model.Activity?.HttpInfo;
}
@if (context != null)
{
<h2 id="requestHeader">Request Details</h2>
<table id="requestDetails">
<colgroup><col id="label" /><col /></colgroup>
<tr>
<th>Path</th>
<td>@context.Path</td>
</tr>
<tr>
<th>Host</th>
<td>@context.Host</td>
</tr>
<tr>
<th>Content Type</th>
<td>@context.ContentType</td>
</tr>
<tr>
<th>Method</th>
<td>@context.Method</td>
</tr>
<tr>
<th>Protocol</th>
<td>@context.Protocol</td>
</tr>
<tr>
<th>Headers</th>
<td id="headerTd">
<table id="headerTable">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var header in context.Headers)
{
<tr>
<td>@header.Key</td>
<td>@string.Join(";", header.Value)</td>
</tr>
}
</tbody>
</table>
</td>
</tr>
<tr>
<th>Status Code</th>
<td>@context.StatusCode</td>
</tr>
<tr>
<th>User</th>
<td>@context.User.Identity.Name</td>
</tr>
<tr>
<th>Claims</th>
<td>
@if (context.User.Claims.Any())
{
<table id="claimsTable">
<thead>
<tr>
<th>Issuer</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var claim in context.User.Claims)
{
<tr>
<td>@claim.Issuer</td>
<td>@claim.Value</td>
</tr>
}
</tbody>
</table>
}
</td>
</tr>
<tr>
<th>Scheme</th>
<td>@context.Scheme</td>
</tr>
<tr>
<th>Query</th>
<td>@context.Query.Value</td>
</tr>
<tr>
<th>Cookies</th>
<td>
@if (context.Cookies.Any())
{
<table id="cookieTable">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var cookie in context.Cookies)
{
<tr>
<td>@cookie.Key</td>
<td>@string.Join(";", cookie.Value)</td>
</tr>
}
</tbody>
</table>
}
</td>
</tr>
</table>
}
<h2>Logs</h2>
<form method="get">
<select name="level">
@foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
<option value="@severityInt" selected="selected">@severity</option>
}
else
{
<option value="@severityInt">@severity</option>
}
}
</select>
<input type="text" name="name" value="@Model.Options.NamePrefix" />
<input type="submit" value="filter" />
</form>
<table id="logs">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Severity</th>
<th>Name</th>
<th>State</th>
<th>Error</th>
</tr>
</thead>
@Traverse(Model.Activity.Root)
</table>
<script type="text/javascript">
$(document).ready(function () {
$("#requestHeader").click(function () {
$("#requestDetails").toggle();
});
});
</script>
</body>
</html>

View File

@ -1,56 +0,0 @@
body {
font-size: 0.9em;
width: 90%;
margin: 0px auto;
}
h1 {
padding-bottom: 10px;
}
h2 {
font-weight: normal;
}
table {
border-spacing: 0px;
width: 100%;
border-collapse: collapse;
border: 1px solid black;
white-space: pre-wrap;
}
th {
font-family: Arial;
}
td, th {
padding: 8px;
}
#headerTable, #cookieTable {
border: none;
height: 100%;
}
#headerTd {
white-space: normal;
}
#label {
width: 20%;
border-right: 1px solid black;
}
#logs{
margin-top: 10px;
margin-bottom: 20px;
}
#logs>tbody>tr>td {
border-right: 1px dashed lightgray;
}
#logs>thead>tr>th {
border: 1px solid black;
}

View File

@ -1,12 +0,0 @@
using System;
namespace Microsoft.AspNetCore.Diagnostics.Elm.Views
{
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class DetailsPageModel
{
public ActivityContext Activity { get; set; }
public ViewOptions Options { get; set; }
}
}

View File

@ -1,579 +0,0 @@
namespace Microsoft.AspNetCore.Diagnostics.Elm.Views
{
#line 1 "LogPage.cshtml"
using System
#line default
#line hidden
;
#line 2 "LogPage.cshtml"
using System.Collections.Generic
#line default
#line hidden
;
#line 3 "LogPage.cshtml"
using System.Globalization
#line default
#line hidden
;
#line 4 "LogPage.cshtml"
using System.Linq
#line default
#line hidden
;
#line 5 "LogPage.cshtml"
using Microsoft.AspNetCore.Diagnostics.Elm
#line default
#line hidden
;
#line 6 "LogPage.cshtml"
using Microsoft.AspNetCore.Diagnostics.Elm.Views
#line default
#line hidden
;
#line 7 "LogPage.cshtml"
using Microsoft.AspNetCore.DiagnosticsViewPage.Views
#line default
#line hidden
;
#line 8 "LogPage.cshtml"
using Microsoft.Extensions.Logging
#line default
#line hidden
;
using System.Threading.Tasks;
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class LogPage : Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView
{
#line 11 "LogPage.cshtml"
public LogPage(LogPageModel model)
{
Model = model;
}
public LogPageModel Model { get; set; }
public HelperResult LogRow(LogInfo log, int level)
{
return new HelperResult((writer) =>
{
if (log.Severity >= Model.Options.MinLevel &&
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
{
WriteLiteralTo(writer, " <tr class=\"logRow\">\r\n <td>");
WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteralTo(writer, "</td>\r\n <td>");
WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time));
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Name}\">");
WriteTo(writer, log.Name);
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteralTo(writer, $"</td>\r\n <td class=\"{severity}\">");
WriteTo(writer, log.Severity);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Message}\"> \r\n");
for (var i = 0; i < level; i++)
{
WriteLiteralTo(writer, " <span class=\"tab\"></span>\r\n");
}
WriteLiteralTo(writer, " ");
WriteTo(writer, log.Message);
WriteLiteralTo(writer, $"\r\n </td>\r\n <td title=\"{log.Exception}\">");
WriteTo(writer, log.Exception);
WriteLiteralTo(writer, "</td>\r\n </tr>\r\n");
}
});
}
public HelperResult Traverse(ScopeNode node, int level, Dictionary<string, int> counts)
{
return new HelperResult((writer) => {
// print start of scope
WriteTo(writer, LogRow(new LogInfo()
{
Name = node.Name,
Time = node.StartTime,
Severity = LogLevel.Debug,
Message = "Beginning " + node.State,
}, level));
var messageIndex = 0;
var childIndex = 0;
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
{
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
{
WriteTo(writer, LogRow(node.Messages[messageIndex], level));
counts[node.Messages[messageIndex].Severity.ToString()]++;
messageIndex++;
}
else
{
WriteTo(writer, Traverse(node.Children[childIndex], level + 1, counts));
childIndex++;
}
}
if (messageIndex < node.Messages.Count)
{
for (var i = messageIndex; i < node.Messages.Count; i++)
{
WriteTo(writer, LogRow(node.Messages[i], level));
counts[node.Messages[i].Severity.ToString()]++;
}
}
else
{
for (var i = childIndex; i < node.Children.Count; i++)
{
WriteTo(writer, Traverse(node.Children[i], level + 1, counts));
}
}
// print end of scope
WriteTo(writer, LogRow(new LogInfo()
{
Name = node.Name,
Time = node.EndTime,
Severity = LogLevel.Debug,
Message = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime)
}, level));
});
}
#line default
#line hidden
#line hidden
public LogPage()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
WriteLiteral("\r\n");
#line 114 "LogPage.cshtml"
Response.ContentType = "text/html";
#line default
#line hidden
WriteLiteral(@"
<!DOCTYPE html>
<html>
<head>
<meta charset=""utf-8"" />
<title>ASP.NET Core Logs</title>
<script src=""//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js""></script>
<style>
body {\r\n font-size: .813em;\r\n white-space: nowrap;\r\n margin: 20px;\r\n}\r\n\r\ncol:nth-child(2n) {\r\n background-color: #FAFAFA;\r\n}\r\n\r\nform { \r\n display: inline-block; \r\n}\r\n\r\nh1 {\r\n margin-left: 25px;\r\n}\r\n\r\ntable {\r\n margin: 0px auto;\r\n border-collapse: collapse;\r\n border-spacing: 0px;\r\n table-layout: fixed;\r\n width: 100%;\r\n}\r\n\r\ntd, th {\r\n padding: 4px;\r\n}\r\n\r\nthead {\r\n font-size: 1em;\r\n font-family: Arial;\r\n}\r\n\r\ntr {\r\n height: 23px;\r\n}\r\n\r\n#requestHeader {\r\n border-bottom: solid 1px gray;\r\n border-top: solid 1px gray;\r\n margin-bottom: 2px;\r\n font-size: 1em;\r\n line-height: 2em;\r\n}\r\n\r\n.collapse {\r\n color: black;\r\n float: right;\r\n font-weight: normal;\r\n width: 1em;\r\n}\r\n\r\n.date, .time {\r\n width: 70px; \r\n}\r\n\r\n.logHeader {\r\n border-bottom: 1px solid lightgray;\r\n color: gray;\r\n text-align: left;\r\n}\r\n\r\n.logState {\r\n text-overflow: ellipsis;\r\n overflow: hidden;\r\n}\r\n\r\n.logTd {\r\n border-left: 1px solid gray;\r\n padding: 0px;\r\n}\r\n\r\n.logs {\r\n width: 80%;\r\n}\r\n\r\n.logRow:hover {\r\n background-color: #D6F5FF;\r\n}\r\n\r\n.requestRow>td {\r\n border-bottom: solid 1px gray;\r\n}\r\n\r\n.severity {\r\n width: 80px;\r\n}\r\n\r\n.summary {\r\n color: black;\r\n line-height: 1.8em;\r\n}\r\n\r\n.summary>th {\r\n font-weight: normal;\r\n}\r\n\r\n.tab {\r\n margin-left: 30px;\r\n}\r\n\r\n#viewOptions {\r\n margin: 20px;\r\n}\r\n\r\n#viewOptions > * {\r\n margin: 5px;\r\n}
body {\r\n font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif;\r\n line-height: 1.4em;\r\n}\r\n\r\nh1 {\r\n font-family: 'Segoe UI', Helvetica, sans-serif;\r\n font-size: 2.5em;\r\n}\r\n\r\ntd {\r\n text-overflow: ellipsis;\r\n overflow: hidden;\r\n}\r\n\r\ntr:nth-child(2n) {\r\n background-color: #F6F6F6;\r\n}\r\n\r\n.critical {\r\n background-color: red;\r\n color: white;\r\n}\r\n\r\n.error {\r\n color: red;\r\n}\r\n\r\n.information {\r\n color: blue;\r\n}\r\n\r\n.debug {\r\n color: black;\r\n}\r\n\r\n.warning {\r\n color: orange;\r\n}
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
<form id=""viewOptions"" method=""get"">
<select name=""level"">
");
#line 133 "LogPage.cshtml"
#line default
#line hidden
#line 133 "LogPage.cshtml"
foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 4934, "\"", 4954, 1);
#line 138 "LogPage.cshtml"
WriteAttributeValue("", 4942, severityInt, 4942, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" selected=\"selected\">");
#line 138 "LogPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 139 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 5083, "\"", 5103, 1);
#line 142 "LogPage.cshtml"
WriteAttributeValue("", 5091, severityInt, 5091, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 142 "LogPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 143 "LogPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </select>\r\n <input type=\"text\" name=\"name\"");
BeginWriteAttribute("value", " value=\"", 5216, "\"", 5249, 1);
#line 146 "LogPage.cshtml"
WriteAttributeValue("", 5224, Model.Options.NamePrefix, 5224, 25, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" />
<input type=""submit"" value=""filter"" />
</form>
<form id=""clear"" method=""post"" action="""">
<button type=""submit"" name=""clear"" value=""1"">Clear Logs</button>
</form>
<table id=""requestTable"">
<thead id=""requestHeader"">
<tr>
<th class=""path"">Path</th>
<th class=""method"">Method</th>
<th class=""host"">Host</th>
<th class=""statusCode"">Status Code</th>
<th class=""logs"">Logs</th>
</tr>
</thead>
<colgroup>
<col />
<col />
<col />
<col />
<col />
</colgroup>
");
#line 170 "LogPage.cshtml"
#line default
#line hidden
#line 170 "LogPage.cshtml"
foreach (var activity in Model.Activities.Reverse())
{
#line default
#line hidden
WriteLiteral(" <tbody>\r\n <tr class=\"requestRow\">\r\n");
#line 174 "LogPage.cshtml"
#line default
#line hidden
#line 174 "LogPage.cshtml"
var activityPath = Model.Path.Value + "/" + activity.Id;
if (activity.HttpInfo != null)
{
#line default
#line hidden
WriteLiteral(" \t<td><a");
BeginWriteAttribute("href", " href=\"", 6313, "\"", 6333, 1);
#line 178 "LogPage.cshtml"
WriteAttributeValue("", 6320, activityPath, 6320, 13, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 6334, "\"", 6365, 1);
#line 178 "LogPage.cshtml"
WriteAttributeValue("", 6342, activity.HttpInfo.Path, 6342, 23, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 178 "LogPage.cshtml"
Write(activity.HttpInfo.Path);
#line default
#line hidden
WriteLiteral("</a></td>\r\n <td>");
#line 179 "LogPage.cshtml"
Write(activity.HttpInfo.Method);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 180 "LogPage.cshtml"
Write(activity.HttpInfo.Host);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 181 "LogPage.cshtml"
Write(activity.HttpInfo.StatusCode);
#line default
#line hidden
WriteLiteral("</td>\r\n");
#line 182 "LogPage.cshtml"
}
else if (activity.RepresentsScope)
{
#line default
#line hidden
WriteLiteral(" <td colspan=\"4\"><a");
BeginWriteAttribute("href", " href=\"", 6755, "\"", 6775, 1);
#line 185 "LogPage.cshtml"
WriteAttributeValue("", 6762, activityPath, 6762, 13, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 6776, "\"", 6804, 1);
#line 185 "LogPage.cshtml"
WriteAttributeValue("", 6784, activity.Root.State, 6784, 20, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 185 "LogPage.cshtml"
Write(activity.Root.State);
#line default
#line hidden
WriteLiteral("</a></td>\r\n");
#line 186 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <td colspan=\"4\"><a");
BeginWriteAttribute("href", " href=\"", 6967, "\"", 6987, 1);
#line 189 "LogPage.cshtml"
WriteAttributeValue("", 6974, activityPath, 6974, 13, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">Non-scope Log</a></td>\r\n");
#line 190 "LogPage.cshtml"
}
#line default
#line hidden
WriteLiteral(@" <td class=""logTd"">
<table class=""logTable"">
<thead class=""logHeader"">
<tr class=""headerRow"">
<th class=""date"">Date</th>
<th class=""time"">Time</th>
<th class=""name"">Name</th>
<th class=""severity"">Severity</th>
<th class=""state"">State</th>
<th>Error<span class=""collapse"">^</span></th>
</tr>
</thead>
");
#line 204 "LogPage.cshtml"
#line default
#line hidden
#line 204 "LogPage.cshtml"
var counts = new Dictionary<string, int>();
counts["Critical"] = 0;
counts["Error"] = 0;
counts["Warning"] = 0;
counts["Information"] = 0;
counts["Debug"] = 0;
#line default
#line hidden
WriteLiteral(" <tbody class=\"logBody\">\r\n");
#line 213 "LogPage.cshtml"
#line default
#line hidden
#line 213 "LogPage.cshtml"
if (!activity.RepresentsScope)
{
// message not within a scope
var logInfo = activity.Root.Messages.FirstOrDefault();
#line default
#line hidden
#line 217 "LogPage.cshtml"
Write(LogRow(logInfo, 0));
#line default
#line hidden
#line 217 "LogPage.cshtml"
counts[logInfo.Severity.ToString()] = 1;
}
else
{
#line default
#line hidden
#line 222 "LogPage.cshtml"
Write(Traverse(activity.Root, 0, counts));
#line default
#line hidden
#line 222 "LogPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n <tbody class=\"summary\">\r\n <tr class=\"logRow\">\r\n <td>");
#line 227 "LogPage.cshtml"
Write(activity.Time.ToString("MM-dd-yyyy HH:mm:ss"));
#line default
#line hidden
WriteLiteral("</td>\r\n");
#line 228 "LogPage.cshtml"
#line default
#line hidden
#line 228 "LogPage.cshtml"
foreach (var kvp in counts)
{
if (string.Equals("Debug", kvp.Key)) {
#line default
#line hidden
WriteLiteral(" <td>");
#line 231 "LogPage.cshtml"
Write(kvp.Value);
#line default
#line hidden
WriteLiteral(" ");
#line 231 "LogPage.cshtml"
Write(kvp.Key);
#line default
#line hidden
WriteLiteral("<span class=\"collapse\">v</span></td>\r\n");
#line 232 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <td>");
#line 235 "LogPage.cshtml"
Write(kvp.Value);
#line default
#line hidden
WriteLiteral(" ");
#line 235 "LogPage.cshtml"
Write(kvp.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n");
#line 236 "LogPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </tr>\r\n </tbody>\r\n </table>\r\n </td>\r\n </tr>\r\n </tbody>\r\n");
#line 244 "LogPage.cshtml"
}
#line default
#line hidden
WriteLiteral(@" </table>
<script type=""text/javascript"">
$(document).ready(function () {
$("".logBody"").hide();
$("".logTable > thead"").hide();
$("".logTable > thead"").click(function () {
$(this).closest("".logTable"").find(""tbody"").hide();
$(this).closest("".logTable"").find("".summary"").show();
$(this).hide();
});
$("".logTable > .summary"").click(function () {
$(this).closest("".logTable"").find(""tbody"").show();
$(this).closest("".logTable"").find(""thead"").show();
$(this).hide();
});
});
</script>
</body>
</html>");
}
#pragma warning restore 1998
}
}

View File

@ -1,263 +0,0 @@
@using System
@using System.Collections.Generic
@using System.Globalization
@using System.Linq
@using Microsoft.AspNetCore.Diagnostics.Elm
@using Microsoft.AspNetCore.Diagnostics.Elm.Views
@using Microsoft.AspNetCore.DiagnosticsViewPage.Views
@using Microsoft.Extensions.Logging
@functions
{
public LogPage(LogPageModel model)
{
Model = model;
}
public LogPageModel Model { get; set; }
public HelperResult LogRow(LogInfo log, int level)
{
return new HelperResult((writer) =>
{
if (log.Severity >= Model.Options.MinLevel &&
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
{
WriteLiteralTo(writer, " <tr class=\"logRow\">\r\n <td>");
WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteralTo(writer, "</td>\r\n <td>");
WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time));
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Name}\">");
WriteTo(writer, log.Name);
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteralTo(writer, $"</td>\r\n <td class=\"{severity}\">");
WriteTo(writer, log.Severity);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Message}\"> \r\n");
for (var i = 0; i < level; i++)
{
WriteLiteralTo(writer, " <span class=\"tab\"></span>\r\n");
}
WriteLiteralTo(writer, " ");
WriteTo(writer, log.Message);
WriteLiteralTo(writer, $"\r\n </td>\r\n <td title=\"{log.Exception}\">");
WriteTo(writer, log.Exception);
WriteLiteralTo(writer, "</td>\r\n </tr>\r\n");
}
});
}
public HelperResult Traverse(ScopeNode node, int level, Dictionary<string, int> counts)
{
return new HelperResult((writer) => {
// print start of scope
WriteTo(writer, LogRow(new LogInfo()
{
Name = node.Name,
Time = node.StartTime,
Severity = LogLevel.Debug,
Message = "Beginning " + node.State,
}, level));
var messageIndex = 0;
var childIndex = 0;
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
{
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
{
WriteTo(writer, LogRow(node.Messages[messageIndex], level));
counts[node.Messages[messageIndex].Severity.ToString()]++;
messageIndex++;
}
else
{
WriteTo(writer, Traverse(node.Children[childIndex], level + 1, counts));
childIndex++;
}
}
if (messageIndex < node.Messages.Count)
{
for (var i = messageIndex; i < node.Messages.Count; i++)
{
WriteTo(writer, LogRow(node.Messages[i], level));
counts[node.Messages[i].Severity.ToString()]++;
}
}
else
{
for (var i = childIndex; i < node.Children.Count; i++)
{
WriteTo(writer, Traverse(node.Children[i], level + 1, counts));
}
}
// print end of scope
WriteTo(writer, LogRow(new LogInfo()
{
Name = node.Name,
Time = node.EndTime,
Severity = LogLevel.Debug,
Message = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime)
}, level));
});
}
}
@{
Response.ContentType = "text/html";
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core Logs</title>
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js"></script>
<style>
<%$ include: LogPage.css %>
<%$ include: Shared.css %>
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
<form id="viewOptions" method="get">
<select name="level">
@foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
<option value="@severityInt" selected="selected">@severity</option>
}
else
{
<option value="@severityInt">@severity</option>
}
}
</select>
<input type="text" name="name" value="@Model.Options.NamePrefix" />
<input type="submit" value="filter" />
</form>
<form id="clear" method="post" action="">
<button type="submit" name="clear" value="1">Clear Logs</button>
</form>
<table id="requestTable">
<thead id="requestHeader">
<tr>
<th class="path">Path</th>
<th class="method">Method</th>
<th class="host">Host</th>
<th class="statusCode">Status Code</th>
<th class="logs">Logs</th>
</tr>
</thead>
<colgroup>
<col />
<col />
<col />
<col />
<col />
</colgroup>
@foreach (var activity in Model.Activities.Reverse())
{
<tbody>
<tr class="requestRow">
@{
var activityPath = Model.Path.Value + "/" + activity.Id;
if (activity.HttpInfo != null)
{
<td><a href="@activityPath" title="@activity.HttpInfo.Path">@activity.HttpInfo.Path</a></td>
<td>@activity.HttpInfo.Method</td>
<td>@activity.HttpInfo.Host</td>
<td>@activity.HttpInfo.StatusCode</td>
}
else if (activity.RepresentsScope)
{
<td colspan="4"><a href="@activityPath" title="@activity.Root.State">@activity.Root.State</a></td>
}
else
{
<td colspan="4"><a href="@activityPath">Non-scope Log</a></td>
}
}
<td class="logTd">
<table class="logTable">
<thead class="logHeader">
<tr class="headerRow">
<th class="date">Date</th>
<th class="time">Time</th>
<th class="name">Name</th>
<th class="severity">Severity</th>
<th class="state">State</th>
<th>Error<span class="collapse">^</span></th>
</tr>
</thead>
@{
var counts = new Dictionary<string, int>();
counts["Critical"] = 0;
counts["Error"] = 0;
counts["Warning"] = 0;
counts["Information"] = 0;
counts["Debug"] = 0;
}
<tbody class="logBody">
@if (!activity.RepresentsScope)
{
// message not within a scope
var logInfo = activity.Root.Messages.FirstOrDefault();
@LogRow(logInfo, 0)
counts[logInfo.Severity.ToString()] = 1;
}
else
{
@Traverse(activity.Root, 0, counts)
}
</tbody>
<tbody class="summary">
<tr class="logRow">
<td>@activity.Time.ToString("MM-dd-yyyy HH:mm:ss")</td>
@foreach (var kvp in counts)
{
if (string.Equals("Debug", kvp.Key)) {
<td>@kvp.Value @kvp.Key<span class="collapse">v</span></td>
}
else
{
<td>@kvp.Value @kvp.Key</td>
}
}
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
}
</table>
<script type="text/javascript">
$(document).ready(function () {
$(".logBody").hide();
$(".logTable > thead").hide();
$(".logTable > thead").click(function () {
$(this).closest(".logTable").find("tbody").hide();
$(this).closest(".logTable").find(".summary").show();
$(this).hide();
});
$(".logTable > .summary").click(function () {
$(this).closest(".logTable").find("tbody").show();
$(this).closest(".logTable").find("thead").show();
$(this).hide();
});
});
</script>
</body>
</html>

View File

@ -1,110 +0,0 @@
body {
font-size: .813em;
white-space: nowrap;
margin: 20px;
}
col:nth-child(2n) {
background-color: #FAFAFA;
}
form {
display: inline-block;
}
h1 {
margin-left: 25px;
}
table {
margin: 0px auto;
border-collapse: collapse;
border-spacing: 0px;
table-layout: fixed;
width: 100%;
}
td, th {
padding: 4px;
}
thead {
font-size: 1em;
font-family: Arial;
}
tr {
height: 23px;
}
#requestHeader {
border-bottom: solid 1px gray;
border-top: solid 1px gray;
margin-bottom: 2px;
font-size: 1em;
line-height: 2em;
}
.collapse {
color: black;
float: right;
font-weight: normal;
width: 1em;
}
.date, .time {
width: 70px;
}
.logHeader {
border-bottom: 1px solid lightgray;
color: gray;
text-align: left;
}
.logState {
text-overflow: ellipsis;
overflow: hidden;
}
.logTd {
border-left: 1px solid gray;
padding: 0px;
}
.logs {
width: 80%;
}
.logRow:hover {
background-color: #D6F5FF;
}
.requestRow>td {
border-bottom: solid 1px gray;
}
.severity {
width: 80px;
}
.summary {
color: black;
line-height: 1.8em;
}
.summary>th {
font-weight: normal;
}
.tab {
margin-left: 30px;
}
#viewOptions {
margin: 20px;
}
#viewOptions > * {
margin: 5px;
}

View File

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Diagnostics.Elm.Views
{
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class LogPageModel
{
public IEnumerable<ActivityContext> Activities { get; set; }
public ViewOptions Options { get; set; }
public PathString Path { get; set; }
}
}

View File

@ -1,39 +0,0 @@
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif;
line-height: 1.4em;
}
h1 {
font-family: 'Segoe UI', Helvetica, sans-serif;
font-size: 2.5em;
}
td {
text-overflow: ellipsis;
overflow: hidden;
}
tr:nth-child(2n) {
background-color: #F6F6F6;
}
.critical {
background-color: red;
color: white;
}
.error {
color: red;
}
.information {
color: blue;
}
.debug {
color: black;
}
.warning {
color: orange;
}

View File

@ -1,39 +0,0 @@
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif;
line-height: 1.4em;
}
h1 {
font-family: 'Segoe UI', Helvetica, sans-serif;
font-size: 2.5em;
}
td {
text-overflow: ellipsis;
overflow: hidden;
}
tr:nth-child(2n) {
background-color: #F6F6F6;
}
.critical {
background-color: red;
color: white;
}
.error {
color: red;
}
.information {
color: blue;
}
.debug {
color: black;
}
.warning {
color: orange;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core middleware for exception handling, exception display pages, and diagnostics information. Includes developer exception page middleware, exception handler middleware, runtime info middleware, status code page middleware, and welcome page middleware</Description>
<TargetFramework>netcoreapp3.0</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;diagnostics</PackageTags>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\shared\**\*.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.Diagnostics.Abstractions\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="$(MicrosoftAspNetCoreHttpExtensionsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="$(MicrosoftAspNetCoreWebUtilitiesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="$(MicrosoftExtensionsFileProvidersPhysicalPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsOptionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.RazorViews.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsRazorViewsSourcesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.StackTrace.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsStackTraceSourcesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.TypeNameHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsTypeNameHelperSourcesPackageVersion)" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,13 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
public sealed class HealthCheckContext
{
/// <summary>
/// Gets or sets the <see cref="HealthCheckRegistration"/> of the currently executing <see cref="IHealthCheck"/>.
/// </summary>
public HealthCheckRegistration Registration { get; set; }
}
}

View File

@ -1,132 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Represent the registration information associated with an <see cref="IHealthCheck"/> implementation.
/// </summary>
/// <remarks>
/// <para>
/// The health check registration is provided as a separate object so that application developers can customize
/// how health check implementations are configured.
/// </para>
/// <para>
/// The registration is provided to an <see cref="IHealthCheck"/> implementation during execution through
/// <see cref="HealthCheckContext.Registration"/>. This allows a health check implementation to access named
/// options or perform other operations based on the registered name.
/// </para>
/// </remarks>
public sealed class HealthCheckRegistration
{
private Func<IServiceProvider, IHealthCheck> _factory;
private string _name;
/// <summary>
/// Creates a new <see cref="HealthCheckRegistration"/> for an existing <see cref="IHealthCheck"/> instance.
/// </summary>
/// <param name="name">The health check name.</param>
/// <param name="instance">The <see cref="IHealthCheck"/> instance.</param>
/// <param name="failureStatus">
/// The <see cref="HealthStatus"/> that should be reported upon failure of the health check. If the provided value
/// is <c>null</c>, then <see cref="HealthStatus.Unhealthy"/> will be reported.
/// </param>
/// <param name="tags">A list of tags that can be used for filtering health checks.</param>
public HealthCheckRegistration(string name, IHealthCheck instance, HealthStatus? failureStatus, IEnumerable<string> tags)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
Name = name;
FailureStatus = failureStatus ?? HealthStatus.Unhealthy;
Tags = new HashSet<string>(tags ?? Array.Empty<string>(), StringComparer.OrdinalIgnoreCase);
Factory = (_) => instance;
}
/// <summary>
/// Creates a new <see cref="HealthCheckRegistration"/> for an existing <see cref="IHealthCheck"/> instance.
/// </summary>
/// <param name="name">The health check name.</param>
/// <param name="factory">A delegate used to create the <see cref="IHealthCheck"/> instance.</param>
/// <param name="failureStatus">
/// The <see cref="HealthStatus"/> that should be reported when the health check reports a failure. If the provided value
/// is <c>null</c>, then <see cref="HealthStatus.Unhealthy"/> will be reported.
/// </param>
/// <param name="tags">A list of tags that can be used for filtering health checks.</param>
public HealthCheckRegistration(
string name,
Func<IServiceProvider, IHealthCheck> factory,
HealthStatus? failureStatus,
IEnumerable<string> tags)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (factory == null)
{
throw new ArgumentNullException(nameof(factory));
}
Name = name;
FailureStatus = failureStatus ?? HealthStatus.Unhealthy;
Tags = new HashSet<string>(tags ?? Array.Empty<string>(), StringComparer.OrdinalIgnoreCase);
Factory = factory;
}
/// <summary>
/// Gets or sets a delegate used to create the <see cref="IHealthCheck"/> instance.
/// </summary>
public Func<IServiceProvider, IHealthCheck> Factory
{
get => _factory;
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_factory = value;
}
}
/// <summary>
/// Gets or sets the <see cref="HealthStatus"/> that should be reported upon failure of the health check.
/// </summary>
public HealthStatus FailureStatus { get; set; }
/// <summary>
/// Gets or sets the health check name.
/// </summary>
public string Name
{
get => _name;
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_name = value;
}
}
/// <summary>
/// Gets a list of tags that can be used for filtering health checks.
/// </summary>
public ISet<string> Tags { get; }
}
}

View File

@ -1,88 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Represents the result of a health check.
/// </summary>
public struct HealthCheckResult
{
private static readonly IReadOnlyDictionary<string, object> _emptyReadOnlyDictionary = new Dictionary<string, object>();
/// <summary>
/// Creates a new <see cref="HealthCheckResult"/> with the specified values for <paramref name="status"/>,
/// <paramref name="exception"/>, <paramref name="description"/>, and <paramref name="data"/>.
/// </summary>
/// <param name="status">A value indicating the status of the component that was checked.</param>
/// <param name="description">A human-readable description of the status of the component that was checked.</param>
/// <param name="exception">An <see cref="Exception"/> representing the exception that was thrown when checking for status (if any).</param>
/// <param name="data">Additional key-value pairs describing the health of the component.</param>
public HealthCheckResult(HealthStatus status, string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null)
{
Status = status;
Description = description;
Exception = exception;
Data = data ?? _emptyReadOnlyDictionary;
}
/// <summary>
/// Gets additional key-value pairs describing the health of the component.
/// </summary>
public IReadOnlyDictionary<string, object> Data { get; }
/// <summary>
/// Gets a human-readable description of the status of the component that was checked.
/// </summary>
public string Description { get; }
/// <summary>
/// Gets an <see cref="Exception"/> representing the exception that was thrown when checking for status (if any).
/// </summary>
public Exception Exception { get; }
/// <summary>
/// Gets a value indicating the status of the component that was checked.
/// </summary>
public HealthStatus Status { get; }
/// <summary>
/// Creates a <see cref="HealthCheckResult"/> representing a healthy component.
/// </summary>
/// <param name="description">A human-readable description of the status of the component that was checked. Optional.</param>
/// <param name="data">Additional key-value pairs describing the health of the component. Optional.</param>
/// <returns>A <see cref="HealthCheckResult"/> representing a healthy component.</returns>
public static HealthCheckResult Healthy(string description = null, IReadOnlyDictionary<string, object> data = null)
{
return new HealthCheckResult(status: HealthStatus.Healthy, description, exception: null, data);
}
/// <summary>
/// Creates a <see cref="HealthCheckResult"/> representing a degraded component.
/// </summary>
/// <param name="description">A human-readable description of the status of the component that was checked. Optional.</param>
/// <param name="exception">An <see cref="Exception"/> representing the exception that was thrown when checking for status. Optional.</param>
/// <param name="data">Additional key-value pairs describing the health of the component. Optional.</param>
/// <returns>A <see cref="HealthCheckResult"/> representing a degraged component.</returns>
public static HealthCheckResult Degraded(string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null)
{
return new HealthCheckResult(status: HealthStatus.Degraded, description, exception: null, data);
}
/// <summary>
/// Creates a <see cref="HealthCheckResult"/> representing an unhealthy component.
/// </summary>
/// <param name="description">A human-readable description of the status of the component that was checked. Optional.</param>
/// <param name="exception">An <see cref="Exception"/> representing the exception that was thrown when checking for status. Optional.</param>
/// <param name="data">Additional key-value pairs describing the health of the component. Optional.</param>
/// <returns>A <see cref="HealthCheckResult"/> representing an unhealthy component.</returns>
public static HealthCheckResult Unhealthy(string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null)
{
return new HealthCheckResult(status: HealthStatus.Unhealthy, description, exception, data);
}
}
}

View File

@ -1,68 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Represents the result of executing a group of <see cref="IHealthCheck"/> instances.
/// </summary>
public sealed class HealthReport
{
/// <summary>
/// Create a new <see cref="HealthReport"/> from the specified results.
/// </summary>
/// <param name="entries">A <see cref="IReadOnlyDictionary{TKey, T}"/> containing the results from each health check.</param>
/// <param name="totalDuration">A value indicating the time the health check service took to execute.</param>
public HealthReport(IReadOnlyDictionary<string, HealthReportEntry> entries, TimeSpan totalDuration)
{
Entries = entries;
Status = CalculateAggregateStatus(entries.Values);
TotalDuration = totalDuration;
}
/// <summary>
/// A <see cref="IReadOnlyDictionary{TKey, T}"/> containing the results from each health check.
/// </summary>
/// <remarks>
/// The keys in this dictionary map the name of each executed health check to a <see cref="HealthReportEntry"/> for the
/// result data retruned from the corresponding health check.
/// </remarks>
public IReadOnlyDictionary<string, HealthReportEntry> Entries { get; }
/// <summary>
/// Gets a <see cref="HealthStatus"/> representing the aggregate status of all the health checks. The value of <see cref="Status"/>
/// will be the most servere status reported by a health check. If no checks were executed, the value is always <see cref="HealthStatus.Healthy"/>.
/// </summary>
public HealthStatus Status { get; }
/// <summary>
/// Gets the time the health check service took to execute.
/// </summary>
public TimeSpan TotalDuration { get; }
private HealthStatus CalculateAggregateStatus(IEnumerable<HealthReportEntry> entries)
{
// This is basically a Min() check, but we know the possible range, so we don't need to walk the whole list
var currentValue = HealthStatus.Healthy;
foreach (var entry in entries)
{
if (currentValue > entry.Status)
{
currentValue = entry.Status;
}
if (currentValue == HealthStatus.Unhealthy)
{
// Game over, man! Game over!
// (We hit the worst possible status, so there's no need to keep iterating)
return currentValue;
}
}
return currentValue;
}
}
}

View File

@ -1,59 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Represents an entry in a <see cref="HealthReport"/>. Corresponds to the result of a single <see cref="IHealthCheck"/>.
/// </summary>
public struct HealthReportEntry
{
private static readonly IReadOnlyDictionary<string, object> _emptyReadOnlyDictionary = new Dictionary<string, object>();
/// <summary>
/// Creates a new <see cref="HealthReportEntry"/> with the specified values for <paramref name="status"/>, <paramref name="exception"/>,
/// <paramref name="description"/>, and <paramref name="data"/>.
/// </summary>
/// <param name="status">A value indicating the health status of the component that was checked.</param>
/// <param name="description">A human-readable description of the status of the component that was checked.</param>
/// <param name="duration">A value indicating the health execution duration.</param>
/// <param name="exception">An <see cref="Exception"/> representing the exception that was thrown when checking for status (if any).</param>
/// <param name="data">Additional key-value pairs describing the health of the component.</param>
public HealthReportEntry(HealthStatus status, string description, TimeSpan duration, Exception exception, IReadOnlyDictionary<string, object> data)
{
Status = status;
Description = description;
Duration = duration;
Exception = exception;
Data = data ?? _emptyReadOnlyDictionary;
}
/// <summary>
/// Gets additional key-value pairs describing the health of the component.
/// </summary>
public IReadOnlyDictionary<string, object> Data { get; }
/// <summary>
/// Gets a human-readable description of the status of the component that was checked.
/// </summary>
public string Description { get; }
/// <summary>
/// Gets the health check execution duration.
/// </summary>
public TimeSpan Duration { get; }
/// <summary>
/// Gets an <see cref="System.Exception"/> representing the exception that was thrown when checking for status (if any).
/// </summary>
public Exception Exception { get; }
/// <summary>
/// Gets the health status of the component that was checked.
/// </summary>
public HealthStatus Status { get; }
}
}

View File

@ -1,37 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Represents the reported status of a health check result.
/// </summary>
/// <remarks>
/// <para>
/// A status of <see cref="Unhealthy"/> should be considered the default value for a failing health check. Application
/// developers may configure a health check to report a different status as desired.
/// </para>
/// <para>
/// The values of this enum or ordered from least healthy to most healthy. So <see cref="HealthStatus.Degraded"/> is
/// greater than <see cref="HealthStatus.Unhealthy"/> but less than <see cref="HealthStatus.Healthy"/>.
/// </para>
/// </remarks>
public enum HealthStatus
{
/// <summary>
/// Indicates that the health check determined that the component was unhealthy, or an unhandled
/// exception was thrown while executing the health check.
/// </summary>
Unhealthy = 0,
/// <summary>
/// Indicates that the health check determined that the component was in a degraded state.
/// </summary>
Degraded = 1,
/// <summary>
/// Indicates that the health check determined that the component was healthy.
/// </summary>
Healthy = 2,
}
}

View File

@ -1,23 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Represents a health check, which can be used to check the status of a component in the application, such as a backend service, database or some internal
/// state.
/// </summary>
public interface IHealthCheck
{
/// <summary>
/// Runs the health check, returning the status of the component being checked.
/// </summary>
/// <param name="context">A context object associated with the current execution.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the health check.</param>
/// <returns>A <see cref="Task{HealthCheckResult}"/> that completes when the health check has finished, yielding the status of the component being checked.</returns>
Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default);
}
}

View File

@ -1,39 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Represents a publisher of <see cref="HealthReport"/> information.
/// </summary>
/// <remarks>
/// <para>
/// The default health checks implementation provided an <c>IHostedService</c> implementation that can
/// be used to execute health checks at regular intervals and provide the resulting <see cref="HealthReport"/>
/// data to all registered <see cref="IHealthCheckPublisher"/> instances.
/// </para>
/// <para>
/// To provide an <see cref="IHealthCheckPublisher"/> implementation, register an instance or type as a singleton
/// service in the dependency injection container.
/// </para>
/// <para>
/// <see cref="IHealthCheckPublisher"/> instances are provided with a <see cref="HealthReport"/> after executing
/// health checks in a background thread. The use of <see cref="IHealthCheckPublisher"/> depend on hosting in
/// an application using <c>IWebHost</c> or generic host (<c>IHost</c>). Execution of <see cref="IHealthCheckPublisher"/>
/// instance is not related to execution of health checks via a middleware.
/// </para>
/// </remarks>
public interface IHealthCheckPublisher
{
/// <summary>
/// Publishes the provided <paramref name="report"/>.
/// </summary>
/// <param name="report">The <see cref="HealthReport"/>. The result of executing a set of health checks.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
/// <returns>A <see cref="Task"/> which will complete when publishing is complete.</returns>
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Abstractions for defining health checks in .NET applications
Commonly Used Types
Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck
</Description>
<RootNamespace>Microsoft.Extensions.Diagnostics.HealthChecks</RootNamespace>
<TargetFramework>netstandard2.0</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>diagnostics;healthchecks</PackageTags>
</PropertyGroup>
</Project>

View File

@ -1,5 +0,0 @@
{
"AssemblyIdentity": "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
"Types": [
]
}

View File

@ -1,304 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
internal class DefaultHealthCheckService : HealthCheckService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IOptions<HealthCheckServiceOptions> _options;
private readonly ILogger<DefaultHealthCheckService> _logger;
public DefaultHealthCheckService(
IServiceScopeFactory scopeFactory,
IOptions<HealthCheckServiceOptions> options,
ILogger<DefaultHealthCheckService> logger)
{
_scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
_options = options ?? throw new ArgumentNullException(nameof(options));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
// We're specifically going out of our way to do this at startup time. We want to make sure you
// get any kind of health-check related error as early as possible. Waiting until someone
// actually tries to **run** health checks would be real baaaaad.
ValidateRegistrations(_options.Value.Registrations);
}
public override async Task<HealthReport> CheckHealthAsync(
Func<HealthCheckRegistration, bool> predicate,
CancellationToken cancellationToken = default)
{
var registrations = _options.Value.Registrations;
using (var scope = _scopeFactory.CreateScope())
{
var context = new HealthCheckContext();
var entries = new Dictionary<string, HealthReportEntry>(StringComparer.OrdinalIgnoreCase);
var totalTime = ValueStopwatch.StartNew();
Log.HealthCheckProcessingBegin(_logger);
foreach (var registration in registrations)
{
if (predicate != null && !predicate(registration))
{
continue;
}
cancellationToken.ThrowIfCancellationRequested();
var healthCheck = registration.Factory(scope.ServiceProvider);
// If the health check does things like make Database queries using EF or backend HTTP calls,
// it may be valuable to know that logs it generates are part of a health check. So we start a scope.
using (_logger.BeginScope(new HealthCheckLogScope(registration.Name)))
{
var stopwatch = ValueStopwatch.StartNew();
context.Registration = registration;
Log.HealthCheckBegin(_logger, registration);
HealthReportEntry entry;
try
{
var result = await healthCheck.CheckHealthAsync(context, cancellationToken);
var duration = stopwatch.GetElapsedTime();
entry = new HealthReportEntry(
status: result.Status,
description: result.Description,
duration: duration,
exception: result.Exception,
data: result.Data);
Log.HealthCheckEnd(_logger, registration, entry, duration);
Log.HealthCheckData(_logger, registration, entry);
}
// Allow cancellation to propagate.
catch (Exception ex) when (ex as OperationCanceledException == null)
{
var duration = stopwatch.GetElapsedTime();
entry = new HealthReportEntry(
status: HealthStatus.Unhealthy,
description: ex.Message,
duration: duration,
exception: ex,
data: null);
Log.HealthCheckError(_logger, registration, ex, duration);
}
entries[registration.Name] = entry;
}
}
var totalElapsedTime = totalTime.GetElapsedTime();
var report = new HealthReport(entries, totalElapsedTime);
Log.HealthCheckProcessingEnd(_logger, report.Status, totalElapsedTime);
return report;
}
}
private static void ValidateRegistrations(IEnumerable<HealthCheckRegistration> registrations)
{
// Scan the list for duplicate names to provide a better error if there are duplicates.
var duplicateNames = registrations
.GroupBy(c => c.Name, StringComparer.OrdinalIgnoreCase)
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();
if (duplicateNames.Count > 0)
{
throw new ArgumentException($"Duplicate health checks were registered with the name(s): {string.Join(", ", duplicateNames)}", nameof(registrations));
}
}
internal static class EventIds
{
public static readonly EventId HealthCheckProcessingBegin = new EventId(100, "HealthCheckProcessingBegin");
public static readonly EventId HealthCheckProcessingEnd = new EventId(101, "HealthCheckProcessingEnd");
public static readonly EventId HealthCheckBegin = new EventId(102, "HealthCheckBegin");
public static readonly EventId HealthCheckEnd = new EventId(103, "HealthCheckEnd");
public static readonly EventId HealthCheckError = new EventId(104, "HealthCheckError");
public static readonly EventId HealthCheckData = new EventId(105, "HealthCheckData");
}
private static class Log
{
private static readonly Action<ILogger, Exception> _healthCheckProcessingBegin = LoggerMessage.Define(
LogLevel.Debug,
EventIds.HealthCheckProcessingBegin,
"Running health checks");
private static readonly Action<ILogger, double, HealthStatus, Exception> _healthCheckProcessingEnd = LoggerMessage.Define<double, HealthStatus>(
LogLevel.Debug,
EventIds.HealthCheckProcessingEnd,
"Health check processing completed after {ElapsedMilliseconds}ms with combined status {HealthStatus}");
private static readonly Action<ILogger, string, Exception> _healthCheckBegin = LoggerMessage.Define<string>(
LogLevel.Debug,
EventIds.HealthCheckBegin,
"Running health check {HealthCheckName}");
// These are separate so they can have different log levels
private static readonly string HealthCheckEndText = "Health check {HealthCheckName} completed after {ElapsedMilliseconds}ms with status {HealthStatus} and '{HealthCheckDescription}'";
private static readonly Action<ILogger, string, double, HealthStatus, string, Exception> _healthCheckEndHealthy = LoggerMessage.Define<string, double, HealthStatus, string>(
LogLevel.Debug,
EventIds.HealthCheckEnd,
HealthCheckEndText);
private static readonly Action<ILogger, string, double, HealthStatus, string, Exception> _healthCheckEndDegraded = LoggerMessage.Define<string, double, HealthStatus, string>(
LogLevel.Warning,
EventIds.HealthCheckEnd,
HealthCheckEndText);
private static readonly Action<ILogger, string, double, HealthStatus, string, Exception> _healthCheckEndUnhealthy = LoggerMessage.Define<string, double, HealthStatus, string>(
LogLevel.Error,
EventIds.HealthCheckEnd,
HealthCheckEndText);
private static readonly Action<ILogger, string, double, HealthStatus, string, Exception> _healthCheckEndFailed = LoggerMessage.Define<string, double, HealthStatus, string>(
LogLevel.Error,
EventIds.HealthCheckEnd,
HealthCheckEndText);
private static readonly Action<ILogger, string, double, Exception> _healthCheckError = LoggerMessage.Define<string, double>(
LogLevel.Error,
EventIds.HealthCheckError,
"Health check {HealthCheckName} threw an unhandled exception after {ElapsedMilliseconds}ms");
public static void HealthCheckProcessingBegin(ILogger logger)
{
_healthCheckProcessingBegin(logger, null);
}
public static void HealthCheckProcessingEnd(ILogger logger, HealthStatus status, TimeSpan duration)
{
_healthCheckProcessingEnd(logger, duration.TotalMilliseconds, status, null);
}
public static void HealthCheckBegin(ILogger logger, HealthCheckRegistration registration)
{
_healthCheckBegin(logger, registration.Name, null);
}
public static void HealthCheckEnd(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry, TimeSpan duration)
{
switch (entry.Status)
{
case HealthStatus.Healthy:
_healthCheckEndHealthy(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
break;
case HealthStatus.Degraded:
_healthCheckEndDegraded(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
break;
case HealthStatus.Unhealthy:
_healthCheckEndUnhealthy(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
break;
}
}
public static void HealthCheckError(ILogger logger, HealthCheckRegistration registration, Exception exception, TimeSpan duration)
{
_healthCheckError(logger, registration.Name, duration.TotalMilliseconds, exception);
}
public static void HealthCheckData(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry)
{
if (entry.Data.Count > 0 && logger.IsEnabled(LogLevel.Debug))
{
logger.Log(
LogLevel.Debug,
EventIds.HealthCheckData,
new HealthCheckDataLogValue(registration.Name, entry.Data),
null,
(state, ex) => state.ToString());
}
}
}
internal class HealthCheckDataLogValue : IReadOnlyList<KeyValuePair<string, object>>
{
private readonly string _name;
private readonly List<KeyValuePair<string, object>> _values;
private string _formatted;
public HealthCheckDataLogValue(string name, IReadOnlyDictionary<string, object> values)
{
_name = name;
_values = values.ToList();
// We add the name as a kvp so that you can filter by health check name in the logs.
// This is the same parameter name used in the other logs.
_values.Add(new KeyValuePair<string, object>("HealthCheckName", name));
}
public KeyValuePair<string, object> this[int index]
{
get
{
if (index < 0 || index >= Count)
{
throw new IndexOutOfRangeException(nameof(index));
}
return _values[index];
}
}
public int Count => _values.Count;
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return _values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _values.GetEnumerator();
}
public override string ToString()
{
if (_formatted == null)
{
var builder = new StringBuilder();
builder.AppendLine($"Health check data for {_name}:");
var values = _values;
for (var i = 0; i < values.Count; i++)
{
var kvp = values[i];
builder.Append(" ");
builder.Append(kvp.Key);
builder.Append(": ");
builder.AppendLine(kvp.Value?.ToString());
}
_formatted = builder.ToString();
}
return _formatted;
}
}
}
}

View File

@ -1,35 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// A simple implementation of <see cref="IHealthCheck"/> which uses a provided delegate to
/// implement the check.
/// </summary>
internal sealed class DelegateHealthCheck : IHealthCheck
{
private readonly Func<CancellationToken, Task<HealthCheckResult>> _check;
/// <summary>
/// Create an instance of <see cref="DelegateHealthCheck"/> from the specified delegate.
/// </summary>
/// <param name="check">A delegate which provides the code to execute when the health check is run.</param>
public DelegateHealthCheck(Func<CancellationToken, Task<HealthCheckResult>> check)
{
_check = check ?? throw new ArgumentNullException(nameof(check));
}
/// <summary>
/// Runs the health check, returning the status of the component being checked.
/// </summary>
/// <param name="context">A context object associated with the current execution.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the health check.</param>
/// <returns>A <see cref="Task{HealthCheckResult}"/> that completes when the health check has finished, yielding the status of the component being checked.</returns>
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) => _check(cancellationToken);
}
}

View File

@ -1,33 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Provides extension methods for registering <see cref="HealthCheckService"/> in an <see cref="IServiceCollection"/>.
/// </summary>
public static class HealthCheckServiceCollectionExtensions
{
/// <summary>
/// Adds the <see cref="HealthCheckService"/> to the container, using the provided delegate to register
/// health checks.
/// </summary>
/// <remarks>
/// This operation is idempotent - multiple invocations will still only result in a single
/// <see cref="HealthCheckService"/> instance in the <see cref="IServiceCollection"/>. It can be invoked
/// multiple times in order to get access to the <see cref="IHealthChecksBuilder"/> in multiple places.
/// </remarks>
/// <param name="services">The <see cref="IServiceCollection"/> to add the <see cref="HealthCheckService"/> to.</param>
/// <returns>An instance of <see cref="IHealthChecksBuilder"/> from which health checks can be registered.</returns>
public static IHealthChecksBuilder AddHealthChecks(this IServiceCollection services)
{
services.TryAddSingleton<HealthCheckService, DefaultHealthCheckService>();
services.TryAddSingleton<IHostedService, HealthCheckPublisherHostedService>();
return new HealthChecksBuilder(services);
}
}
}

View File

@ -1,33 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Microsoft.Extensions.DependencyInjection
{
internal class HealthChecksBuilder : IHealthChecksBuilder
{
public HealthChecksBuilder(IServiceCollection services)
{
Services = services;
}
public IServiceCollection Services { get; }
public IHealthChecksBuilder Add(HealthCheckRegistration registration)
{
if (registration == null)
{
throw new ArgumentNullException(nameof(registration));
}
Services.Configure<HealthCheckServiceOptions>(options =>
{
options.Registrations.Add(registration);
});
return this;
}
}
}

View File

@ -1,191 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Provides basic extension methods for registering <see cref="IHealthCheck"/> instances in an <see cref="IHealthChecksBuilder"/>.
/// </summary>
public static class HealthChecksBuilderAddCheckExtensions
{
/// <summary>
/// Adds a new health check with the specified name and implementation.
/// </summary>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="instance">An <see cref="IHealthCheck"/> instance.</param>
/// <param name="failureStatus">
/// The <see cref="HealthStatus"/> that should be reported when the health check reports a failure. If the provided value
/// is <c>null</c>, then <see cref="HealthStatus.Unhealthy"/> will be reported.
/// </param>
/// <param name="tags">A list of tags that can be used to filter health checks.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
public static IHealthChecksBuilder AddCheck(
this IHealthChecksBuilder builder,
string name,
IHealthCheck instance,
HealthStatus? failureStatus = null,
IEnumerable<string> tags = null)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
return builder.Add(new HealthCheckRegistration(name, instance, failureStatus, tags));
}
/// <summary>
/// Adds a new health check with the specified name and implementation.
/// </summary>
/// <typeparam name="T">The health check implementation type.</typeparam>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="failureStatus">
/// The <see cref="HealthStatus"/> that should be reported when the health check reports a failure. If the provided value
/// is <c>null</c>, then <see cref="HealthStatus.Unhealthy"/> will be reported.
/// </param>
/// <param name="tags">A list of tags that can be used to filter health checks.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
/// <remarks>
/// This method will use <see cref="ActivatorUtilities.GetServiceOrCreateInstance{T}(IServiceProvider)"/> to create the health check
/// instance when needed. If a service of type <typeparamref name="T"/> is registred in the dependency injection container
/// with any liftime it will be used. Otherwise an instance of type <typeparamref name="T"/> will be constructed with
/// access to services from the dependency injection container.
/// </remarks>
public static IHealthChecksBuilder AddCheck<T>(
this IHealthChecksBuilder builder,
string name,
HealthStatus? failureStatus = null,
IEnumerable<string> tags = null) where T : class, IHealthCheck
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return builder.Add(new HealthCheckRegistration(name, s => ActivatorUtilities.GetServiceOrCreateInstance<T>(s), failureStatus, tags));
}
// NOTE: AddTypeActivatedCheck has overloads rather than default parameters values, because default parameter values don't
// play super well with params.
/// <summary>
/// Adds a new type activated health check with the specified name and implementation.
/// </summary>
/// <typeparam name="T">The health check implementation type.</typeparam>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="args">Additional arguments to provide to the constructor.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
/// <remarks>
/// This method will use <see cref="ActivatorUtilities.CreateInstance{T}(IServiceProvider, object[])"/> to create the health check
/// instance when needed. Additional arguments can be provided to the constructor via <paramref name="args"/>.
/// </remarks>
public static IHealthChecksBuilder AddTypeActivatedCheck<T>(this IHealthChecksBuilder builder, string name, params object[] args) where T : class, IHealthCheck
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return AddTypeActivatedCheck<T>(builder, name, failureStatus: null, tags: null);
}
/// <summary>
/// Adds a new type activated health check with the specified name and implementation.
/// </summary>
/// <typeparam name="T">The health check implementation type.</typeparam>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="failureStatus">
/// The <see cref="HealthStatus"/> that should be reported when the health check reports a failure. If the provided value
/// is <c>null</c>, then <see cref="HealthStatus.Unhealthy"/> will be reported.
/// </param>
/// <param name="args">Additional arguments to provide to the constructor.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
/// <remarks>
/// This method will use <see cref="ActivatorUtilities.CreateInstance{T}(IServiceProvider, object[])"/> to create the health check
/// instance when needed. Additional arguments can be provided to the constructor via <paramref name="args"/>.
/// </remarks>
public static IHealthChecksBuilder AddTypeActivatedCheck<T>(
this IHealthChecksBuilder builder,
string name,
HealthStatus? failureStatus,
params object[] args) where T : class, IHealthCheck
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return AddTypeActivatedCheck<T>(builder, name, failureStatus, tags: null);
}
/// <summary>
/// Adds a new type activated health check with the specified name and implementation.
/// </summary>
/// <typeparam name="T">The health check implementation type.</typeparam>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="failureStatus">
/// The <see cref="HealthStatus"/> that should be reported when the health check reports a failure. If the provided value
/// is <c>null</c>, then <see cref="HealthStatus.Unhealthy"/> will be reported.
/// </param>
/// <param name="tags">A list of tags that can be used to filter health checks.</param>
/// <param name="args">Additional arguments to provide to the constructor.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
/// <remarks>
/// This method will use <see cref="ActivatorUtilities.CreateInstance{T}(IServiceProvider, object[])"/> to create the health check
/// instance when needed. Additional arguments can be provided to the constructor via <paramref name="args"/>.
/// </remarks>
public static IHealthChecksBuilder AddTypeActivatedCheck<T>(
this IHealthChecksBuilder builder,
string name,
HealthStatus? failureStatus,
IEnumerable<string> tags,
params object[] args) where T : class, IHealthCheck
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return builder.Add(new HealthCheckRegistration(name, s => ActivatorUtilities.CreateInstance<T>(s, args), failureStatus, tags));
}
}
}

View File

@ -1,149 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Provides extension methods for registering delegates with the <see cref="IHealthChecksBuilder"/>.
/// </summary>
public static class HealthChecksBuilderDelegateExtensions
{
/// <summary>
/// Adds a new health check with the specified name and implementation.
/// </summary>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="tags">A list of tags that can be used to filter health checks.</param>
/// <param name="check">A delegate that provides the health check implementation.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
public static IHealthChecksBuilder AddCheck(
this IHealthChecksBuilder builder,
string name,
Func<HealthCheckResult> check,
IEnumerable<string> tags = null)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (check == null)
{
throw new ArgumentNullException(nameof(check));
}
var instance = new DelegateHealthCheck((ct) => Task.FromResult(check()));
return builder.Add(new HealthCheckRegistration(name, instance, failureStatus: null, tags));
}
/// <summary>
/// Adds a new health check with the specified name and implementation.
/// </summary>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="tags">A list of tags that can be used to filter health checks.</param>
/// <param name="check">A delegate that provides the health check implementation.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
public static IHealthChecksBuilder AddCheck(
this IHealthChecksBuilder builder,
string name,
Func<CancellationToken, HealthCheckResult> check,
IEnumerable<string> tags = null)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (check == null)
{
throw new ArgumentNullException(nameof(check));
}
var instance = new DelegateHealthCheck((ct) => Task.FromResult(check(ct)));
return builder.Add(new HealthCheckRegistration(name, instance, failureStatus: null, tags));
}
/// <summary>
/// Adds a new health check with the specified name and implementation.
/// </summary>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="tags">A list of tags that can be used to filter health checks.</param>
/// <param name="check">A delegate that provides the health check implementation.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
public static IHealthChecksBuilder AddAsyncCheck(
this IHealthChecksBuilder builder,
string name,
Func<Task<HealthCheckResult>> check,
IEnumerable<string> tags = null)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (check == null)
{
throw new ArgumentNullException(nameof(check));
}
var instance = new DelegateHealthCheck((ct) => check());
return builder.Add(new HealthCheckRegistration(name, instance, failureStatus: null, tags));
}
/// <summary>
/// Adds a new health check with the specified name and implementation.
/// </summary>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="name">The name of the health check.</param>
/// <param name="tags">A list of tags that can be used to filter health checks.</param>
/// <param name="check">A delegate that provides the health check implementation.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
public static IHealthChecksBuilder AddAsyncCheck(
this IHealthChecksBuilder builder,
string name,
Func<CancellationToken, Task<HealthCheckResult>> check,
IEnumerable<string> tags = null)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (check == null)
{
throw new ArgumentNullException(nameof(check));
}
var instance = new DelegateHealthCheck((ct) => check(ct));
return builder.Add(new HealthCheckRegistration(name, instance, failureStatus: null, tags));
}
}
}

View File

@ -1,24 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// A builder used to register health checks.
/// </summary>
public interface IHealthChecksBuilder
{
/// <summary>
/// Adds a <see cref="HealthCheckRegistration"/> for a health check.
/// </summary>
/// <param name="registration">The <see cref="HealthCheckRegistration"/>.</param>
IHealthChecksBuilder Add(HealthCheckRegistration registration);
/// <summary>
/// Gets the <see cref="IServiceCollection"/> into which <see cref="IHealthCheck"/> instances should be registered.
/// </summary>
IServiceCollection Services { get; }
}
}

View File

@ -1,48 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
internal class HealthCheckLogScope : IReadOnlyList<KeyValuePair<string, object>>
{
public string HealthCheckName { get; }
int IReadOnlyCollection<KeyValuePair<string, object>>.Count { get; } = 1;
KeyValuePair<string, object> IReadOnlyList<KeyValuePair<string, object>>.this[int index]
{
get
{
if (index == 0)
{
return new KeyValuePair<string, object>(nameof(HealthCheckName), HealthCheckName);
}
throw new ArgumentOutOfRangeException(nameof(index));
}
}
/// <summary>
/// Creates a new instance of <see cref="HealthCheckLogScope"/> with the provided name.
/// </summary>
/// <param name="healthCheckName">The name of the health check being executed.</param>
public HealthCheckLogScope(string healthCheckName)
{
HealthCheckName = healthCheckName;
}
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
{
yield return new KeyValuePair<string, object>(nameof(HealthCheckName), HealthCheckName);
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<KeyValuePair<string, object>>)this).GetEnumerator();
}
}
}

View File

@ -1,262 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
internal sealed class HealthCheckPublisherHostedService : IHostedService
{
private readonly HealthCheckService _healthCheckService;
private readonly IOptions<HealthCheckPublisherOptions> _options;
private readonly ILogger _logger;
private readonly IHealthCheckPublisher[] _publishers;
private CancellationTokenSource _stopping;
private Timer _timer;
public HealthCheckPublisherHostedService(
HealthCheckService healthCheckService,
IOptions<HealthCheckPublisherOptions> options,
ILogger<HealthCheckPublisherHostedService> logger,
IEnumerable<IHealthCheckPublisher> publishers)
{
if (healthCheckService == null)
{
throw new ArgumentNullException(nameof(healthCheckService));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
if (publishers == null)
{
throw new ArgumentNullException(nameof(publishers));
}
_healthCheckService = healthCheckService;
_options = options;
_logger = logger;
_publishers = publishers.ToArray();
_stopping = new CancellationTokenSource();
}
internal bool IsStopping => _stopping.IsCancellationRequested;
internal bool IsTimerRunning => _timer != null;
public Task StartAsync(CancellationToken cancellationToken = default)
{
if (_publishers.Length == 0)
{
return Task.CompletedTask;
}
// IMPORTANT - make sure this is the last thing that happens in this method. The timer can
// fire before other code runs.
_timer = NonCapturingTimer.Create(Timer_Tick, null, dueTime: _options.Value.Delay, period: _options.Value.Period);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken = default)
{
try
{
_stopping.Cancel();
}
catch
{
// Ignore exceptions thrown as a result of a cancellation.
}
if (_publishers.Length == 0)
{
return Task.CompletedTask;
}
_timer?.Dispose();
_timer = null;
return Task.CompletedTask;
}
// Yes, async void. We need to be async. We need to be void. We handle the exceptions in RunAsync
private async void Timer_Tick(object state)
{
await RunAsync();
}
// Internal for testing
internal async Task RunAsync()
{
var duration = ValueStopwatch.StartNew();
Logger.HealthCheckPublisherProcessingBegin(_logger);
CancellationTokenSource cancellation = null;
try
{
var timeout = _options.Value.Timeout;
cancellation = CancellationTokenSource.CreateLinkedTokenSource(_stopping.Token);
cancellation.CancelAfter(timeout);
await RunAsyncCore(cancellation.Token);
Logger.HealthCheckPublisherProcessingEnd(_logger, duration.GetElapsedTime());
}
catch (OperationCanceledException) when (IsStopping)
{
// This is a cancellation - if the app is shutting down we want to ignore it. Otherwise, it's
// a timeout and we want to log it.
}
catch (Exception ex)
{
// This is an error, publishing failed.
Logger.HealthCheckPublisherProcessingEnd(_logger, duration.GetElapsedTime(), ex);
}
finally
{
cancellation.Dispose();
}
}
private async Task RunAsyncCore(CancellationToken cancellationToken)
{
// Forcibly yield - we want to unblock the timer thread.
await Task.Yield();
// The health checks service does it's own logging, and doesn't throw exceptions.
var report = await _healthCheckService.CheckHealthAsync(_options.Value.Predicate, cancellationToken);
var publishers = _publishers;
var tasks = new Task[publishers.Length];
for (var i = 0; i < publishers.Length; i++)
{
tasks[i] = RunPublisherAsync(publishers[i], report, cancellationToken);
}
await Task.WhenAll(tasks);
}
private async Task RunPublisherAsync(IHealthCheckPublisher publisher, HealthReport report, CancellationToken cancellationToken)
{
var duration = ValueStopwatch.StartNew();
try
{
Logger.HealthCheckPublisherBegin(_logger, publisher);
await publisher.PublishAsync(report, cancellationToken);
Logger.HealthCheckPublisherEnd(_logger, publisher, duration.GetElapsedTime());
}
catch (OperationCanceledException) when (IsStopping)
{
// This is a cancellation - if the app is shutting down we want to ignore it. Otherwise, it's
// a timeout and we want to log it.
}
catch (OperationCanceledException ocex)
{
Logger.HealthCheckPublisherTimeout(_logger, publisher, duration.GetElapsedTime());
throw ocex;
}
catch (Exception ex)
{
Logger.HealthCheckPublisherError(_logger, publisher, duration.GetElapsedTime(), ex);
throw ex;
}
}
internal static class EventIds
{
public static readonly EventId HealthCheckPublisherProcessingBegin = new EventId(100, "HealthCheckPublisherProcessingBegin");
public static readonly EventId HealthCheckPublisherProcessingEnd = new EventId(101, "HealthCheckPublisherProcessingEnd");
public static readonly EventId HealthCheckPublisherProcessingError = new EventId(101, "HealthCheckPublisherProcessingError");
public static readonly EventId HealthCheckPublisherBegin = new EventId(102, "HealthCheckPublisherBegin");
public static readonly EventId HealthCheckPublisherEnd = new EventId(103, "HealthCheckPublisherEnd");
public static readonly EventId HealthCheckPublisherError = new EventId(104, "HealthCheckPublisherError");
public static readonly EventId HealthCheckPublisherTimeout = new EventId(104, "HealthCheckPublisherTimeout");
}
private static class Logger
{
private static readonly Action<ILogger, Exception> _healthCheckPublisherProcessingBegin = LoggerMessage.Define(
LogLevel.Debug,
EventIds.HealthCheckPublisherProcessingBegin,
"Running health check publishers");
private static readonly Action<ILogger, double, Exception> _healthCheckPublisherProcessingEnd = LoggerMessage.Define<double>(
LogLevel.Debug,
EventIds.HealthCheckPublisherProcessingEnd,
"Health check publisher processing completed after {ElapsedMilliseconds}ms");
private static readonly Action<ILogger, IHealthCheckPublisher, Exception> _healthCheckPublisherBegin = LoggerMessage.Define<IHealthCheckPublisher>(
LogLevel.Debug,
EventIds.HealthCheckPublisherBegin,
"Running health check publisher '{HealthCheckPublisher}'");
private static readonly Action<ILogger, IHealthCheckPublisher, double, Exception> _healthCheckPublisherEnd = LoggerMessage.Define<IHealthCheckPublisher, double>(
LogLevel.Debug,
EventIds.HealthCheckPublisherEnd,
"Health check '{HealthCheckPublisher}' completed after {ElapsedMilliseconds}ms");
private static readonly Action<ILogger, IHealthCheckPublisher, double, Exception> _healthCheckPublisherError = LoggerMessage.Define<IHealthCheckPublisher, double>(
LogLevel.Error,
EventIds.HealthCheckPublisherError,
"Health check {HealthCheckPublisher} threw an unhandled exception after {ElapsedMilliseconds}ms");
private static readonly Action<ILogger, IHealthCheckPublisher, double, Exception> _healthCheckPublisherTimeout = LoggerMessage.Define<IHealthCheckPublisher, double>(
LogLevel.Error,
EventIds.HealthCheckPublisherTimeout,
"Health check {HealthCheckPublisher} was canceled after {ElapsedMilliseconds}ms");
public static void HealthCheckPublisherProcessingBegin(ILogger logger)
{
_healthCheckPublisherProcessingBegin(logger, null);
}
public static void HealthCheckPublisherProcessingEnd(ILogger logger, TimeSpan duration, Exception exception = null)
{
_healthCheckPublisherProcessingEnd(logger, duration.TotalMilliseconds, exception);
}
public static void HealthCheckPublisherBegin(ILogger logger, IHealthCheckPublisher publisher)
{
_healthCheckPublisherBegin(logger, publisher, null);
}
public static void HealthCheckPublisherEnd(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration)
{
_healthCheckPublisherEnd(logger, publisher, duration.TotalMilliseconds, null);
}
public static void HealthCheckPublisherError(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration, Exception exception)
{
_healthCheckPublisherError(logger, publisher, duration.TotalMilliseconds, exception);
}
public static void HealthCheckPublisherTimeout(ILogger logger, IHealthCheckPublisher publisher, TimeSpan duration)
{
_healthCheckPublisherTimeout(logger, publisher, duration.TotalMilliseconds, null);
}
}
}
}

View File

@ -1,84 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Options for the default service that executes <see cref="IHealthCheckPublisher"/> instances.
/// </summary>
public sealed class HealthCheckPublisherOptions
{
private TimeSpan _delay;
private TimeSpan _period;
public HealthCheckPublisherOptions()
{
_delay = TimeSpan.FromSeconds(5);
_period = TimeSpan.FromSeconds(30);
}
/// <summary>
/// Gets or sets the initial delay applied after the application starts before executing
/// <see cref="IHealthCheckPublisher"/> instances. The delay is applied once at startup, and does
/// not apply to subsequent iterations. The default value is 5 seconds.
/// </summary>
public TimeSpan Delay
{
get => _delay;
set
{
if (value == System.Threading.Timeout.InfiniteTimeSpan)
{
throw new ArgumentException($"The {nameof(Delay)} must not be infinite.", nameof(value));
}
_delay = value;
}
}
/// <summary>
/// Gets or sets the period of <see cref="IHealthCheckPublisher"/> execution. The default value is
/// 30 seconds.
/// </summary>
/// <remarks>
/// The <see cref="Period"/> cannot be set to a value lower than 1 second.
/// </remarks>
public TimeSpan Period
{
get => _period;
set
{
if (value < TimeSpan.FromSeconds(1))
{
throw new ArgumentException($"The {nameof(Period)} must be greater than or equal to one second.", nameof(value));
}
if (value == System.Threading.Timeout.InfiniteTimeSpan)
{
throw new ArgumentException($"The {nameof(Period)} must not be infinite.", nameof(value));
}
_delay = value;
}
}
/// <summary>
/// Gets or sets a predicate that is used to filter the set of health checks executed.
/// </summary>
/// <remarks>
/// If <see cref="Predicate"/> is <c>null</c>, the health check publisher service will run all
/// registered health checks - this is the default behavior. To run a subset of health checks,
/// provide a function that filters the set of checks. The predicate will be evaluated each period.
/// </remarks>
public Func<HealthCheckRegistration, bool> Predicate { get; set; }
/// <summary>
/// Gets or sets the timeout for executing the health checks an all <see cref="IHealthCheckPublisher"/>
/// instances. Use <see cref="System.Threading.Timeout.InfiniteTimeSpan"/> to execute with no timeout.
/// The default value is 30 seconds.
/// </summary>
public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(30);
}
}

View File

@ -1,61 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// A service which can be used to check the status of <see cref="IHealthCheck"/> instances
/// registered in the application.
/// </summary>
/// <remarks>
/// <para>
/// The default implementation of <see cref="HealthCheckService"/> is registered in the dependency
/// injection container as a singleton service by calling
/// <see cref="HealthCheckServiceCollectionExtensions.AddHealthChecks(IServiceCollection)"/>.
/// </para>
/// <para>
/// The <see cref="IHealthChecksBuilder"/> returned by
/// <see cref="HealthCheckServiceCollectionExtensions.AddHealthChecks(IServiceCollection)"/>
/// provides a convenience API for registering health checks.
/// </para>
/// <para>
/// <see cref="IHealthCheck"/> implementations can be registered through extension methods provided by
/// <see cref="IHealthChecksBuilder"/>.
/// </para>
/// </remarks>
public abstract class HealthCheckService
{
/// <summary>
/// Runs all the health checks in the application and returns the aggregated status.
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> which can be used to cancel the health checks.</param>
/// <returns>
/// A <see cref="Task{T}"/> which will complete when all the health checks have been run,
/// yielding a <see cref="HealthReport"/> containing the results.
/// </returns>
public Task<HealthReport> CheckHealthAsync(CancellationToken cancellationToken = default)
{
return CheckHealthAsync(predicate: null, cancellationToken);
}
/// <summary>
/// Runs the provided health checks and returns the aggregated status
/// </summary>
/// <param name="predicate">
/// A predicate that can be used to include health checks based on user-defined criteria.
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> which can be used to cancel the health checks.</param>
/// <returns>
/// A <see cref="Task{T}"/> which will complete when all the health checks have been run,
/// yielding a <see cref="HealthReport"/> containing the results.
/// </returns>
public abstract Task<HealthReport> CheckHealthAsync(
Func<HealthCheckRegistration, bool> predicate,
CancellationToken cancellationToken = default);
}
}

View File

@ -1,18 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace Microsoft.Extensions.Diagnostics.HealthChecks
{
/// <summary>
/// Options for the default implementation of <see cref="HealthCheckService"/>
/// </summary>
public sealed class HealthCheckServiceOptions
{
/// <summary>
/// Gets the health check registrations.
/// </summary>
public ICollection<HealthCheckRegistration> Registrations { get; } = new List<HealthCheckRegistration>();
}
}

View File

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Components for performing health checks in .NET applications
Commonly Used Types:
Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckService
Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder
</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>diagnostics;healthchecks</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(MicrosoftExtensionsHostingAbstractionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.NonCapturingTimer.Sources" Version="$(MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsOptionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.ValueStopwatch.Sources" Version="$(MicrosoftExtensionsValueStopwatchSourcesPackageVersion)" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@ -1,3 +0,0 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.Extensions.Diagnostics.HealthChecks.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View File

@ -1,5 +0,0 @@
{
"AssemblyIdentity": "Microsoft.Extensions.Diagnostics.HealthChecks, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
"Types": [
]
}

Some files were not shown because too many files have changed in this diff Show More