AdlsDotNetSDK/LatencyTracker.cs (66 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.Azure.DataLake.Store
{
/// <summary>
/// Single entry, comma separated:
/// 1. Client Request ID
/// 2. latency in milliseconds
/// 3. error code(if request failed)
/// 4. Operation
/// 5. Request+response body Size(if available, zero otherwise)
/// 6. Instance of ADLStoreClient(a unique number per instance in this VM)
///
/// Multiple entries can be on a single request.Entries will be separated by semicolons
/// Limit max entries on a single request to three, to limit increase in HTTP request size.
///
/// All apis are threadsafe.
/// </summary>
public class LatencyTracker
{
/// <summary>
/// Queue containing the latency entries
/// </summary>
private static readonly Queue<string> LatencyQueue = new Queue<string>();
/// <summary>
/// Maximum size of the latency queue
/// </summary>
private const int Maxsize = 256;
/// <summary>
/// Maximum number of latency entries in one request
/// </summary>
private const int Maxperline = 3;
/// <summary>
/// Tracks whether latencyTracker is disabled
/// </summary>
private static bool _disabled;
/// <summary>
/// Disables the Latency tracker
/// </summary>
public static void Disable()
{
lock (LatencyQueue)
{
_disabled = true;
LatencyQueue.Clear();
}
}
/// <summary>
/// Adds a latency entry to the back of queue
/// </summary>
/// <param name="value">Value to add</param>
private static void Add(string value)
{
//Need a lock operation because doing AddIf
lock (LatencyQueue)
{
if (LatencyQueue.Count < Maxsize)
{
LatencyQueue.Enqueue(value);
}
}
}
/// <summary>
/// Returns the front element of queue if there is any else returns null
/// </summary>
/// <returns>Front element of queue if there is else null</returns>
private static string Dequeue()
{
lock (LatencyQueue)
{
if (LatencyQueue.Count > 0)
{
return LatencyQueue.Dequeue();
}
return null;
}
}
/// <summary>
/// Add error/latency details of last http request to the queue
/// </summary>
/// <param name="clientRequestId">Client request GUID</param>
/// <param name="retry">Retry number</param>
/// <param name="latency">Total latency</param>
/// <param name="error">Error</param>
/// <param name="opCode">OpCode of the Http request</param>
/// <param name="length">Data length+Response length</param>
/// <param name="clientId">ADLS Client Id</param>
internal static void AddLatency(string clientRequestId, int retry, long latency, string error, string opCode, long length, long clientId)
{
if (_disabled) return;
Add(clientRequestId + "." + retry + "," + latency + "," + (string.IsNullOrEmpty(error) ? "" : error) + "," + opCode + "," + length + "," + clientId);
}
/// <summary>
/// Retrieves the latency/error entries for upto maximum last 3 requests
/// </summary>
/// <returns></returns>
internal static string GetLatency()
{
lock (LatencyQueue)
{
if (_disabled) return null;
}
int line = 0;
StringBuilder builder = new StringBuilder(2 * Maxperline);
do
{
string entry = Dequeue();
if (entry == null)
{
break;
}
builder.Append(builder.Length == 0 ? entry : ";" + entry);
} while (++line < Maxperline);
return builder.ToString();
}
}
}