// This file is provided under The MIT License as part of RiptideNetworking.
// Copyright (c) Tom Weiland
// For additional information please see the included LICENSE.md file or view it on GitHub:
// https://github.com/RiptideNetworking/Riptide/blob/main/LICENSE.md
namespace Riptide.Utils
{
/// Tracks and manages various metrics of a .
public class ConnectionMetrics
{
/// The total number of bytes received across all send modes since the last call, including those in duplicate and, in
/// the case of notify messages, out-of-order packets. Does not include packet header bytes, which may vary by transport.
public int BytesIn => UnreliableBytesIn + NotifyBytesIn + ReliableBytesIn;
/// The total number of bytes sent across all send modes since the last call, including those in automatic resends.
/// Does not include packet header bytes, which may vary by transport.
public int BytesOut => UnreliableBytesOut + NotifyBytesOut + ReliableBytesOut;
/// The total number of messages received across all send modes since the last call, including duplicate and out-of-order notify messages.
public int MessagesIn => UnreliableIn + NotifyIn + ReliableIn;
/// The total number of messages sent across all send modes since the last call, including automatic resends.
public int MessagesOut => UnreliableOut + NotifyOut + ReliableOut;
/// The total number of bytes received in unreliable messages since the last call. Does not include packet header bytes, which may vary by transport.
public int UnreliableBytesIn { get; private set; }
/// The total number of bytes sent in unreliable messages since the last call. Does not include packet header bytes, which may vary by transport.
public int UnreliableBytesOut { get; internal set; }
/// The number of unreliable messages received since the last call.
public int UnreliableIn { get; private set; }
/// The number of unreliable messages sent since the last call.
public int UnreliableOut { get; internal set; }
/// The total number of bytes received in notify messages since the last call, including those in duplicate and out-of-order packets.
/// Does not include packet header bytes, which may vary by transport.
public int NotifyBytesIn { get; private set; }
/// The total number of bytes sent in notify messages since the last call. Does not include packet header bytes, which may vary by transport.
public int NotifyBytesOut { get; internal set; }
/// The number of notify messages received since the last call, including duplicate and out-of-order ones.
public int NotifyIn { get; private set; }
/// The number of notify messages sent since the last call.
public int NotifyOut { get; internal set; }
/// The number of duplicate or out-of-order notify messages which were received, but discarded (not handled) since the last call.
public int NotifyDiscarded { get; internal set; }
/// The number of notify messages lost since the last call.
public int NotifyLost { get; private set; }
/// The number of notify messages delivered since the last call.
public int NotifyDelivered { get; private set; }
/// The number of notify messages lost of the last 64 notify messages to be lost or delivered.
public int RollingNotifyLost { get; private set; }
/// The number of notify messages delivered of the last 64 notify messages to be lost or delivered.
public int RollingNotifyDelivered { get; private set; }
/// The loss rate (0-1) among the last 64 notify messages.
public float RollingNotifyLossRate => RollingNotifyLost / 64f;
/// The total number of bytes received in reliable messages since the last call, including those in duplicate packets.
/// Does not include packet header bytes, which may vary by transport.
public int ReliableBytesIn { get; private set; }
/// The total number of bytes sent in reliable messages since the last call, including those in automatic resends.
/// Does not include packet header bytes, which may vary by transport.
public int ReliableBytesOut { get; internal set; }
/// The number of reliable messages received since the last call, including duplicates.
public int ReliableIn { get; private set; }
/// The number of reliable messages sent since the last call, including automatic resends (each resend adds to this value).
public int ReliableOut { get; internal set; }
/// The number of duplicate reliable messages which were received, but discarded (and not handled) since the last call.
public int ReliableDiscarded { get; internal set; }
/// The number of unique reliable messages sent since the last call.
/// A message only counts towards this the first time it is sent—subsequent resends are not counted.
public int ReliableUniques { get; internal set; }
/// The number of send attempts that were required to deliver recent reliable messages.
public readonly RollingStat RollingReliableSends;
/// The left-most bit of a , used to store the oldest value in the .
private const ulong ULongLeftBit = 1ul << 63;
/// Which recent notify messages were lost. Each bit corresponds to a message.
private ulong notifyLossTracker;
/// How many of the 's bits are in use.
private int notifyBufferCount;
/// Initializes metrics.
public ConnectionMetrics()
{
Reset();
RollingNotifyDelivered = 0;
RollingNotifyLost = 0;
notifyLossTracker = 0;
notifyBufferCount = 0;
RollingReliableSends = new RollingStat(64);
}
/// Resets all non-rolling metrics to 0.
public void Reset()
{
UnreliableBytesIn = 0;
UnreliableBytesOut = 0;
UnreliableIn = 0;
UnreliableOut = 0;
NotifyBytesIn = 0;
NotifyBytesOut = 0;
NotifyIn = 0;
NotifyOut = 0;
NotifyDiscarded = 0;
NotifyLost = 0;
NotifyDelivered = 0;
ReliableBytesIn = 0;
ReliableBytesOut = 0;
ReliableIn = 0;
ReliableOut = 0;
ReliableDiscarded = 0;
ReliableUniques = 0;
}
/// Updates the metrics associated with receiving an unreliable message.
/// The number of bytes that were received.
internal void ReceivedUnreliable(int byteCount)
{
UnreliableBytesIn += byteCount;
UnreliableIn++;
}
/// Updates the metrics associated with sending an unreliable message.
/// The number of bytes that were sent.
internal void SentUnreliable(int byteCount)
{
UnreliableBytesOut += byteCount;
UnreliableOut++;
}
/// Updates the metrics associated with receiving a notify message.
/// The number of bytes that were received.
internal void ReceivedNotify(int byteCount)
{
NotifyBytesIn += byteCount;
NotifyIn++;
}
/// Updates the metrics associated with sending a notify message.
/// The number of bytes that were sent.
internal void SentNotify(int byteCount)
{
NotifyBytesOut += byteCount;
NotifyOut++;
}
/// Updates the metrics associated with delivering a notify message.
internal void DeliveredNotify()
{
NotifyDelivered++;
if (notifyBufferCount < 64)
{
RollingNotifyDelivered++;
notifyBufferCount++;
}
else if ((notifyLossTracker & ULongLeftBit) == 0)
{
// The one being removed from the buffer was not delivered
RollingNotifyDelivered++;
RollingNotifyLost--;
}
notifyLossTracker <<= 1;
notifyLossTracker |= 1;
}
/// Updates the metrics associated with losing a notify message.
internal void LostNotify()
{
NotifyLost++;
if (notifyBufferCount < 64)
{
RollingNotifyLost++;
notifyBufferCount++;
}
else if ((notifyLossTracker & ULongLeftBit) != 0)
{
// The one being removed from the buffer was delivered
RollingNotifyDelivered--;
RollingNotifyLost++;
}
notifyLossTracker <<= 1;
}
/// Updates the metrics associated with receiving a reliable message.
/// The number of bytes that were received.
internal void ReceivedReliable(int byteCount)
{
ReliableBytesIn += byteCount;
ReliableIn++;
}
/// Updates the metrics associated with sending a reliable message.
/// The number of bytes that were sent.
internal void SentReliable(int byteCount)
{
ReliableBytesOut += byteCount;
ReliableOut++;
}
}
}