//
using Masuit.Tools;
using Microsoft.Extensions.Logging;
using NewLife.Serialization;
using SqlSugar;
using System.Globalization;
using UAParser;
namespace SafeCampus.Web.Core;
///
/// 数据库写入器
///
public class DatabaseLoggingWriter : IDatabaseLoggingWriter
{
private readonly ISearcher _searcher;
private readonly SqlSugarScope _db;
private readonly ILogger _logger;
public DatabaseLoggingWriter(ILogger logger, ISearcher searcher)
{
_db = DbContext.DB;
_logger = logger;
_searcher = searcher;
}
public async Task WriteAsync(LogMessage logMsg, bool flush)
{
//获取请求json字符串
var jsonString = logMsg.Context.Get("loggingMonitor").ToString();
//转成实体
var loggingMonitor = jsonString.ToJsonEntity();
//日志时间赋值
loggingMonitor.LogDateTime = logMsg.LogDateTime;
// loggingMonitor.ReturnInformation.Value
//验证失败和没有DisplayTitle之类的不记录日志
if (loggingMonitor.Validation == null && loggingMonitor.DisplayTitle != null)
{
//获取操作名称
var operation = loggingMonitor.DisplayTitle;
var client = (ClientInfo)logMsg.Context.Get(LoggingConst.CLIENT);//获取客户端信息
var path = logMsg.Context.Get(LoggingConst.PATH).ToString();//获取操作名称
var method = logMsg.Context.Get(LoggingConst.METHOD).ToString();//获取方法
//表示访问日志
if (operation == EventSubscriberConst.LOGIN_B || operation == EventSubscriberConst.LOGIN_OUT_B)
{
//如果没有异常信息
if (loggingMonitor.Exception == null)
{
await CreateVisitLog(operation, loggingMonitor, client);//添加到访问日志
}
else
{
//添加到异常日志
await CreateOperationLog(operation, path, loggingMonitor, client);
}
}
else
{
//只有定义了Title的POST方法才记录日志
if (!operation.Contains("/") && method == "POST")
{
//添加到操作日志
await CreateOperationLog(operation, path, loggingMonitor, client);
}
}
}
}
///
/// 创建访问日志
///
/// 访问类型
/// loggingMonitor
/// 客户端信息
private async Task CreateVisitLog(string operation, LoggingMonitorJson loggingMonitor, ClientInfo clientInfo)
{
string name;//用户姓名
string opAccount;//用户账号
if (operation == EventSubscriberConst.LOGIN_B)
{
//如果是登录,用户信息就从返回值里拿
var result = loggingMonitor.ReturnInformation.Value.ToJson();//返回值转json
var userInfo = result.ToJsonEntity>();//格式化成user表
name = userInfo.Data.Name;//赋值姓名
opAccount = userInfo.Data.Account;//赋值账号
}
else
{
//如果是登录出,用户信息就从AuthorizationClaims里拿
name = loggingMonitor.AuthorizationClaims.Where(it => it.Type == ClaimConst.NAME).Select(it => it.Value).FirstOrDefault();
opAccount = loggingMonitor.AuthorizationClaims.Where(it => it.Type == ClaimConst.ACCOUNT).Select(it => it.Value).FirstOrDefault();
}
//日志表实体
var devLogVisit = new SysLogVisit
{
Name = operation,
Category = operation == EventSubscriberConst.LOGIN_B ? CateGoryConst.LOG_LOGIN : CateGoryConst.LOG_LOGOUT,
ExeStatus = SysLogConst.SUCCESS,
OpAddress = GetLoginAddress(loggingMonitor.RemoteIPv4),
OpIp = loggingMonitor.RemoteIPv4,
OpBrowser = clientInfo.UA.Family + clientInfo.UA.Major,
OpOs = clientInfo.OS.Family + clientInfo.OS.Major,
OpTime = loggingMonitor.LogDateTime,
OpUser = name,
OpAccount = opAccount
};
await _db.CopyNew().InsertableWithAttr(devLogVisit).IgnoreColumns(true).SplitTable().ExecuteCommandAsync();//入库
}
///
/// 创建操作日志
///
/// 操作名称
/// 请求地址
/// loggingMonitor
/// 客户端信息
///
private async Task CreateOperationLog(string operation, string path, LoggingMonitorJson loggingMonitor,
ClientInfo clientInfo)
{
//用户名称
var name = loggingMonitor.AuthorizationClaims?.Where(it => it.Type == ClaimConst.NAME).Select(it => it.Value).FirstOrDefault();
//账号
var opAccount = loggingMonitor.AuthorizationClaims?.Where(it => it.Type == ClaimConst.ACCOUNT).Select(it => it.Value).FirstOrDefault();
//获取参数json字符串,
var paramJson = loggingMonitor.Parameters == null || loggingMonitor.Parameters.Count == 0
? null
: loggingMonitor.Parameters[0].Value.ToJsonString();
//获取结果json字符串
var resultJson = string.Empty;
if (loggingMonitor.ReturnInformation != null)//如果有返回值
{
if (loggingMonitor.ReturnInformation.Value != null)//如果返回值不为空
{
var time = loggingMonitor.ReturnInformation.Value.Time != null
? DateTime.Parse(loggingMonitor.ReturnInformation.Value.Time)
: DateTime.Now;//转成时间
loggingMonitor.ReturnInformation.Value.Time = time.ToString(CultureInfo.CurrentCulture);//转成字符串
resultJson = loggingMonitor.ReturnInformation.Value.ToJsonString();
}
}
//操作日志表实体
var devLogOperate = new SysLogOperate
{
Name = operation,
Category = CateGoryConst.LOG_OPERATE,
ExeStatus = SysLogConst.SUCCESS,
OpAddress = GetLoginAddress(loggingMonitor.RemoteIPv4),
OpIp = loggingMonitor.RemoteIPv4,
OpBrowser = clientInfo.UA.Family + clientInfo.UA.Major,
OpOs = clientInfo.OS.Family + clientInfo.OS.Major,
OpTime = loggingMonitor.LogDateTime,
OpUser = name,
OpAccount = opAccount,
ReqMethod = loggingMonitor.HttpMethod,
ReqUrl = path,
ResultJson = resultJson,
ClassName = loggingMonitor.DisplayName,
MethodName = loggingMonitor.ActionName,
ParamJson = paramJson
};
//如果异常不为空
if (loggingMonitor.Exception != null)
{
devLogOperate.Category = CateGoryConst.LOG_EXCEPTION;//操作类型为异常
devLogOperate.ExeStatus = SysLogConst.FAIL;//操作状态为失败
devLogOperate.ExeMessage = loggingMonitor.Exception.Type + ":" + loggingMonitor.Exception.Message + "\n"
+ loggingMonitor.Exception.StackTrace;
}
await _db.CopyNew().InsertableWithAttr(devLogOperate).IgnoreColumns(true).SplitTable().ExecuteCommandAsync();//入库
}
///
/// 解析IP地址
///
///
///
private string GetLoginAddress(string ip)
{
var loginAddress = "未知";
try
{
var ipInfo = _searcher.Search(ip);//解析ip
loginAddress = ipInfo?.Replace("0|", "");//去掉前面的0|
}
catch (global::System.Exception ex)
{
_logger.LogError("IP解析错误" + ex, ex);
}
return loginAddress;
}
}