using Microsoft.AspNetCore.Http; using Microsoft.OpenApi.Models; using SqlSugar; using StackExchange.Profiling.Internal; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization.Formatters; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; using WIDESEA_Core.DB; using WIDESEA_Core.Enums; using WIDESEA_Core.Helper; using WIDESEA_Core.HttpContextUser; using WIDESEA_Core.Seed; namespace WIDESEA_Core.LogHelper { public static class Logger { public static ConcurrentQueue loggerQueueData = new ConcurrentQueue(); static Logger() { Task.Run(() => { StartWriteLog(); }); } static void StartWriteLog() { DataTable queueTable = CreateEmptyTable(); while (true) { try { //如果队列中有数据且队列表中的行数小于500,则将队列中的数据写入队列表 if (loggerQueueData.Count() > 0 && queueTable.Rows.Count < 500) { DequeueToTable(queueTable); continue; } //每5秒写一次数据 Thread.Sleep(5000); //如果队列表中的行数为0,则跳过本次循环 if (queueTable.Rows.Count == 0) { continue; } //创建SqlSugarClient对象,用于连接数据库 SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig() { ConnectionString = DBContext.GetMainConnectionDb().Connection, IsAutoCloseConnection = true, DbType = MainDb.DbType, }); //将队列表中的数据批量插入数据库 int rows = sugarClient.Fastest().AS("Sys_Log").BulkCopy(queueTable); //清空队列表 queueTable.Clear(); } catch (Exception ex) { //打印异常信息 Console.WriteLine(ex.ToString()); } } } private static void DequeueToTable(DataTable queueTable) { loggerQueueData.TryDequeue(out dynamic log); if (log != null) { DataRow row = queueTable.NewRow(); // 如果log的BeginDate为空或者BeginDate的年份小于2010,则将BeginDate设置为当前时间 if (log.BeginDate == null || log.BeginDate?.Year < 2010) { log.BeginDate = DateTime.Now; } // 如果log的EndDate为空,则将EndDate设置为当前时间 if (log.EndDate == null) { log.EndDate = DateTime.Now; } // row["Id"] = log.Id; // 将RequestParam中的换行符替换为空字符串 row["RequestParam"] = log.RequestParam?.Replace("\r\n", "").Replace("\n", ""); // 将ResponseParam中的换行符替换为空字符串 row["ResponseParam"] = log.ResponseParam?.Replace("\r\n", "").Replace("\n", ""); row["Success"] = log.Success ?? -1; // 将BeginDate设置为log的BeginDate row["BeginDate"] = log.BeginDate; // 将EndDate设置为log的EndDate row["EndDate"] = log.EndDate; // 计算ElapsedTime,即EndDate减去BeginDate的毫秒数 row["ElapsedTime"] = ((DateTime)log.EndDate - (DateTime)log.BeginDate).TotalMilliseconds; // 将UserIP设置为log的UserIP row["UserIP"] = log.UserIP; // 将Url设置为log的Url row["Url"] = log.Url; // 如果log的UserId为空,则将UserId设置为-1,否则设置为log的UserId row["UserId"] = log.UserId ?? -1; // 将UserName设置为log的UserName row["UserName"] = log.UserName; row["MethodName"] = log.MethodName; row["Methodremark"] = log.Methodremark; // 将row添加到queueTable中 queueTable.Rows.Add(row); } } private static DataTable CreateEmptyTable() { DataTable queueTable = new DataTable(); queueTable.Columns.Add("BeginDate", Type.GetType("System.DateTime")); queueTable.Columns.Add("ElapsedTime", Type.GetType("System.Int32")); queueTable.Columns.Add("EndDate", Type.GetType("System.DateTime")); queueTable.Columns.Add("RequestParam", typeof(string)); queueTable.Columns.Add("ResponseParam", typeof(string)); queueTable.Columns.Add("Success", Type.GetType("System.Int32")); queueTable.Columns.Add("Url", typeof(string)); queueTable.Columns.Add("UserIP", typeof(string)); queueTable.Columns.Add("UserName", typeof(string)); queueTable.Columns.Add("UserId", Type.GetType("System.Int32")); queueTable.Columns.Add("MethodName", typeof(string)); queueTable.Columns.Add("Methodremark", typeof(string)); //queueTable.Columns.Add("ServiceIP", typeof(string)); //queueTable.Columns.Add("BrowserType", typeof(string)); //queueTable.Columns.Add("Role_Id", Type.GetType("System.Int32")); return queueTable; } public static void Add(string requestParameter, string responseParameter) { dynamic log = null; string MethodName = string.Empty; string Methodremark = string.Empty; try { //获取当前HttpContext HttpContext context = App.HttpContext; //如果HttpContext为空,则返回 if (context == null) { return; } //如果请求方法为OPTIONS,则返回 if (context.Request.Method == "OPTIONS") return; //获取RequestLogModel实例 RequestLogModel logModel = (context.RequestServices.GetService(typeof(RequestLogModel)) as RequestLogModel) ?? new RequestLogModel { RequestDate = DateTime.Now }; #region 获取接口注释 try { string path = context.Request.Path; var names = path.Split('/'); var basePath = AppContext.BaseDirectory + "WIDESEA_WMSServer"; Assembly assembly = Assembly.LoadFrom(basePath); List types = assembly.GetTypes().Where(x => x.Name.Contains(names[2] + "Controller")).ToList(); if (types.Count > 0) { //MethodInfo methodInfo = types.First().GetMethod("login"); MethodInfo methodInfo = types.First().GetMethods() .FirstOrDefault(m => m.Name.Equals(names[3], StringComparison.OrdinalIgnoreCase)); if (methodInfo != null) { MethodName = methodInfo.Name; string xmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, methodInfo.DeclaringType.Assembly.GetName().Name + ".xml"); //if (!File.Exists(xmlPath)) return "XML documentation file not found."; // 检查文件是否存在 // 加载XML文档并解析摘要信息 XDocument xdoc = XDocument.Load(xmlPath); string membername = $"M:{methodInfo.DeclaringType.FullName}.{methodInfo.Name}"; var member = xdoc.Descendants("member") .FirstOrDefault(m => m.Attribute("name").Value.ToString().Contains(membername));// 定位到方法节点 //.FirstOrDefault(m => m.Attribute("name")?.Value == $"M:{methodInfo.DeclaringType.FullName}.{methodInfo.Name}"); // 定位到方法节点 //if (member == null) return "Member not found in XML documentation."; // 检查方法是否在XML文档中找到 //var summary = member?.Element("summary")?.Value ?? "No summary provided."; // 获取摘要信息或默认值 Methodremark = member?.Element("summary")?.Value.Replace("\n", "").Replace(" ", "") ?? methodInfo.Name; // 获取摘要信息或默认值 } } } catch (Exception ex) { } #endregion //获取当前用户 IUser user = App.User; //创建日志对象 log = new { //请求开始时间 BeginDate = logModel.RequestDate, //请求结束时间 EndDate = DateTime.Now, //请求参数 RequestParam = requestParameter, //响应参数 ResponseParam = responseParameter, //方法名称 MethodName = MethodName, //方法描述 Methodremark= Methodremark, //响应状态 Success = LogStatusEnum.Success.ObjToInt(), //请求URL Url = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Path, //客户端IP UserIP = GetClientIP(context)?.Replace("::ffff:", "").Replace("::1", "127.0.0.1"), //用户ID UserId = user.UserId, //用户名 UserName = user.UserName }; } catch (Exception exception) { //如果发生异常,则创建日志对象 log = log ?? new { //请求开始时间 BeginDate = DateTime.Now, //请求结束时间 EndDate = DateTime.Now, //请求参数 RequestParam = requestParameter, //响应参数 ResponseParam = responseParameter, //方法名称 MethodName = MethodName, //方法描述 Methodremark = Methodremark, //响应状态 Success = LogStatusEnum.Error.ObjToInt(), }; } //添加系统日志 loggerQueueData.Enqueue(log); } public static void Add(string url, string requestParameter, string responseParameter, DateTime beginDate) { dynamic? log = null; try { //获取当前用户 IUser? user = App.User; //创建日志对象 log = new { //请求开始时间 BeginDate = beginDate, //请求结束时间 EndDate = DateTime.Now, //请求参数 RequestParam = requestParameter, //响应参数 ResponseParam = responseParameter, //请求URL Url = url, //客户端IP UserIP = "", //用户ID UserId = user?.UserId, //用户名 UserName = user?.UserName }; } catch (Exception exception) { //如果发生异常,则创建日志对象 log = log ?? new { //请求开始时间 BeginDate = DateTime.Now, //请求结束时间 EndDate = DateTime.Now, //请求参数 RequestParam = requestParameter, //响应参数 ResponseParam = responseParameter, }; } //添加系统日志 loggerQueueData.Enqueue(log); } public static string GetClientIP(HttpContext context) { // 获取请求头中的X-Forwarded-For字段,并将其转换为字符串 var ip = context.Request.Headers["X-Forwarded-For"].ObjToString(); // 如果X-Forwarded-For字段为空,则获取远程IP地址 if (string.IsNullOrEmpty(ip)) { ip = context.Connection.RemoteIpAddress.ObjToString(); } // 返回IP地址 return ip; } } }