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<dynamic> loggerQueueData = new ConcurrentQueue<dynamic>();
|
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<DataTable>().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<Type> 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;
|
}
|
}
|
}
|