317 lines
12 KiB
C#
317 lines
12 KiB
C#
using Microsoft.AspNetCore.Http;
|
||
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Data;
|
||
using System.Data.SqlClient;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Web;
|
||
using VOL.Core.Configuration;
|
||
using VOL.Core.Const;
|
||
using VOL.Core.DBManager;
|
||
using VOL.Core.Enums;
|
||
using VOL.Core.Extensions;
|
||
using VOL.Core.ManageUser;
|
||
using VOL.Entity.DomainModels;
|
||
|
||
namespace VOL.Core.Services
|
||
{
|
||
/// <summary>
|
||
/// 通过内置队列异步定时写日志
|
||
/// </summary>
|
||
public static class Logger
|
||
{
|
||
public static ConcurrentQueue<Sys_Log> loggerQueueData = new ConcurrentQueue<Sys_Log>();
|
||
private static DateTime lastClearFileDT = DateTime.Now.AddDays(-1);
|
||
private static string _loggerPath = AppSetting.DownLoadPath + "Logger\\Queue\\";
|
||
|
||
static Logger()
|
||
{
|
||
Task.Run(() =>
|
||
{
|
||
Start();
|
||
if (DBType.Name != "MsSql")
|
||
{
|
||
return;
|
||
}
|
||
try
|
||
{
|
||
DBServerProvider.SqlDapper.ExcuteNonQuery("set global local_infile = 'ON';", null);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"日志启动调用mysql数据库异常:{ex.Message},{ex.StackTrace}");
|
||
}
|
||
});
|
||
}
|
||
|
||
public static void Info(string message)
|
||
{
|
||
Info(LoggerType.Info, message);
|
||
}
|
||
|
||
public static void Info(LoggerType loggerType, string message = null)
|
||
{
|
||
Info(loggerType, message, null, null);
|
||
}
|
||
|
||
public static void Info(LoggerType loggerType, string requestParam, string resposeParam, string ex = null)
|
||
{
|
||
Add(loggerType, requestParam, resposeParam, ex, LoggerStatus.Info);
|
||
}
|
||
|
||
public static void OK(string message)
|
||
{
|
||
OK(LoggerType.Success, message);
|
||
}
|
||
|
||
public static void OK(LoggerType loggerType, string message = null)
|
||
{
|
||
OK(loggerType, message, null, null);
|
||
}
|
||
|
||
public static void OK(LoggerType loggerType, string requestParam, string resposeParam, string ex = null)
|
||
{
|
||
Add(loggerType, requestParam, resposeParam, ex, LoggerStatus.Success);
|
||
}
|
||
|
||
public static void Error(string message)
|
||
{
|
||
Error(LoggerType.Error, message);
|
||
}
|
||
|
||
public static void Error(LoggerType loggerType, string message)
|
||
{
|
||
Error(loggerType, message, null, null);
|
||
}
|
||
|
||
public static void Error(LoggerType loggerType, string requestParam, string resposeParam, string ex = null)
|
||
{
|
||
Add(loggerType, requestParam, resposeParam, ex, LoggerStatus.Error);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 多线程调用日志
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
public static void AddAsync(string message, string ex = null)
|
||
{
|
||
AddAsync(LoggerType.Info, null, message, ex, ex != null ? LoggerStatus.Error : LoggerStatus.Info);
|
||
}
|
||
|
||
public static void AddAsync(LoggerType loggerType, string requestParameter, string responseParameter, string ex, LoggerStatus status)
|
||
{
|
||
var log = new Sys_Log()
|
||
{
|
||
BeginDate = DateTime.Now,
|
||
EndDate = DateTime.Now,
|
||
User_Id = 0,
|
||
UserName = "",
|
||
// Role_Id = ,
|
||
LogType = loggerType.ToString(),
|
||
ExceptionInfo = ex,
|
||
RequestParameter = requestParameter,
|
||
ResponseParameter = responseParameter,
|
||
Success = (int)status
|
||
};
|
||
loggerQueueData.Enqueue(log);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="requestParameter">请求参数</param>
|
||
/// <param name="responseParameter">响应参数</param>
|
||
/// <param name="success">响应结果1、成功,2、异常,0、其他</param>
|
||
/// <param name="userInfo">用户数据</param>
|
||
private static void Add(LoggerType loggerType, string requestParameter, string responseParameter, string ex, LoggerStatus status)
|
||
{
|
||
Sys_Log log = null;
|
||
try
|
||
{
|
||
HttpContext context = Utilities.HttpContext.Current;
|
||
if (context==null) return;
|
||
if (context.Request.Method == "OPTIONS") return;
|
||
ActionObserver cctionObserver = (context.RequestServices.GetService(typeof(ActionObserver)) as ActionObserver);
|
||
if (context == null)
|
||
{
|
||
WriteText($"未获取到httpcontext信息,type:{loggerType.ToString()},reqParam:{requestParameter},respParam:{responseParameter},ex:{ex},success:{status.ToString()}");
|
||
return;
|
||
}
|
||
UserInfo userInfo = UserContext.Current.UserInfo;
|
||
log = new Sys_Log()
|
||
{
|
||
BeginDate = cctionObserver.RequestDate,
|
||
EndDate = DateTime.Now,
|
||
User_Id = userInfo.User_Id,
|
||
UserName = userInfo.UserTrueName,
|
||
Role_Id = userInfo.Role_Id,
|
||
LogType = loggerType.ToString(),
|
||
ExceptionInfo = ex,
|
||
RequestParameter = requestParameter,
|
||
ResponseParameter = responseParameter,
|
||
Success = (int)status
|
||
};
|
||
SetServicesInfo(log, context);
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
log = log ?? new Sys_Log()
|
||
{
|
||
BeginDate = DateTime.Now,
|
||
EndDate = DateTime.Now,
|
||
LogType = loggerType.ToString(),
|
||
RequestParameter = requestParameter,
|
||
ResponseParameter = responseParameter,
|
||
Success = (int)status,
|
||
ExceptionInfo = ex + exception.Message
|
||
};
|
||
}
|
||
loggerQueueData.Enqueue(log);
|
||
}
|
||
|
||
private static void Start()
|
||
{
|
||
DataTable queueTable = CreateEmptyTable();
|
||
while (true)
|
||
{
|
||
try
|
||
{
|
||
if (loggerQueueData.Count() > 0 && queueTable.Rows.Count < 500)
|
||
{
|
||
DequeueToTable(queueTable); continue;
|
||
}
|
||
//每5秒写一次数据
|
||
Thread.Sleep(1000);
|
||
if (queueTable.Rows.Count == 0) { continue; }
|
||
|
||
DBServerProvider.SqlDapper.BulkInsert(queueTable, "Sys_Log", SqlBulkCopyOptions.KeepIdentity, null, _loggerPath);
|
||
|
||
queueTable.Clear();
|
||
|
||
if ((DateTime.Now - lastClearFileDT).TotalDays > 1)
|
||
{
|
||
Utilities.FileHelper.DeleteFolder(_loggerPath);
|
||
lastClearFileDT = DateTime.Now;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"日志批量写入数据时出错:{ex.Message}");
|
||
WriteText(ex.Message + ex.StackTrace + ex.Source);
|
||
queueTable.Clear();
|
||
}
|
||
}
|
||
}
|
||
|
||
private static void WriteText(string message)
|
||
{
|
||
try
|
||
{
|
||
Utilities.FileHelper.WriteFile(_loggerPath + "WriteError\\", $"{DateTime.Now.ToString("yyyyMMdd")}.txt", message + "\r\n");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"日志写入文件时出错:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
private static void DequeueToTable(DataTable queueTable)
|
||
{
|
||
loggerQueueData.TryDequeue(out Sys_Log log);
|
||
DataRow row = queueTable.NewRow();
|
||
if (log.BeginDate == null || log.BeginDate?.Year < 2010)
|
||
{
|
||
log.BeginDate = DateTime.Now;
|
||
}
|
||
if (log.EndDate == null)
|
||
{
|
||
log.EndDate = DateTime.Now;
|
||
}
|
||
// row["Id"] = log.Id;
|
||
row["LogType"] = log.LogType;
|
||
row["RequestParameter"] = log.RequestParameter?.Replace("\r\n", "");
|
||
row["ResponseParameter"] = log.ResponseParameter?.Replace("\r\n", "");
|
||
row["ExceptionInfo"] = log.ExceptionInfo;
|
||
row["Success"] = log.Success ?? -1;
|
||
row["BeginDate"] = log.BeginDate;
|
||
row["EndDate"] = log.EndDate;
|
||
row["ElapsedTime"] = ((DateTime)log.EndDate - (DateTime)log.BeginDate).TotalMilliseconds;
|
||
row["UserIP"] = log.UserIP;
|
||
row["ServiceIP"] = log.ServiceIP;
|
||
row["BrowserType"] = log.BrowserType;
|
||
row["Url"] = log.Url;
|
||
row["User_Id"] = log.User_Id ?? -1;
|
||
row["UserName"] = log.UserName;
|
||
row["Role_Id"] = log.Role_Id ?? -1;
|
||
queueTable.Rows.Add(row);
|
||
}
|
||
|
||
private static DataTable CreateEmptyTable()
|
||
{
|
||
DataTable queueTable = new DataTable();
|
||
|
||
// 定义与数据库中小写字段匹配的列
|
||
//queueTable.Columns.Add("id", typeof(int)); // 主键ID
|
||
queueTable.Columns.Add("begindate", typeof(DateTime)); // 开始时间
|
||
queueTable.Columns.Add("url", typeof(string)); // 请求地址
|
||
queueTable.Columns.Add("logtype", typeof(string)); // 日志类型
|
||
queueTable.Columns.Add("success", typeof(int)); // 响应状态
|
||
queueTable.Columns.Add("elapsedtime", typeof(int)); // 时长(毫秒)
|
||
queueTable.Columns.Add("requestparameter", typeof(string)); // 请求参数
|
||
queueTable.Columns.Add("responseparameter", typeof(string)); // 响应参数
|
||
queueTable.Columns.Add("exceptioninfo", typeof(string)); // 异常信息
|
||
queueTable.Columns.Add("userip", typeof(string)); // 用户IP
|
||
queueTable.Columns.Add("serviceip", typeof(string)); // 服务器IP
|
||
queueTable.Columns.Add("browsertype", typeof(string)); // 浏览器类型
|
||
queueTable.Columns.Add("user_id", typeof(int)); // 用户ID
|
||
queueTable.Columns.Add("username", typeof(string)); // 用户名称
|
||
queueTable.Columns.Add("role_id", typeof(int)); // 角色ID
|
||
queueTable.Columns.Add("enddate", typeof(DateTime)); // 结束时间
|
||
|
||
return queueTable;
|
||
}
|
||
|
||
|
||
|
||
public static void SetServicesInfo(Sys_Log log, HttpContext context)
|
||
{
|
||
log.Url = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase +
|
||
context.Request.Path;
|
||
|
||
log.UserIP = context.GetUserIp()?.Replace("::ffff:", "");
|
||
log.ServiceIP = context.Connection.LocalIpAddress.MapToIPv4().ToString() + ":" + context.Connection.LocalPort;
|
||
|
||
log.BrowserType = context.Request.Headers["User-Agent"];
|
||
if (log.BrowserType != null && log.BrowserType.Length > 190)
|
||
{
|
||
log.BrowserType = log.BrowserType.Substring(0, 190);
|
||
}
|
||
if (string.IsNullOrEmpty(log.RequestParameter))
|
||
{
|
||
try
|
||
{
|
||
log.RequestParameter = context.GetRequestParameters();
|
||
if (log.RequestParameter != null)
|
||
{
|
||
log.RequestParameter = HttpUtility.UrlDecode(log.RequestParameter, Encoding.UTF8);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.ExceptionInfo += $"日志读取参数出错:{ex.Message}";
|
||
Console.WriteLine($"日志读取参数出错:{ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public enum LoggerStatus
|
||
{
|
||
Success = 1,
|
||
Error = 2,
|
||
Info = 3
|
||
}
|
||
} |