Skip to content

Include export status for every file #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Api/Monai.Deploy.InformaticsGateway.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</PackageReference>
<PackageReference Include="Macross.Json.Extensions" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="6.0.9" />
<PackageReference Include="Monai.Deploy.Messaging" Version="0.1.6" />
<PackageReference Include="Monai.Deploy.Messaging" Version="0.1.7-rc0009" />
<PackageReference Include="Monai.Deploy.Storage" Version="0.2.7" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!--
<!--
~ Copyright 2021-2022 MONAI Consortium
~
~ Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -30,7 +30,7 @@
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageReference Include="Monai.Deploy.Messaging" Version="0.1.6" />
<PackageReference Include="Monai.Deploy.Messaging" Version="0.1.7-rc0009" />
<PackageReference Include="Monai.Deploy.Storage" Version="0.2.7" />
<PackageReference Include="System.IO.Abstractions" Version="17.2.3" />
</ItemGroup>
Expand Down
15 changes: 10 additions & 5 deletions src/InformaticsGateway/Logging/Log.500.ExportService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public static partial class Log
[LoggerMessage(EventId = 501, Level = LogLevel.Warning, Message = "{ServiceName} paused due to insufficient storage space. Available storage space: {availableFreeSpace:D}.")]
public static partial void ExportPausedDueToInsufficientStorageSpace(this ILogger logger, string serviceName, long availableFreeSpace);

[LoggerMessage(EventId = 502, Level = LogLevel.Warning, Message = "The export request {exportTaskId} is already queued for export.")]
public static partial void ExportRequestAlreadyQueued(this ILogger logger, string exportTaskId);
[LoggerMessage(EventId = 502, Level = LogLevel.Warning, Message = "Correlation ID={correlationId}. The export request {exportTaskId} is already queued for export.")]
public static partial void ExportRequestAlreadyQueued(this ILogger logger, string correlationId, string exportTaskId);

[LoggerMessage(EventId = 503, Level = LogLevel.Debug, Message = "Downloading {file}.")]
public static partial void DownloadingFile(this ILogger logger, string file);
Expand All @@ -49,8 +49,8 @@ public static partial class Log
[LoggerMessage(EventId = 508, Level = LogLevel.Error, Message = "Error acknowledging message. Waiting {timeSpan} before next retry. Retry attempt {retryCount}.")]
public static partial void ErrorAcknowledgingMessageWithRetry(this ILogger logger, Exception ex, TimeSpan timeSpan, int retryCount);

[LoggerMessage(EventId = 509, Level = LogLevel.Information, Message = "Sending acknowledgement.")]
public static partial void SendingAckowledgement(this ILogger logger);
[LoggerMessage(EventId = 509, Level = LogLevel.Information, Message = "Sending acknowledgment.")]
public static partial void SendingAcknowledgement(this ILogger logger);

[LoggerMessage(EventId = 510, Level = LogLevel.Error, Message = "Error publishing message. Waiting {timeSpan} before next retry. Retry attempt {retryCount}.")]
public static partial void ErrorPublishingExportCompleteEventWithRetry(this ILogger logger, Exception ex, TimeSpan timeSpan, int retryCount);
Expand Down Expand Up @@ -109,13 +109,18 @@ public static partial class Log
[LoggerMessage(EventId = 528, Level = LogLevel.Error, Message = "Failed to export with error {status}.")]
public static partial void DimseExportInstanceError(this ILogger logger, DicomStatus status);

[LoggerMessage(EventId = 529, Level = LogLevel.Error, Message = "Error while adding DICOM C-STORE request: {message}")]
[LoggerMessage(EventId = 529, Level = LogLevel.Error, Message = "{message}")]
public static partial void DimseExportErrorAddingInstance(this ILogger logger, string message, Exception ex);

[LoggerMessage(EventId = 530, Level = LogLevel.Error, Message = "{message}")]
public static partial void ExportException(this ILogger logger, string message, Exception ex);

