// 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++; } } }