using System.ComponentModel.DataAnnotations; using System.IO.Abstractions; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Text; using qmonlib.Attributes; using Quadarax.Foundation.Core.Logging; using Quadarax.Foundation.Core.Reflection.Extensions; namespace qmonlib { public class QMonClient : QMonHostBase { #region *** Properties *** protected override Uri UriGeneral => Configuration.TargetUriGeneral; protected override Uri UriData => Configuration.TargetUriData; protected override TimeSpan IntervalGeneral => Configuration.EmitGeneralInterval; protected override TimeSpan? IntervalData => Configuration.EmitDataInterval; public string InstanceIdentifier { get; } #endregion #region *** Fields *** private IDictionary _generalCache = new Dictionary(); #endregion #region *** Constructors *** public QMonClient(string instanceIdentifier, QMonClientConfiuration configuration, ILogger? externalLogger) : base(configuration, externalLogger) { InstanceIdentifier = instanceIdentifier ?? throw new ArgumentNullException(nameof(instanceIdentifier)); ScanAssemblies(); } private void ScanAssemblies() { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { var types = assembly.GetTypesWithAttribute(true); foreach (var type in types) { var monItemGeneral = new MonItemGeneral { Caption = type.GetCustomAttribute()?.Caption ?? type.Name, Description = type.GetCustomAttribute()?.Description ?? string.Empty, ViewType = MonItemGeneral.MonViewType.Item }; var properties = type.GetPropertiesWithAttribute(true); var keys = new List>(); foreach (var property in properties) { var itemDescriptor = new MonItemGeneral.ItemDescriptor { Name = property.Name, TypeName = property.PropertyType.Name, Label = property.GetCustomAttribute()?.Label ?? property.Name, Description = property.GetCustomAttribute()?.Description ?? string.Empty, Order = property.GetCustomAttribute()?.Order ?? 0, _propertyInfo = property }; monItemGeneral.Items.Add(itemDescriptor); if (property.GetCustomAttribute() != null) { keys.Add(new Tuple(property.Name, property.GetCustomAttribute()!.KeyOrder)); } } foreach (var key in keys.OrderBy(x => x.Item2)) { var ord = monItemGeneral.Items.FindIndex(x => x.Name == key.Item1); if (ord>=0) monItemGeneral.KeyOrdinals.Add(ord); } _generalCache.Add(type.FullName!, monItemGeneral); } } } #endregion #region *** Public Operations *** #endregion #region *** Protected Operations *** protected override void OnDisposing() { base.OnDisposing(); _generalCache.Clear(); } protected override void OnTimerData(object? state) { } protected override void OnTimerGeneral(object? state) { if (state == null) throw new ArgumentNullException(nameof(state)); var owner = (QMonClient)state; try { var data = new MonGeneral() { InstanceIdentifier = owner.InstanceIdentifier, Items = new List() }; data.Items.AddRange(owner._generalCache.Values); var dataOut = Serialize(data); UdpClientGeneral.Send(dataOut); Log(LogSeverityEnum.Trace, $"[{InstanceIdentifier}] Sent General packet size = {dataOut.Length} bytes"); } catch(Exception ex) { Log(LogSeverityEnum.Error, $"[{InstanceIdentifier}] Error sending general data", ex); } } private byte[] Serialize(MonGeneral data) { if (data == null) throw new ArgumentNullException(nameof(data)); var json = Binder.SaveToString(data); return Encoding.UTF8.GetBytes(json); } protected override UdpClient CreateUdpClient(Uri targetUri) { var ep = new IPEndPoint(IPAddress.Parse(targetUri.DnsSafeHost), targetUri.Port); var udpClient = new UdpClient(); udpClient.Connect(ep); return udpClient; } protected override void OnOpen() { } protected override void OnClose() { } #endregion #region *** Nested Types *** #endregion } }