From fa961b003f74f0e6dbeebe97a992a447b043764e Mon Sep 17 00:00:00 2001 From: Unai Zorrilla Date: Fri, 28 Sep 2018 18:14:58 +0200 Subject: [PATCH 1/2] Added execution time duration (HealthReportEntry TotalDuration) (#493) * Added execution time duration into HealthReportEntry and TotalDuration on HealthReport * review PR feedback from @rynowak. * added the same duration into HealthReportEntry and log when the health check throw --- .../DefaultHealthCheckService.cs | 28 ++++++++++++------ .../HealthReport.cs | 10 ++++++- .../HealthReportEntry.cs | 9 +++++- .../HealthReportTest.cs | 29 ++++++++++++++----- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.Extensions.Diagnostics.HealthChecks/DefaultHealthCheckService.cs b/src/Microsoft.Extensions.Diagnostics.HealthChecks/DefaultHealthCheckService.cs index f1a41ea303..1b08acb60b 100644 --- a/src/Microsoft.Extensions.Diagnostics.HealthChecks/DefaultHealthCheckService.cs +++ b/src/Microsoft.Extensions.Diagnostics.HealthChecks/DefaultHealthCheckService.cs @@ -73,30 +73,40 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks try { var result = await healthCheck.CheckHealthAsync(context, cancellationToken); + var duration = stopwatch.GetElapsedTime(); entry = new HealthReportEntry( - result.Result ? HealthStatus.Healthy : registration.FailureStatus, - result.Description, - result.Exception, - result.Data); + status: result.Result ? HealthStatus.Healthy : registration.FailureStatus, + description: result.Description, + duration: duration, + exception: result.Exception, + data: result.Data); - Log.HealthCheckEnd(_logger, registration, entry, stopwatch.GetElapsedTime()); + Log.HealthCheckEnd(_logger, registration, entry, duration); Log.HealthCheckData(_logger, registration, entry); } // Allow cancellation to propagate. catch (Exception ex) when (ex as OperationCanceledException == null) { - entry = new HealthReportEntry(HealthStatus.Failed, ex.Message, ex, data: null); - Log.HealthCheckError(_logger, registration, ex, stopwatch.GetElapsedTime()); + var duration = stopwatch.GetElapsedTime(); + entry = new HealthReportEntry( + status: HealthStatus.Failed, + description: ex.Message, + duration: duration, + exception: ex, + data: null); + + Log.HealthCheckError(_logger, registration, ex, duration); } entries[registration.Name] = entry; } } - var report = new HealthReport(entries); - Log.HealthCheckProcessingEnd(_logger, report.Status, totalTime.GetElapsedTime()); + var totalElapsedTime = totalTime.GetElapsedTime(); + var report = new HealthReport(entries, totalElapsedTime); + Log.HealthCheckProcessingEnd(_logger, report.Status, totalElapsedTime); return report; } } diff --git a/src/Microsoft.Extensions.Diagnostics.HealthChecks/HealthReport.cs b/src/Microsoft.Extensions.Diagnostics.HealthChecks/HealthReport.cs index 29359a547f..a0e6fac1cd 100644 --- a/src/Microsoft.Extensions.Diagnostics.HealthChecks/HealthReport.cs +++ b/src/Microsoft.Extensions.Diagnostics.HealthChecks/HealthReport.cs @@ -1,6 +1,7 @@ // 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 @@ -14,10 +15,12 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks /// Create a new from the specified results. /// /// A containing the results from each health check. - public HealthReport(IReadOnlyDictionary entries) + /// A value indicating the time the health check service took to execute. + public HealthReport(IReadOnlyDictionary entries, TimeSpan totalDuration) { Entries = entries; Status = CalculateAggregateStatus(entries.Values); + TotalDuration = totalDuration; } /// @@ -35,6 +38,11 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks /// public HealthStatus Status { get; } + /// + /// Gets the time the health check service took to execute. + /// + public TimeSpan TotalDuration { get; } + private HealthStatus CalculateAggregateStatus(IEnumerable entries) { // This is basically a Min() check, but we know the possible range, so we don't need to walk the whole list diff --git a/src/Microsoft.Extensions.Diagnostics.HealthChecks/HealthReportEntry.cs b/src/Microsoft.Extensions.Diagnostics.HealthChecks/HealthReportEntry.cs index 17ed5ae288..2898c93aa4 100644 --- a/src/Microsoft.Extensions.Diagnostics.HealthChecks/HealthReportEntry.cs +++ b/src/Microsoft.Extensions.Diagnostics.HealthChecks/HealthReportEntry.cs @@ -19,12 +19,14 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks /// /// A value indicating the health status of the component that was checked. /// A human-readable description of the status of the component that was checked. + /// A value indicating the health execution duration. /// An representing the exception that was thrown when checking for status (if any). /// Additional key-value pairs describing the health of the component. - public HealthReportEntry(HealthStatus status, string description, Exception exception, IReadOnlyDictionary data) + public HealthReportEntry(HealthStatus status, string description, TimeSpan duration, Exception exception, IReadOnlyDictionary data) { Status = status; Description = description; + Duration = duration; Exception = exception; Data = data ?? _emptyReadOnlyDictionary; } @@ -39,6 +41,11 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks /// public string Description { get; } + /// + /// Gets the health check execution duration. + /// + public TimeSpan Duration { get; } + /// /// Gets an representing the exception that was thrown when checking for status (if any). /// diff --git a/test/Microsoft.Extensions.Diagnostics.HealthChecks.Tests/HealthReportTest.cs b/test/Microsoft.Extensions.Diagnostics.HealthChecks.Tests/HealthReportTest.cs index 9ce0a4b620..453398e639 100644 --- a/test/Microsoft.Extensions.Diagnostics.HealthChecks.Tests/HealthReportTest.cs +++ b/test/Microsoft.Extensions.Diagnostics.HealthChecks.Tests/HealthReportTest.cs @@ -1,6 +1,7 @@ // 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 Xunit; @@ -17,15 +18,29 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks { var result = new HealthReport(new Dictionary() { - {"Foo", new HealthReportEntry(HealthStatus.Healthy, null, null, null) }, - {"Bar", new HealthReportEntry(HealthStatus.Healthy, null, null, null) }, - {"Baz", new HealthReportEntry(status, exception: null, description: null, data: null) }, - {"Quick", new HealthReportEntry(HealthStatus.Healthy, null, null, null) }, - {"Quack", new HealthReportEntry(HealthStatus.Healthy, null, null, null) }, - {"Quock", new HealthReportEntry(HealthStatus.Healthy, null, null, null) }, - }); + {"Foo", new HealthReportEntry(HealthStatus.Healthy, null,TimeSpan.MinValue, null, null) }, + {"Bar", new HealthReportEntry(HealthStatus.Healthy, null, TimeSpan.MinValue,null, null) }, + {"Baz", new HealthReportEntry(status, exception: null, description: null,duration:TimeSpan.MinValue, data: null) }, + {"Quick", new HealthReportEntry(HealthStatus.Healthy, null, TimeSpan.MinValue, null, null) }, + {"Quack", new HealthReportEntry(HealthStatus.Healthy, null, TimeSpan.MinValue, null, null) }, + {"Quock", new HealthReportEntry(HealthStatus.Healthy, null, TimeSpan.MinValue, null, null) }, + }, totalDuration: TimeSpan.MinValue); Assert.Equal(status, result.Status); } + + [Theory] + [InlineData(200)] + [InlineData(300)] + [InlineData(400)] + public void TotalDuration_MatchesTotalDurationParameter(int milliseconds) + { + var result = new HealthReport(new Dictionary() + { + {"Foo", new HealthReportEntry(HealthStatus.Healthy, null,TimeSpan.MinValue, null, null) } + }, totalDuration: TimeSpan.FromMilliseconds(milliseconds)); + + Assert.Equal(TimeSpan.FromMilliseconds(milliseconds), result.TotalDuration); + } } } From 4fc5c7c11b69b6598efd81f6a60aac7fdca8701d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Sep 2018 17:10:32 -0700 Subject: [PATCH 2/2] automated: bulk infrastructure updates. Update bootstrapper scripts and remove unnecessary signing properties --- Directory.Build.props | 3 --- run.ps1 | 6 +++--- run.sh | 10 +++++----- .../Diagnostics.FunctionalTests.csproj | 1 - 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6fc59be2d0..d79e6a446b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,9 +14,6 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true - Microsoft - MicrosoftNuGet - true true diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..4c1fed5646 100755 --- a/run.sh +++ b/run.sh @@ -220,7 +220,7 @@ if [ -f "$config_file" ]; 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." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python ; then @@ -228,7 +228,7 @@ if [ -f "$config_file" ]; 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." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python3 ; then @@ -236,11 +236,11 @@ if [ -f "$config_file" ]; 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." + __error "$config_file contains invalid JSON." exit 1 fi else - _error 'Missing required command: jq or python. Could not parse the JSON file.' + __error 'Missing required command: jq or python. Could not parse the JSON file.' exit 1 fi @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild diff --git a/test/Diagnostics.FunctionalTests/Diagnostics.FunctionalTests.csproj b/test/Diagnostics.FunctionalTests/Diagnostics.FunctionalTests.csproj index 34524fc4a6..019ffa7fda 100644 --- a/test/Diagnostics.FunctionalTests/Diagnostics.FunctionalTests.csproj +++ b/test/Diagnostics.FunctionalTests/Diagnostics.FunctionalTests.csproj @@ -3,7 +3,6 @@ $(StandardTestTfms) false - false Diagnostics.FunctionalTests