Skip to content
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

Ai 357 #505

Merged
merged 4 commits into from
Jan 19, 2024
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/Storage/Hl7FileStorageMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace Monai.Deploy.InformaticsGateway.Api.Storage
public sealed record Hl7FileStorageMetadata : FileStorageMetadata
{
public const string Hl7SubDirectoryName = "ehr";
public const string FileExtension = ".txt";
public const string FileExtension = ".hl7";

/// <inheritdoc/>
[JsonIgnore]
Expand Down
3 changes: 3 additions & 0 deletions src/InformaticsGateway/Logging/Log.5000.DataPlugins.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,8 @@ public static partial class Log

[LoggerMessage(EventId = 5007, Level = LogLevel.Error, Message = "Error executing plug-in: {plugin}.")]
public static partial void ErrorAddingOutputDataPlugIn(this ILogger logger, Exception d, string plugin);

[LoggerMessage(EventId = 5008, Level = LogLevel.Trace, Message = "Import plugin executed: {pluginName}. now: {fileMetadata}")]
public static partial void InputDataPlugInEngineexecuted(this ILogger logger, string pluginName, string fileMetadata);
}
}
17 changes: 13 additions & 4 deletions src/InformaticsGateway/Logging/Log.800.Hl7Service.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ public static partial class Log
[LoggerMessage(EventId = 809, Level = LogLevel.Debug, Message = "Acknowledgment type={value}.")]
public static partial void AcknowledgmentType(this ILogger logger, string value);

[LoggerMessage(EventId = 810, Level = LogLevel.Information, Message = "Acknowledgment sent: length={length}.")]
public static partial void AcknowledgmentSent(this ILogger logger, int length);
[LoggerMessage(EventId = 810, Level = LogLevel.Information, Message = "Acknowledgment sent message:{message} length:{length}.")]
public static partial void AcknowledgmentSent(this ILogger logger, string message, int length);

[LoggerMessage(EventId = 811, Level = LogLevel.Debug, Message = "HL7 bytes received: {length}.")]
public static partial void Hl7MessageBytesRead(this ILogger logger, int length);

[LoggerMessage(EventId = 812, Level = LogLevel.Debug, Message = "Parsing message with {length} bytes.")]
public static partial void Hl7GenerateMessage(this ILogger logger, int length);
[LoggerMessage(EventId = 812, Level = LogLevel.Debug, Message = "Parsing message with {length} bytes. {message}")]
public static partial void Hl7GenerateMessage(this ILogger logger, int length, string message);

[LoggerMessage(EventId = 813, Level = LogLevel.Debug, Message = "Waiting for HL7 message.")]
public static partial void HL7ReadingMessage(this ILogger logger);
Expand Down Expand Up @@ -105,5 +105,14 @@ public static partial class Log
[LoggerMessage(EventId = 827, Level = LogLevel.Warning, Message = "HL7 plugin loading exceptions")]
public static partial void HL7PluginLoadingExceptions(this ILogger logger, Exception ex);

[LoggerMessage(EventId = 828, Level = LogLevel.Information, Message = "HL7 message recieved. {message}")]
public static partial void Hl7MessageReceieved(this ILogger logger, string message);

[LoggerMessage(EventId = 829, Level = LogLevel.Trace, Message = "HL7 config Not matching message Id {senderId} configId {configID}")]
public static partial void Hl7NotMatchingConfig(this ILogger logger, string senderId, string configID);

[LoggerMessage(EventId = 830, Level = LogLevel.Error, Message = "Error generating HL7 acknowledgment. for message {message}")]
public static partial void ErrorGeneratingHl7Acknowledgment(this ILogger logger, Exception ex, string message);

}
}
1 change: 1 addition & 0 deletions src/InformaticsGateway/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@
ext.RegisterLayoutRenderer("servicename", logEvent => typeof(Program).Namespace);
ext.RegisterLayoutRenderer("serviceversion", logEvent => assemblyVersionNumber);
ext.RegisterLayoutRenderer("machinename", logEvent => Environment.MachineName);
ext.RegisterLayoutRenderer("appname", logEvent => "MIG");

Check warning on line 185 in src/InformaticsGateway/Program.cs

View check run for this annotation

