From 88194df32043fb1fb38ac37a15733847205dc0cb Mon Sep 17 00:00:00 2001 From: Will Sugarman Date: Wed, 17 Nov 2021 14:28:16 -0800 Subject: [PATCH] Migrate to .NET 6.0 (#1192) - Update global.json - Update target frameworks to net6.0 - Dicom server - Dicom cast - Scale testing - Update Azure Functions to v4 - Update docker images - Update ARM templates - Address analyzer issues - Use AsSpan over Substring - Use PascalCase for template placeholders - (Ignored) Use logging delegates for performance - (Somewhat ignored) Ensure message templates are constant - Update NuGet packages - Update healthcare-shared-components due to SQL tooling --- .editorconfig | 2 ++ .github/dependabot.yml | 8 ++++++ .github/workflows/codeql-analysis.yml | 6 ++--- CredScanSuppressions.json | 8 ------ Directory.Build.props | 20 +++++---------- Microsoft.Health.Dicom.sln | 8 +++--- build/build.yml | 8 +++--- converter/dicom-cast/build/docker/Dockerfile | 4 +-- ...oft.Health.DicomCast.Core.UnitTests.csproj | 2 +- .../Features/Worker/ChangeFeedProcessor.cs | 8 +++--- .../Microsoft.Health.DicomCast.Core.csproj | 2 +- .../Microsoft.Health.DicomCast.Hosting.csproj | 6 ++--- ...th.DicomCast.TableStorage.UnitTests.csproj | 4 +-- .../Storage/TableClientInitializer.cs | 4 +-- .../Features/Storage/TableExceptionStore.cs | 4 +-- ...osoft.Health.DicomCast.TableStorage.csproj | 2 +- docker/functions/Dockerfile | 10 +++----- global.json | 2 +- .../featuresenabled-azuredeploy.json | 8 +++--- samples/docker/docker-compose.yaml | 2 +- samples/templates/default-azuredeploy.json | 10 ++++---- .../Extensions/HttpResponseExtensionsTests.cs | 12 ++++----- .../TransferSyntaxModelBinderTests.cs | 2 +- ...icrosoft.Health.Dicom.Api.UnitTests.csproj | 4 +-- .../Controllers/ChangeFeedController.cs | 4 +-- .../Controllers/DeleteController.cs | 6 ++--- .../Controllers/ExtendedQueryTagController.cs | 10 ++++---- .../Controllers/QueryController.cs | 6 ++--- .../Controllers/RetrieveController.cs | 14 +++++------ .../Controllers/StoreController.cs | 2 +- .../Extensions/HttpResponseExtensions.cs | 9 ++++++- .../Features/Audit/AuditLogger.cs | 4 +++ .../Exceptions/ExceptionHandlingMiddleware.cs | 2 +- .../Microsoft.Health.Dicom.Api.csproj | 14 +++++------ .../Microsoft.Health.Dicom.Blob.csproj | 2 +- .../Microsoft.Health.Dicom.Client.csproj | 6 ++--- ...nceEntryReaderForSinglePartRequestTests.cs | 13 ++++++++-- ...crosoft.Health.Dicom.Core.UnitTests.csproj | 6 ++--- .../Features/Common/DicomTagParser.cs | 4 +-- .../Features/Delete/DeleteService.cs | 6 ++--- .../Features/Partition/PartitionCache.cs | 2 +- .../Features/Partition/PartitionService.cs | 4 +-- .../Retrieve/RetrieveTransferSyntaxHandler.cs | 2 +- .../Validation/LongStringValidation.cs | 2 +- .../Microsoft.Health.Dicom.Core.csproj | 4 +-- .../Microsoft.Health.Dicom.Functions.csproj | 6 ++--- .../Microsoft.Health.Dicom.Metadata.csproj | 2 +- ...h.Dicom.Operations.Client.UnitTests.csproj | 4 +-- ...soft.Health.Dicom.Operations.Client.csproj | 2 +- ...t.Health.Dicom.Operations.UnitTests.csproj | 6 ++--- .../Microsoft.Health.Dicom.Operations.csproj | 5 ++-- ...ft.Health.Dicom.SqlServer.UnitTests.csproj | 4 +-- .../Extensions/ILoggerExtensions.cs | 23 +++++++++++++++++ .../ChangeFeed/SqlChangeFeedStoreV4.cs | 2 +- .../ChangeFeed/SqlChangeFeedStoreV6.cs | 2 +- .../SqlExtendedQueryTagStoreV2.cs | 5 ++-- .../SqlExtendedQueryTagStoreV4.cs | 6 ++--- .../Features/Query/SqlQueryStoreV4.cs | 2 ++ .../Features/Store/SqlIndexDataStoreV1.cs | 2 +- .../Microsoft.Health.Dicom.SqlServer.csproj | 2 +- ...Microsoft.Health.Dicom.Tests.Common.csproj | 4 +-- .../TranscoderTestDataHelper.cs | 10 -------- src/Microsoft.Health.Dicom.Web/Dockerfile | 4 +-- .../Microsoft.Health.Dicom.Web.csproj | 7 +++--- .../Features/TranscoderTests.cs | 2 +- ...soft.Health.Dicom.Tests.Integration.csproj | 9 ++++--- ...icrosoft.Health.Dicom.Web.Tests.E2E.csproj | 4 +-- tools/scale-testing/Common/Common.csproj | 6 ++--- .../MessageHandler/MessageHandler.csproj | 10 ++++---- tools/scale-testing/MessageHandler/Program.cs | 4 +-- .../MessageUploader/MessageUploader.csproj | 10 ++++---- .../scale-testing/MessageUploader/Program.cs | 2 +- .../PersonInstanceGenerator.csproj | 8 +++--- .../PersonInstanceGenerator/Program.cs | 4 +-- .../QidoFunctionApp/QidoFunctionApp.csproj | 23 +++++++++++++---- .../QidoQueryGenerator.csproj | 2 +- .../RetrieveBlobNames/Program.cs | 4 +-- .../RetrieveBlobNames.csproj | 8 +++--- .../StowFunctionApp/StowFunctionApp.csproj | 25 ++++++++++++++----- .../WadoFunctionApp/WadoFunctionApp.csproj | 22 ++++++++++++---- .../WadoMetadataFunctionApp.csproj | 22 ++++++++++++---- .../templates/default-azuredeploy.json | 4 +-- 82 files changed, 302 insertions(+), 233 deletions(-) create mode 100644 src/Microsoft.Health.Dicom.SqlServer/Extensions/ILoggerExtensions.cs diff --git a/.editorconfig b/.editorconfig index d6fd0476e7..786cd744e0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -196,6 +196,7 @@ dotnet_diagnostic.CA1032.severity = suggestion # Implement standard exception co dotnet_diagnostic.CA1054.severity = error # URI parameters should not be strings dotnet_diagnostic.CA1305.severity = suggestion # Specify IFormatProvider dotnet_diagnostic.CA1716.severity = warning # Identifiers should not match keywords +dotnet_diagnostic.CA1848.severity = none # Do not encourage LoggerMessage delegates in every instance dotnet_diagnostic.CA2007.severity = suggestion # Do not directly await a Task # Code Style Rules @@ -215,6 +216,7 @@ file_header_template = --------------------------------------------------------- dotnet_diagnostic.IDE0073.severity = warning # C++ Files + [*.{cpp,h,in}] curly_bracket_next_line = true indent_brace_style = Allman diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 952ad2b399..91bce802c2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -18,6 +18,14 @@ updates: timezone: "America/Los_Angeles" open-pull-requests-limit: 30 + - package-ecosystem: "nuget" + directory: "/tools/scale-testing" + schedule: + interval: "daily" + time: "09:00" + timezone: "America/Los_Angeles" + open-pull-requests-limit: 30 + - package-ecosystem: "docker" directory: "/" schedule: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f6dcceb7bc..f7d5b99755 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -26,12 +26,12 @@ jobs: uses: actions/setup-dotnet@v1.8.2 if: ${{ matrix.language == 'csharp' }} - # For Az Func and SQL Code-Gen - - name: 'Setup dotnet 3.1.x' + # SQL Code-Gen (TODO: Delete once shared components moves to .NET 6.0) + - name: 'Setup dotnet 5.x' uses: actions/setup-dotnet@v1.8.2 if: ${{ matrix.language == 'csharp' }} with: - dotnet-version: '3.1.x' + dotnet-version: '5.x' # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/CredScanSuppressions.json b/CredScanSuppressions.json index 5f76e66e8b..a583c34925 100644 --- a/CredScanSuppressions.json +++ b/CredScanSuppressions.json @@ -9,14 +9,6 @@ "placeholder": "globalAdminServicePrincipal", "_justification": "Service principal for local testing." }, - { - "placeholder": "Oc+osXvPQ172LU1flk53w6GFM7ixfjk9NELrkLtBt+k0ML585ECReA==", - "_justification": "Master key for Azure Function while using docker-compose." - }, - { - "placeholder": "cP0rhNdD/l9Dli+kEPQwupVqfTjksqK0dmMrZo/63mD0u0ezUrRl8Q==", - "_justification": "Function key for Azure Function while using docker-compose." - }, { "placeholder": "123!@#passforCI#$", "_justification": "Test admin password for testing SQL server using docker during CI" diff --git a/Directory.Build.props b/Directory.Build.props index ad3ec354ec..9c7f5a9d50 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,9 @@ - Microsoft Health Team $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + 5.0.0 + Microsoft Health Team Microsoft Corporation Copyright © Microsoft Corporation. All rights reserved. true @@ -11,28 +12,19 @@ 2.0.55 4.0.8 true - 3.2.39 + 3.2.44 true - 3.3.0 + 3.6.0 Latest - 3.1.20 MIT Microsoft Health true - 5.0.0 + 6.0.0 true true - - - - $(NetCoreApp3PackageVersion) - - - - @@ -42,7 +34,7 @@ - 5.0 + 6.0 AllEnabledByDefault true diff --git a/Microsoft.Health.Dicom.sln b/Microsoft.Health.Dicom.sln index c63eaadb42..eb4e749fcc 100644 --- a/Microsoft.Health.Dicom.sln +++ b/Microsoft.Health.Dicom.sln @@ -29,7 +29,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Dicom.Func EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Dicom.Metadata", "src\Microsoft.Health.Dicom.Metadata\Microsoft.Health.Dicom.Metadata.csproj", "{1E91CFB9-45D0-4742-A23D-0FF4E2D73A73}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Health.Dicom.Operations", "src\Microsoft.Health.Dicom.Operations\Microsoft.Health.Dicom.Operations.csproj", "{C71E1BDD-2B8E-47F3-8801-AE95F5F39941}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Dicom.Operations", "src\Microsoft.Health.Dicom.Operations\Microsoft.Health.Dicom.Operations.csproj", "{C71E1BDD-2B8E-47F3-8801-AE95F5F39941}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Dicom.Operations.Client", "src\Microsoft.Health.Dicom.Operations.Client\Microsoft.Health.Dicom.Operations.Client.csproj", "{F896C916-144F-412E-B3DE-C9D0D9B8EDD1}" EndProject @@ -147,20 +147,20 @@ Global {E15123F6-5A28-4D86-A28D-30FCB699B9EE} = {176641B3-297C-4E04-A83D-8F80F80485E8} {FA0484A7-AA0C-4CC6-A75F-1D6B23DD847D} = {176641B3-297C-4E04-A83D-8F80F80485E8} {BB88616C-6208-43D0-B9EF-79FC0652A151} = {176641B3-297C-4E04-A83D-8F80F80485E8} + {1E91CFB9-45D0-4742-A23D-0FF4E2D73A73} = {176641B3-297C-4E04-A83D-8F80F80485E8} + {C71E1BDD-2B8E-47F3-8801-AE95F5F39941} = {176641B3-297C-4E04-A83D-8F80F80485E8} {F896C916-144F-412E-B3DE-C9D0D9B8EDD1} = {176641B3-297C-4E04-A83D-8F80F80485E8} {3D5D7F69-C766-450A-AA3D-00A50E115E9C} = {176641B3-297C-4E04-A83D-8F80F80485E8} {3D679950-A578-45AD-AF89-FAF89580375F} = {176641B3-297C-4E04-A83D-8F80F80485E8} - {1E91CFB9-45D0-4742-A23D-0FF4E2D73A73} = {176641B3-297C-4E04-A83D-8F80F80485E8} {0F57D85C-8FA4-4DBE-BF44-1CA5109125A5} = {176641B3-297C-4E04-A83D-8F80F80485E8} {DFB41ECC-726C-4DBA-8AD3-17FB0A2546CA} = {8C9A0050-5D22-4398-9F93-DDCD80B3BA51} {A88DAB6A-BE0E-41BD-AB48-D1156FB6443C} = {176641B3-297C-4E04-A83D-8F80F80485E8} {ECC018C1-BFA8-44BE-B560-ACB05CA57251} = {176641B3-297C-4E04-A83D-8F80F80485E8} {BFB96311-9B1A-41C1-ABF1-4F6522660084} = {176641B3-297C-4E04-A83D-8F80F80485E8} {1D0ECFDA-2AF2-4796-995D-A7C6E18C9CD1} = {8C9A0050-5D22-4398-9F93-DDCD80B3BA51} - {C71E1BDD-2B8E-47F3-8801-AE95F5F39941} = {176641B3-297C-4E04-A83D-8F80F80485E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E370FB31-CF95-47D1-B1E1-863A77973FF8} RESX_SortFileContentOnSave = True + SolutionGuid = {E370FB31-CF95-47D1-B1E1-863A77973FF8} EndGlobalSection EndGlobal diff --git a/build/build.yml b/build/build.yml index e9b0f9b51f..49a07f4f78 100644 --- a/build/build.yml +++ b/build/build.yml @@ -5,15 +5,15 @@ parameters: steps: - task: UseDotNet@2 - displayName: 'Use .NET Core sdk' + displayName: 'Use .NET sdk' inputs: useGlobalJson: true - # For Az Func and SQL Code-Gen + # SQL Code-Gen (TODO: Delete once shared components moves to .NET 6.0) - task: UseDotNet@2 - displayName: 'Use .NET Core 3.1.x SDK' + displayName: 'Use .NET 5.x SDK' inputs: - version: '3.1.x' + version: '5.x' - task: DotNetCoreCLI@2 displayName: 'dotnet build $(buildConfiguration)' diff --git a/converter/dicom-cast/build/docker/Dockerfile b/converter/dicom-cast/build/docker/Dockerfile index 3ff2564181..70bdb1175b 100644 --- a/converter/dicom-cast/build/docker/Dockerfile +++ b/converter/dicom-cast/build/docker/Dockerfile @@ -1,5 +1,5 @@ # Start from the sdk image -FROM mcr.microsoft.com/dotnet/sdk:5.0.402-alpine3.13@sha256:f08db3184fc8fbb12dd4a9d12eb2e3c0a36ca60a4dd13759edde22605fbd00bd AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0.100-alpine3.14@sha256:1d9d66775f0d67cb68af9c7a083d22b576ea96f3f7a6893660d48f536b73e59f AS build # Set the working directory to where the source is located WORKDIR /dicom-cast/src @@ -12,7 +12,7 @@ RUN dotnet build "./converter/dicom-cast/src/Microsoft.Health.DicomCast.Hosting/ RUN dotnet publish "./converter/dicom-cast/src/Microsoft.Health.DicomCast.Hosting/Microsoft.Health.DicomCast.Hosting.csproj" -c Release -o "/.build" --no-build # Build the runtime image -FROM mcr.microsoft.com/dotnet/aspnet:5.0.11-alpine3.13@sha256:2b67665d62471d30de99340361d516d4555a9276cb4ff78fb09db784384b1574 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:6.0.0-alpine3.14@sha256:1c893087b6d9cfe54d025dfeeda385358e79dcedd9a16f6ccdc9e5aa080db0f6 AS runtime RUN set -x && \ addgroup nonroot && \ diff --git a/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core.UnitTests/Microsoft.Health.DicomCast.Core.UnitTests.csproj b/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core.UnitTests/Microsoft.Health.DicomCast.Core.UnitTests.csproj index 9ceee853fd..19bafef4eb 100644 --- a/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core.UnitTests/Microsoft.Health.DicomCast.Core.UnitTests.csproj +++ b/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core.UnitTests/Microsoft.Health.DicomCast.Core.UnitTests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 diff --git a/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core/Features/Worker/ChangeFeedProcessor.cs b/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core/Features/Worker/ChangeFeedProcessor.cs index e28a07bf28..49a80feefe 100644 --- a/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core/Features/Worker/ChangeFeedProcessor.cs +++ b/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core/Features/Worker/ChangeFeedProcessor.cs @@ -81,11 +81,11 @@ public async Task ProcessAsync(TimeSpan pollIntervalDuringCatchup, CancellationT if (!(changeFeedEntry.Action == ChangeFeedAction.Create && changeFeedEntry.State == ChangeFeedState.Deleted)) { await _fhirTransactionPipeline.ProcessAsync(changeFeedEntry, cancellationToken); - _logger.LogInformation("Successfully processed DICOM event with SequenceID: {sequenceId}", changeFeedEntry.Sequence); + _logger.LogInformation("Successfully processed DICOM event with SequenceID: {SequenceId}", changeFeedEntry.Sequence); } else { - _logger.LogInformation("Skip DICOM event with SequenceId {sequenceId} due to deletion before processing creation.", changeFeedEntry.Sequence); + _logger.LogInformation("Skip DICOM event with SequenceId {SequenceId} due to deletion before processing creation.", changeFeedEntry.Sequence); } } catch (Exception ex) @@ -114,7 +114,7 @@ await _exceptionStore.WriteExceptionAsync( errorType, cancellationToken); - _logger.LogError("Failed to process DICOM event with SequenceID: {sequenceId}, StudyUid: {studyUid}, SeriesUid: {seriesUid}, instanceUid: {instanceUid} and will not be retried further. Continuing to next event.", changeFeedEntry.Sequence, studyUid, seriesUid, instanceUid); + _logger.LogError("Failed to process DICOM event with SequenceID: {SequenceId}, StudyUid: {StudyUid}, SeriesUid: {SeriesUid}, instanceUid: {InstanceUid} and will not be retried further. Continuing to next event.", changeFeedEntry.Sequence, studyUid, seriesUid, instanceUid); } else { @@ -127,7 +127,7 @@ await _exceptionStore.WriteExceptionAsync( await _syncStateService.UpdateSyncStateAsync(newSyncState, cancellationToken); - _logger.LogInformation("Processed DICOM events sequenced {sequenceId}-{maxSequence}.", state.SyncedSequence + 1, maxSequence); + _logger.LogInformation("Processed DICOM events sequenced {SequenceId}-{MaxSequence}.", state.SyncedSequence + 1, maxSequence); state = newSyncState; diff --git a/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core/Microsoft.Health.DicomCast.Core.csproj b/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core/Microsoft.Health.DicomCast.Core.csproj index 7516655bde..5998c4d10f 100644 --- a/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core/Microsoft.Health.DicomCast.Core.csproj +++ b/converter/dicom-cast/src/Microsoft.Health.DicomCast.Core/Microsoft.Health.DicomCast.Core.csproj @@ -2,7 +2,7 @@ Common primitives and utilities used by Microsoft's DICOM Cast APIs. - net5.0 + net6.0 diff --git a/converter/dicom-cast/src/Microsoft.Health.DicomCast.Hosting/Microsoft.Health.DicomCast.Hosting.csproj b/converter/dicom-cast/src/Microsoft.Health.DicomCast.Hosting/Microsoft.Health.DicomCast.Hosting.csproj index 6e9476ad72..08379c7b6b 100644 --- a/converter/dicom-cast/src/Microsoft.Health.DicomCast.Hosting/Microsoft.Health.DicomCast.Hosting.csproj +++ b/converter/dicom-cast/src/Microsoft.Health.DicomCast.Hosting/Microsoft.Health.DicomCast.Hosting.csproj @@ -1,12 +1,12 @@ - net5.0 + net6.0 - + @@ -15,7 +15,7 @@ - + diff --git a/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage.UnitTests/Microsoft.Health.DicomCast.TableStorage.UnitTests.csproj b/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage.UnitTests/Microsoft.Health.DicomCast.TableStorage.UnitTests.csproj index 8885e33c2d..33ad483bff 100644 --- a/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage.UnitTests/Microsoft.Health.DicomCast.TableStorage.UnitTests.csproj +++ b/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage.UnitTests/Microsoft.Health.DicomCast.TableStorage.UnitTests.csproj @@ -1,7 +1,7 @@ - + - net5.0 + net6.0 false diff --git a/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Features/Storage/TableClientInitializer.cs b/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Features/Storage/TableClientInitializer.cs index 923be5917c..c29bb07de1 100644 --- a/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Features/Storage/TableClientInitializer.cs +++ b/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Features/Storage/TableClientInitializer.cs @@ -55,11 +55,11 @@ public async Task IntializeDataStoreAsync(CloudTableClient client) CloudTable table = client.GetTableReference(tableName); if (await table.CreateIfNotExistsAsync()) { - _logger.LogInformation("Created Table named: {0}", tableName); + _logger.LogInformation("Created Table named '{TableName}'", tableName); } else { - _logger.LogInformation("Table {0} already exists", tableName); + _logger.LogInformation("Table '{TableName}' already exists", tableName); } } diff --git a/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Features/Storage/TableExceptionStore.cs b/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Features/Storage/TableExceptionStore.cs index e611831d1e..8b46592fe8 100644 --- a/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Features/Storage/TableExceptionStore.cs +++ b/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Features/Storage/TableExceptionStore.cs @@ -103,11 +103,11 @@ public async Task WriteRetryableExceptionAsync(ChangeFeedEntry changeFeedEntry, try { await table.ExecuteAsync(operation, cancellationToken); - _logger.LogInformation("Retryable error when processsing changefeed entry: {ChangeFeedSequence} for DICOM instance with StudyUID: {StudyUID}, SeriesUID: {SeriesUID}, InstanceUID: {InstanceUID}. Tried {retryNum} time(s). Waiting {milliseconds} milliseconds . Stored into table: {Table} in table storage.", changeFeedSequence, studyUid, seriesUid, instanceUid, retryNum, nextDelayTimeSpan.TotalMilliseconds, Constants.TransientRetryTableName); + _logger.LogInformation("Retryable error when processsing changefeed entry: {ChangeFeedSequence} for DICOM instance with StudyUID: {StudyUID}, SeriesUID: {SeriesUID}, InstanceUID: {InstanceUID}. Tried {RetryNum} time(s). Waiting {Milliseconds} milliseconds . Stored into table: {Table} in table storage.", changeFeedSequence, studyUid, seriesUid, instanceUid, retryNum, nextDelayTimeSpan.TotalMilliseconds, Constants.TransientRetryTableName); } catch { - _logger.LogInformation("Retryable error when processsing changefeed entry: {ChangeFeedSequence} for DICOM instance with StudyUID: {StudyUID}, SeriesUID: {SeriesUID}, InstanceUID: {InstanceUID}. Tried {retryNum} time(s). Failed to store to table storage.", changeFeedSequence, studyUid, seriesUid, instanceUid, retryNum); + _logger.LogInformation("Retryable error when processsing changefeed entry: {ChangeFeedSequence} for DICOM instance with StudyUID: {StudyUID}, SeriesUID: {SeriesUID}, InstanceUID: {InstanceUID}. Tried {RetryNum} time(s). Failed to store to table storage.", changeFeedSequence, studyUid, seriesUid, instanceUid, retryNum); throw; } } diff --git a/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Microsoft.Health.DicomCast.TableStorage.csproj b/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Microsoft.Health.DicomCast.TableStorage.csproj index 5d9151f4e8..f19e915668 100644 --- a/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Microsoft.Health.DicomCast.TableStorage.csproj +++ b/converter/dicom-cast/src/Microsoft.Health.DicomCast.TableStorage/Microsoft.Health.DicomCast.TableStorage.csproj @@ -2,7 +2,7 @@ Azure Cosmos DB table storage utilities for Microsoft's DICOM Cast APIs. - net5.0 + net6.0 diff --git a/docker/functions/Dockerfile b/docker/functions/Dockerfile index e2d118f79c..29b3081d3d 100644 --- a/docker/functions/Dockerfile +++ b/docker/functions/Dockerfile @@ -5,17 +5,13 @@ # To enable ssh & remote debugging on app service change the base image to the one below # FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice -FROM mcr.microsoft.com/azure-functions/dotnet:3.3.1@sha256:6b05f6aa60767db3a295064b146f0e5b7a13ef967261085aa723feea3025ed36 AS az-func-runtime +FROM mcr.microsoft.com/azure-functions/dotnet:4.0.1.16816@sha256:2c18c4ca6ad982257e9023161329c38be6d9d494bc48a6aae15ef43cc8f7ea5d AS az-func-runtime ENV AzureFunctionsJobHost__Logging__Console__IsEnabled=true \ AzureWebJobsScriptRoot=/home/site/wwwroot # Copy the DICOM Server repository and build the Azure Functions project -# Note: While the latest .NET SDK is used for building, Azure Functions build target requires .NET Core 3.1 to be installed -FROM mcr.microsoft.com/dotnet/sdk:5.0.402-alpine3.13@sha256:f08db3184fc8fbb12dd4a9d12eb2e3c0a36ca60a4dd13759edde22605fbd00bd AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0.100-alpine3.14@sha256:1d9d66775f0d67cb68af9c7a083d22b576ea96f3f7a6893660d48f536b73e59f AS build ARG BUILD_CONFIGURATION=Release -RUN set -x && \ - apk add --no-cache bash && \ - curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin -Channel 3.1 -InstallDir /usr/share/dotnet WORKDIR /dicom-server COPY . . WORKDIR /dicom-server/src/Microsoft.Health.Dicom.Functions @@ -24,7 +20,7 @@ RUN dotnet build "Microsoft.Health.Dicom.Functions.csproj" -c $BUILD_CONFIGURATI # Publish the Azure Functions from the build FROM build as publish ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "Microsoft.Health.Dicom.Functions.csproj" -c $BUILD_CONFIGURATION --no-build --framework netcoreapp3.1 -o /home/site/wwwroot +RUN dotnet publish "Microsoft.Health.Dicom.Functions.csproj" -c $BUILD_CONFIGURATION --no-build --framework net6.0 -o /home/site/wwwroot # Copy the published application FROM az-func-runtime AS dicom-az-func diff --git a/global.json b/global.json index 200e186ecd..047020849f 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "5.0.402" + "version": "6.0.100" } } diff --git a/release/templates/featuresenabled-azuredeploy.json b/release/templates/featuresenabled-azuredeploy.json index 99f47365b6..045c172589 100644 --- a/release/templates/featuresenabled-azuredeploy.json +++ b/release/templates/featuresenabled-azuredeploy.json @@ -37,7 +37,7 @@ "metadata": { "description": "The type of the solution" } - }, + }, "sqlAdminPassword": { "type": "securestring", "metadata": { @@ -109,7 +109,7 @@ { "apiVersion": "2015-08-01", "type": "config", - "name": "appsettings", + "name": "appsettings", "properties": "[union(json(concat('{\"ApplicationInsights__InstrumentationKey\": \"', concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsInstrumentationKeyResourceId'), '2015-06-01').secretUriWithVersion, ')'), '\"}')), json(concat('{\"AzureWebJobsStorage\": \"', concat('@Microsoft.KeyVault(SecretUri=', reference(variables('azureStorageConnectionStringResourceId'), '2015-06-01').secretUriWithVersion, ')'), '\"}')), json(concat('{\"BlobStore__ConnectionString\": \"', concat('@Microsoft.KeyVault(SecretUri=', reference(variables('azureStorageConnectionStringResourceId'), '2015-06-01').secretUriWithVersion, ')'), '\"}')), json(concat('{\"SqlServer__ConnectionString\": \"', concat('@Microsoft.KeyVault(SecretUri=', reference(variables('sqlServerConnectionStringWithPartitionsResourceId'), '2015-06-01').secretUriWithVersion, ')'), '\"}')), variables('combinedDicomServerConfigProperties'))]", "dependsOn": [ "[variables('featuresEnabledAppServiceResourceId')]" @@ -118,13 +118,13 @@ { "apiVersion": "2015-08-01", "type": "siteextensions", - "name": "AspNetCoreRuntime.5.0.x64", + "name": "AspNetCoreRuntime.6.0.x64", "dependsOn": [ "[variables('featuresEnabledAppServiceResourceId')]", "[resourceId('Microsoft.Web/sites/config', variables('featuresEnabledServiceName'), 'appsettings')]" // Avoid restarts mid-installation ], "properties": { - "version": "5.0.11" + "version": "6.0.0" } } ] diff --git a/samples/docker/docker-compose.yaml b/samples/docker/docker-compose.yaml index 7b01ea099e..08c07d997f 100644 --- a/samples/docker/docker-compose.yaml +++ b/samples/docker/docker-compose.yaml @@ -18,7 +18,7 @@ services: - azurite azurite: - image: mcr.microsoft.com/azure-storage/azurite:3.14.2@sha256:443c9b28466219e21005e638a28ac4bcc6d3860509d3fc9ec8753fce64424b29 + image: mcr.microsoft.com/azure-storage/azurite:3.14.3@sha256:a9f79c01d9ef44549af22935345b5f622d45bef01c771f25a0c87c893b49f978 restart: always # # Uncomment if you want to expose azure storage explorer against localhost # ports: diff --git a/samples/templates/default-azuredeploy.json b/samples/templates/default-azuredeploy.json index 2496e8b304..788e151853 100644 --- a/samples/templates/default-azuredeploy.json +++ b/samples/templates/default-azuredeploy.json @@ -199,7 +199,7 @@ "staticDicomFunctionAppConfigProperties": { "AzureWebJobsDisableHomepage": "true", "CONTAINER_NAME": "azure-webjobs-secrets", - "FUNCTIONS_EXTENSION_VERSION": "~3", + "FUNCTIONS_EXTENSION_VERSION": "~4", "FUNCTIONS_WORKER_RUNTIME": "dotnet", "WEBSITE_ENABLE_SYNC_UPDATE_SITE": "1" }, @@ -277,13 +277,13 @@ { "apiVersion": "2015-08-01", "type": "siteextensions", - "name": "AspNetCoreRuntime.5.0.x64", + "name": "AspNetCoreRuntime.6.0.x64", "dependsOn": [ "[variables('appServiceResourceId')]", "[resourceId('Microsoft.Web/sites/config', variables('serviceName'), 'appsettings')]" // Avoid restarts mid-installation ], "properties": { - "version": "5.0.11" + "version": "6.0.0" } }, { @@ -294,7 +294,7 @@ "dependsOn": [ "[variables('appServiceResourceId')]", "[resourceId('Microsoft.Web/sites/config', variables('serviceName'), 'appsettings')]", - "[concat(variables('appServiceResourceId'), '/siteextensions/AspNetCoreRuntime.5.0.x64')]" + "[concat(variables('appServiceResourceId'), '/siteextensions/AspNetCoreRuntime.6.0.x64')]" ], "properties": { "packageUri": "[variables('deployWebPackageUrl')]" @@ -330,7 +330,7 @@ }, { "name": "FUNCTIONS_EXTENSION_VERSION", - "value": "~3" + "value": "~4" }, { "name": "FUNCTIONS_WORKER_RUNTIME", diff --git a/src/Microsoft.Health.Dicom.Api.UnitTests/Extensions/HttpResponseExtensionsTests.cs b/src/Microsoft.Health.Dicom.Api.UnitTests/Extensions/HttpResponseExtensionsTests.cs index 9bbabdd7c3..d84d076971 100644 --- a/src/Microsoft.Health.Dicom.Api.UnitTests/Extensions/HttpResponseExtensionsTests.cs +++ b/src/Microsoft.Health.Dicom.Api.UnitTests/Extensions/HttpResponseExtensionsTests.cs @@ -4,7 +4,6 @@ // ------------------------------------------------------------------------------------------------- using System; -using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using Microsoft.Health.Dicom.Api.Extensions; @@ -26,20 +25,19 @@ public void GivenNullParameters_WhenAddLocationHeader_ThenThrowsArgumentNullExce } [Theory] - [InlineData("https://absolute.url:8080/there%20are%20spaces")] - [InlineData("/relative/url?with=query&string=and#fragment")] - [SuppressMessage("Design", "CA1054:URI-like parameters should not be strings", Justification = "XUnit more easily leverages compile-time values.")] - public void GivenValidLocationHeader_WhenAddLocationHeader_ThenShouldAddExpectedHeader(string url) + [InlineData("https://absolute.url:8080/there are spaces", "https://absolute.url:8080/there%20are%20spaces")] + [InlineData("/relative/url?with=query&string=and#fragment", "/relative/url?with=query&string=and#fragment")] + public void GivenValidLocationHeader_WhenAddLocationHeader_ThenShouldAddExpectedHeader(string actual, string expected) { var response = new DefaultHttpContext().Response; - var uri = new Uri(url, UriKind.RelativeOrAbsolute); + var uri = new Uri(actual, UriKind.RelativeOrAbsolute); Assert.False(response.Headers.ContainsKey(HeaderNames.Location)); response.AddLocationHeader(uri); Assert.True(response.Headers.TryGetValue(HeaderNames.Location, out StringValues headerValue)); Assert.Single(headerValue); - Assert.Equal(url, headerValue[0]); // Should continue to be escaped! + Assert.Equal(expected, headerValue[0]); // Should continue to be escaped! } [Fact] diff --git a/src/Microsoft.Health.Dicom.Api.UnitTests/Features/ModelBinders/TransferSyntaxModelBinderTests.cs b/src/Microsoft.Health.Dicom.Api.UnitTests/Features/ModelBinders/TransferSyntaxModelBinderTests.cs index 24c14c1c34..781686ef9d 100644 --- a/src/Microsoft.Health.Dicom.Api.UnitTests/Features/ModelBinders/TransferSyntaxModelBinderTests.cs +++ b/src/Microsoft.Health.Dicom.Api.UnitTests/Features/ModelBinders/TransferSyntaxModelBinderTests.cs @@ -23,7 +23,7 @@ public class TransferSyntaxModelBinderTests public async Task GivenHeaderWithValidTransferSyntax_WhenBindingTransferSyntax_ModelIsSetAndExpectedResultIsParsed(string contextValue, string expectedResult) { ModelBindingContext bindingContext = Substitute.For(); - bindingContext.HttpContext.Request.Headers["Accept"].Returns(new StringValues(contextValue)); + bindingContext.HttpContext.Request.Headers.Accept.Returns(new StringValues(contextValue)); ModelStateDictionary modelStateDictionary = new ModelStateDictionary(); bindingContext.ModelState.Returns(modelStateDictionary); diff --git a/src/Microsoft.Health.Dicom.Api.UnitTests/Microsoft.Health.Dicom.Api.UnitTests.csproj b/src/Microsoft.Health.Dicom.Api.UnitTests/Microsoft.Health.Dicom.Api.UnitTests.csproj index de06ca2640..bd5fb75fab 100644 --- a/src/Microsoft.Health.Dicom.Api.UnitTests/Microsoft.Health.Dicom.Api.UnitTests.csproj +++ b/src/Microsoft.Health.Dicom.Api.UnitTests/Microsoft.Health.Dicom.Api.UnitTests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 @@ -14,7 +14,7 @@ - + diff --git a/src/Microsoft.Health.Dicom.Api/Controllers/ChangeFeedController.cs b/src/Microsoft.Health.Dicom.Api/Controllers/ChangeFeedController.cs index 8ccb00531c..207152a34f 100644 --- a/src/Microsoft.Health.Dicom.Api/Controllers/ChangeFeedController.cs +++ b/src/Microsoft.Health.Dicom.Api/Controllers/ChangeFeedController.cs @@ -48,7 +48,7 @@ public ChangeFeedController(IMediator mediator, ILogger lo [AuditEventType(AuditEventSubType.ChangeFeed)] public async Task GetChangeFeed([FromQuery] long offset = 0, [FromQuery] int limit = 10, [FromQuery] bool includeMetadata = true) { - _logger.LogInformation("Change feed was read with an offset of {offset} and limit of {limit} and metadata is {metadata} included.", offset, limit, includeMetadata ? string.Empty : "not"); + _logger.LogInformation("Change feed was read with an offset of {Offset} and limit of {Limit} and metadata is {Metadata} included.", offset, limit, includeMetadata ? string.Empty : "not"); var response = await _mediator.GetChangeFeed( offset, @@ -69,7 +69,7 @@ public async Task GetChangeFeed([FromQuery] long offset = 0, [Fro [AuditEventType(AuditEventSubType.ChangeFeed)] public async Task GetChangeFeedLatest([FromQuery] bool includeMetadata = true) { - _logger.LogInformation("Change feed latest was read and metadata is {metadata} included.", includeMetadata ? string.Empty : "not"); + _logger.LogInformation("Change feed latest was read and metadata is {Metadata} included.", includeMetadata ? string.Empty : "not"); var response = await _mediator.GetChangeFeedLatest( includeMetadata, diff --git a/src/Microsoft.Health.Dicom.Api/Controllers/DeleteController.cs b/src/Microsoft.Health.Dicom.Api/Controllers/DeleteController.cs index cfc35107c7..00b43305f5 100644 --- a/src/Microsoft.Health.Dicom.Api/Controllers/DeleteController.cs +++ b/src/Microsoft.Health.Dicom.Api/Controllers/DeleteController.cs @@ -48,7 +48,7 @@ public DeleteController(IMediator mediator, ILogger logger) [AuditEventType(AuditEventSubType.Delete)] public async Task DeleteStudyAsync(string studyInstanceUid) { - _logger.LogInformation("DICOM Web Delete Study request received, with study instance UID {studyInstanceUid}.", studyInstanceUid); + _logger.LogInformation("DICOM Web Delete Study request received, with study instance UID {StudyInstanceUid}.", studyInstanceUid); DeleteResourcesResponse deleteResponse = await _mediator.DeleteDicomStudyAsync( studyInstanceUid, cancellationToken: HttpContext.RequestAborted); @@ -67,7 +67,7 @@ public async Task DeleteStudyAsync(string studyInstanceUid) [AuditEventType(AuditEventSubType.Delete)] public async Task DeleteSeriesAsync(string studyInstanceUid, string seriesInstanceUid) { - _logger.LogInformation("DICOM Web Delete Series request received, with study instance UID {studyInstanceUid} and series UID {seriesInstanceUid}.", studyInstanceUid, seriesInstanceUid); + _logger.LogInformation("DICOM Web Delete Series request received, with study instance UID {StudyInstanceUid} and series UID {SeriesInstanceUid}.", studyInstanceUid, seriesInstanceUid); DeleteResourcesResponse deleteResponse = await _mediator.DeleteDicomSeriesAsync( studyInstanceUid, seriesInstanceUid, cancellationToken: HttpContext.RequestAborted); @@ -86,7 +86,7 @@ public async Task DeleteSeriesAsync(string studyInstanceUid, stri [AuditEventType(AuditEventSubType.Delete)] public async Task DeleteInstanceAsync(string studyInstanceUid, string seriesInstanceUid, string sopInstanceUid) { - _logger.LogInformation("DICOM Web Delete Instance request received, with study instance UID {studyInstanceUid}, series UID {seriesInstanceUid} and instance UID {sopInstanceUid}.", studyInstanceUid, seriesInstanceUid, sopInstanceUid); + _logger.LogInformation("DICOM Web Delete Instance request received, with study instance UID {StudyInstanceUid}, series UID {SeriesInstanceUid} and instance UID {SopInstanceUid}.", studyInstanceUid, seriesInstanceUid, sopInstanceUid); DeleteResourcesResponse deleteResponse = await _mediator.DeleteDicomInstanceAsync( studyInstanceUid, seriesInstanceUid, sopInstanceUid, cancellationToken: HttpContext.RequestAborted); diff --git a/src/Microsoft.Health.Dicom.Api/Controllers/ExtendedQueryTagController.cs b/src/Microsoft.Health.Dicom.Api/Controllers/ExtendedQueryTagController.cs index 584e694de1..9e6a332725 100644 --- a/src/Microsoft.Health.Dicom.Api/Controllers/ExtendedQueryTagController.cs +++ b/src/Microsoft.Health.Dicom.Api/Controllers/ExtendedQueryTagController.cs @@ -62,7 +62,7 @@ public ExtendedQueryTagController( [AuditEventType(AuditEventSubType.AddExtendedQueryTag)] public async Task PostAsync([Required][FromBody] IReadOnlyCollection extendedQueryTags) { - _logger.LogInformation("DICOM Web Add Extended Query Tag request received, with extendedQueryTags {extendedQueryTags}.", extendedQueryTags); + _logger.LogInformation("DICOM Web Add Extended Query Tag request received, with extendedQueryTags {ExtendedQueryTags}.", extendedQueryTags); EnsureFeatureIsEnabled(); AddExtendedQueryTagResponse response = await _mediator.AddExtendedQueryTagsAsync(extendedQueryTags, HttpContext.RequestAborted); @@ -79,7 +79,7 @@ public async Task PostAsync([Required][FromBody] IReadOnlyCollect [AuditEventType(AuditEventSubType.RemoveExtendedQueryTag)] public async Task DeleteAsync(string tagPath) { - _logger.LogInformation("DICOM Web Delete Extended Query Tag request received, with extended query tag path {tagPath}.", tagPath); + _logger.LogInformation("DICOM Web Delete Extended Query Tag request received, with extended query tag path {TagPath}.", tagPath); EnsureFeatureIsEnabled(); await _mediator.DeleteExtendedQueryTagAsync(tagPath, HttpContext.RequestAborted); @@ -139,7 +139,7 @@ public async Task GetTagsAsync([FromQuery] PaginationOptions opti [AuditEventType(AuditEventSubType.GetExtendedQueryTag)] public async Task GetTagAsync(string tagPath) { - _logger.LogInformation("DICOM Web Get Extended Query Tag request received for extended query tag: {tagPath}", tagPath); + _logger.LogInformation("DICOM Web Get Extended Query Tag request received for extended query tag: {TagPath}", tagPath); EnsureFeatureIsEnabled(); GetExtendedQueryTagResponse response = await _mediator.GetExtendedQueryTagAsync(tagPath, HttpContext.RequestAborted); @@ -170,7 +170,7 @@ public async Task GetTagErrorsAsync( [FromRoute] string tagPath, [FromQuery] PaginationOptions options) { - _logger.LogInformation("DICOM Web Get Extended Query Tag Errors request received for extended query tag: {tagPath}", tagPath); + _logger.LogInformation("DICOM Web Get Extended Query Tag Errors request received for extended query tag: {TagPath}", tagPath); EnsureArg.IsNotNull(options, nameof(options)); EnsureFeatureIsEnabled(); @@ -195,7 +195,7 @@ public async Task GetTagErrorsAsync( public async Task UpdateTagAsync([FromRoute] string tagPath, [FromBody] UpdateExtendedQueryTagOptions newValue) { EnsureArg.IsNotNull(newValue, nameof(newValue)); - _logger.LogInformation("DICOM Web Update Extended Query Tag Query Status request received for extended query tag {tagPath} and new value {newValue}", tagPath, $"{nameof(newValue.QueryStatus)}: '{newValue.QueryStatus}'"); + _logger.LogInformation("DICOM Web Update Extended Query Tag Query Status request received for extended query tag {TagPath} and new value {NewValue}", tagPath, $"{nameof(newValue.QueryStatus)}: '{newValue.QueryStatus}'"); EnsureFeatureIsEnabled(); var response = await _mediator.UpdateExtendedQueryTagAsync(tagPath, newValue.ToEntry(), HttpContext.RequestAborted); diff --git a/src/Microsoft.Health.Dicom.Api/Controllers/QueryController.cs b/src/Microsoft.Health.Dicom.Api/Controllers/QueryController.cs index 2b459a7295..ff5025cd15 100644 --- a/src/Microsoft.Health.Dicom.Api/Controllers/QueryController.cs +++ b/src/Microsoft.Health.Dicom.Api/Controllers/QueryController.cs @@ -103,7 +103,7 @@ public async Task QueryForSeriesAsync([FromQuery] QueryOptions op [AuditEventType(AuditEventSubType.Query)] public async Task QueryForSeriesInStudyAsync([FromRoute] string studyInstanceUid, [FromQuery] QueryOptions options) { - _logger.LogInformation("DICOM Web Query Series request for study {studyInstanceUid} received. QueryString {RequestQueryString}.", studyInstanceUid, Request.QueryString); + _logger.LogInformation("DICOM Web Query Series request for study {StudyInstanceUid} received. QueryString {RequestQueryString}.", studyInstanceUid, Request.QueryString); EnsureArg.IsNotNull(options); var response = await _mediator.QueryDicomResourcesAsync( @@ -149,7 +149,7 @@ public async Task QueryForInstancesAsync([FromQuery] QueryOptions [AuditEventType(AuditEventSubType.Query)] public async Task QueryForInstancesInStudyAsync([FromRoute] string studyInstanceUid, [FromQuery] QueryOptions options) { - _logger.LogInformation("DICOM Web Query Instances for study {studyInstanceUid} received. QueryString {RequestQueryString}.", studyInstanceUid, Request.QueryString); + _logger.LogInformation("DICOM Web Query Instances for study {StudyInstanceUid} received. QueryString {RequestQueryString}.", studyInstanceUid, Request.QueryString); EnsureArg.IsNotNull(options); var response = await _mediator.QueryDicomResourcesAsync( @@ -172,7 +172,7 @@ public async Task QueryForInstancesInStudyAsync([FromRoute] strin [AuditEventType(AuditEventSubType.Query)] public async Task QueryForInstancesInSeriesAsync([FromRoute] string studyInstanceUid, [FromRoute] string seriesInstanceUid, [FromQuery] QueryOptions options) { - _logger.LogInformation("DICOM Web Query Instances for study {studyInstanceUid} and series {seriesInstanceUid} received. QueryString {RequestQueryString}.", studyInstanceUid, seriesInstanceUid, Request.QueryString); + _logger.LogInformation("DICOM Web Query Instances for study {StudyInstanceUid} and series {SeriesInstanceUid} received. QueryString {RequestQueryString}.", studyInstanceUid, seriesInstanceUid, Request.QueryString); EnsureArg.IsNotNull(options); var response = await _mediator.QueryDicomResourcesAsync( diff --git a/src/Microsoft.Health.Dicom.Api/Controllers/RetrieveController.cs b/src/Microsoft.Health.Dicom.Api/Controllers/RetrieveController.cs index ab575f9cd6..edee47e2ca 100644 --- a/src/Microsoft.Health.Dicom.Api/Controllers/RetrieveController.cs +++ b/src/Microsoft.Health.Dicom.Api/Controllers/RetrieveController.cs @@ -60,7 +60,7 @@ public RetrieveController(IMediator mediator, ILogger logger [AuditEventType(AuditEventSubType.Retrieve)] public async Task GetStudyAsync(string studyInstanceUid) { - _logger.LogInformation("DICOM Web Retrieve Transaction request received, for study: {studyInstanceUid}.", studyInstanceUid); + _logger.LogInformation("DICOM Web Retrieve Transaction request received, for study: {StudyInstanceUid}.", studyInstanceUid); RetrieveResourceResponse response = await _mediator.RetrieveDicomStudyAsync(studyInstanceUid, HttpContext.Request.GetAcceptHeaders(), HttpContext.RequestAborted); @@ -82,7 +82,7 @@ public async Task GetStudyAsync(string studyInstanceUid) [AuditEventType(AuditEventSubType.RetrieveMetadata)] public async Task GetStudyMetadataAsync([FromHeader(Name = IfNoneMatch)] string ifNoneMatch, string studyInstanceUid) { - _logger.LogInformation("DICOM Web Retrieve Metadata Transaction request received, for study: {studyInstanceUid}.", studyInstanceUid); + _logger.LogInformation("DICOM Web Retrieve Metadata Transaction request received, for study: {StudyInstanceUid}.", studyInstanceUid); RetrieveMetadataResponse response = await _mediator.RetrieveDicomStudyMetadataAsync(studyInstanceUid, ifNoneMatch, HttpContext.RequestAborted); @@ -104,7 +104,7 @@ public async Task GetSeriesAsync( string studyInstanceUid, string seriesInstanceUid) { - _logger.LogInformation("DICOM Web Retrieve Transaction request received, for study: {studyInstanceUid}, series: {seriesInstanceUid}.", studyInstanceUid, seriesInstanceUid); + _logger.LogInformation("DICOM Web Retrieve Transaction request received, for study: {StudyInstanceUid}, series: {SeriesInstanceUid}.", studyInstanceUid, seriesInstanceUid); RetrieveResourceResponse response = await _mediator.RetrieveDicomSeriesAsync( studyInstanceUid, seriesInstanceUid, HttpContext.Request.GetAcceptHeaders(), HttpContext.RequestAborted); @@ -127,7 +127,7 @@ public async Task GetSeriesAsync( [AuditEventType(AuditEventSubType.RetrieveMetadata)] public async Task GetSeriesMetadataAsync([FromHeader(Name = IfNoneMatch)] string ifNoneMatch, string studyInstanceUid, string seriesInstanceUid) { - _logger.LogInformation("DICOM Web Retrieve Metadata Transaction request received, for study: {studyInstanceUid}, series: {seriesInstanceUid}.", studyInstanceUid, seriesInstanceUid); + _logger.LogInformation("DICOM Web Retrieve Metadata Transaction request received, for study: {StudyInstanceUid}, series: {SeriesInstanceUid}.", studyInstanceUid, seriesInstanceUid); RetrieveMetadataResponse response = await _mediator.RetrieveDicomSeriesMetadataAsync( studyInstanceUid, seriesInstanceUid, ifNoneMatch, HttpContext.RequestAborted); @@ -151,7 +151,7 @@ public async Task GetInstanceAsync( string seriesInstanceUid, string sopInstanceUid) { - _logger.LogInformation("DICOM Web Retrieve Transaction request received, for study: '{studyInstanceUid}', series: '{seriesInstanceUid}', instance: '{sopInstanceUid}'.", studyInstanceUid, seriesInstanceUid, sopInstanceUid); + _logger.LogInformation("DICOM Web Retrieve Transaction request received, for study: '{StudyInstanceUid}', series: '{SeriesInstanceUid}', instance: '{SopInstanceUid}'.", studyInstanceUid, seriesInstanceUid, sopInstanceUid); RetrieveResourceResponse response = await _mediator.RetrieveDicomInstanceAsync( studyInstanceUid, seriesInstanceUid, sopInstanceUid, HttpContext.Request.GetAcceptHeaders(), HttpContext.RequestAborted); @@ -181,7 +181,7 @@ public async Task GetInstanceMetadataAsync( string seriesInstanceUid, string sopInstanceUid) { - _logger.LogInformation("DICOM Web Retrieve Metadata Transaction request received, for study: {studyInstanceUid}, series: {seriesInstanceUid}, instance: {sopInstanceUid}.", studyInstanceUid, seriesInstanceUid, sopInstanceUid); + _logger.LogInformation("DICOM Web Retrieve Metadata Transaction request received, for study: {StudyInstanceUid}, series: {SeriesInstanceUid}, instance: {SopInstanceUid}.", studyInstanceUid, seriesInstanceUid, sopInstanceUid); RetrieveMetadataResponse response = await _mediator.RetrieveDicomInstanceMetadataAsync( studyInstanceUid, seriesInstanceUid, sopInstanceUid, ifNoneMatch, HttpContext.RequestAborted); @@ -206,7 +206,7 @@ public async Task GetFramesAsync( string sopInstanceUid, [FromRoute][ModelBinder(typeof(IntArrayModelBinder))] int[] frames) { - _logger.LogInformation("DICOM Web Retrieve Transaction request received, for study: {studyInstanceUid}, series: {seriesInstanceUid}, instance: {sopInstanceUid}, frames: {frames}.", studyInstanceUid, seriesInstanceUid, sopInstanceUid, string.Join(", ", frames ?? Array.Empty())); + _logger.LogInformation("DICOM Web Retrieve Transaction request received, for study: {StudyInstanceUid}, series: {SeriesInstanceUid}, instance: {SopInstanceUid}, frames: {Frames}.", studyInstanceUid, seriesInstanceUid, sopInstanceUid, string.Join(", ", frames ?? Array.Empty())); RetrieveResourceResponse response = await _mediator.RetrieveDicomFramesAsync( studyInstanceUid, seriesInstanceUid, sopInstanceUid, frames, HttpContext.Request.GetAcceptHeaders(), HttpContext.RequestAborted); diff --git a/src/Microsoft.Health.Dicom.Api/Controllers/StoreController.cs b/src/Microsoft.Health.Dicom.Api/Controllers/StoreController.cs index a770e82363..b5166b4e45 100644 --- a/src/Microsoft.Health.Dicom.Api/Controllers/StoreController.cs +++ b/src/Microsoft.Health.Dicom.Api/Controllers/StoreController.cs @@ -85,7 +85,7 @@ public async Task PostInstanceInStudyAsync(string studyInstanceUi private async Task PostAsync(string studyInstanceUid) { long fileSize = Request.ContentLength ?? 0; - _logger.LogInformation("DICOM Web Store Transaction request received, with study instance UID {studyInstanceUid} and file size of {fileSize} bytes", studyInstanceUid, fileSize); + _logger.LogInformation("DICOM Web Store Transaction request received, with study instance UID {StudyInstanceUid} and file size of {FileSize} bytes", studyInstanceUid, fileSize); StoreResponse storeResponse = await _mediator.StoreDicomResourcesAsync( Request.Body, diff --git a/src/Microsoft.Health.Dicom.Api/Extensions/HttpResponseExtensions.cs b/src/Microsoft.Health.Dicom.Api/Extensions/HttpResponseExtensions.cs index 03cbbbc9a2..e97291ffa4 100644 --- a/src/Microsoft.Health.Dicom.Api/Extensions/HttpResponseExtensions.cs +++ b/src/Microsoft.Health.Dicom.Api/Extensions/HttpResponseExtensions.cs @@ -15,12 +15,14 @@ internal static class HttpResponseExtensions { public const string ErroneousAttributesHeader = "erroneous-dicom-attributes"; + private static readonly Uri ExampleRoot = new Uri("https://example.com/", UriKind.Absolute); + public static void AddLocationHeader(this HttpResponse response, Uri locationUrl) { EnsureArg.IsNotNull(response, nameof(response)); EnsureArg.IsNotNull(locationUrl, nameof(locationUrl)); - response.Headers.Add(HeaderNames.Location, Uri.EscapeUriString(locationUrl.ToString())); + response.Headers.Add(HeaderNames.Location, locationUrl.IsAbsoluteUri ? locationUrl.AbsoluteUri : GetRelativeUri(locationUrl)); } public static bool TryAddErroneousAttributesHeader(this HttpResponse response, IReadOnlyCollection erroneousAttributes) @@ -35,5 +37,10 @@ public static bool TryAddErroneousAttributesHeader(this HttpResponse response, I response.Headers.Add(ErroneousAttributesHeader, string.Join(",", erroneousAttributes)); return true; } + + private static string GetRelativeUri(Uri uri) + // ExampleRoot is necessary as GetComponents, like many of the URI members, throws an exception + // when used on relative URI instances. As a workaround, we make it absolute temporarily. + => new Uri(ExampleRoot, uri).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.SchemeAndServer & ~UriComponents.UserInfo, UriFormat.UriEscaped); } } diff --git a/src/Microsoft.Health.Dicom.Api/Features/Audit/AuditLogger.cs b/src/Microsoft.Health.Dicom.Api/Features/Audit/AuditLogger.cs index 7fc08109c0..3f0fd63293 100644 --- a/src/Microsoft.Health.Dicom.Api/Features/Audit/AuditLogger.cs +++ b/src/Microsoft.Health.Dicom.Api/Features/Audit/AuditLogger.cs @@ -71,6 +71,9 @@ public void LogAudit( customerHeadersInString = string.Join(";", customHeaders.Select(header => $"{header.Key}={header.Value}")); } +#pragma warning disable CA2254 + // AuditMessageFormat is not const and erroneously flags CA2254. + // While the template does indeed change per OS, it does not change the variables in use. _logger.LogInformation( AuditMessageFormat, auditAction, @@ -83,6 +86,7 @@ public void LogAudit( correlationId, claimsInString, customerHeadersInString); +#pragma warning restore CA2254 } } } diff --git a/src/Microsoft.Health.Dicom.Api/Features/Exceptions/ExceptionHandlingMiddleware.cs b/src/Microsoft.Health.Dicom.Api/Features/Exceptions/ExceptionHandlingMiddleware.cs index e84a3cb718..621d84344c 100644 --- a/src/Microsoft.Health.Dicom.Api/Features/Exceptions/ExceptionHandlingMiddleware.cs +++ b/src/Microsoft.Health.Dicom.Api/Features/Exceptions/ExceptionHandlingMiddleware.cs @@ -98,7 +98,7 @@ private IActionResult MapExceptionToResult(Exception exception) statusCode = HttpStatusCode.InternalServerError; break; case UnauthorizedDicomActionException udae: - _logger.LogInformation("Expected data actions not available: {dataActions}", udae.ExpectedDataActions); + _logger.LogInformation("Expected data actions not available: {DataActions}", udae.ExpectedDataActions); statusCode = HttpStatusCode.Forbidden; break; case DicomServerException _: diff --git a/src/Microsoft.Health.Dicom.Api/Microsoft.Health.Dicom.Api.csproj b/src/Microsoft.Health.Dicom.Api/Microsoft.Health.Dicom.Api.csproj index 00bc495614..c0169365db 100644 --- a/src/Microsoft.Health.Dicom.Api/Microsoft.Health.Dicom.Api.csproj +++ b/src/Microsoft.Health.Dicom.Api/Microsoft.Health.Dicom.Api.csproj @@ -2,7 +2,7 @@ Common components, such as controllers, for Microsoft's DICOMweb APIs using ASP.NET Core. - net5.0 + net6.0 @@ -14,10 +14,10 @@ - - - - + + + + @@ -27,9 +27,7 @@ - - - + diff --git a/src/Microsoft.Health.Dicom.Blob/Microsoft.Health.Dicom.Blob.csproj b/src/Microsoft.Health.Dicom.Blob/Microsoft.Health.Dicom.Blob.csproj index a66b21fd40..22a711ef51 100644 --- a/src/Microsoft.Health.Dicom.Blob/Microsoft.Health.Dicom.Blob.csproj +++ b/src/Microsoft.Health.Dicom.Blob/Microsoft.Health.Dicom.Blob.csproj @@ -2,7 +2,7 @@ Azure blob storage utilities for Microsoft's DICOMweb APIs. - net5.0 + net6.0 diff --git a/src/Microsoft.Health.Dicom.Client/Microsoft.Health.Dicom.Client.csproj b/src/Microsoft.Health.Dicom.Client/Microsoft.Health.Dicom.Client.csproj index 8d6d3de96b..bfed389513 100644 --- a/src/Microsoft.Health.Dicom.Client/Microsoft.Health.Dicom.Client.csproj +++ b/src/Microsoft.Health.Dicom.Client/Microsoft.Health.Dicom.Client.csproj @@ -2,7 +2,7 @@ Defines a RESTful client for interacting with DICOMweb APIs. - net5.0 + net6.0 @@ -15,13 +15,13 @@ - + IDicomWebClient.cs - + DicomWebClient.cs diff --git a/src/Microsoft.Health.Dicom.Core.UnitTests/Features/Store/Entries/DicomInstanceEntryReaderForSinglePartRequestTests.cs b/src/Microsoft.Health.Dicom.Core.UnitTests/Features/Store/Entries/DicomInstanceEntryReaderForSinglePartRequestTests.cs index 6a92eb645d..aa22505a63 100644 --- a/src/Microsoft.Health.Dicom.Core.UnitTests/Features/Store/Entries/DicomInstanceEntryReaderForSinglePartRequestTests.cs +++ b/src/Microsoft.Health.Dicom.Core.UnitTests/Features/Store/Entries/DicomInstanceEntryReaderForSinglePartRequestTests.cs @@ -3,12 +3,12 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- +using System.Buffers; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Options; using Microsoft.Health.Abstractions.Exceptions; using Microsoft.Health.Dicom.Core.Configs; @@ -149,12 +149,21 @@ public async Task ConvertAsync(Stream stream, CancellationToken cancella MemoryStream seekableStream = new MemoryStream(); stream.CopyTo(seekableStream); - await seekableStream.DrainAsync(cancellationToken); + await DrainAsync(seekableStream, cancellationToken); seekableStream.Seek(0, SeekOrigin.Begin); return seekableStream; } + + private static async Task DrainAsync(Stream stream, CancellationToken cancellationToken = default) + { + const int bufferSize = 4096; + using IMemoryOwner bufferOwner = MemoryPool.Shared.Rent(bufferSize); + + while (await stream.ReadAsync(bufferOwner.Memory, cancellationToken) > 0) + { } + } } } } diff --git a/src/Microsoft.Health.Dicom.Core.UnitTests/Microsoft.Health.Dicom.Core.UnitTests.csproj b/src/Microsoft.Health.Dicom.Core.UnitTests/Microsoft.Health.Dicom.Core.UnitTests.csproj index 0ae9d38638..874cef5bc2 100644 --- a/src/Microsoft.Health.Dicom.Core.UnitTests/Microsoft.Health.Dicom.Core.UnitTests.csproj +++ b/src/Microsoft.Health.Dicom.Core.UnitTests/Microsoft.Health.Dicom.Core.UnitTests.csproj @@ -1,14 +1,13 @@ - net5.0 + net6.0 - @@ -18,10 +17,9 @@ - + - diff --git a/src/Microsoft.Health.Dicom.Core/Features/Common/DicomTagParser.cs b/src/Microsoft.Health.Dicom.Core/Features/Common/DicomTagParser.cs index 335b181f0f..1a87c50c0f 100644 --- a/src/Microsoft.Health.Dicom.Core/Features/Common/DicomTagParser.cs +++ b/src/Microsoft.Health.Dicom.Core/Features/Common/DicomTagParser.cs @@ -56,12 +56,12 @@ private static DicomTag ParseDicomTagNumber(string s) return null; } - if (!ushort.TryParse(s.Substring(0, 4), NumberStyles.HexNumber, null, out ushort group)) + if (!ushort.TryParse(s.AsSpan(0, 4), NumberStyles.HexNumber, null, out ushort group)) { return null; } - if (!ushort.TryParse(s.Substring(4, 4), NumberStyles.HexNumber, null, out ushort element)) + if (!ushort.TryParse(s.AsSpan(4, 4), NumberStyles.HexNumber, null, out ushort element)) { return null; } diff --git a/src/Microsoft.Health.Dicom.Core/Features/Delete/DeleteService.cs b/src/Microsoft.Health.Dicom.Core/Features/Delete/DeleteService.cs index 700e776c44..c24bdb3440 100644 --- a/src/Microsoft.Health.Dicom.Core/Features/Delete/DeleteService.cs +++ b/src/Microsoft.Health.Dicom.Core/Features/Delete/DeleteService.cs @@ -119,16 +119,16 @@ public Task DeleteInstanceNowAsync(string studyInstanceUid, string seriesInstanc int newRetryCount = await _indexDataStore.IncrementDeletedInstanceRetryAsync(deletedInstanceIdentifier, GenerateCleanupAfter(_deletedInstanceCleanupConfiguration.RetryBackOff), cancellationToken); if (newRetryCount > _deletedInstanceCleanupConfiguration.MaxRetries) { - _logger.LogCritical(cleanupException, "Failed to cleanup instance {deletedInstanceIdentifier}. Retry count is now {newRetryCount} and retry will not be re-attempted.", deletedInstanceIdentifier, newRetryCount); + _logger.LogCritical(cleanupException, "Failed to cleanup instance {DeletedInstanceIdentifier}. Retry count is now {NewRetryCount} and retry will not be re-attempted.", deletedInstanceIdentifier, newRetryCount); } else { - _logger.LogError(cleanupException, "Failed to cleanup instance {deletedInstanceIdentifier}. Retry count is now {newRetryCount}.", deletedInstanceIdentifier, newRetryCount); + _logger.LogError(cleanupException, "Failed to cleanup instance {DeletedInstanceIdentifier}. Retry count is now {NewRetryCount}.", deletedInstanceIdentifier, newRetryCount); } } catch (Exception incrementException) { - _logger.LogCritical(incrementException, "Failed to increment cleanup retry for instance {deletedInstanceIdentifier}.", deletedInstanceIdentifier); + _logger.LogCritical(incrementException, "Failed to increment cleanup retry for instance {DeletedInstanceIdentifier}.", deletedInstanceIdentifier); success = false; } } diff --git a/src/Microsoft.Health.Dicom.Core/Features/Partition/PartitionCache.cs b/src/Microsoft.Health.Dicom.Core/Features/Partition/PartitionCache.cs index dadec0588b..69e6584542 100644 --- a/src/Microsoft.Health.Dicom.Core/Features/Partition/PartitionCache.cs +++ b/src/Microsoft.Health.Dicom.Core/Features/Partition/PartitionCache.cs @@ -72,7 +72,7 @@ public async Task GetOrAddPartitionAsync(Func AddPartitionAsync(string partitionName, { EnsureArg.IsNotNull(partitionName, nameof(partitionName)); - _logger.LogInformation("Creating partition with name '{partitionName}'.", partitionName); + _logger.LogInformation("Creating partition with name '{PartitionName}'.", partitionName); var partitionEntry = await _partitionCache.GetOrAddPartitionAsync(_partitionStore.AddPartitionAsync, partitionName, cancellationToken); @@ -40,7 +40,7 @@ public async Task GetPartitionAsync(string partitionName, { EnsureArg.IsNotNull(partitionName, nameof(partitionName)); - _logger.LogInformation("Getting partition with name '{partitionName}'.", partitionName); + _logger.LogInformation("Getting partition with name '{PartitionName}'.", partitionName); var partitionEntry = await _partitionCache.GetOrAddPartitionAsync(_partitionStore.GetPartitionAsync, partitionName, cancellationToken); return new GetPartitionResponse(partitionEntry); diff --git a/src/Microsoft.Health.Dicom.Core/Features/Retrieve/RetrieveTransferSyntaxHandler.cs b/src/Microsoft.Health.Dicom.Core/Features/Retrieve/RetrieveTransferSyntaxHandler.cs index bdca819ee8..385c5eb6ac 100644 --- a/src/Microsoft.Health.Dicom.Core/Features/Retrieve/RetrieveTransferSyntaxHandler.cs +++ b/src/Microsoft.Health.Dicom.Core/Features/Retrieve/RetrieveTransferSyntaxHandler.cs @@ -49,7 +49,7 @@ public string GetTransferSyntax(ResourceType resourceType, IEnumerable 1) diff --git a/src/Microsoft.Health.Dicom.Core/Features/Validation/LongStringValidation.cs b/src/Microsoft.Health.Dicom.Core/Features/Validation/LongStringValidation.cs index 2c670f8606..a1c874d841 100644 --- a/src/Microsoft.Health.Dicom.Core/Features/Validation/LongStringValidation.cs +++ b/src/Microsoft.Health.Dicom.Core/Features/Validation/LongStringValidation.cs @@ -33,7 +33,7 @@ public static void Validate(string value, string name) ElementMaxLengthValidation.Validate(value, 64, name, DicomVR.LO); - if (value.Contains("\\", StringComparison.OrdinalIgnoreCase) || ContainsControlExceptEsc(value)) + if (value.Contains('\\', StringComparison.OrdinalIgnoreCase) || ContainsControlExceptEsc(value)) { throw ElementValidationExceptionFactory.CreateInvalidCharactersException(name, DicomVR.LO, value); } diff --git a/src/Microsoft.Health.Dicom.Core/Microsoft.Health.Dicom.Core.csproj b/src/Microsoft.Health.Dicom.Core/Microsoft.Health.Dicom.Core.csproj index f899774fd1..c50999956d 100644 --- a/src/Microsoft.Health.Dicom.Core/Microsoft.Health.Dicom.Core.csproj +++ b/src/Microsoft.Health.Dicom.Core/Microsoft.Health.Dicom.Core.csproj @@ -2,7 +2,7 @@ Common primitives and utilities used by Microsoft's DICOMweb APIs. - netcoreapp3.1;net5.0 + net6.0 @@ -12,7 +12,7 @@ - + diff --git a/src/Microsoft.Health.Dicom.Functions/Microsoft.Health.Dicom.Functions.csproj b/src/Microsoft.Health.Dicom.Functions/Microsoft.Health.Dicom.Functions.csproj index 666d98d3d3..db99492e12 100644 --- a/src/Microsoft.Health.Dicom.Functions/Microsoft.Health.Dicom.Functions.csproj +++ b/src/Microsoft.Health.Dicom.Functions/Microsoft.Health.Dicom.Functions.csproj @@ -1,9 +1,9 @@ - v3 + v4 true - netcoreapp3.1 + net6.0 @@ -16,7 +16,7 @@ - + diff --git a/src/Microsoft.Health.Dicom.Metadata/Microsoft.Health.Dicom.Metadata.csproj b/src/Microsoft.Health.Dicom.Metadata/Microsoft.Health.Dicom.Metadata.csproj index 7e547085c7..0dd24192af 100644 --- a/src/Microsoft.Health.Dicom.Metadata/Microsoft.Health.Dicom.Metadata.csproj +++ b/src/Microsoft.Health.Dicom.Metadata/Microsoft.Health.Dicom.Metadata.csproj @@ -2,7 +2,7 @@ Utilities for managing a metadata store for use within Microsoft's DICOMweb APIs. - netcoreapp3.1;net5.0 + net6.0 diff --git a/src/Microsoft.Health.Dicom.Operations.Client.UnitTests/Microsoft.Health.Dicom.Operations.Client.UnitTests.csproj b/src/Microsoft.Health.Dicom.Operations.Client.UnitTests/Microsoft.Health.Dicom.Operations.Client.UnitTests.csproj index 5ae9fa5027..4cfdeb9d37 100644 --- a/src/Microsoft.Health.Dicom.Operations.Client.UnitTests/Microsoft.Health.Dicom.Operations.Client.UnitTests.csproj +++ b/src/Microsoft.Health.Dicom.Operations.Client.UnitTests/Microsoft.Health.Dicom.Operations.Client.UnitTests.csproj @@ -1,13 +1,13 @@ - net5.0 + net6.0 false - + diff --git a/src/Microsoft.Health.Dicom.Operations.Client/Microsoft.Health.Dicom.Operations.Client.csproj b/src/Microsoft.Health.Dicom.Operations.Client/Microsoft.Health.Dicom.Operations.Client.csproj index a1ecf15664..029a0aff1d 100644 --- a/src/Microsoft.Health.Dicom.Operations.Client/Microsoft.Health.Dicom.Operations.Client.csproj +++ b/src/Microsoft.Health.Dicom.Operations.Client/Microsoft.Health.Dicom.Operations.Client.csproj @@ -2,7 +2,7 @@ Defines a client for interacting with the DICOM Azure Functions. - net5.0 + net6.0 diff --git a/src/Microsoft.Health.Dicom.Operations.UnitTests/Microsoft.Health.Dicom.Operations.UnitTests.csproj b/src/Microsoft.Health.Dicom.Operations.UnitTests/Microsoft.Health.Dicom.Operations.UnitTests.csproj index 38897199e8..41a5dd4c31 100644 --- a/src/Microsoft.Health.Dicom.Operations.UnitTests/Microsoft.Health.Dicom.Operations.UnitTests.csproj +++ b/src/Microsoft.Health.Dicom.Operations.UnitTests/Microsoft.Health.Dicom.Operations.UnitTests.csproj @@ -2,7 +2,7 @@ false - netcoreapp3.1 + net6.0 @@ -12,9 +12,9 @@ - + - + diff --git a/src/Microsoft.Health.Dicom.Operations/Microsoft.Health.Dicom.Operations.csproj b/src/Microsoft.Health.Dicom.Operations/Microsoft.Health.Dicom.Operations.csproj index 76d4430742..d1cc435862 100644 --- a/src/Microsoft.Health.Dicom.Operations/Microsoft.Health.Dicom.Operations.csproj +++ b/src/Microsoft.Health.Dicom.Operations/Microsoft.Health.Dicom.Operations.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 @@ -14,12 +14,11 @@ - + - diff --git a/src/Microsoft.Health.Dicom.SqlServer.UnitTests/Microsoft.Health.Dicom.SqlServer.UnitTests.csproj b/src/Microsoft.Health.Dicom.SqlServer.UnitTests/Microsoft.Health.Dicom.SqlServer.UnitTests.csproj index 74b07b5fdf..ab56944865 100644 --- a/src/Microsoft.Health.Dicom.SqlServer.UnitTests/Microsoft.Health.Dicom.SqlServer.UnitTests.csproj +++ b/src/Microsoft.Health.Dicom.SqlServer.UnitTests/Microsoft.Health.Dicom.SqlServer.UnitTests.csproj @@ -1,14 +1,14 @@ - net5.0 + net6.0 - + diff --git a/src/Microsoft.Health.Dicom.SqlServer/Extensions/ILoggerExtensions.cs b/src/Microsoft.Health.Dicom.SqlServer/Extensions/ILoggerExtensions.cs new file mode 100644 index 0000000000..29a1a0414e --- /dev/null +++ b/src/Microsoft.Health.Dicom.SqlServer/Extensions/ILoggerExtensions.cs @@ -0,0 +1,23 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.Diagnostics; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Health.Dicom.SqlServer.Extensions +{ + internal static class ILoggerExtensions + { + private static readonly Action LogSuccess = + LoggerMessage.Define( + LogLevel.Information, + default, + "SQL stored procedure '{Name}' successfully executed after {ElapsedMs} ms"); + + public static void StoredProcedureSucceeded(this ILogger logger, string name, Stopwatch sw) + => LogSuccess(logger, name, sw.ElapsedMilliseconds, null); + } +} diff --git a/src/Microsoft.Health.Dicom.SqlServer/Features/ChangeFeed/SqlChangeFeedStoreV4.cs b/src/Microsoft.Health.Dicom.SqlServer/Features/ChangeFeed/SqlChangeFeedStoreV4.cs index e7dd9c893a..671b79da4a 100644 --- a/src/Microsoft.Health.Dicom.SqlServer/Features/ChangeFeed/SqlChangeFeedStoreV4.cs +++ b/src/Microsoft.Health.Dicom.SqlServer/Features/ChangeFeed/SqlChangeFeedStoreV4.cs @@ -18,7 +18,7 @@ namespace Microsoft.Health.Dicom.SqlServer.Features.ChangeFeed { - public class SqlChangeFeedStoreV4 : ISqlChangeFeedStore + internal class SqlChangeFeedStoreV4 : ISqlChangeFeedStore { public virtual SchemaVersion Version => SchemaVersion.V4; diff --git a/src/Microsoft.Health.Dicom.SqlServer/Features/ChangeFeed/SqlChangeFeedStoreV6.cs b/src/Microsoft.Health.Dicom.SqlServer/Features/ChangeFeed/SqlChangeFeedStoreV6.cs index 6fb80ba321..b1cb0c50a8 100644 --- a/src/Microsoft.Health.Dicom.SqlServer/Features/ChangeFeed/SqlChangeFeedStoreV6.cs +++ b/src/Microsoft.Health.Dicom.SqlServer/Features/ChangeFeed/SqlChangeFeedStoreV6.cs @@ -17,7 +17,7 @@ namespace Microsoft.Health.Dicom.SqlServer.Features.ChangeFeed { - public class SqlChangeFeedStoreV6 : SqlChangeFeedStoreV4 + internal class SqlChangeFeedStoreV6 : SqlChangeFeedStoreV4 { public override SchemaVersion Version => SchemaVersion.V6; diff --git a/src/Microsoft.Health.Dicom.SqlServer/Features/ExtendedQueryTag/SqlExtendedQueryTagStoreV2.cs b/src/Microsoft.Health.Dicom.SqlServer/Features/ExtendedQueryTag/SqlExtendedQueryTagStoreV2.cs index e67a68e8e8..458cf022bd 100644 --- a/src/Microsoft.Health.Dicom.SqlServer/Features/ExtendedQueryTag/SqlExtendedQueryTagStoreV2.cs +++ b/src/Microsoft.Health.Dicom.SqlServer/Features/ExtendedQueryTag/SqlExtendedQueryTagStoreV2.cs @@ -17,6 +17,7 @@ using Microsoft.Health.Dicom.Core; using Microsoft.Health.Dicom.Core.Exceptions; using Microsoft.Health.Dicom.Core.Features.ExtendedQueryTag; +using Microsoft.Health.Dicom.SqlServer.Extensions; using Microsoft.Health.Dicom.SqlServer.Features.Schema; using Microsoft.Health.Dicom.SqlServer.Features.Schema.Model; using Microsoft.Health.SqlServer.Features.Client; @@ -119,7 +120,7 @@ public override async Task GetExtendedQueryTagAs V2.ExtendedQueryTag.TagStatus); executionTimeWatch.Stop(); - Logger.LogInformation(executionTimeWatch.ElapsedMilliseconds.ToString()); + Logger.StoredProcedureSucceeded(nameof(V2.GetExtendedQueryTag), executionTimeWatch); return new ExtendedQueryTagStoreJoinEntry(tagKey, tagPath, tagVR, tagPrivateCreator, (QueryTagLevel)tagLevel, (ExtendedQueryTagStatus)tagStatus, QueryStatus.Enabled, 0); } @@ -186,7 +187,7 @@ private async Task> GetAllExtendedQueryTags } executionTimeWatch.Stop(); - Logger.LogInformation(executionTimeWatch.ElapsedMilliseconds.ToString()); + Logger.StoredProcedureSucceeded(nameof(V2.GetExtendedQueryTag), executionTimeWatch); } } diff --git a/src/Microsoft.Health.Dicom.SqlServer/Features/ExtendedQueryTag/SqlExtendedQueryTagStoreV4.cs b/src/Microsoft.Health.Dicom.SqlServer/Features/ExtendedQueryTag/SqlExtendedQueryTagStoreV4.cs index fb1a3ca55f..53a8ccf20d 100644 --- a/src/Microsoft.Health.Dicom.SqlServer/Features/ExtendedQueryTag/SqlExtendedQueryTagStoreV4.cs +++ b/src/Microsoft.Health.Dicom.SqlServer/Features/ExtendedQueryTag/SqlExtendedQueryTagStoreV4.cs @@ -68,7 +68,7 @@ public override async Task> GetExt } executionTimeWatch.Stop(); - Logger.LogInformation(executionTimeWatch.ElapsedMilliseconds.ToString()); + Logger.StoredProcedureSucceeded(nameof(VLatest.GetExtendedQueryTags), executionTimeWatch); } } @@ -102,7 +102,7 @@ public override async Task GetExtendedQueryTagAs VLatest.ExtendedQueryTagOperation.OperationId.AsNullable()); executionTimeWatch.Stop(); - Logger.LogInformation(executionTimeWatch.ElapsedMilliseconds.ToString()); + Logger.StoredProcedureSucceeded(nameof(VLatest.GetExtendedQueryTag), executionTimeWatch); return new ExtendedQueryTagStoreJoinEntry(tagKey, tagPath, tagVR, tagPrivateCreator, (QueryTagLevel)tagLevel, (ExtendedQueryTagStatus)tagStatus, (QueryStatus)queryStatus, errorCount, operationId); } @@ -142,7 +142,7 @@ public override async Task> GetExt } executionTimeWatch.Stop(); - Logger.LogInformation(executionTimeWatch.ElapsedMilliseconds.ToString()); + Logger.StoredProcedureSucceeded(nameof(VLatest.GetExtendedQueryTagsByKey), executionTimeWatch); } } diff --git a/src/Microsoft.Health.Dicom.SqlServer/Features/Query/SqlQueryStoreV4.cs b/src/Microsoft.Health.Dicom.SqlServer/Features/Query/SqlQueryStoreV4.cs index 6394636fdc..72c998b4f2 100644 --- a/src/Microsoft.Health.Dicom.SqlServer/Features/Query/SqlQueryStoreV4.cs +++ b/src/Microsoft.Health.Dicom.SqlServer/Features/Query/SqlQueryStoreV4.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Data; +using System.Diagnostics.CodeAnalysis; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -78,6 +79,7 @@ public virtual async Task QueryAsync( return new QueryResult(results); } + [SuppressMessage("Usage", "CA2254:Template should be a static expression", Justification = "Template does not contain placeholders.")] protected void LogSqlCommand(SqlCommandWrapper sqlCommandWrapper) { var sb = new StringBuilder(); diff --git a/src/Microsoft.Health.Dicom.SqlServer/Features/Store/SqlIndexDataStoreV1.cs b/src/Microsoft.Health.Dicom.SqlServer/Features/Store/SqlIndexDataStoreV1.cs index 6674e1371f..0116b22c3d 100644 --- a/src/Microsoft.Health.Dicom.SqlServer/Features/Store/SqlIndexDataStoreV1.cs +++ b/src/Microsoft.Health.Dicom.SqlServer/Features/Store/SqlIndexDataStoreV1.cs @@ -315,7 +315,7 @@ SELECT MIN({VLatest.DeletedInstance.DeletedDateTime}) { await sqlDataReader.ReadAsync(cancellationToken); - if (sqlDataReader.IsDBNull(0)) + if (await sqlDataReader.IsDBNullAsync(0, cancellationToken)) { return DateTimeOffset.UtcNow; } diff --git a/src/Microsoft.Health.Dicom.SqlServer/Microsoft.Health.Dicom.SqlServer.csproj b/src/Microsoft.Health.Dicom.SqlServer/Microsoft.Health.Dicom.SqlServer.csproj index 7ef7372725..9e025e48a5 100644 --- a/src/Microsoft.Health.Dicom.SqlServer/Microsoft.Health.Dicom.SqlServer.csproj +++ b/src/Microsoft.Health.Dicom.SqlServer/Microsoft.Health.Dicom.SqlServer.csproj @@ -2,7 +2,7 @@ SQL Server extensions and utilities used by Microsoft's DICOMweb APIs. - netcoreapp3.1;net5.0 + net6.0 diff --git a/src/Microsoft.Health.Dicom.Tests.Common/Microsoft.Health.Dicom.Tests.Common.csproj b/src/Microsoft.Health.Dicom.Tests.Common/Microsoft.Health.Dicom.Tests.Common.csproj index 896ec5b629..95332b6bcc 100644 --- a/src/Microsoft.Health.Dicom.Tests.Common/Microsoft.Health.Dicom.Tests.Common.csproj +++ b/src/Microsoft.Health.Dicom.Tests.Common/Microsoft.Health.Dicom.Tests.Common.csproj @@ -2,13 +2,13 @@ true - netcoreapp3.1;net5.0 + net6.0 - + diff --git a/src/Microsoft.Health.Dicom.Tests.Common/TranscoderTests/TranscoderTestDataHelper.cs b/src/Microsoft.Health.Dicom.Tests.Common/TranscoderTests/TranscoderTestDataHelper.cs index 769cdad3e3..68ca9bff48 100644 --- a/src/Microsoft.Health.Dicom.Tests.Common/TranscoderTests/TranscoderTestDataHelper.cs +++ b/src/Microsoft.Health.Dicom.Tests.Common/TranscoderTests/TranscoderTestDataHelper.cs @@ -6,9 +6,7 @@ using System; using System.Collections.Generic; using System.IO; -using System.Security.Cryptography; using System.Text.Json; -using EnsureThat; namespace Microsoft.Health.Dicom.Tests.Common.TranscoderTests { @@ -79,14 +77,6 @@ public static IEnumerable GetTestDatas(string testDataRootFo } } - public static string GetHashFromStream(Stream byteStream) - { - EnsureArg.IsNotNull(byteStream, nameof(byteStream)); - byte[] result = ToByteArray(byteStream); - using var sha256Managed = new SHA256Managed(); - return Convert.ToBase64String(sha256Managed.ComputeHash(result)); - } - private static byte[] ToByteArray(Stream stream) { using (var memoryStream = new MemoryStream()) diff --git a/src/Microsoft.Health.Dicom.Web/Dockerfile b/src/Microsoft.Health.Dicom.Web/Dockerfile index d1c2ea295c..4f581fa851 100644 --- a/src/Microsoft.Health.Dicom.Web/Dockerfile +++ b/src/Microsoft.Health.Dicom.Web/Dockerfile @@ -1,7 +1,7 @@ # See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. # Define the "runtime" image which will run the DICOM Server -FROM mcr.microsoft.com/dotnet/aspnet:5.0.11-alpine3.13@sha256:2b67665d62471d30de99340361d516d4555a9276cb4ff78fb09db784384b1574 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:6.0.0-alpine3.14@sha256:1c893087b6d9cfe54d025dfeeda385358e79dcedd9a16f6ccdc9e5aa080db0f6 AS runtime RUN set -x && \ # See https://www.abhith.net/blog/docker-sql-error-on-aspnet-core-alpine/ apk add --no-cache icu-libs && \ @@ -13,7 +13,7 @@ EXPOSE 8080 USER nonroot # Copy the DICOM Server project and build it -FROM mcr.microsoft.com/dotnet/sdk:5.0.402-alpine3.13@sha256:f08db3184fc8fbb12dd4a9d12eb2e3c0a36ca60a4dd13759edde22605fbd00bd AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0.100-alpine3.14@sha256:1d9d66775f0d67cb68af9c7a083d22b576ea96f3f7a6893660d48f536b73e59f AS build ARG BUILD_CONFIGURATION=Release ARG CONTINUOUS_INTEGRATION_BUILD=false WORKDIR /dicom-server diff --git a/src/Microsoft.Health.Dicom.Web/Microsoft.Health.Dicom.Web.csproj b/src/Microsoft.Health.Dicom.Web/Microsoft.Health.Dicom.Web.csproj index 590c417ecb..05a1b2bd74 100644 --- a/src/Microsoft.Health.Dicom.Web/Microsoft.Health.Dicom.Web.csproj +++ b/src/Microsoft.Health.Dicom.Web/Microsoft.Health.Dicom.Web.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 true 5af726e8-ef4d-4c66-9d3a-25b8d546261e @@ -10,13 +10,12 @@ - + - + - diff --git a/test/Microsoft.Health.Dicom.Tests.Integration/Features/TranscoderTests.cs b/test/Microsoft.Health.Dicom.Tests.Integration/Features/TranscoderTests.cs index dd51f13cd6..3eaddf20e5 100644 --- a/test/Microsoft.Health.Dicom.Tests.Integration/Features/TranscoderTests.cs +++ b/test/Microsoft.Health.Dicom.Tests.Integration/Features/TranscoderTests.cs @@ -152,7 +152,7 @@ private string GetFramesHashCode(DicomFile dicomFile) private string GetByteArrayHashCode(byte[] byteArray) { - return Convert.ToBase64String(new SHA1Managed().ComputeHash(byteArray)); + return Convert.ToBase64String(HashAlgorithm.Create(nameof(SHA1)).ComputeHash(byteArray)); } } } diff --git a/test/Microsoft.Health.Dicom.Tests.Integration/Microsoft.Health.Dicom.Tests.Integration.csproj b/test/Microsoft.Health.Dicom.Tests.Integration/Microsoft.Health.Dicom.Tests.Integration.csproj index b7f3ac38b7..44432c4031 100644 --- a/test/Microsoft.Health.Dicom.Tests.Integration/Microsoft.Health.Dicom.Tests.Integration.csproj +++ b/test/Microsoft.Health.Dicom.Tests.Integration/Microsoft.Health.Dicom.Tests.Integration.csproj @@ -1,7 +1,7 @@ - + - net5.0 + net6.0 true false @@ -22,13 +22,14 @@ - + - + + diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Microsoft.Health.Dicom.Web.Tests.E2E.csproj b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Microsoft.Health.Dicom.Web.Tests.E2E.csproj index a368577fe5..1861003bfa 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Microsoft.Health.Dicom.Web.Tests.E2E.csproj +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Microsoft.Health.Dicom.Web.Tests.E2E.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 true false @@ -18,7 +18,7 @@ - + diff --git a/tools/scale-testing/Common/Common.csproj b/tools/scale-testing/Common/Common.csproj index c7164cb1b4..7db6987dfc 100644 --- a/tools/scale-testing/Common/Common.csproj +++ b/tools/scale-testing/Common/Common.csproj @@ -1,14 +1,14 @@ - net5.0 + net6.0 - + - + diff --git a/tools/scale-testing/MessageHandler/MessageHandler.csproj b/tools/scale-testing/MessageHandler/MessageHandler.csproj index 531314a3e8..ffe6946af7 100644 --- a/tools/scale-testing/MessageHandler/MessageHandler.csproj +++ b/tools/scale-testing/MessageHandler/MessageHandler.csproj @@ -1,12 +1,12 @@ - + Exe - net5.0 + net6.0 - - - + + + diff --git a/tools/scale-testing/MessageHandler/Program.cs b/tools/scale-testing/MessageHandler/Program.cs index 2209e06db4..40c085fa9f 100644 --- a/tools/scale-testing/MessageHandler/Program.cs +++ b/tools/scale-testing/MessageHandler/Program.cs @@ -47,11 +47,11 @@ public static async Task Main() }; var client = new SecretClient(new Uri(KnownApplicationUrls.KeyVaultUrl), new DefaultAzureCredential(), options); - KeyVaultSecret secret = client.GetSecret(KnownSecretNames.ServiceBusConnectionString); + KeyVaultSecret secret = await client.GetSecretAsync(KnownSecretNames.ServiceBusConnectionString); s_serviceBusConnectionString = secret.Value; - secret = client.GetSecret(KnownSecretNames.AppConfigurationConnectionString); + secret = await client.GetSecretAsync(KnownSecretNames.AppConfigurationConnectionString); var builder = new ConfigurationBuilder(); builder.AddAzureAppConfiguration(secret.Value); diff --git a/tools/scale-testing/MessageUploader/MessageUploader.csproj b/tools/scale-testing/MessageUploader/MessageUploader.csproj index 62549654b9..82fc715c18 100644 --- a/tools/scale-testing/MessageUploader/MessageUploader.csproj +++ b/tools/scale-testing/MessageUploader/MessageUploader.csproj @@ -1,12 +1,12 @@ - + Exe - net5.0 + net6.0 - - - + + + diff --git a/tools/scale-testing/MessageUploader/Program.cs b/tools/scale-testing/MessageUploader/Program.cs index ece5914f8d..70b7545d55 100644 --- a/tools/scale-testing/MessageUploader/Program.cs +++ b/tools/scale-testing/MessageUploader/Program.cs @@ -41,7 +41,7 @@ public static async Task Main(string[] args) }; var client = new SecretClient(new Uri(KnownApplicationUrls.KeyVaultUrl), new DefaultAzureCredential(), options); - KeyVaultSecret secret = client.GetSecret(KnownSecretNames.ServiceBusConnectionString); + KeyVaultSecret secret = await client.GetSecretAsync(KnownSecretNames.ServiceBusConnectionString); s_serviceBusConnectionString = secret.Value; s_topicName = args[0]; diff --git a/tools/scale-testing/PersonInstanceGenerator/PersonInstanceGenerator.csproj b/tools/scale-testing/PersonInstanceGenerator/PersonInstanceGenerator.csproj index f87056ca82..0fd541783b 100644 --- a/tools/scale-testing/PersonInstanceGenerator/PersonInstanceGenerator.csproj +++ b/tools/scale-testing/PersonInstanceGenerator/PersonInstanceGenerator.csproj @@ -2,13 +2,13 @@ Exe - net5.0 + net6.0 - - - + + + diff --git a/tools/scale-testing/PersonInstanceGenerator/Program.cs b/tools/scale-testing/PersonInstanceGenerator/Program.cs index 7fe83252b0..87d51d8fce 100644 --- a/tools/scale-testing/PersonInstanceGenerator/Program.cs +++ b/tools/scale-testing/PersonInstanceGenerator/Program.cs @@ -143,7 +143,7 @@ public static async Task Main(string[] args) }; var client = new SecretClient(new Uri(KnownApplicationUrls.KeyVaultUrl), new DefaultAzureCredential(), options); - KeyVaultSecret secret = client.GetSecret(KnownSecretNames.ServiceBusConnectionString); + KeyVaultSecret secret = await client.GetSecretAsync(KnownSecretNames.ServiceBusConnectionString); s_serviceBusConnectionString = secret.Value; @@ -210,7 +210,7 @@ public static async Task Main(string[] args) // Send the message to the topic await s_topicClient.SendAsync(message); - sw.WriteLine(patient); + await sw.WriteLineAsync(patient); } catch (Exception exception) { diff --git a/tools/scale-testing/QidoFunctionApp/QidoFunctionApp.csproj b/tools/scale-testing/QidoFunctionApp/QidoFunctionApp.csproj index 28bfa4ad0b..c228cf1c70 100644 --- a/tools/scale-testing/QidoFunctionApp/QidoFunctionApp.csproj +++ b/tools/scale-testing/QidoFunctionApp/QidoFunctionApp.csproj @@ -1,16 +1,28 @@ + - net5.0 - v3 + net6.0 + v4 + - - - + + + + + + + + + + + + + PreserveNewest @@ -20,4 +32,5 @@ Never + diff --git a/tools/scale-testing/QidoQueryGenerator/QidoQueryGenerator.csproj b/tools/scale-testing/QidoQueryGenerator/QidoQueryGenerator.csproj index cffae21c5c..83d1a62f1c 100644 --- a/tools/scale-testing/QidoQueryGenerator/QidoQueryGenerator.csproj +++ b/tools/scale-testing/QidoQueryGenerator/QidoQueryGenerator.csproj @@ -2,7 +2,7 @@ Exe - net5.0 + net6.0 diff --git a/tools/scale-testing/RetrieveBlobNames/Program.cs b/tools/scale-testing/RetrieveBlobNames/Program.cs index 312a1b8cfd..f6b93816df 100644 --- a/tools/scale-testing/RetrieveBlobNames/Program.cs +++ b/tools/scale-testing/RetrieveBlobNames/Program.cs @@ -39,7 +39,7 @@ public static async Task Main(string[] args) }; var client = new SecretClient(new Uri(KnownApplicationUrls.KeyVaultUrl), new DefaultAzureCredential(), options); - KeyVaultSecret secret = client.GetSecret(KnownSecretNames.BlobStoreConnectionString); + KeyVaultSecret secret = await client.GetSecretAsync(KnownSecretNames.BlobStoreConnectionString); s_containerConnectionString = secret.Value; @@ -56,7 +56,7 @@ public static async Task Main(string[] args) string[] parsedInstanceName = blob.Name.Split(KnownSeparators.MessageSeparators, StringSplitOptions.RemoveEmptyEntries); studies.Add(parsedInstanceName[0]); series.Add(parsedInstanceName[0] + " " + parsedInstanceName[1]); - sw.WriteLine(blob.Name); + await sw.WriteLineAsync(blob.Name); i++; Console.WriteLine(blob.Name + " Count:" + i); } diff --git a/tools/scale-testing/RetrieveBlobNames/RetrieveBlobNames.csproj b/tools/scale-testing/RetrieveBlobNames/RetrieveBlobNames.csproj index 185d7a6701..9ddcbf6f81 100644 --- a/tools/scale-testing/RetrieveBlobNames/RetrieveBlobNames.csproj +++ b/tools/scale-testing/RetrieveBlobNames/RetrieveBlobNames.csproj @@ -2,14 +2,14 @@ Exe - net5.0 + net6.0 - - + + - + diff --git a/tools/scale-testing/StowFunctionApp/StowFunctionApp.csproj b/tools/scale-testing/StowFunctionApp/StowFunctionApp.csproj index 979d06570e..c228cf1c70 100644 --- a/tools/scale-testing/StowFunctionApp/StowFunctionApp.csproj +++ b/tools/scale-testing/StowFunctionApp/StowFunctionApp.csproj @@ -1,16 +1,28 @@ - + + - net5.0 - v3 + net6.0 + v4 + - - - + + + + + + + + + + + + + PreserveNewest @@ -20,4 +32,5 @@ Never + diff --git a/tools/scale-testing/WadoFunctionApp/WadoFunctionApp.csproj b/tools/scale-testing/WadoFunctionApp/WadoFunctionApp.csproj index 28bfa4ad0b..189bc09903 100644 --- a/tools/scale-testing/WadoFunctionApp/WadoFunctionApp.csproj +++ b/tools/scale-testing/WadoFunctionApp/WadoFunctionApp.csproj @@ -1,16 +1,27 @@ + - net5.0 - v3 + net6.0 + v4 + - - - + + + + + + + + + + + + PreserveNewest @@ -20,4 +31,5 @@ Never + diff --git a/tools/scale-testing/WadoMetadataFunctionApp/WadoMetadataFunctionApp.csproj b/tools/scale-testing/WadoMetadataFunctionApp/WadoMetadataFunctionApp.csproj index 979d06570e..7b91b5d5dc 100644 --- a/tools/scale-testing/WadoMetadataFunctionApp/WadoMetadataFunctionApp.csproj +++ b/tools/scale-testing/WadoMetadataFunctionApp/WadoMetadataFunctionApp.csproj @@ -1,16 +1,27 @@  + - net5.0 - v3 + net6.0 + v4 + - - - + + + + + + + + + + + + PreserveNewest @@ -20,4 +31,5 @@ Never + diff --git a/tools/scale-testing/templates/default-azuredeploy.json b/tools/scale-testing/templates/default-azuredeploy.json index 861e75aff1..997c073302 100644 --- a/tools/scale-testing/templates/default-azuredeploy.json +++ b/tools/scale-testing/templates/default-azuredeploy.json @@ -129,13 +129,13 @@ "resources": [ { "apiVersion": "2015-08-01", - "name": "AspNetCoreRuntime.5.0.x64", + "name": "AspNetCoreRuntime.6.0.x64", "type": "siteextensions", "dependsOn": [ "[variables('appServiceResourceId')]" ], "properties": { - "version": "5.0.11" + "version": "6.0.0" } } ]