Skip to content

Commit

Permalink
feat: added histogram metrics for bundle size (#25)
Browse files Browse the repository at this point in the history
* chore(deps): updated prometheus to v5

* feat: added histogram metrics for bundle size

Closes #20

* refactor: dont allocate a bad request outcome and use a static one instead
  • Loading branch information
chgl committed Aug 18, 2021
1 parent db5749f commit e51a656
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 17 deletions.
43 changes: 29 additions & 14 deletions src/FhirPseudonymizer/Controllers/FhirController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Health.Fhir.Anonymizer.Core;
using Prometheus;

namespace FhirPseudonymizer.Controllers
{
Expand All @@ -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;
Expand All @@ -39,8 +49,18 @@ public FhirController(IConfiguration config, ILogger<FhirController> 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; }

/// <summary>
/// Apply de-identification rules to the given FHIR resource. The rules can be configured using the anonymization.yaml
/// config file.
Expand All @@ -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}",
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions src/FhirPseudonymizer/FhirPseudonymizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
<PackageReference Include="Hl7.Fhir.R4" Version="3.4.0" />
<PackageReference Include="Hl7.FhirPath" Version="3.4.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.11.1" />
<PackageReference Include="prometheus-net" Version="4.2.0" />
<PackageReference Include="prometheus-net.AspNetCore" Version="4.2.0" />
<PackageReference Include="prometheus-net" Version="5.0.0" />
<PackageReference Include="prometheus-net.AspNetCore" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.5" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="5.0.1" />
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="2.1.0" />
Expand Down
1 change: 0 additions & 1 deletion src/FhirPseudonymizer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}));
}
}
Expand Down

0 comments on commit e51a656

Please sign in to comment.