using System; using System.Collections.Concurrent; using UMC.Data; using System.Text; using System.Net.Sockets; namespace UMC.Proxy { class LogSetting : UMC.Data.DataProvider { UdpClient client; class UdpWriter : System.IO.TextWriter { byte[] _buffers; short _bufferSize, _seq = 0; UdpClient client; int hashcode; public override Encoding Encoding => Encoding.UTF8; public UdpWriter(UdpClient client) { this.client = client; this.hashcode = Guid.NewGuid().GetHashCode(); _buffers = System.Buffers.ArrayPool.Shared.Rent(548); } public override void Flush() { BitConverter.TryWriteBytes(_buffers, hashcode); BitConverter.TryWriteBytes(_buffers.AsSpan(4), -_seq); _seq = 0; BitConverter.TryWriteBytes(_buffers.AsSpan(6), _bufferSize); this.client.Send(_buffers, _bufferSize + 8); _bufferSize = 0; this.hashcode = Guid.NewGuid().GetHashCode(); } public override void Close() { base.Dispose(true); } protected override void Dispose(bool disposing) { if (_buffers != null) { System.Buffers.ArrayPool.Shared.Return(_buffers); } _buffers = null; base.Dispose(disposing); } char[] _chars = new char[1]; void Send() { BitConverter.TryWriteBytes(_buffers, hashcode); BitConverter.TryWriteBytes(_buffers.AsSpan(4), _seq); _seq++; BitConverter.TryWriteBytes(_buffers.AsSpan(6), _bufferSize); this.client.Send(_buffers, _bufferSize + 8); _bufferSize = 0; } public override void Write(char value) { if (_bufferSize + 6 > 540) { Send(); _bufferSize = 0; } _chars[0] = value; _bufferSize += Convert.ToInt16(Encoding.UTF8.GetBytes(_chars, 0, 1, _buffers, _bufferSize + 8)); } } public static LogSetting Instance() { if (_Instance == null) { _Instance = new LogSetting(); _Instance.LoadConf(); } return _Instance; } static LogSetting _Instance; bool _isWriter = false; public virtual bool IsWriter { get { return _isWriter; } } public void LoadConf() { var provider = Reflection.Configuration("assembly")?["Log"]; if (provider != null) { var host = provider["host"]; if (String.IsNullOrEmpty(host) == false) { var port = Utility.IntParse(provider["port"], 5188); _isWriter = true; this.client = new UdpClient(host, port); } else { _isWriter = false; } } else { _isWriter = false; } foreach (var l in _logMetas) { l.Dispose(); } _logMetas.Clear(); } ConcurrentQueue _logMetas = new ConcurrentQueue(); public virtual void Write(Web.WebMeta logMeta) { if (this._isWriter) { UdpWriter writer; if (_logMetas.TryDequeue(out writer)) { } else { writer = new UdpWriter(this.client); } UMC.Data.JSON.Serialize(logMeta, writer); writer.Flush(); _logMetas.Enqueue(writer); } } public static void Instance(LogSetting logSetting, Provider provider) { logSetting.Provider = provider; _Instance = logSetting; } } }