deprecate(lmxproxy): move all LmxProxy code, tests, and docs to deprecated/
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.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
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)];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user