LmxProxy is no longer needed. Moved the entire lmxproxy/ workspace, DCL adapter files, and related docs to deprecated/. Removed LmxProxy registration from DataConnectionFactory, project reference from DCL, protocol option from UI, and cleaned up all requirement docs.
101 lines
3.5 KiB
C#
101 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace ZB.MOM.WW.LmxProxy.Client
|
|
{
|
|
/// <summary>
|
|
/// Metrics collection for client operations
|
|
/// </summary>
|
|
internal class ClientMetrics
|
|
{
|
|
private readonly ConcurrentDictionary<string, long> _operationCounts = new();
|
|
private readonly ConcurrentDictionary<string, long> _errorCounts = new();
|
|
private readonly ConcurrentDictionary<string, List<long>> _latencies = new();
|
|
private readonly object _latencyLock = new();
|
|
|
|
/// <summary>
|
|
/// Increments the operation count for a specific operation.
|
|
/// </summary>
|
|
/// <param name="operation">The operation name.</param>
|
|
public void IncrementOperationCount(string operation)
|
|
{
|
|
_operationCounts.AddOrUpdate(operation, 1, (_, oldValue) => oldValue + 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Increments the error count for a specific operation.
|
|
/// </summary>
|
|
/// <param name="operation">The operation name.</param>
|
|
public void IncrementErrorCount(string operation)
|
|
{
|
|
_errorCounts.AddOrUpdate(operation, 1, (_, oldValue) => oldValue + 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Records latency for a specific operation.
|
|
/// </summary>
|
|
/// <param name="operation">The operation name.</param>
|
|
/// <param name="milliseconds">The latency in milliseconds.</param>
|
|
public void RecordLatency(string operation, long milliseconds)
|
|
{
|
|
lock (_latencyLock)
|
|
{
|
|
if (!_latencies.ContainsKey(operation))
|
|
{
|
|
_latencies[operation] = [];
|
|
}
|
|
_latencies[operation].Add(milliseconds);
|
|
|
|
// Keep only last 1000 entries to prevent memory growth
|
|
if (_latencies[operation].Count > 1000)
|
|
{
|
|
_latencies[operation].RemoveAt(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a snapshot of current metrics.
|
|
/// </summary>
|
|
/// <returns>A dictionary containing metric data.</returns>
|
|
public Dictionary<string, object> GetSnapshot()
|
|
{
|
|
var snapshot = new Dictionary<string, object>();
|
|
|
|
foreach (KeyValuePair<string, long> kvp in _operationCounts)
|
|
{
|
|
snapshot[$"{kvp.Key}_count"] = kvp.Value;
|
|
}
|
|
|
|
foreach (KeyValuePair<string, long> kvp in _errorCounts)
|
|
{
|
|
snapshot[$"{kvp.Key}_errors"] = kvp.Value;
|
|
}
|
|
|
|
lock (_latencyLock)
|
|
{
|
|
foreach (KeyValuePair<string, List<long>> kvp in _latencies)
|
|
{
|
|
if (kvp.Value.Any())
|
|
{
|
|
snapshot[$"{kvp.Key}_avg_latency_ms"] = kvp.Value.Average();
|
|
snapshot[$"{kvp.Key}_p95_latency_ms"] = GetPercentile(kvp.Value, 95);
|
|
snapshot[$"{kvp.Key}_p99_latency_ms"] = GetPercentile(kvp.Value, 99);
|
|
}
|
|
}
|
|
}
|
|
|
|
return snapshot;
|
|
}
|
|
|
|
private double GetPercentile(List<long> values, int percentile)
|
|
{
|
|
var sorted = values.OrderBy(x => x).ToList();
|
|
int index = (int)Math.Ceiling(percentile / 100.0 * sorted.Count) - 1;
|
|
return sorted[Math.Max(0, index)];
|
|
}
|
|
}
|
|
}
|