[LoggerMessage(EventId = 531, Level = LogLevel.Warning, Message = "Export service paused due to insufficient storage space. Available storage space: {availableFreeSpace:D}")]
public static partial void ExportServiceStoppedDueToLowStorageSpace(this ILogger logger, long availableFreeSpace);

[LoggerMessage(EventId = 532, Level = LogLevel.Information, Message = "Correlation ID={correlationId}. Export request {exportTaskId} received & queued for processing.")]
public static partial void ExportRequestQueuedForProcessing(this ILogger logger, string correlationId, string exportTaskId);


}
}
4 changes: 2 additions & 2 deletions src/InformaticsGateway/Monai.Deploy.InformaticsGateway.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!--
<!--
~ Copyright 2022 MONAI Consortium
~
~ Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -48,7 +48,7 @@
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageReference Include="Monai.Deploy.Messaging.RabbitMQ" Version="0.1.6" />
<PackageReference Include="Monai.Deploy.Messaging.RabbitMQ" Version="0.1.7-rc0009" />
<PackageReference Include="Monai.Deploy.Storage" Version="0.2.7" />
<PackageReference Include="Monai.Deploy.Storage.MinIO" Version="0.2.7" />
<PackageReference Include="Polly" Version="7.2.3" />
Expand Down
23 changes: 18 additions & 5 deletions src/InformaticsGateway/Services/Export/DicomWebExportService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
using Monai.Deploy.InformaticsGateway.Logging;
using Monai.Deploy.InformaticsGateway.Repositories;
using Monai.Deploy.InformaticsGateway.Services.Common;
using Monai.Deploy.Messaging.Events;
using Polly;

