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);