diff --git a/src/FhirPseudonymizer/Controllers/FhirController.cs b/src/FhirPseudonymizer/Controllers/FhirController.cs index 7be10e6..b08fea7 100644 --- a/src/FhirPseudonymizer/Controllers/FhirController.cs +++ b/src/FhirPseudonymizer/Controllers/FhirController.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Health.Fhir.Anonymizer.Core; +using Prometheus; namespace FhirPseudonymizer.Controllers { @@ -27,6 +28,15 @@ namespace FhirPseudonymizer.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] public class FhirController : ControllerBase { + private static readonly Histogram BundleSizeHistogram = Metrics + .CreateHistogram("fhirpseudonymizer_received_bundle_size", "Histogram of received bundle sizes.", + new HistogramConfiguration + { + // we divide measurements in 10 buckets of 5 each, up to 50. + Buckets = Histogram.LinearBuckets(start: 1, width: 5, count: 20), + LabelNames = new[] { "operation" }, + }); + private readonly IAnonymizerEngine anonymizer; private readonly IConfiguration config; private readonly IDePseudonymizerEngine dePseudonymizer; @@ -39,8 +49,18 @@ public FhirController(IConfiguration config, ILogger logger, IAn this.logger = logger; this.anonymizer = anonymizer; this.dePseudonymizer = dePseudonymizer; + + BadRequestOutcome = new(); + BadRequestOutcome.Issue.Add(new OperationOutcome.IssueComponent + { + Severity = OperationOutcome.IssueSeverity.Error, + Code = OperationOutcome.IssueType.Processing, + Diagnostics = "Received malformed or missing resource" + }); } + private OperationOutcome BadRequestOutcome { get; } + /// /// Apply de-identification rules to the given FHIR resource. The rules can be configured using the anonymization.yaml /// config file. @@ -59,7 +79,7 @@ public Resource DeIdentify([FromBody] Resource resource) { logger.LogWarning("Bad Request: received request body is empty."); Response.StatusCode = StatusCodes.Status400BadRequest; - return GetBadRequestOutcome(); + return BadRequestOutcome; } logger.LogDebug("De-Identifying resource {resourceType}/{resourceId}", @@ -78,9 +98,11 @@ private Resource Anonymize(Resource resource) using var activity = Program.ActivitySource.StartActivity(nameof(Anonymize)); activity?.AddTag("resource.type", resource.TypeName); activity?.AddTag("resource.id", resource.Id); + if (resource is Bundle bundle) { activity?.AddTag("bundle.size", bundle.Entry.Count); + BundleSizeHistogram.WithLabels(nameof(DeIdentify)).Observe(bundle.Entry.Count); } try @@ -109,12 +131,17 @@ public Resource DePseudonymize([FromBody] Resource resource) { logger.LogWarning("Bad Request: received request body is empty."); Response.StatusCode = StatusCodes.Status400BadRequest; - return GetBadRequestOutcome(); + return BadRequestOutcome; } logger.LogDebug("De-Pseudonymizing resource {resourceType}/{resourceId}", resource.TypeName, resource.Id); + if (resource is Bundle bundle) + { + BundleSizeHistogram.WithLabels(nameof(DePseudonymize)).Observe(bundle.Entry.Count); + } + try { return dePseudonymizer.DePseudonymizeResource(resource); @@ -154,18 +181,6 @@ public CapabilityStatement GetMetadata() }; } - private static OperationOutcome GetBadRequestOutcome() - { - var outcome = new OperationOutcome(); - outcome.Issue.Add(new OperationOutcome.IssueComponent - { - Severity = OperationOutcome.IssueSeverity.Error, - Code = OperationOutcome.IssueType.Processing, - Diagnostics = "Received malformed or missing resource" - }); - return outcome; - } - private static OperationOutcome GetInternalErrorOutcome(Exception exc) { var outcome = new OperationOutcome(); diff --git a/src/FhirPseudonymizer/FhirPseudonymizer.csproj b/src/FhirPseudonymizer/FhirPseudonymizer.csproj index 28fa59a..d91a749 100644 --- a/src/FhirPseudonymizer/FhirPseudonymizer.csproj +++ b/src/FhirPseudonymizer/FhirPseudonymizer.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/FhirPseudonymizer/Program.cs b/src/FhirPseudonymizer/Program.cs index 21370be..2ffc588 100644 --- a/src/FhirPseudonymizer/Program.cs +++ b/src/FhirPseudonymizer/Program.cs @@ -25,7 +25,6 @@ public static IHostBuilder CreateHostBuilder(string[] args) options.UseUtcTimestamp = true; options.IncludeScopes = true; options.TimestampFormat = "yyyy-MM-ddTHH:mm:ssZ "; - options.SingleLine = true; })); } }