Initial commit: JDE Scoping Tool migration project

Set up repository with legacy .NET Framework 4.8 source (OLD/),
new .NET 10 Blazor solution (NEW/), OpenSpec specifications,
documentation, and project configuration.
This commit is contained in:
Joseph Doherty
2026-01-02 07:43:29 -05:00
commit 26ff8d9b4f
1761 changed files with 596509 additions and 0 deletions
@@ -0,0 +1,53 @@
using System.Diagnostics;
namespace JdeScoping.DataSync.Telemetry;
/// <summary>
/// Activity source for distributed tracing of data sync operations.
/// </summary>
public static class DataSyncActivitySource
{
/// <summary>
/// The activity source for data sync operations.
/// </summary>
public static readonly ActivitySource Source = new("JdeScoping.DataSync", "1.0.0");
/// <summary>
/// Starts an activity for a sync operation.
/// </summary>
/// <param name="tableName">The table being synced.</param>
/// <param name="updateType">The type of update (Hourly, Daily, Mass).</param>
/// <returns>The started activity, or null if no listeners.</returns>
public static Activity? StartSyncOperation(string tableName, string updateType)
{
return Source.StartActivity("SyncTable")?
.SetTag("table.name", tableName)
.SetTag("update.type", updateType);
}
/// <summary>
/// Starts an activity for a batch processing operation.
/// </summary>
/// <param name="tableName">The table being synced.</param>
/// <param name="batchNumber">The batch number.</param>
/// <param name="recordCount">The number of records in the batch.</param>
/// <returns>The started activity, or null if no listeners.</returns>
public static Activity? StartBatchOperation(string tableName, int batchNumber, int recordCount)
{
return Source.StartActivity("ProcessBatch")?
.SetTag("table.name", tableName)
.SetTag("batch.number", batchNumber)
.SetTag("record.count", recordCount);
}
/// <summary>
/// Starts an activity for a MERGE operation.
/// </summary>
/// <param name="tableName">The destination table.</param>
/// <returns>The started activity, or null if no listeners.</returns>
public static Activity? StartMergeOperation(string tableName)
{
return Source.StartActivity("ExecuteMerge")?
.SetTag("table.name", tableName);
}
}
@@ -0,0 +1,114 @@
using System.Diagnostics.Metrics;
namespace JdeScoping.DataSync.Telemetry;
/// <summary>
/// Metrics for data sync operations.
/// </summary>
public class DataSyncMetrics
{
private readonly Counter<long> _operationsStarted;
private readonly Counter<long> _operationsCompleted;
private readonly Counter<long> _operationsFailed;
private readonly Histogram<double> _operationDuration;
private readonly Histogram<long> _recordsProcessed;
private readonly Counter<long> _cycleErrors;
private readonly Counter<long> _cyclesCompleted;
/// <summary>
/// Initializes a new instance of the <see cref="DataSyncMetrics"/> class.
/// </summary>
public DataSyncMetrics(IMeterFactory meterFactory)
{
var meter = meterFactory.Create("JdeScoping.DataSync");
_operationsStarted = meter.CreateCounter<long>(
"datasync.operations.started",
unit: "{operation}",
description: "Number of sync operations started");
_operationsCompleted = meter.CreateCounter<long>(
"datasync.operations.completed",
unit: "{operation}",
description: "Number of sync operations completed successfully");
_operationsFailed = meter.CreateCounter<long>(
"datasync.operations.failed",
unit: "{operation}",
description: "Number of sync operations that failed");
_operationDuration = meter.CreateHistogram<double>(
"datasync.operation.duration",
unit: "s",
description: "Duration of sync operations in seconds");
_recordsProcessed = meter.CreateHistogram<long>(
"datasync.records.processed",
unit: "{record}",
description: "Number of records processed per operation");
_cycleErrors = meter.CreateCounter<long>(
"datasync.cycle.errors",
unit: "{error}",
description: "Number of errors in sync cycles");
_cyclesCompleted = meter.CreateCounter<long>(
"datasync.cycles.completed",
unit: "{cycle}",
description: "Number of sync cycles completed");
}
/// <summary>
/// Records that a sync operation has started.
/// </summary>
public void RecordOperationStarted(string tableName, string updateType)
{
_operationsStarted.Add(1,
new KeyValuePair<string, object?>("table", tableName),
new KeyValuePair<string, object?>("type", updateType));
}
/// <summary>
/// Records that a sync operation completed successfully.
/// </summary>
public void RecordOperationCompleted(string tableName, string updateType, long recordCount, double durationSeconds)
{
var tags = new KeyValuePair<string, object?>[]
{
new("table", tableName),
new("type", updateType)
};
_operationsCompleted.Add(1, tags);
_operationDuration.Record(durationSeconds, tags);
_recordsProcessed.Record(recordCount, tags);
}
/// <summary>
/// Records that a sync operation failed.
/// </summary>
public void RecordOperationFailed(string tableName, string updateType)
{
_operationsFailed.Add(1,
new KeyValuePair<string, object?>("table", tableName),
new KeyValuePair<string, object?>("type", updateType));
}
/// <summary>
/// Records an error in the sync cycle.
/// </summary>
public void RecordCycleError()
{
_cycleErrors.Add(1);
}
/// <summary>
/// Records completion of a sync cycle.
/// </summary>
public void RecordCycleCompleted(int successCount, int failedCount, double durationSeconds)
{
_cyclesCompleted.Add(1,
new KeyValuePair<string, object?>("success_count", successCount),
new KeyValuePair<string, object?>("failed_count", failedCount));
}
}