using System;
|
using System.Security.Cryptography;
|
using System.Text;
|
using System.Threading.Tasks;
|
using CommonUtil.Config;
|
using CommonUtil.Json;
|
using CommonUtil.RabbitMQ;
|
using NLog;
|
using NLog.Config;
|
using NLog.Layouts;
|
using NLog.Targets;
|
|
namespace CommonUtil.Log
|
{
|
/// <summary>
|
/// 日志工具类。基于NLog https://github.com/NLog/NLog
|
/// </summary>
|
public class LogUtil
|
{
|
private readonly static Logger _logger = LogManager.GetCurrentClassLogger();
|
|
private const string DEBUG = "debug";
|
private const string ERROR = "error";
|
private const string FATAL = "fatal";
|
private const string TRACE = "trace";
|
private const string INFO = "info";
|
private const string EMAIL_TARGET = "emailTarget";
|
private const string CONSOLE_TARGET = "consoleTarget";
|
private const string DEBUG_FILE_TARGET = "debugFileTarget";
|
private const string ERROR_FILE_TARGET = "errorFileTarget";
|
private const string INFO_FILE_TARGET = "infoFileTarget";
|
private const string FATAL_FILE_TARGET = "fatalFileTarget";
|
private const string TRACE_FILE_TARGET = "traceFileTarget";
|
// private const string robotSecret = "SECe281ae32807c0665db4e478e85c5f2d7e1ba7c7c05556fabf992b716a513aeb3";
|
//private const string robotWebhook = "https://oapi.dingtalk.com/robot/send?access_token=77a969114188f052f0269b0a81c07e99d2beb9790132be9dcded72a5fc9349d1";
|
//100M
|
private const long LOG_SIZE = 104857600;
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
static LogUtil()
|
{
|
var logIsEmailNameConfig = ConfigUtil.Configuration["LogEmailName"];
|
var isStandard = ConfigUtil.Configuration["isStandard"];
|
var logIsEmailName = logIsEmailNameConfig.IsNullOrEmpty() ? "多卖异常报警" : logIsEmailNameConfig.ToStringEx();
|
var logIsEmailConfig = ConfigUtil.Configuration["LogIsEmail"];
|
bool isLogIsEmail = logIsEmailConfig.IsNullOrEmpty() ? false : logIsEmailConfig.ToBool();
|
var logIsEmailToConfig = ConfigUtil.Configuration["LogEmailTo"];
|
string[] emailTo = logIsEmailToConfig.IsNullOrEmpty() ? new string[] { } : logIsEmailToConfig.Split(',');
|
|
string fileName = "${basedir}/logs/${shortdate}-${fileName}.log";
|
//string layout = "[${longdate}]^_^[${uppercase:${level}}]^_^${message}^_^${exception:format=tostring}${newline}";
|
string runTime = isStandard.IsNullOrEmpty() ? "production" : isStandard == "1" ? "staging" : "production";
|
|
var layout = new JsonLayout
|
{
|
Attributes =
|
{
|
new JsonAttribute
|
{
|
EscapeForwardSlash = false,
|
EscapeUnicode = false,
|
// 这是应用的别名,如 crm,jinggeng,ecrm,必须小写
|
Layout = "fullchannel",
|
Name = "appName",
|
},
|
new JsonAttribute
|
{
|
EscapeForwardSlash = false,
|
EscapeUnicode = false,
|
// 这是应用的运行环境,如 staging:测试/预发环境;production:线上环境
|
Layout = runTime,
|
Name = "environment",
|
},
|
|
new JsonAttribute
|
{
|
EscapeForwardSlash = false,
|
EscapeUnicode = false,
|
Layout = "${logger}",
|
Name = "logger",
|
},
|
new JsonAttribute
|
{
|
EscapeForwardSlash = false,
|
EscapeUnicode = false,
|
Layout = "${longdate}",
|
Name = "time",
|
},
|
new JsonAttribute
|
{
|
EscapeForwardSlash = false,
|
EscapeUnicode = false,
|
Layout = "${level:upperCase=true}",
|
Name = "level",
|
},
|
new JsonAttribute
|
{
|
EscapeForwardSlash = false,
|
EscapeUnicode = false,
|
Layout = "${message}",
|
Name = "message",
|
},
|
new JsonAttribute
|
{
|
EscapeForwardSlash = false,
|
EscapeUnicode = false,
|
Layout = "${exception:format=tostring}",
|
Name = "exception",
|
}
|
}
|
};
|
var config = new LoggingConfiguration();
|
|
var consoleTarget = new ColoredConsoleTarget(CONSOLE_TARGET)
|
{
|
Layout = layout,
|
};
|
config.AddTarget(consoleTarget);
|
|
var traceFileTarget = new FileTarget(TRACE_FILE_TARGET)
|
{
|
FileName = fileName,
|
Layout = layout,
|
ArchiveAboveSize = LOG_SIZE,
|
};
|
config.AddTarget(traceFileTarget);
|
|
|
var debugFileTarget = new FileTarget(DEBUG_FILE_TARGET)
|
{
|
FileName = fileName,
|
Layout = layout,
|
ArchiveAboveSize = LOG_SIZE,
|
};
|
config.AddTarget(debugFileTarget);
|
|
var errorFileTarget = new FileTarget(ERROR_FILE_TARGET)
|
{
|
FileName = fileName,
|
Layout = layout,
|
ArchiveAboveSize = LOG_SIZE,
|
};
|
config.AddTarget(errorFileTarget);
|
|
var infoFileTarget = new FileTarget(INFO_FILE_TARGET)
|
{
|
FileName = fileName,
|
Layout = layout,
|
ArchiveAboveSize = LOG_SIZE,
|
};
|
config.AddTarget(infoFileTarget);
|
|
//NetworkTarget networkTarget = new NetworkTarget(NETWORK_TARGET)
|
//{
|
// Address = "tcp://localhost:5044",
|
// Layout = layout
|
//};
|
|
NetworkTarget networkTarget = new NetworkTarget("networkTarget")
|
{
|
KeepConnection = false,
|
MaxConnections = 10,
|
OnOverflow = NetworkTargetOverflowAction.Split,
|
Address = "tcp://47.92.111.210:8001",
|
NewLine = true,
|
Layout = layout
|
};
|
config.AddTarget(networkTarget);
|
|
var fatalFileTarget = new FileTarget(FATAL_FILE_TARGET)
|
{
|
FileName = fileName,
|
Layout = layout,
|
ArchiveAboveSize = LOG_SIZE,
|
};
|
config.AddTarget(fatalFileTarget);
|
|
if (isLogIsEmail)
|
{
|
var emailTarget = new MailTarget(EMAIL_TARGET)
|
{
|
Name = logIsEmailName,
|
//邮件主题
|
Subject = logIsEmailName,
|
//发件人
|
From = "warning@taocrm.com",
|
//收件人
|
To = string.Join(",", emailTo),
|
Header = "-----------HEAD-----------",
|
Body = layout,
|
Footer = "-----------FOOT-----------",
|
AddNewLines = true,
|
SmtpServer = "smtp.ym.163.com",
|
SmtpPort = 25,
|
SmtpAuthentication = SmtpAuthenticationMode.Basic,
|
SmtpUserName = "warning@taocrm.com",
|
SmtpPassword = "7C4dmE3exj",
|
};
|
config.AddTarget(emailTarget);
|
|
// 配置日志级别输出对象到邮件
|
#if !DEBUG
|
//config.AddRuleForOneLevel(LogLevel.Fatal, emailTarget);
|
//config.AddRuleForOneLevel(LogLevel.Error, emailTarget);
|
#endif
|
}
|
// 配置日志级别输出对象到文件
|
config.AddRuleForOneLevel(LogLevel.Debug, debugFileTarget);
|
config.AddRuleForOneLevel(LogLevel.Info, infoFileTarget);
|
config.AddRuleForOneLevel(LogLevel.Error, errorFileTarget);
|
config.AddRuleForOneLevel(LogLevel.Fatal, fatalFileTarget);
|
|
// 配置日志级别输出对象到控制台
|
|
//config.AddRuleForAllLevels(consoleTarget);
|
//config.AddRuleForAllLevels(networkTarget);
|
|
#if !DEBUG
|
// 配置日志不允许报出异常,以免影响主程序运行
|
LogManager.ThrowExceptions = false;
|
// 配置日志不允许报出异常,以免影响主程序运行
|
LogManager.ThrowConfigExceptions = false;
|
#endif
|
LogManager.Configuration = config;
|
}
|
|
|
/// <summary>
|
/// 记录调试信息
|
/// </summary>
|
public static void Debug(string msg)
|
{
|
Debug(msg, DEBUG);
|
}
|
|
/// <summary>
|
/// 记录调试信息
|
/// </summary>
|
public static void Debug(string msg, string fileName)
|
{
|
DoLog(DEBUG_FILE_TARGET, LogLevel.Debug, msg, fileName, null);
|
}
|
|
///// <summary>
|
///// 记录调试信息
|
///// </summary>
|
//public static void Debug<T>(T value)
|
//{
|
// _logger.Debug(value);
|
//}
|
|
/// <summary>
|
/// 记录异常信息
|
/// </summary>
|
public static void Error(string msg)
|
{
|
Error(msg, ERROR);
|
}
|
|
/// <summary>
|
/// 记录异常信息
|
/// </summary>
|
public static void Error(string msg, string fileName)
|
{
|
Error(msg, fileName, null);
|
}
|
|
|
/// <summary>
|
/// 记录异常信息
|
/// </summary>
|
public static void Error(Exception exception)
|
{
|
Error(exception, null);
|
}
|
|
/// <summary>
|
/// 记录异常信息
|
/// </summary>
|
public static void Error(Exception exception, string msg)
|
{
|
Error(msg, ERROR, exception);
|
}
|
|
/// <summary>
|
/// 记录异常信息
|
/// </summary>
|
public static void Error(string msg, string fileName, Exception exception)
|
{
|
DoLog(ERROR_FILE_TARGET, LogLevel.Error, msg, fileName, exception);
|
string robotMsg = $"# {fileName} \n > 告警时间:{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} \n* " + (!msg.IsNullOrEmpty() ? msg : "") + "," + (!exception.IsNull() ? exception.ToString() : "");
|
// OapiRobotSend(fileName, robotMsg);
|
}
|
|
|
///// <summary>
|
///// 记录异常信息
|
///// </summary>
|
//public static void Error<T>(T value)
|
//{
|
// _logger.Error(value);
|
//}
|
|
/// <summary>
|
/// 记录可用信息
|
/// </summary>
|
public static void Info(string msg)
|
{
|
Info(msg, INFO);
|
}
|
|
|
/// <summary>
|
/// 记录可用信息
|
/// </summary>
|
public static void Info(string msg, string fileName)
|
{
|
DoLog(INFO_FILE_TARGET, LogLevel.Info, msg, fileName, null);
|
}
|
|
///// <summary>
|
///// 记录可用信息
|
///// </summary>
|
//public static void Info<T>(T value)
|
//{
|
// _logger.Info(value);
|
//}
|
|
|
/// <summary>
|
/// 记录跟踪信息
|
/// </summary>
|
public static void Trace(string msg)
|
{
|
Trace(msg, TRACE);
|
}
|
|
/// <summary>
|
/// 记录跟踪信息
|
/// </summary>
|
public static void Trace(string msg, string fileName)
|
{
|
DoLog(TRACE_FILE_TARGET, LogLevel.Trace, msg, fileName, null);
|
}
|
|
/// <summary>
|
/// 记录操作日志
|
/// </summary>
|
/// <param name="log"></param>
|
public static void Trace(TraceLogModel log)
|
{
|
Task.Run(() =>
|
{
|
//WebUtil webUtil = new WebUtil();
|
//var txtParams = new Dictionary<string, object>{
|
// {"messageBody",log.ObjectToJson() },
|
// {"eventKey","duomai.log.log.senduserbehavior" }
|
//};
|
|
//webUtil.DoPostWithJson("http://114.55.4.22:8010/SendMessage/SendEventMessage", txtParams, null);
|
|
MessageModel model = new MessageModel(log.UserId, "duomai.log.log.senduserbehavior", log.ObjectToJson(), MessageTypeEnum.common, "duomai.log.log.senduserbehavior");
|
MQClient.SendMessage(model);
|
});
|
|
DoLog(TRACE_FILE_TARGET, LogLevel.Trace, log.ObjectToJson(), "操作日志", null);
|
}
|
|
/// <summary>
|
/// 记录操作日志
|
/// </summary>
|
/// <param name="app"></param>
|
/// <param name="userId"></param>
|
/// <param name="userName"></param>
|
/// <param name="subUserId"></param>
|
/// <param name="subUserName"></param>
|
/// <param name="module"></param>
|
/// <param name="desc"></param>
|
/// <param name="type"></param>
|
/// <param name="memo"></param>
|
/// <param name="ip"></param>
|
/// <param name="isSuccess"></param>
|
public static void Trace(string app, string userId, string userName, string module, string desc, string type, string memo, string ip, string subUserId = "", string subUserName = "", bool isSuccess = true)
|
{
|
TraceLogModel log = new TraceLogModel
|
{
|
App = app,
|
UserId = userId,
|
UserName = userName,
|
Module = module,
|
Desc = desc,
|
Type = type,
|
Memo = memo,
|
Ip = ip,
|
IsSuccess = isSuccess,
|
SubUserId = subUserId,
|
SubUserName = subUserName,
|
Time = DateTime.Now
|
};
|
Trace(log);
|
}
|
|
///// <summary>
|
///// 记录跟踪信息
|
///// </summary>
|
//public static void Trace(string msg, params object[] args)
|
//{
|
// _logger.Trace(msg, args);
|
//}
|
|
///// <summary>
|
///// 记录跟踪信息
|
///// </summary>
|
//public static void Trace<T>(T value)
|
//{
|
// _logger.Trace(value);
|
//}
|
|
/// <summary>
|
/// 记录跟踪信息
|
/// </summary>
|
public static void Fatal(string msg)
|
{
|
Fatal(msg, FATAL);
|
}
|
|
/// <summary>
|
/// 记录宕机信息
|
/// </summary>
|
public static void Fatal(string msg, string fileName)
|
{
|
DoLog(FATAL_FILE_TARGET, LogLevel.Fatal, msg, fileName, null);
|
}
|
|
///// <summary>
|
///// 记录宕机信息
|
///// </summary>
|
//public static void Fatal<T>(T value)
|
//{
|
// _logger.Fatal(value);
|
//}
|
|
|
/// <summary>
|
/// 执行记录日志
|
/// </summary>
|
/// <param name="targetName">指定模板</param>
|
/// <param name="logLevel">日志级别</param>
|
/// <param name="msg">日志内容</param>
|
/// <param name="fileName">文件名</param>
|
/// <param name="exception">异常信息,可填</param>
|
private static void DoLog(string targetName, LogLevel logLevel, string msg, string fileName, Exception exception)
|
{
|
if (!string.IsNullOrEmpty(targetName))
|
{
|
if (string.IsNullOrEmpty(fileName))
|
{
|
fileName = "${level}";
|
}
|
FileTarget target = LogManager.Configuration.FindTargetByName<FileTarget>(targetName);
|
target.FileName = "${basedir}/logs/${shortdate}-" + fileName + ".log";
|
}
|
|
_logger.Log(logLevel, exception, msg);
|
}
|
}
|
}
|