diff --git a/src/lib/Microsoft.Health.Fhir.Ingest/Data/ResourceOperation.cs b/src/lib/Microsoft.Health.Fhir.Ingest/Data/ResourceOperation.cs new file mode 100644 index 00000000..a2801865 --- /dev/null +++ b/src/lib/Microsoft.Health.Fhir.Ingest/Data/ResourceOperation.cs @@ -0,0 +1,20 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +namespace Microsoft.Health.Fhir.Ingest.Data +{ + public enum ResourceOperation + { + /// + /// FHIR resource created + /// + Created, + + /// + /// FHIR resource updated + /// + Updated, + } +} diff --git a/src/lib/Microsoft.Health.Fhir.Ingest/Data/ResourceType.cs b/src/lib/Microsoft.Health.Fhir.Ingest/Data/ResourceType.cs index 1ddbb6de..d83ceb94 100644 --- a/src/lib/Microsoft.Health.Fhir.Ingest/Data/ResourceType.cs +++ b/src/lib/Microsoft.Health.Fhir.Ingest/Data/ResourceType.cs @@ -21,5 +21,10 @@ public enum ResourceType /// Encounter Resource /// Encounter, + + /// + /// Observation Resource + /// + Observation, } } diff --git a/src/lib/Microsoft.Health.Fhir.Ingest/Telemetry/Metrics/IomtMetrics.cs b/src/lib/Microsoft.Health.Fhir.Ingest/Telemetry/Metrics/IomtMetrics.cs index 2d1ecfbb..4a22346c 100644 --- a/src/lib/Microsoft.Health.Fhir.Ingest/Telemetry/Metrics/IomtMetrics.cs +++ b/src/lib/Microsoft.Health.Fhir.Ingest/Telemetry/Metrics/IomtMetrics.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using EnsureThat; using Microsoft.Health.Common.Telemetry; +using Microsoft.Health.Fhir.Ingest.Data; namespace Microsoft.Health.Fhir.Ingest.Telemetry { @@ -175,6 +176,23 @@ public static Metric NotSupported() return _notSupported; } + /// + /// A metric for when a FHIR resource has been saved. + /// + /// The type of FHIR resource that was saved. + /// The operation performed on the FHIR resource. + public static Metric FhirResourceSaved(ResourceType resourceType, ResourceOperation resourceOperation) + { + return new Metric( + "FhirResourceSaved", + new Dictionary + { + { _nameDimension, $"{resourceType}{resourceOperation}" }, + { _categoryDimension, Category.Traffic }, + { _operationDimension, ConnectorOperation.FHIRConversion }, + }); + } + public static Metric UnhandledException(string exceptionName, string connectorStage) { EnsureArg.IsNotNull(exceptionName); diff --git a/src/lib/Microsoft.Health.Fhir.R4.Ingest/Service/R4FhirImportService.cs b/src/lib/Microsoft.Health.Fhir.R4.Ingest/Service/R4FhirImportService.cs index c56c2595..be58aa34 100644 --- a/src/lib/Microsoft.Health.Fhir.R4.Ingest/Service/R4FhirImportService.cs +++ b/src/lib/Microsoft.Health.Fhir.R4.Ingest/Service/R4FhirImportService.cs @@ -12,7 +12,9 @@ using Microsoft.Health.Extensions.Fhir; using Microsoft.Health.Extensions.Fhir.Search; using Microsoft.Health.Fhir.Ingest.Data; +using Microsoft.Health.Fhir.Ingest.Telemetry; using Microsoft.Health.Fhir.Ingest.Template; +using Microsoft.Health.Logging.Telemetry; using Polly; using Model = Hl7.Fhir.Model; @@ -24,12 +26,14 @@ public class R4FhirImportService : private readonly FhirClient _client; private readonly IFhirTemplateProcessor, Model.Observation> _fhirTemplateProcessor; private readonly IMemoryCache _observationCache; + private readonly ITelemetryLogger _logger; - public R4FhirImportService(IResourceIdentityService resourceIdentityService, FhirClient fhirClient, IFhirTemplateProcessor, Model.Observation> fhirTemplateProcessor, IMemoryCache observationCache) + public R4FhirImportService(IResourceIdentityService resourceIdentityService, FhirClient fhirClient, IFhirTemplateProcessor, Model.Observation> fhirTemplateProcessor, IMemoryCache observationCache, ITelemetryLogger logger) { _fhirTemplateProcessor = EnsureArg.IsNotNull(fhirTemplateProcessor, nameof(fhirTemplateProcessor)); _client = EnsureArg.IsNotNull(fhirClient, nameof(fhirClient)); _observationCache = EnsureArg.IsNotNull(observationCache, nameof(observationCache)); + _logger = EnsureArg.IsNotNull(logger, nameof(logger)); ResourceIdentityService = EnsureArg.IsNotNull(resourceIdentityService, nameof(resourceIdentityService)); } @@ -64,6 +68,7 @@ public virtual async Task SaveObservationAsync(ILookupTemplate SaveObservationAsync(ILookupTemplate(); var config = Substitute.For>(); - var service = Substitute.ForPartsOf(identityService, fhirClient, templateProcessor, cache) + var logger = Substitute.For(); + + var service = Substitute.ForPartsOf(identityService, fhirClient, templateProcessor, cache, logger) .Mock(m => m.SaveObservationAsync(default, default, default).ReturnsForAnyArgs(string.Empty)); await service.ProcessAsync(config, measurementGroup); @@ -76,7 +79,9 @@ public async void GivenNotFoundObservation_WhenSaveObservationAsync_ThenCreateIn var cache = Substitute.For(); var config = Substitute.For>(); - var service = new R4FhirImportService(identityService, fhirClient, templateProcessor, cache); + var logger = Substitute.For(); + + var service = new R4FhirImportService(identityService, fhirClient, templateProcessor, cache, logger); var result = await service.SaveObservationAsync(config, observationGroup, ids); @@ -121,7 +126,9 @@ public async void GivenFoundObservation_WhenSaveObservationAsync_ThenUpdateInvok var cache = Substitute.For(); var config = Substitute.For>(); - var service = new R4FhirImportService(identityService, fhirClient, templateProcessor, cache); + var logger = Substitute.For(); + + var service = new R4FhirImportService(identityService, fhirClient, templateProcessor, cache, logger); var result = await service.SaveObservationAsync(config, observationGroup, ids); @@ -179,7 +186,9 @@ public async void GivenFoundObservationAndConflictOnSave_WhenSaveObservationAsyn var cache = Substitute.For(); var config = Substitute.For>(); - var service = new R4FhirImportService(identityService, fhirClient, templateProcessor, cache); + var logger = Substitute.For(); + + var service = new R4FhirImportService(identityService, fhirClient, templateProcessor, cache, logger); var result = await service.SaveObservationAsync(config, observationGroup, ids); @@ -205,7 +214,9 @@ public void GivenValidTemplate_WhenGenerateObservation_ExpectedReferencesSet_Tes var identifer = new Model.Identifier(); var config = Substitute.For>(); - var service = new R4FhirImportService(identityService, fhirClient, templateProcessor, cache); + var logger = Substitute.For(); + + var service = new R4FhirImportService(identityService, fhirClient, templateProcessor, cache, logger); var result = service.GenerateObservation(config, observationGroup, identifer, ids);