Codecov / codecov/patch

src/InformaticsGateway/Program.cs#L185

Added line #L185 was not covered by tests
})
.LoadConfigurationFromAppSettings()
.GetCurrentClassLogger();
Expand Down
11 changes: 7 additions & 4 deletions src/InformaticsGateway/Services/Common/InputDataPluginEngine.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using FellowOakDicom;
using Microsoft.Extensions.Logging;
Expand All @@ -31,7 +32,7 @@ internal class InputDataPlugInEngine : IInputDataPlugInEngine
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<InputDataPlugInEngine> _logger;
private IReadOnlyList<IInputDataPlugIn>? _plugsins;
private IReadOnlyList<IInputDataPlugIn>? _plugins;

public InputDataPlugInEngine(IServiceProvider serviceProvider, ILogger<InputDataPlugInEngine> logger)
{
Expand All @@ -41,20 +42,22 @@ public InputDataPlugInEngine(IServiceProvider serviceProvider, ILogger<InputData

public void Configure(IReadOnlyList<string> pluginAssemblies)
{
_plugsins = LoadPlugIns(_serviceProvider, pluginAssemblies);
_plugins = LoadPlugIns(_serviceProvider, pluginAssemblies);
}

public async Task<Tuple<DicomFile, FileStorageMetadata>> ExecutePlugInsAsync(DicomFile dicomFile, FileStorageMetadata fileMetadata)
{
if (_plugsins == null)
if (_plugins == null)
{
throw new PlugInInitializationException("InputDataPlugInEngine not configured, please call Configure() first.");
}

foreach (var plugin in _plugsins)
foreach (var plugin in _plugins)
{
_logger.ExecutingInputDataPlugIn(plugin.Name);
(dicomFile, fileMetadata) = await plugin.ExecuteAsync(dicomFile, fileMetadata).ConfigureAwait(false);

_logger.InputDataPlugInEngineexecuted(plugin.Name, JsonSerializer.Serialize(fileMetadata));
}

return new Tuple<DicomFile, FileStorageMetadata>(dicomFile, fileMetadata);
Expand Down
20 changes: 11 additions & 9 deletions src/InformaticsGateway/Services/Common/InputHL7DataPlugInEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,22 @@ public void Configure(IReadOnlyList<string> pluginAssemblies)

public async Task<Tuple<Message, FileStorageMetadata>> ExecutePlugInsAsync(Message hl7File, FileStorageMetadata fileMetadata, Hl7ApplicationConfigEntity? configItem)
{
if (_plugsins == null)
if (configItem?.PlugInAssemblies is not null && configItem.PlugInAssemblies.Any())
{
throw new PlugInInitializationException("InputHL7DataPlugInEngine not configured, please call Configure() first.");
}
if (_plugsins == null)
{
throw new PlugInInitializationException("InputHL7DataPlugInEngine not configured, please call Configure() first.");
}

foreach (var plugin in _plugsins)
{
if (configItem is not null && configItem.PlugInAssemblies.Exists(a => a.StartsWith(plugin.ToString()!)))
foreach (var plugin in _plugsins)
{
_logger.ExecutingInputDataPlugIn(plugin.Name);
(hl7File, fileMetadata) = await plugin.ExecuteAsync(hl7File, fileMetadata).ConfigureAwait(false);
if (configItem is not null && configItem.PlugInAssemblies.Exists(a => a.StartsWith(plugin.ToString()!)))
{
_logger.ExecutingInputDataPlugIn(plugin.Name);
(hl7File, fileMetadata) = await plugin.ExecuteAsync(hl7File, fileMetadata).ConfigureAwait(false);
}
}
}

return new Tuple<Message, FileStorageMetadata>(hl7File, fileMetadata);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ private async void OnTimedEvent(Object? source, System.Timers.ElapsedEventArgs e
}
foreach (var key in _payloads.Keys)
{
var payload = await _payloads[key].WithCancellation(_tokenSource.Token);
var payload = await _payloads[key].WithCancellation(_tokenSource.Token).ConfigureAwait(false);
using var loggerScope = _logger.BeginScope(new LoggingDataDictionary<string, object> { { "CorrelationId", payload.CorrelationId } });

_logger.BucketElapsedTime(key, payload.Timeout, payload.ElapsedTime().TotalSeconds, payload.Files.Count, payload.FilesUploaded, payload.FilesFailedToUpload);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using System;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
Expand Down Expand Up @@ -169,6 +170,8 @@ private async Task SendArtifactRecievedEvent(Payload payload)
};
artifiactRecievedEvent.DataOrigins.AddRange(payload.DataOrigins);

_logger.LogTrace($"Adding files to ArtifactsReceivedEvent files {JsonSerializer.Serialize(payload)}");

artifiactRecievedEvent.Artifacts = payload.Files.Select(f => new Artifact { Type = f.DataOrigin.ArtifactType, Path = f.File.UploadPath }).ToList();

var message = new JsonMessage<ArtifactsReceivedEvent>(
Expand Down
3 changes: 2 additions & 1 deletion src/InformaticsGateway/Services/Export/Hl7ExportService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
using Monai.Deploy.InformaticsGateway.Api.Mllp;
using Monai.Deploy.Messaging.Common;
using Polly;
using System.Linq;

namespace Monai.Deploy.InformaticsGateway.Services.Export
{
Expand Down Expand Up @@ -119,7 +120,7 @@ private async Task ExecuteHl7Export(
.ExecuteAsync(async () =>
{
await _mllpService.SendMllp(
IPAddress.Parse(destination.HostIp),
Dns.GetHostAddresses(destination.HostIp).First(),
destination.Port, Encoding.UTF8.GetString(exportRequestData.FileContent),
cancellationToken
).ConfigureAwait(false);
Expand Down
28 changes: 23 additions & 5 deletions src/InformaticsGateway/Services/HealthLevel7/MllpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,31 @@

if (ShouldSendAcknowledgment(message))
{
var ackMessage = message.GetACK();
Message ackMessage = message;
try
{
ackMessage = message.GetACK(false);
}
catch (Exception ex)

Check warning on line 167 in src/InformaticsGateway/Services/HealthLevel7/MllpClient.cs

View check run for this annotation

Codecov / codecov/patch

src/InformaticsGateway/Services/HealthLevel7/MllpClient.cs#L167

Added line #L167 was not covered by tests
{
_logger.ErrorGeneratingHl7Acknowledgment(ex, message.HL7Message);
_exceptions.Add(ex);
return;

Check warning on line 171 in src/InformaticsGateway/Services/HealthLevel7/MllpClient.cs

View check run for this annotation

Codecov / codecov/patch

src/InformaticsGateway/Services/HealthLevel7/MllpClient.cs#L169-L171

Added lines #L169 - L171 were not covered by tests
}

if (ackMessage is null)
{
var ex = new Exception("Error generating HL7 acknowledgment.");
_logger.ErrorGeneratingHl7Acknowledgment(ex, message.HL7Message);
_exceptions.Add(ex);
return;

Check warning on line 179 in src/InformaticsGateway/Services/HealthLevel7/MllpClient.cs

View check run for this annotation

Codecov / codecov/patch

src/InformaticsGateway/Services/HealthLevel7/MllpClient.cs#L176-L179

Added lines #L176 - L179 were not covered by tests
}
var ackData = new ReadOnlyMemory<byte>(ackMessage.GetMLLP());
try
{
await clientStream.WriteAsync(ackData, cancellationToken).ConfigureAwait(false);
await clientStream.FlushAsync(cancellationToken).ConfigureAwait(false);
_logger.AcknowledgmentSent(ackData.Length);
_logger.AcknowledgmentSent(ackMessage.HL7Message, ackData.Length);
}
catch (Exception ex)
{
Expand All @@ -181,7 +199,7 @@
try
{
var value = message.DefaultSegment(Resources.MessageHeaderSegment).Fields(Resources.AcceptAcknowledgementType);
if (value is null)
if (value is null || string.IsNullOrWhiteSpace(value.Value))
{
return true;
}
Expand Down Expand Up @@ -211,9 +229,9 @@
try
{
var text = data.Substring(messageStartIndex, endIndex - messageStartIndex);
_logger.Hl7GenerateMessage(text.Length);
_logger.Hl7GenerateMessage(text.Length, text);
message = new Message(text);
message.ParseMessage();
message.ParseMessage(false);
data = data.Length > endIndex ? data.Substring(messageEndIndex) : string.Empty;
return true;
}
Expand Down
34 changes: 16 additions & 18 deletions src/InformaticsGateway/Services/HealthLevel7/MllpExtract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using FellowOakDicom;
Expand All @@ -29,19 +30,11 @@

namespace Monai.Deploy.InformaticsGateway.Api.Mllp
{
public sealed class MllpExtract : IMllpExtract
public sealed class MllpExtract(IHl7ApplicationConfigRepository hl7ApplicationConfigRepository, IExternalAppDetailsRepository externalAppDetailsRepository, ILogger<MllpExtract> logger) : IMllpExtract
{
private readonly ILogger<MllpExtract> _logger;
private readonly IHl7ApplicationConfigRepository _hl7ApplicationConfigRepository;
private readonly IExternalAppDetailsRepository _externalAppDetailsRepository;

public MllpExtract(IHl7ApplicationConfigRepository hl7ApplicationConfigRepository, IExternalAppDetailsRepository externalAppDetailsRepository, ILogger<MllpExtract> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_hl7ApplicationConfigRepository = hl7ApplicationConfigRepository ?? throw new ArgumentNullException(nameof(hl7ApplicationConfigRepository));
_externalAppDetailsRepository = externalAppDetailsRepository ?? throw new ArgumentNullException(nameof(externalAppDetailsRepository));
}

private readonly ILogger<MllpExtract> _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly IHl7ApplicationConfigRepository _hl7ApplicationConfigRepository = hl7ApplicationConfigRepository ?? throw new ArgumentNullException(nameof(hl7ApplicationConfigRepository));
private readonly IExternalAppDetailsRepository _externalAppDetailsRepository = externalAppDetailsRepository ?? throw new ArgumentNullException(nameof(externalAppDetailsRepository));

public async Task<Message> ExtractInfo(Hl7FileStorageMetadata meta, Message message, Hl7ApplicationConfigEntity configItem)
{
Expand Down Expand Up @@ -87,7 +80,7 @@ public async Task<Message> ExtractInfo(Hl7FileStorageMetadata meta, Message mess
_logger.Hl7NoConfig();
return null;
}
_logger.Hl7ConfigLoaded($"Config: {config}");
_logger.Hl7ConfigLoaded($"Config: {JsonSerializer.Serialize(config)}");
// get config for vendorId
var configItem = GetConfig(config, message);
if (configItem == null)
Expand Down Expand Up @@ -115,15 +108,20 @@ public async Task<Message> ExtractInfo(Hl7FileStorageMetadata meta, Message mess
throw new Exception($"Invalid DataLinkType: {type}");
}

internal static Hl7ApplicationConfigEntity? GetConfig(List<Hl7ApplicationConfigEntity> config, Message message)
internal Hl7ApplicationConfigEntity? GetConfig(List<Hl7ApplicationConfigEntity> config, Message message)
{
foreach (var item in config)
{
var t = message.GetValue(item.SendingId.Key);
if (item.SendingId.Value == message.GetValue(item.SendingId.Key))
var sendingId = message.GetValue(item.SendingId.Key);
if (item.SendingId.Value == sendingId)
{
_logger.Hl7FoundMatchingConfig(sendingId, JsonSerializer.Serialize(item));
return item;
}
else
{
_logger.Hl7NotMatchingConfig(sendingId, item.SendingId.Value);
}
}
return null;
}
Expand All @@ -143,7 +141,7 @@ private Message RepopulateMessage(Hl7ApplicationConfigEntity config, ExternalApp
{
var newMess = message.HL7Message.Replace(oldvalue, details.PatientId);
message = new Message(newMess);
message.ParseMessage();
message.ParseMessage(true);
}
}
else if (tag == DicomTag.StudyInstanceUID)
Expand All @@ -155,7 +153,7 @@ private Message RepopulateMessage(Hl7ApplicationConfigEntity config, ExternalApp
{
var newMess = message.HL7Message.Replace(oldvalue, details.StudyInstanceUid);
message = new Message(newMess);
message.ParseMessage();
message.ParseMessage(true);
}
}
}
Expand Down
Loading
Loading