From 6e49f60fbcef0057ec0b03f5cb5f5a26d7095be7 Mon Sep 17 00:00:00 2001 From: Leath Cooper Date: Sat, 26 Oct 2024 08:17:02 -0400 Subject: [PATCH] additional metrics --- Projects/Server/Network/NetState/NetState.cs | 14 ++++++++ Projects/Server/Network/TcpServer.cs | 31 ++++++++++++++--- Projects/Server/Telemetry.cs | 4 ++- .../Engines/Harvest/Core/HarvestSystem.cs | 11 +++++++ .../PlayerMurderSystem.cs | 9 +++++ Projects/UOContent/Spells/Base/Spell.cs | 33 ++++++++++++------- 6 files changed, 85 insertions(+), 17 deletions(-) diff --git a/Projects/Server/Network/NetState/NetState.cs b/Projects/Server/Network/NetState/NetState.cs index 172be42aa..18f94743c 100755 --- a/Projects/Server/Network/NetState/NetState.cs +++ b/Projects/Server/Network/NetState/NetState.cs @@ -23,6 +23,7 @@ using System; using System.Buffers; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.Metrics; using System.IO; using System.Net; using System.Net.Sockets; @@ -37,6 +38,8 @@ public delegate int EncodePacket(ReadOnlySpan inputBuffer, Span outp public partial class NetState : IComparable, IValueLinkListNode { + private static readonly Counter packetCounter = + Telemetry.NetworkMeter.CreateCounter("net_state_packet_counter"); private static readonly ILogger logger = LogFactory.GetLogger(typeof(NetState)); private static readonly TimeSpan ConnectingSocketIdleLimit = TimeSpan.FromMilliseconds(5000); // 5 seconds @@ -476,6 +479,12 @@ public partial class NetState : IComparable, IValueLinkListNode[] + { + new("PacketID", span[0]), + new("Kind", "SERVER"), + }); + SendPipe.Writer.Advance((uint)length); if (!_flushQueued) @@ -564,6 +573,11 @@ public partial class NetState : IComparable, IValueLinkListNode[] + { + new("PacketID", packetId), + new("Kind", "CLIENT"), + }); // These can arrive at any time and are only informational if (_protocolState != ProtocolState.AwaitingSeed && IncomingPackets.IsInfoPacket(packetId)) { diff --git a/Projects/Server/Network/TcpServer.cs b/Projects/Server/Network/TcpServer.cs index be526f703..8a77dcba6 100644 --- a/Projects/Server/Network/TcpServer.cs +++ b/Projects/Server/Network/TcpServer.cs @@ -14,6 +14,7 @@ *************************************************************************/ using System.Collections.Generic; +using System.Diagnostics.Metrics; using System.IO; using System.Linq; using System.Net; @@ -27,6 +28,18 @@ namespace Server.Network; public static class TcpServer { + private static readonly Counter attemptedConnectionsCounter = + Telemetry.NetworkMeter.CreateCounter("tcp_server_attempted_connections_count"); + + private static readonly Counter ipLimitedConnectionsCounter = + Telemetry.NetworkMeter.CreateCounter("tcp_server_ip_limited_connections_count"); + + private static readonly Counter firewalledConnectionsCounter = + Telemetry.NetworkMeter.CreateCounter("tcp_server_firewalled_connections_count"); + + private static readonly Counter allowedConnectionsCounter = + Telemetry.NetworkMeter.CreateCounter("tcp_server_allowed_connections_count"); + private static readonly ILogger logger = LogFactory.GetLogger(typeof(TcpServer)); // AccountLoginReject BadComm @@ -78,11 +91,14 @@ public static class TcpServer } public static IEnumerable GetListeningAddresses(IPEndPoint ipep) => - NetworkInterface.GetAllNetworkInterfaces().SelectMany(adapter => - adapter.GetIPProperties().UnicastAddresses - .Where(uip => ipep.AddressFamily == uip.Address.AddressFamily) - .Select(uip => new IPEndPoint(uip.Address, ipep.Port)) - ); + NetworkInterface.GetAllNetworkInterfaces() + .SelectMany( + adapter => + adapter.GetIPProperties() + .UnicastAddresses + .Where(uip => ipep.AddressFamily == uip.Address.AddressFamily) + .Select(uip => new IPEndPoint(uip.Address, ipep.Port)) + ); public static Socket CreateListener(IPEndPoint ipep) { @@ -133,13 +149,17 @@ public static class TcpServer socket = await listener.AcceptAsync(); var remoteIP = ((IPEndPoint)socket.RemoteEndPoint)!.Address; + attemptedConnectionsCounter.Add(1); + if (!IPLimiter.Verify(remoteIP)) { + ipLimitedConnectionsCounter.Add(1); TraceDisconnect("Past IP limit threshold", remoteIP); logger.Debug("{Address} Past IP limit threshold", remoteIP); } else if (Firewall.IsBlocked(remoteIP)) { + firewalledConnectionsCounter.Add(1); TraceDisconnect("Firewalled", remoteIP); logger.Debug("{Address} Firewalled", remoteIP); } @@ -150,6 +170,7 @@ public static class TcpServer if (args.AllowConnection) { + allowedConnectionsCounter.Add(1); _ = new NetState(socket); continue; } diff --git a/Projects/Server/Telemetry.cs b/Projects/Server/Telemetry.cs index 7f7cf8a6f..da600e248 100644 --- a/Projects/Server/Telemetry.cs +++ b/Projects/Server/Telemetry.cs @@ -12,6 +12,7 @@ public class Telemetry public static readonly Meter AccountingMeter = new("ModernUO.Accounting"); public static readonly Meter ItemsMeter = new("ModernUO.Items"); public static readonly Meter MobilesMeter = new("ModernUO.Mobiles"); + public static readonly Meter NetworkMeter = new("ModernUO.Network"); public static readonly Meter EconomyMeter = new("ModernUO.Economy"); public static void Start() @@ -20,12 +21,13 @@ public class Telemetry .ConfigureResource(r => r.AddService("ModernUO")) .AddOtlpExporter(options => { - options.BatchExportProcessorOptions.ScheduledDelayMilliseconds = TimeSpan.FromSeconds(10.0).Milliseconds; + options.BatchExportProcessorOptions.ScheduledDelayMilliseconds = TimeSpan.FromSeconds(20.0).Milliseconds; }) .AddMeter("ModernUO.Accounting") .AddMeter("ModernUO.Items") .AddMeter("ModernUO.Mobiles") .AddMeter("ModernUO.Economy") + .AddMeter("ModernUO.Network") .AddView( "gold_created_histogram", new ExplicitBucketHistogramConfiguration() diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestSystem.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestSystem.cs index 84337d61d..8864324b5 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestSystem.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestSystem.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Diagnostics.Metrics; using Server.Items; using Server.Targeting; @@ -6,6 +8,8 @@ namespace Server.Engines.Harvest { public abstract class HarvestSystem { + private static readonly Counter harvestedResourcesCounter = + Telemetry.EconomyMeter.CreateCounter("harvested_resources_count"); public HarvestDefinition[] Definitions { get; init; } public virtual bool CheckTool(Mobile from, Item tool) @@ -196,6 +200,13 @@ namespace Server.Engines.Harvest bank.Consume(item.Amount, from); + harvestedResourcesCounter.Add(item.Amount, new KeyValuePair[] + { + new("Resource", item.GetType().Name), + new("Map", map?.Name), + new("Region", from?.Region.Name), + }); + if (Give(from, item, def.PlaceAtFeetIfFull)) { SendSuccessTo(from, item, resource); diff --git a/Projects/UOContent/Engines/Player Murder System/PlayerMurderSystem.cs b/Projects/UOContent/Engines/Player Murder System/PlayerMurderSystem.cs index 7fda051ff..5785bb226 100644 --- a/Projects/UOContent/Engines/Player Murder System/PlayerMurderSystem.cs +++ b/Projects/UOContent/Engines/Player Murder System/PlayerMurderSystem.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.Metrics; using System.Runtime.InteropServices; using Server.Collections; +using Server.Ethics; using Server.Logging; using Server.Mobiles; @@ -10,6 +12,7 @@ namespace Server.Engines.PlayerMurderSystem; public class PlayerMurderSystem : GenericPersistence { + private static readonly Counter playerMurderCounter = Telemetry.MobilesMeter.CreateCounter("player_murder_count"); private static PlayerMurderSystem _playerMurderPersistence; private static readonly ILogger logger = LogFactory.GetLogger(typeof(PlayerMurderSystem)); @@ -166,6 +169,12 @@ public class PlayerMurderSystem : GenericPersistence public static void OnPlayerMurder(PlayerMobile player) { + playerMurderCounter.Add(1, new KeyValuePair[] + { + new("Map", player.Map?.Name), + new("Region", player.Region?.Name), + }); + var context = GetOrCreateMurderContext(player); context.ShortTermMurders++; player.Kills++; diff --git a/Projects/UOContent/Spells/Base/Spell.cs b/Projects/UOContent/Spells/Base/Spell.cs index ec04e9158..f6407a178 100644 --- a/Projects/UOContent/Spells/Base/Spell.cs +++ b/Projects/UOContent/Spells/Base/Spell.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.Metrics; using Server.Engines.ConPVP; using Server.Items; using Server.Misc; @@ -15,6 +16,8 @@ namespace Server.Spells { public abstract class Spell : ISpell { + protected static readonly Counter spellCastCount = Telemetry.MobilesMeter.CreateCounter("spell_cast_count"); + private static readonly TimeSpan NextSpellDelay = TimeSpan.FromSeconds(0.75); private static readonly TimeSpan AnimateDelay = TimeSpan.FromSeconds(1.5); // In reality, it's ANY delayed Damage spell Post-AoS that can't stack, but, only @@ -922,43 +925,51 @@ namespace Server.Spells private class CastTimer : Timer { - private readonly Spell m_Spell; + private readonly Spell _spell; public CastTimer(Spell spell, TimeSpan castDelay) : base(castDelay) { - m_Spell = spell; + _spell = spell; } protected override void OnTick() { - var caster = m_Spell?.Caster; + var caster = _spell?.Caster; if (caster == null) { return; } - if (m_Spell.State == SpellState.Casting && caster.Spell == m_Spell) + if (_spell.State == SpellState.Casting && caster.Spell == _spell) { - m_Spell.State = SpellState.Sequencing; - m_Spell._castTimer = null; - caster.OnSpellCast(m_Spell); - caster.Region?.OnSpellCast(caster, m_Spell); + _spell.State = SpellState.Sequencing; + _spell._castTimer = null; + caster.OnSpellCast(_spell); + caster.Region?.OnSpellCast(caster, _spell); caster.NextSpellTime = - Core.TickCount + (int)m_Spell.GetCastRecovery().TotalMilliseconds; // Spell.NextSpellDelay; + Core.TickCount + (int)_spell.GetCastRecovery().TotalMilliseconds; // Spell.NextSpellDelay; caster.Delta(MobileDelta.Flags); // Update paralyze var originalTarget = caster.Target; - m_Spell.OnCast(); + _spell.OnCast(); if (caster.Player && caster.Target != originalTarget) { caster.Target?.BeginTimeout(caster, 30000); // 30 seconds } - m_Spell._castTimer = null; + spellCastCount.Add(1, new KeyValuePair[] + { + new("SpellName", _spell.Name), + new("Skill", $"{_spell.CastSkill}"), + new("Map", $"{caster.Map.Name}"), + new("Region", $"{caster.Region?.Name}"), + }); + + _spell._castTimer = null; } }