namespace Monai.Deploy.InformaticsGateway.Services.Export
Expand Down Expand Up @@ -74,7 +75,7 @@ public DicomWebExportService(

protected override async Task<ExportRequestDataMessage> ExportDataBlockCallback(ExportRequestDataMessage exportRequestData, CancellationToken cancellationToken)
{
using var loggerScope = _logger.BeginScope(new LoggingDataDictionary<string, object> { { "ExportTaskId", exportRequestData.ExportTaskId }, { "CorrelationId", exportRequestData.CorrelationId } });
using var loggerScope = _logger.BeginScope(new LoggingDataDictionary<string, object> { { "ExportTaskId", exportRequestData.ExportTaskId }, { "CorrelationId", exportRequestData.CorrelationId }, { "Filename", exportRequestData.Filename } });

using var scope = _serviceScopeFactory.CreateScope();
var repository = scope.ServiceProvider.GetRequiredService<IInferenceRequestRepository>();
Expand All @@ -98,7 +99,7 @@ private async Task HandleTransaction(ExportRequestDataMessage exportRequestData,
{
var errorMessage = $"The specified inference request '{transaction}' cannot be found and will not be exported.";
_logger.InferenceRequestExportDestinationNotFound(transaction);
exportRequestData.SetFailed(errorMessage);
exportRequestData.SetFailed(FileExportStatus.ConfigurationError, errorMessage);
return;
}

Expand All @@ -108,7 +109,7 @@ private async Task HandleTransaction(ExportRequestDataMessage exportRequestData,
{
var errorMessage = "The inference request '{transaction}' contains no `outputResources` nor any DICOMweb export destinations.";
_logger.InferenceRequestExportNoDestinationNotFound();
exportRequestData.SetFailed(errorMessage);
exportRequestData.SetFailed(FileExportStatus.ConfigurationError, errorMessage);
return;
}

Expand All @@ -126,9 +127,21 @@ private async Task HandleTransaction(ExportRequestDataMessage exportRequestData,

private async Task ExportToDicomWebDestination(IDicomWebClient dicomWebClient, ExportRequestDataMessage exportRequestData, RequestOutputDataResource destination, CancellationToken cancellationToken)
{
DicomFile dicomFile;
try
{
dicomFile = _dicomToolkit.Load(exportRequestData.FileContent);
}
catch (Exception ex)
{
var errorMessage = $"Error reading DICOM file: {ex.Message}.";
_logger.ExportException(errorMessage, ex);
exportRequestData.SetFailed(FileExportStatus.UnsupportedDataType, errorMessage);
return;
}

try
{
var dicomFile = _dicomToolkit.Load(exportRequestData.FileContent);
await Policy
.Handle<Exception>()
.WaitAndRetryAsync(
Expand All @@ -147,7 +160,7 @@ await Policy
{
var errorMessage = ex.Message;
_logger.ExportException(errorMessage, ex);
exportRequestData.SetFailed(errorMessage);
exportRequestData.SetFailed(FileExportStatus.ServiceError, errorMessage);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class ExportRequestDataMessage
public byte[] FileContent { get; private set; }
public bool IsFailed { get; private set; }
public IList<string> Messages { get; init; }
public FileExportStatus ExportStatus { get; private set; }
public string Filename { get; }

public string ExportTaskId
{
Expand All @@ -44,15 +46,14 @@ public string[] Destinations
get { return _exportRequest.Destinations; }
}

public string Filename { get; }

public ExportRequestDataMessage(ExportRequestEvent exportRequest, string filename)
{
IsFailed = false;
Messages = new List<string>();

_exportRequest = exportRequest ?? throw new System.ArgumentNullException(nameof(exportRequest));
Filename = filename ?? throw new System.ArgumentNullException(nameof(filename));
ExportStatus = FileExportStatus.Success;
}

public void SetData(byte[] data)
Expand All @@ -61,9 +62,11 @@ public void SetData(byte[] data)
FileContent = data;
}

public void SetFailed(string errorMessage)
public void SetFailed(FileExportStatus fileExportStatus, string errorMessage)
{
Guard.Against.NullOrWhiteSpace(errorMessage, nameof(errorMessage));

ExportStatus = fileExportStatus;
IsFailed = true;
Messages.Add(errorMessage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ public ExportRequestEventDetails(ExportRequestEvent exportRequest)
/// <summary>
/// Gets whether the export task is completed or not based on file count.
/// </summary>
public bool IsCompleted
{ get { return (SucceededFiles + FailedFiles) == Files.Count(); } }
public bool IsCompleted { get { return (SucceededFiles + FailedFiles) == Files.Count(); } }

public Dictionary<string, FileExportStatus> FileStatuses { get; private set; } = new Dictionary<string, FileExportStatus>();


public ExportStatus Status
{
Expand Down
11 changes: 7 additions & 4 deletions src/InformaticsGateway/Services/Export/ExportServiceBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private void OnMessageReceivedCallback(MessageReceivedEventArgs eventArgs)
var exportRequest = eventArgs.Message.ConvertTo<ExportRequestEvent>();
if (_exportRequests.ContainsKey(exportRequest.ExportTaskId))
{
_logger.ExportRequestAlreadyQueued(exportRequest.ExportTaskId);
_logger.ExportRequestAlreadyQueued(exportRequest.CorrelationId, exportRequest.ExportTaskId);
return;
}

Expand All @@ -174,6 +174,7 @@ private void OnMessageReceivedCallback(MessageReceivedEventArgs eventArgs)

_exportRequests.Add(exportRequest.ExportTaskId, exportRequestWithDetails);
exportFlow.Post(exportRequestWithDetails);
_logger.ExportRequestQueuedForProcessing(exportRequest.CorrelationId, exportRequest.ExportTaskId);
}

exportFlow.Complete();
Expand Down Expand Up @@ -229,7 +230,7 @@ private IEnumerable<ExportRequestDataMessage> DownloadPayloadActionCallback(Expo
{
var errorMessage = $"Error downloading payload.";
_logger.ErrorDownloadingPayload(ex);
exportRequestData.SetFailed(errorMessage);
exportRequestData.SetFailed(FileExportStatus.DownloadError, errorMessage);
}

yield return exportRequestData;
Expand All @@ -243,6 +244,7 @@ private void ReportingActionBlock(ExportRequestDataMessage exportRequestData)
var exportRequest = _exportRequests[exportRequestData.ExportTaskId];
lock (SyncRoot)
{
exportRequest.FileStatuses.Add(exportRequestData.Filename, exportRequestData.ExportStatus);
if (exportRequestData.IsFailed)
{
exportRequest.FailedFiles++;
Expand All @@ -265,7 +267,8 @@ private void ReportingActionBlock(ExportRequestDataMessage exportRequestData)

_logger.ExportCompleted(exportRequest.FailedFiles, exportRequest.Files.Count());

var exportCompleteEvent = new ExportCompleteEvent(exportRequest, exportRequest.Status);
var exportCompleteEvent = new ExportCompleteEvent(exportRequest, exportRequest.Status, exportRequest.FileStatuses);

var jsonMessage = new JsonMessage<ExportCompleteEvent>(exportCompleteEvent, MessageBrokerConfiguration.InformaticsGatewayApplicationId, exportRequest.CorrelationId, exportRequest.DeliveryTag);

Policy
Expand All @@ -278,7 +281,7 @@ private void ReportingActionBlock(ExportRequestDataMessage exportRequestData)
})
.Execute(() =>
{
_logger.SendingAckowledgement();
_logger.SendingAcknowledgement();
_messageSubscriber.Acknowledge(jsonMessage);
});

Expand Down
23 changes: 18 additions & 5 deletions src/InformaticsGateway/Services/Export/ScuExportService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using System.Threading;
using System.Threading.Tasks;
using Ardalis.GuardClauses;
using FellowOakDicom;
using FellowOakDicom.Network;
using FellowOakDicom.Network.Client;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -30,6 +31,7 @@
using Monai.Deploy.InformaticsGateway.Configuration;
using Monai.Deploy.InformaticsGateway.Logging;
using Monai.Deploy.InformaticsGateway.Repositories;
using Monai.Deploy.Messaging.Events;
using Polly;

namespace Monai.Deploy.InformaticsGateway.Services.Export
Expand Down Expand Up @@ -86,7 +88,7 @@ private async Task HandleDesination(ExportRequestDataMessage exportRequestData,
catch (ConfigurationException ex)
{
_logger.ScuExportConfigurationError(ex.Message, ex);
exportRequestData.SetFailed(ex.Message);
exportRequestData.SetFailed(FileExportStatus.ConfigurationError, ex.Message);
return;
}

Expand Down Expand Up @@ -155,10 +157,21 @@ private async Task<bool> GenerateRequestsAsync(
IDicomClient client,
ManualResetEvent manualResetEvent)
{
DicomFile dicomFile;
try
{
var dicomFile = _dicomToolkit.Load(exportRequestData.FileContent);
dicomFile = _dicomToolkit.Load(exportRequestData.FileContent);
}
catch (Exception ex)
{
var errorMessage = $"Error reading DICOM file: {ex.Message}";
_logger.ExportException(errorMessage, ex);
exportRequestData.SetFailed(FileExportStatus.UnsupportedDataType, errorMessage);
return false;
}

try
{
var request = new DicomCStoreRequest(dicomFile);

request.OnResponseReceived += (req, response) =>
Expand All @@ -171,7 +184,7 @@ private async Task<bool> GenerateRequestsAsync(
{
var errorMessage = $"Failed to export with error {response.Status}";
_logger.DimseExportInstanceError(response.Status);
exportRequestData.SetFailed(errorMessage);
exportRequestData.SetFailed(FileExportStatus.ServiceError, errorMessage);
}
manualResetEvent.Set();
};
Expand All @@ -183,7 +196,7 @@ private async Task<bool> GenerateRequestsAsync(
{
var errorMessage = $"Error while adding DICOM C-STORE request: {exception.Message}";
_logger.DimseExportErrorAddingInstance(exception.Message, exception);
exportRequestData.SetFailed(errorMessage);
exportRequestData.SetFailed(FileExportStatus.ServiceError, errorMessage);
return false;
}
}
Expand Down Expand Up @@ -213,7 +226,7 @@ private void HandleCStoreException(Exception ex, ExportRequestDataMessage export
}

_logger.ExportException(errorMessage, ex);
exportRequestData.SetFailed(errorMessage);
exportRequestData.SetFailed(FileExportStatus.ServiceError, errorMessage);
}
}
}
Loading