From 3ea8818d37b54cf79cbfa55d7ca663097d2f340b Mon Sep 17 00:00:00 2001 From: Jan-Marius Vatle <48485965+janmarius@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:43:40 +0200 Subject: [PATCH] FIX-2387 Exclude unshared mnemonics when comparing log data (#2393) --- .../Workers/CompareLogDataWorker.cs | 63 +++++-------------- .../components/Modals/ReportModal.tsx | 10 ++- .../Workers/CompareLogDataWorker.Tests.cs | 28 +++------ 3 files changed, 32 insertions(+), 69 deletions(-) diff --git a/Src/WitsmlExplorer.Api/Workers/CompareLogDataWorker.cs b/Src/WitsmlExplorer.Api/Workers/CompareLogDataWorker.cs index 2f3150aaf..3d61b7dc0 100644 --- a/Src/WitsmlExplorer.Api/Workers/CompareLogDataWorker.cs +++ b/Src/WitsmlExplorer.Api/Workers/CompareLogDataWorker.cs @@ -27,6 +27,7 @@ public class CompareLogDataWorker : BaseWorker, IWorker public JobType JobType => JobType.CompareLogData; private List _compareLogDataReportItems; private Dictionary _mnemonicsMismatchCount; + private Dictionary _unsharedMnemonics; private string _sourceServerName; private string _targetServerName; private const int MaxMismatchesLimit = 500; @@ -61,6 +62,9 @@ public CompareLogDataWorker(ILogger logger, IWitsmlClientProv // Set up mnemonics mismatch count dictionary _mnemonicsMismatchCount = new Dictionary(); + // Set up unshared mnemonics dictionary + _unsharedMnemonics = new Dictionary(); + // Get logs WitsmlLog sourceLog = await LogWorkerTools.GetLog(GetSourceWitsmlClientOrThrow(), job.SourceLog, ReturnElements.HeaderOnly); WitsmlLog targetLog = await LogWorkerTools.GetLog(GetTargetWitsmlClientOrThrow(), job.TargetLog, ReturnElements.HeaderOnly); @@ -102,12 +106,12 @@ public CompareLogDataWorker(ILogger logger, IWitsmlClientProv } else if (sourceLogMnemonics.Contains(mnemonic)) { - await AddUnsharedMnemonicData(ServerType.Source, GetSourceWitsmlClientOrThrow(), sourceLog, mnemonic); + _unsharedMnemonics[mnemonic] = sourceLog.Name; } else if (targetLogMnemonics.Contains(mnemonic)) { - await AddUnsharedMnemonicData(ServerType.Target, GetTargetWitsmlClientOrThrow(), targetLog, mnemonic); + _unsharedMnemonics[mnemonic] = targetLog.Name; } else { @@ -154,49 +158,6 @@ private async Task AddSharedMnemonicData(WitsmlLog sourceLog, WitsmlLog targetLo } } - private async Task AddUnsharedMnemonicData(ServerType serverType, IWitsmlClient witsmlClient, WitsmlLog log, string mnemonic) - { - WitsmlLogData mnemonicData = await LogWorkerTools.GetLogDataForCurve(witsmlClient, log, mnemonic, Logger); - - foreach (string dataRow in mnemonicData.Data.Select(row => row.Data)) - { - if (_mnemonicsMismatchCount[mnemonic] >= MaxMismatchesLimit) break; - - var data = dataRow.Split(CommonConstants.DataSeparator); - var index = data.First(); - var value = data.Last(); - - if (_isEqualNumOfDecimals && serverType == ServerType.Source) - { - AddReportItem(mnemonic, index, value, null); - } - else if (_isEqualNumOfDecimals && serverType == ServerType.Target) - { - AddReportItem(mnemonic, index, null, value); - } - else if (!_isEqualNumOfDecimals && serverType == ServerType.Source && (_sourceDepthLogDecimals < _targetDepthLogDecimals)) - { - AddUnequalServerDecimalsReportItem(mnemonic, index, null, value, null); - } - else if (!_isEqualNumOfDecimals && serverType == ServerType.Source && (_sourceDepthLogDecimals > _targetDepthLogDecimals)) - { - AddUnequalServerDecimalsReportItem(mnemonic, null, index, null, value); - } - else if (!_isEqualNumOfDecimals && serverType == ServerType.Target && (_targetDepthLogDecimals < _sourceDepthLogDecimals)) - { - AddUnequalServerDecimalsReportItem(mnemonic, index, null, value, null); - } - else if (!_isEqualNumOfDecimals && serverType == ServerType.Target && (_targetDepthLogDecimals > _sourceDepthLogDecimals)) - { - AddUnequalServerDecimalsReportItem(mnemonic, null, index, null, value); - } - else - { - throw new ArgumentException($"serverType={serverType} not supported."); - } - } - } - private void CompareLogData(Dictionary sourceData, Dictionary targetData, string mnemonic) { List indexes = sourceData.Keys.Union(targetData.Keys).ToList(); @@ -287,23 +248,29 @@ private bool IsMnemonicDataEqual(string sourceValue, string targetValue) private BaseReport GenerateReport(WitsmlLog sourceLog, WitsmlLog targetLog) { var sortedMnemonicsMismatchCount = _mnemonicsMismatchCount.OrderByDescending(x => x.Value); - string mnemonicsMismatchCountResult = "\nNumber of mismatches for each mnemonic:"; + string mnemonicsMismatchCountResult = "\nNumber of mismatches for each shared mnemonic:"; foreach (KeyValuePair keyValues in sortedMnemonicsMismatchCount) { mnemonicsMismatchCountResult += keyValues.Value >= 500 ? $"\n{keyValues.Key}: {keyValues.Value:n0} or more" : $"\n{keyValues.Key}: {keyValues.Value:n0}"; } + string unsharedMnemonicsResult = _unsharedMnemonics.Count > 0 ? "\nUnshared mnemonics:" : ""; + foreach (KeyValuePair mnemonic in _unsharedMnemonics) + { + unsharedMnemonicsResult += $"\n{mnemonic.Key}: Only exists in {mnemonic.Value}"; + } + string indexRange = _compareAllIndexes ? "" : GetSharedIntervalReportFormat(sourceLog, targetLog); return new BaseReport { Title = $"Log data comparison", Summary = _compareLogDataReportItems.Count > 0 - ? $"Found {_compareLogDataReportItems.Count:n0} mismatches in the {(_isDepthLog ? "depth" : "time")} logs '{sourceLog.Name}' and '{targetLog.Name}':{indexRange}" + mnemonicsMismatchCountResult + ? $"Found {_compareLogDataReportItems.Count:n0} mismatches in the shared mnemonics in the {(_isDepthLog ? "depth" : "time")} logs '{sourceLog.Name}' and '{targetLog.Name}':{indexRange}" + unsharedMnemonicsResult + mnemonicsMismatchCountResult : $"No mismatches were found in the data indexes of the {(_isDepthLog ? "depth" : "time")} logs '{sourceLog.Name}' and '{targetLog.Name}'{indexRange}.", ReportItems = _compareLogDataReportItems, WarningMessage = _compareLogDataReportItems.Count >= MaxMismatchesLimit ? $"When finding {MaxMismatchesLimit:n0} mismatches while searching through data indexes for any mnemonic, we stop comparing the log data for that particular mnemonic. This is because {MaxMismatchesLimit:n0} is the maximum limit for mismatches during the search for each mnemonic. It indicates that there might be an issue with the compare log setup. However, you can still access the report for the comparison performed below." : null, - JobDetails = $"SourceServer::{_sourceServerName}|TargetServer::{_targetServerName}|SourceLog::{sourceLog.Name}|TargetLog::{targetLog.Name}" + JobDetails = $"SourceServer::{_sourceServerName}|TargetServer::{_targetServerName}|SourceLog::{sourceLog.Name}|TargetLog::{targetLog.Name}|Number of mismatches for shared mnemonics::{_compareLogDataReportItems.Count:n0}|Number of unshared mnemonics::{_unsharedMnemonics.Count:n0}" }; } diff --git a/Src/WitsmlExplorer.Frontend/components/Modals/ReportModal.tsx b/Src/WitsmlExplorer.Frontend/components/Modals/ReportModal.tsx index 88a89eb40..8d3253db1 100644 --- a/Src/WitsmlExplorer.Frontend/components/Modals/ReportModal.tsx +++ b/Src/WitsmlExplorer.Frontend/components/Modals/ReportModal.tsx @@ -25,6 +25,7 @@ import React, { useEffect, useState } from "react"; import JobService from "services/jobService"; import NotificationService from "services/notificationService"; import styled from "styled-components"; +import { Colors } from "styles/Colors"; export interface ReportModal { report?: BaseReport; @@ -104,7 +105,8 @@ export const ReportModal = (props: ReportModal): React.ReactElement => { {report.jobDetails.split("|").map((jobDetail) => { const keyValuePair = jobDetail.split("::"); return ( - { return report; }; +const StyledTextField = styled(TextField)<{ colors: Colors }>` + label { + color: ${(props) => props.colors.interactive.primaryResting}; + } +`; + const ContentLayout = styled.div` display: flex; flex-direction: column; diff --git a/Tests/WitsmlExplorer.Api.Tests/Workers/CompareLogDataWorker.Tests.cs b/Tests/WitsmlExplorer.Api.Tests/Workers/CompareLogDataWorker.Tests.cs index 96e101068..72ce517b3 100644 --- a/Tests/WitsmlExplorer.Api.Tests/Workers/CompareLogDataWorker.Tests.cs +++ b/Tests/WitsmlExplorer.Api.Tests/Workers/CompareLogDataWorker.Tests.cs @@ -203,7 +203,7 @@ public async Task CompareLogDataWorker_MismatchInSharedIndexTimeLogs_ReturnsMism } [Fact] - public async Task CompareLogData_DifferentNumberOfMnemonicsDepthLogs_ReturnsMismatchedReportItems() + public async Task CompareLogData_DifferentNumberOfMnemonicsDepthLogs_ReturnsOnlySharedMnemonicsMismatchedReportItems() { SetupWorker(0, 0); string indexType = WitsmlLog.WITSML_INDEX_TYPE_MD; @@ -222,16 +222,15 @@ public async Task CompareLogData_DifferentNumberOfMnemonicsDepthLogs_ReturnsMism StartIndex = "0", EndIndex = "1", LogCurveInfo = new() { ("IndexCurve", CommonConstants.Unit.Meter), ("Curve1", "Unit1"), ("Curve2", "Unit2") }, - Data = new() { "0,0,0", "1,0,0" } + Data = new() { "0,1,0", "1,0,0" } }; var job = SetupTest(sourceLog, targetLog); var (workerResult, refreshAction) = await _worker.Execute(job); List resultReportItems = job.JobInfo.Report.ReportItems.Select(x => (CompareLogDataItem)x).ToList(); - int expectedNumberOfMismatches = 2; - CompareLogDataItem expectedMismatchItem1 = CreateCompareLogDataItem("0", "Curve2", null, "0"); - CompareLogDataItem expectedMismatchItem2 = CreateCompareLogDataItem("1", "Curve2", null, "0"); + int expectedNumberOfMismatches = 1; + CompareLogDataItem expectedMismatchItem1 = CreateCompareLogDataItem("0", "Curve1", "0", "1"); Assert.Equal(expectedNumberOfMismatches, resultReportItems.Count); @@ -239,15 +238,10 @@ public async Task CompareLogData_DifferentNumberOfMnemonicsDepthLogs_ReturnsMism Assert.Equal(expectedMismatchItem1.Mnemonic, resultReportItems[0].Mnemonic); Assert.Equal(expectedMismatchItem1.SourceValue, resultReportItems[0].SourceValue); Assert.Equal(expectedMismatchItem1.TargetValue, resultReportItems[0].TargetValue); - - Assert.Equal(expectedMismatchItem2.Index, resultReportItems[1].Index); - Assert.Equal(expectedMismatchItem2.Mnemonic, resultReportItems[1].Mnemonic); - Assert.Equal(expectedMismatchItem2.SourceValue, resultReportItems[1].SourceValue); - Assert.Equal(expectedMismatchItem2.TargetValue, resultReportItems[1].TargetValue); } [Fact] - public async Task CompareLogData_DifferentNumberOfMnemonicsTimeLogs_ReturnsMismatchedReportItems() + public async Task CompareLogData_DifferentNumberOfMnemonicsTimeLogs_ReturnsOnlySharedMnemonicsMismatchedReportItems() { SetupWorker(0, 0); string indexType = WitsmlLog.WITSML_INDEX_TYPE_DATE_TIME; @@ -266,16 +260,15 @@ public async Task CompareLogData_DifferentNumberOfMnemonicsTimeLogs_ReturnsMisma StartIndex = "2023-09-28T08:10:00Z", EndIndex = "2023-09-28T08:11:00Z", LogCurveInfo = new() { ("IndexCurve", "DateTime"), ("Curve1", "Unit1"), ("Curve2", "Unit2") }, - Data = new() { "2023-09-28T08:10:00Z,0,0", "2023-09-28T08:11:00Z,0,0" } + Data = new() { "2023-09-28T08:10:00Z,1,0", "2023-09-28T08:11:00Z,0,0" } }; var job = SetupTest(sourceLog, targetLog); var (workerResult, refreshAction) = await _worker.Execute(job); List resultReportItems = job.JobInfo.Report.ReportItems.Select(x => (CompareLogDataItem)x).ToList(); - int expectedNumberOfMismatches = 2; - CompareLogDataItem expectedMismatchItem1 = CreateCompareLogDataItem("2023-09-28T08:10:00Z", "Curve2", null, "0"); - CompareLogDataItem expectedMismatchItem2 = CreateCompareLogDataItem("2023-09-28T08:11:00Z", "Curve2", null, "0"); + int expectedNumberOfMismatches = 1; + CompareLogDataItem expectedMismatchItem1 = CreateCompareLogDataItem("2023-09-28T08:10:00Z", "Curve1", "0", "1"); Assert.Equal(expectedNumberOfMismatches, resultReportItems.Count); @@ -283,11 +276,6 @@ public async Task CompareLogData_DifferentNumberOfMnemonicsTimeLogs_ReturnsMisma Assert.Equal(expectedMismatchItem1.Mnemonic, resultReportItems[0].Mnemonic); Assert.Equal(expectedMismatchItem1.SourceValue, resultReportItems[0].SourceValue); Assert.Equal(expectedMismatchItem1.TargetValue, resultReportItems[0].TargetValue); - - Assert.Equal(expectedMismatchItem2.Index, resultReportItems[1].Index); - Assert.Equal(expectedMismatchItem2.Mnemonic, resultReportItems[1].Mnemonic); - Assert.Equal(expectedMismatchItem2.SourceValue, resultReportItems[1].SourceValue); - Assert.Equal(expectedMismatchItem2.TargetValue, resultReportItems[1].TargetValue); } [Fact]