203 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 
 | |
| 
 | |
| using System;
 | |
| using System.Runtime.CompilerServices;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace FishNet.Managing.Statistic
 | |
| {
 | |
|     [System.Serializable]
 | |
|     public class NetworkTraficStatistics
 | |
|     {
 | |
|         #region Public.
 | |
|         /// <summary>
 | |
|         /// Called when NetworkTraffic is updated for the client.
 | |
|         /// </summary>
 | |
|         public event Action<NetworkTrafficArgs> OnClientNetworkTraffic;
 | |
|         /// <summary>
 | |
|         /// Called when NetworkTraffic is updated for the server.
 | |
|         /// </summary>
 | |
|         public event Action<NetworkTrafficArgs> OnServerNetworkTraffic;
 | |
|         #endregion
 | |
| 
 | |
|         #region Serialized.
 | |
|         /// <summary>
 | |
|         /// How often to update traffic statistics.
 | |
|         /// </summary>
 | |
|         [Tooltip("How often to update traffic statistics.")]
 | |
|         [SerializeField]
 | |
|         [Range(0f, 10f)]
 | |
|         private float _updateInteval = 1f;
 | |
|         /// <summary>
 | |
|         /// 
 | |
|         /// </summary>
 | |
|         [Tooltip("True to update client statistics.")]
 | |
|         [SerializeField]
 | |
|         private bool _updateClient;
 | |
|         /// <summary>
 | |
|         /// True to update client statistics.
 | |
|         /// </summary>
 | |
|         public bool UpdateClient
 | |
|         {
 | |
|             get => _updateClient;
 | |
|             private set => _updateClient = value;
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Sets UpdateClient value.
 | |
|         /// </summary>
 | |
|         /// <param name="update"></param>
 | |
|         public void SetUpdateClient(bool update)
 | |
|         {
 | |
|             UpdateClient = update;
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// 
 | |
|         /// </summary>
 | |
|         [Tooltip("True to update server statistics.")]
 | |
|         [SerializeField]
 | |
|         private bool _updateServer;
 | |
|         /// <summary>
 | |
|         /// True to update client statistics.
 | |
|         /// </summary>
 | |
|         public bool UpdateServer
 | |
|         {
 | |
|             get => _updateServer;
 | |
|             private set => _updateServer = value;
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Sets UpdateServer value.
 | |
|         /// </summary>
 | |
|         /// <param name="update"></param>
 | |
|         public void SetUpdateServer(bool update)
 | |
|         {
 | |
|             UpdateServer = update;
 | |
|         }
 | |
|         #endregion
 | |
| 
 | |
|         #region Private.
 | |
|         /// <summary>
 | |
|         /// NetworkManager for this statistics.
 | |
|         /// </summary>
 | |
|         private NetworkManager _networkManager;
 | |
|         /// <summary>
 | |
|         /// Bytes sent to the server from local client.
 | |
|         /// </summary>
 | |
|         private ulong _client_toServerBytes;
 | |
|         /// <summary>
 | |
|         /// Bytes received on the local client from the server.
 | |
|         /// </summary>
 | |
|         private ulong _client_fromServerBytes;
 | |
|         /// <summary>
 | |
|         /// Bytes sent to all clients from the local server.
 | |
|         /// </summary>
 | |
|         private ulong _server_toClientsBytes;
 | |
|         /// <summary>
 | |
|         /// Bytes received on the local server from all clients.
 | |
|         /// </summary>
 | |
|         private ulong _server_fromClientsBytes;
 | |
|         /// <summary>
 | |
|         /// Next time network traffic updates may invoke.
 | |
|         /// </summary>
 | |
|         private float _nextUpdateTime;
 | |
|         /// <summary>
 | |
|         /// Size suffixes as text.
 | |
|         /// </summary>
 | |
|         private static readonly string[] _sizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
 | |
|         #endregion
 | |
| 
 | |
|         internal void InitializeOnce_Internal(NetworkManager manager)
 | |
|         {
 | |
|             _networkManager = manager;
 | |
|             manager.TimeManager.OnPreTick += TimeManager_OnPreTick;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Called before the TimeManager ticks.
 | |
|         /// </summary>
 | |
|         private void TimeManager_OnPreTick()
 | |
|         {
 | |
|             if (Time.unscaledTime < _nextUpdateTime)
 | |
|                 return;
 | |
|             _nextUpdateTime = Time.unscaledTime + _updateInteval;
 | |
| 
 | |
|             if (UpdateClient && _networkManager.IsClient)
 | |
|                 OnClientNetworkTraffic?.Invoke(new NetworkTrafficArgs(_client_toServerBytes, _client_fromServerBytes));
 | |
|             if (UpdateServer && _networkManager.IsServer)
 | |
|                 OnServerNetworkTraffic?.Invoke(new NetworkTrafficArgs(_server_fromClientsBytes, _server_toClientsBytes));
 | |
| 
 | |
|             _client_toServerBytes = 0;
 | |
|             _client_fromServerBytes = 0;
 | |
|             _server_toClientsBytes = 0;
 | |
|             _server_fromClientsBytes = 0;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Called when the local client sends data.
 | |
|         /// </summary>
 | |
|         internal void LocalClientSentData(ulong dataLength)
 | |
|         {
 | |
|             _client_toServerBytes = Math.Min(_client_toServerBytes + dataLength, ulong.MaxValue);
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when the local client receives data.
 | |
|         /// </summary>
 | |
|         public void LocalClientReceivedData(ulong dataLength)
 | |
|         {
 | |
|             _client_fromServerBytes = Math.Min(_client_fromServerBytes + dataLength, ulong.MaxValue);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Called when the local client sends data.
 | |
|         /// </summary>
 | |
|         internal void LocalServerSentData(ulong dataLength)
 | |
|         {
 | |
|             _server_toClientsBytes = Math.Min(_server_toClientsBytes + dataLength, ulong.MaxValue);
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when the local client receives data.
 | |
|         /// </summary>
 | |
|         public void LocalServerReceivedData(ulong dataLength)
 | |
|         {
 | |
|             _server_fromClientsBytes = Math.Min(_server_fromClientsBytes + dataLength, ulong.MaxValue);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //Attribution: https://stackoverflow.com/questions/14488796/does-net-provide-an-easy-way-convert-bytes-to-kb-mb-gb-etc
 | |
|         /// <summary>
 | |
|         /// Formats passed in bytes value to the largest possible data type with 2 decimals.
 | |
|         /// </summary>
 | |
|         public static string FormatBytesToLargest(ulong bytes)
 | |
|         {
 | |
|             int decimalPlaces = 2;
 | |
|             if (bytes == 0)
 | |
|             {
 | |
|                 decimalPlaces = 0;
 | |
|                 return string.Format("{0:n" + decimalPlaces + "} bytes", 0);
 | |
|             }
 | |
| 
 | |
|             // mag is 0 for bytes, 1 for KB, 2, for MB, etc.
 | |
|             int mag = (int)Math.Log(bytes, 1024);
 | |
| 
 | |
|             // 1L << (mag * 10) == 2 ^ (10 * mag) 
 | |
|             // [i.e. the number of bytes in the unit corresponding to mag]
 | |
|             decimal adjustedSize = (decimal)bytes / (1L << (mag * 10));
 | |
| 
 | |
|             // make adjustment when the value is large enough that
 | |
|             // it would round up to 1000 or more
 | |
|             if (Math.Round(adjustedSize, decimalPlaces) >= 1000)
 | |
|             {
 | |
|                 mag += 1;
 | |
|                 adjustedSize /= 1024;
 | |
|             }
 | |
| 
 | |
|             //Don't show decimals for bytes.
 | |
|             if (mag == 0)
 | |
|                 decimalPlaces = 0;
 | |
| 
 | |
|             return string.Format("{0:n" + decimalPlaces + "} {1}", adjustedSize, _sizeSuffixes[mag]);
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
| } |