You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

494 lines
18 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using NLog;
using NLog.Config;
using NLog.Targets;
using NLog.Targets.Wrappers;
using System;
using System.IO;
using Common.Logging;
using System.Net;
using System.Threading.Tasks;
using System.Text;
using System.Linq;
using NLog.Layouts;
using System.Collections.Generic;
using Newtonsoft.Json;
using NLog.RestTarget;
using NLog.Common;
using System.Diagnostics;
using POSV.Utils;
using System.Security.Cryptography;
using POSV;
using System.Windows.Forms;
using POSV.Common.Util;
namespace POSV.Utils
{
public static class NLogUtils
{
private static object locker = new object();
static NLogUtils()
{
string dataDirFullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory , @"data/backup/");
if (!Directory.Exists(dataDirFullPath))
{
lock (locker)
{
if (!Directory.Exists(dataDirFullPath))
{
Directory.CreateDirectory(dataDirFullPath);
}
}
}
string logDirFullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory , @"logs/");
if (!Directory.Exists(logDirFullPath))
{
lock (locker)
{
if (!Directory.Exists(logDirFullPath))
{
Directory.CreateDirectory(logDirFullPath);
}
}
}
}
//zhangy 2020-02-19 Edit 修改日志文件输出格式添加按日归档、保留7日模式
static void nlog_to_file_and_archive(LoggingConfiguration config)
{
var fileTarget = new FileTarget
{
MaxArchiveFiles = 7,
FileName = "${basedir}/logs/log.txt" ,
Layout = Layout.FromString("${longdate} | [${uppercase:${level}}] | ${logger} | ${message} | ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}") ,
ArchiveFileName = "${basedir}/logs/archives/log${shortdate}.{#####}.txt",
ArchiveEvery = FileArchivePeriod.Day,
ArchiveNumbering = ArchiveNumberingMode.Rolling,
EnableArchiveFileCompression = true,
ConcurrentWrites = true,
KeepFileOpen = false,
AutoFlush = true,
DeleteOldFileOnStartup = false,
CreateDirs = true,
};
AsyncTargetWrapper wrapper = new AsyncTargetWrapper();
wrapper.WrappedTarget = fileTarget;
wrapper.QueueLimit = 5000;
wrapper.OverflowAction = AsyncTargetWrapperOverflowAction.Discard;
// Adding "File" as one of the log targets
config.AddTarget("file" , wrapper);
config.LoggingRules.Add(new NLog.Config.LoggingRule("*" , NLog.LogLevel.Info , wrapper));
}
static void nlog_to_console(LoggingConfiguration config)
{
var consoleTarget = new ColoredConsoleTarget
{
Layout = Layout.FromString("${longdate} | [${uppercase:${level}}] | ${logger} | ${message} | ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}")
};
AsyncTargetWrapper wrapper = new AsyncTargetWrapper();
wrapper.WrappedTarget = consoleTarget;
wrapper.QueueLimit = 5000;
wrapper.OverflowAction = AsyncTargetWrapperOverflowAction.Discard;
config.AddTarget("console" , wrapper);
config.LoggingRules.Add(new LoggingRule("*" , NLog.LogLevel.Info , wrapper));
}
public static void InitLogger()
{
try
{
NLog.LogManager.ThrowExceptions = true;
var config = new LoggingConfiguration();
nlog_to_console(config);
nlog_to_file_and_archive(config);
NLog.LogManager.Configuration = config;
CommonLoggingAdapter.AdapterLogger();
}
catch (Exception ex)
{
ExceptionUtils.Current.Handle(ex);
}
}
}
}
namespace NLog.RestTarget
{
[Target("QiNiuLogService")]
public sealed class QiNiuLogTarget : TargetWithLayout
{
public QiNiuLogTarget()
{
RepoName = string.Empty;
Authorization = string.Empty;
ServerAddress = string.Empty;
Parameters = new List<LogParameterInfo>();
}
/// <summary>
/// 队列名称
/// </summary>
[RequiredParameter]
public string RepoName { get; set; }
/// <summary>
/// 授权信息
/// </summary>
[RequiredParameter]
public string Authorization { get; set; }
/// <summary>
/// 请求地址
/// </summary>
[RequiredParameter]
public string ServerAddress { get; set; }
/// <summary>
/// 参数
/// </summary>
[ArrayParameter(typeof(LogParameterInfo), "parameter")]
public IList<LogParameterInfo> Parameters { get; private set; }
private LayoutWithHeaderAndFooter LHF
{
get => (LayoutWithHeaderAndFooter)base.Layout;
set => base.Layout = value;
}
public override Layout Layout
{
get => LHF.Layout;
set
{
if (value is LayoutWithHeaderAndFooter)
{
base.Layout = value;
}
else if (LHF == null)
{
LHF = new LayoutWithHeaderAndFooter()
{
Layout = value
};
}
else
{
LHF.Layout = value;
}
}
}
protected override void Write(AsyncLogEventInfo[] logEvents)
{
bool isUploadToQiniu = Global.Instance.GlobalConfigBoolValue(ConfigConstant.LOG_UPLOAD_TO_QINIU, false);
Console.WriteLine(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + isUploadToQiniu);
if (isUploadToQiniu)
{
SendTheMessageToRemoteHost(logEvents);
}
}
private void SendTheMessageToRemoteHost(AsyncLogEventInfo[] logEvents)
{
try
{
foreach (var logEvent in logEvents)
{
var uri = new Uri(this.ServerAddress);
var eventInfo = logEvent.LogEvent;
//WiFi网络仅仅上传Error级别的消息
if (Global.Instance.IsWiFi)
{
if (eventInfo.Level != LogLevel.Error || eventInfo.Level != LogLevel.Fatal)
{
continue;
}
}
var tenantNo = Global.Instance.Authc != null ? Global.Instance.Authc.TenantId : "000000";
var storeId = Global.Instance.Authc != null ? Global.Instance.Authc.StoreId : "000000000000000000";
var storeNo = Global.Instance.Authc != null ? Global.Instance.Authc.StoreNo : "000000";
var storeName = Global.Instance.Authc != null ? Global.Instance.Authc.StoreName : "";
var posId = Global.Instance.Authc != null ? Global.Instance.Authc.PosId : "000000000000000000";
var posNo = Global.Instance.Authc != null ? Global.Instance.Authc.PosNo : "000000";
Parameters.Clear();
Parameters.Add(new LogParameterInfo() { Name = "appsign", Layout = Constant.APP_SIGN });
Parameters.Add(new LogParameterInfo() { Name = "version", Layout = Application.ProductVersion });
var theme = Global.Instance.GlobalConfigStringValue(ConfigConstant.LAYOUT_THEME, ThemeEnum..ToString());
Parameters.Add(new LogParameterInfo() { Name = "layout", Layout = theme });
Parameters.Add(new LogParameterInfo() { Name = "tenantNo", Layout = tenantNo });
Parameters.Add(new LogParameterInfo() { Name = "storeId", Layout = storeId });
Parameters.Add(new LogParameterInfo() { Name = "storeNo", Layout = storeNo });
Parameters.Add(new LogParameterInfo() { Name = "storeName", Layout = storeName });
Parameters.Add(new LogParameterInfo() { Name = "posId", Layout = posId });
Parameters.Add(new LogParameterInfo() { Name = "posNo", Layout = posNo });
Parameters.Add(new LogParameterInfo() { Name = "sequenceId", Layout = eventInfo.SequenceID });
Parameters.Add(new LogParameterInfo() { Name = "message", Layout = eventInfo.FormattedMessage });
Parameters.Add(new LogParameterInfo() { Name = "level", Layout = eventInfo.Level.Name });
Parameters.Add(new LogParameterInfo() { Name = "loggerName", Layout = eventInfo.LoggerName });
Parameters.Add(new LogParameterInfo() { Name = "loggerDate", Layout = eventInfo.TimeStamp.ToString("yyyy-MM-dd HH:mm:ss") });
string errorMessage = string.Empty;
var exception = eventInfo.Exception;
if (exception != null)
{
errorMessage = GetExceptionInfo(exception);
}
Parameters.Add(new LogParameterInfo() { Name = "exception", Layout = errorMessage });
StringBuilder stringBuilder = new StringBuilder();
foreach (var item in Parameters)
{
stringBuilder.Append($"{item.Name}={item.Layout}\t");
}
string message = stringBuilder.ToString().Replace("\r", "\\r").Replace("\n", "\\n");
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
using (var client = new ExpectContinueAware())
{
Console.WriteLine(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+Encoding.UTF8.GetByteCount(string.Concat(message, "\n")));
client.Headers.Add("Content-Type", "text/plain");
client.Headers.Add("Authorization", this.Authorization);
client.Encoding = Encoding.UTF8;
client.UploadStringCompleted += (sender, e) => { };
client.UploadStringAsync(uri, "POST", string.Concat(message,"\n"));
}
}
}
catch (Exception ex)
{
ExceptionUtils.Current.Handle(ex);
}
}
private string GetExceptionInfo(Exception e)
{
string errorMessage = e.Message + " " + e.StackTrace;
if (e.InnerException != null)
{
errorMessage += e.InnerException.Message + " " + e.InnerException.StackTrace;
if (e.InnerException.InnerException != null)
{
errorMessage += e.InnerException.InnerException.Message + " " + e.InnerException.InnerException.StackTrace;
}
}
return errorMessage;
}
}
public class ExpectContinueAware : System.Net.WebClient
{
protected override System.Net.WebRequest GetWebRequest(Uri address)
{
System.Net.WebRequest request = base.GetWebRequest(address);
if (request is System.Net.HttpWebRequest)
{
var hwr = request as System.Net.HttpWebRequest;
hwr.ServicePoint.Expect100Continue = false;
}
return request;
}
}
public class Auth
{
public const string ContentType = "Content-Type";
public const string ContentMD5 = "Content-MD5";
public const string Date = "Date";
public const string Authorization = "Authorization";
private string accessKey;
private string secretKey;
public Auth(string accessKey, string secretKey)
{
this.accessKey = accessKey;
this.secretKey = secretKey;
}
/// <summary>
/// SignRequest signs the request in the algorithm of Pandora
/// see doc here at
/// </summary>
/// <param name="url"></param>
/// <param name="method"></param>
/// <param name="headers">
/// method - request method
/// resource - request path
/// expires - deadline in unix timestamp in seconds
/// contentType - content type
/// contentMD5 - content md5, optional
/// headers - sorted headers whose keys start with X-Qiniu-
/// </param>
/// <param name="qiniuSubResource"></param>
/// <returns></returns>
public string SignRequest(string url, string method, Dictionary<string, string> headers)
{
Dictionary<string, object> tokenDesc = new Dictionary<string, object>();
//filter the qiniu heades
List<string> qiniuHeaderKeys = new List<string>();
foreach (string key in headers.Keys)
{
if (key.StartsWith("X-Qiniu-"))
{
qiniuHeaderKeys.Add(key);
}
}
qiniuHeaderKeys.Sort();
string canHeadersStr = null;
if (qiniuHeaderKeys.Count > 0)
{
List<string> canHeaders = new List<string>();
foreach (string key in qiniuHeaderKeys)
{
canHeaders.Add(String.Format("{0}:{1}", key.ToLower(), headers[key]));
}
canHeadersStr = String.Join("\n", canHeaders);
}
if (!String.IsNullOrEmpty(canHeadersStr))
{
tokenDesc["headers"] = canHeadersStr;
}
//check other headers
if (headers.ContainsKey(ContentType))
{
tokenDesc["contentType"] = headers[ContentType];
}
if (headers.ContainsKey(ContentMD5))
{
tokenDesc["contentMD5"] = headers[ContentMD5];
}
Uri reqURI = new Uri(url);
tokenDesc["resource"] = reqURI.AbsolutePath;
tokenDesc["method"] = method;
tokenDesc["expires"] = GetUnixTimestampInSeconds() + 24 * 60 * 60 * 7;
string tokenDescData = JsonConvert.SerializeObject(tokenDesc);
return String.Format("Pandora {0}", this.SignWithData(tokenDescData));
}
private string encodedSign(byte[] data)
{
HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(this.secretKey));
byte[] digest = hmac.ComputeHash(data);
return UrlSafeBase64Encode(digest);
}
private string encodedSign(string str)
{
byte[] data = Encoding.UTF8.GetBytes(str);
return encodedSign(data);
}
public string Sign(byte[] data)
{
return string.Format("{0}:{1}", this.accessKey, encodedSign(data));
}
public string Sign(string str)
{
byte[] data = Encoding.UTF8.GetBytes(str);
return Sign(data);
}
public string SignWithData(byte[] data)
{
string encodedData = UrlSafeBase64Encode(data);
return string.Format("{0}:{1}:{2}", this.accessKey, encodedSign(encodedData), encodedData);
}
public string SignWithData(string str)
{
byte[] data = Encoding.UTF8.GetBytes(str);
return SignWithData(data);
}
public static long GetUnixTimestampInSeconds()
{
System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // current zone
long timeStamp = (long)(DateTime.Now - startTime).TotalMilliseconds / 1000; // timestamp in seconds
return timeStamp;
}
public static string CreateHttpDateTime(DateTime dateTime)
{
return dateTime.ToUniversalTime().ToString("r");
}
public static string CreateRFC3339DateTime(DateTime dateTime)
{
return dateTime.ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz");
}
public static DateTime FromRFC3339DateTime(string dateTimeStr)
{
return DateTime.Parse(dateTimeStr);
}
public static string UrlSafeBase64Encode(string text)
{
return UrlSafeBase64Encode(Encoding.UTF8.GetBytes(text));
}
public static string UrlSafeBase64Encode(byte[] data)
{
return Convert.ToBase64String(data).Replace('+', '-').Replace('/', '_');
}
public static string UrlSafeBase64Encode(string bucket, string key)
{
return UrlSafeBase64Encode(bucket + ":" + key);
}
public static byte[] UrlsafeBase64Decode(string text)
{
return Convert.FromBase64String(text.Replace('-', '+').Replace('_', '/'));
}
}
public class LogParameterInfo
{
public string Name { get; set; }
public object Layout { get; set; }
public override bool Equals(object obj)
{
var o = obj as LogParameterInfo;
return o != null && Name == o.Name;
}
public override int GetHashCode()
{
return 31 * 17 + ((this == null) ? -1 : base.GetHashCode());
}
}
}