日志

parent 7a3a52b7
......@@ -115,8 +115,8 @@ public ApiResponse ExtractData([CustomizeValidator(RuleSet = "Template"), FromBo
return new ApiResponse(ResponseType.Fail, "医院无效");
var user = claim.At(request.Token);
extractService.ExtractData(request.ID, user.Mail, hospital);
//BackgroundJob.Enqueue(() => extractService.ExtractData(request.ID, user.Mail, hospital));
//extractService.ExtractData(request.ID, user.Mail, hospital);
BackgroundJob.Enqueue(() => extractService.ExtractData(request.ID, user.Mail, hospital));
return new ApiResponse(ResponseType.OK, "HIS绩效数据提取任务正在执行,稍后我们将以邮件的通知您!");
}
}
......
......@@ -38,6 +38,8 @@ public ActionsFilter(ILoggerFactory factory, IMemoryCache cache, IHostingEnviron
//记录Request请求
var kv = GetRequestContent(request);
_logger.LogInformation($"请求内容 {request.Method}:{JsonHelper.Serialize(kv)}");
LogHelper.Information($"请求地址:{context.HttpContext.Request.Path};请求参数:{JsonHelper.Serialize(kv)}", "请求内容");
//接口禁用
var disable = ((ControllerActionDescriptor)context.ActionDescriptor).MethodInfo.GetCustomAttributes(typeof(DisableAttribute), true);
if (disable.Length > 0)
......@@ -72,6 +74,7 @@ public ActionsFilter(ILoggerFactory factory, IMemoryCache cache, IHostingEnviron
context.Result = new ObjectResult(response);
var jsonData = JsonHelper.Serialize(context.Result);
_logger.LogInformation($"响应结果:{jsonData}");
LogHelper.Information($"请求地址:{context.HttpContext.Request.Path};响应结果:{jsonData}", "响应结果");
}
//记录response结果
else
......@@ -83,6 +86,7 @@ public ActionsFilter(ILoggerFactory factory, IMemoryCache cache, IHostingEnviron
var objectResult = (ObjectResult)executedContext.Result;
var jsonData = JsonHelper.Serialize(objectResult.Value);
_logger.LogInformation($"响应结果:{jsonData}");
LogHelper.Information($"请求地址:{context.HttpContext.Request.Path};响应结果:{jsonData}", "响应结果");
}
}
......
......@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Performance.DtoModels;
using Performance.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -23,18 +24,23 @@ public Task OnExceptionAsync(ExceptionContext context)
if (context.Exception is PerformanceException)
{
_logger.LogWarning($"接口错误警告:{context.Exception.ToString()}");
context.Result = new ObjectResult(new ApiResponse(ResponseType.Fail, context.Exception.Message));
var response = new ApiResponse(ResponseType.Fail, context.Exception.Message);
context.Result = new ObjectResult(response);
LogHelper.Warning(JsonHelper.Serialize(response), "接口错误警告");
}
else if (context.Exception is PerformanceTokenErrorException)
{
_logger.LogWarning($"Token Error:{context.Exception.ToString()}");
context.Result = new ObjectResult(new ApiResponse(ResponseType.TokenError, context.Exception.Message));
var response = new ApiResponse(ResponseType.TokenError, context.Exception.Message);
context.Result = new ObjectResult(response);
LogHelper.Warning(JsonHelper.Serialize(response), "Token Error");
}
else
{
_logger.LogError($"接口异常:{context.Exception.ToString()}");
var response = new ApiResponse(ResponseType.Error, "接口内部异常", context.Exception.Message);
context.Result = new ObjectResult(response);
LogHelper.Error(JsonHelper.Serialize(response), "接口内部异常");
}
return Task.CompletedTask;
}
......
......@@ -47,6 +47,7 @@ public Startup(IConfiguration configuration)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
LogHelper.Initialize(Configuration.GetSection("AppConnection:RedisConnectionString").Value, "MTEzMTAyMzEzNDYzMzY5MzE4NA");
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
#region appsetting注入
......
......@@ -9,7 +9,7 @@
"AppConnection": {
"PerformanceConnectionString": "server=192.168.18.166;database=db_performance;uid=root;pwd=1234qwer;pooling=true;charset=utf8;convert zero datetime=true;port=3306;connection timeout=120;max pool size=512;allow user variables=true;",
"HangfireConnectionString": "server=192.168.18.166;database=db_hangfire;uid=root;pwd=1234qwer;port=3306;allow user variables=true;",
"RedisConnectionString": "116.62.245.55:6379,defaultDatabase=1"
"RedisConnectionString": "116.62.245.55:6379,defaultDatabase=2"
},
"Application": {
//登录过期时间
......
......@@ -8,7 +8,7 @@
"AppConnection": {
"PerformanceConnectionString": "server=116.62.245.55;database=db_performance;uid=suvalue;pwd=suvalue2017;pooling=true;charset=utf8;convert zero datetime=true;port=3306;connection timeout=120;max pool size=512;allow user variables=true;",
"HangfireConnectionString": "server=116.62.245.55;database=db_hangfire;uid=suvalue;pwd=suvalue2017;port=3306;allow user variables=true;",
"redisconnectionstring": "116.62.245.55:6379,defaultdatabase=2"
"RedisConnectionString": "116.62.245.55:6379,defaultdatabase=2"
},
//互亿
"HuyiSmsConfig": {
......
using CSRedis;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
public static class LogHelper
{
private static AsyncLocal<string> _asyncLocal;
private static BlockingCollection<Log> _queue;
private static object _lockObject;
private static string _secretKey;
private static IHttpContextAccessor _contextAccessor;
public static void Initialize(string redisConnectionString, string secretKey)
{
_secretKey = secretKey;
var client = new CSRedisClient(redisConnectionString);
_queue = new BlockingCollection<Log>();
_asyncLocal = new AsyncLocal<string>();
_lockObject = new object();
_contextAccessor = new HttpContextAccessor();
Task.Factory.StartNew(() =>
{
while (!_queue.IsCompleted)
{
var log = _queue.Take();
client.LPush("log.queue", log);
}
});
}
public static void Trace(string message, params string[] tag)
{
WriteLog(message, tag, LogLevel.Trace);
}
public static void Debug(string message, params string[] tag)
{
WriteLog(message, tag, LogLevel.Debug);
}
public static void Information(string message, params string[] tag)
{
WriteLog(message, tag, LogLevel.Information);
}
public static void Warning(string message, params string[] tag)
{
WriteLog(message, tag, LogLevel.Warning);
}
public static void Error(string message, params string[] tag)
{
WriteLog(message, tag, LogLevel.Error);
}
public static void Fatal(string message, params string[] tag)
{
WriteLog(message, tag, LogLevel.Fatal);
}
private static void WriteLog(string message, string[] tag, LogLevel logLevel)
{
try
{
if (_contextAccessor.HttpContext == null)
{
if (string.IsNullOrEmpty(_asyncLocal.Value))
lock (_lockObject)
Guid.NewGuid().ToString("N");
}
else
{
_asyncLocal.Value = _contextAccessor.HttpContext.TraceIdentifier;
}
Log log = new Log
{
Id = SnowflakeId.Default().NextId(),
Level = logLevel,
LogTime = DateTime.Now,
Message = message,
Stack = GetStackInfo(),
TraceId = _asyncLocal.Value,
Tag = tag.ToList(),
SecretKey = _secretKey
};
_queue.Add(log);
}
catch { }
}
private static List<string> GetStackInfo()
{
StackTrace trace = new StackTrace(true);
List<string> result = new List<string>();
for (int i = 0; i < trace.FrameCount; i++)
{
StackFrame frame = trace.GetFrame(i);
MethodBase method = frame.GetMethod();
if (method.DeclaringType == null
|| method.DeclaringType.FullName.StartsWith("System")
|| method.DeclaringType.FullName.StartsWith("Microsoft")
|| method.DeclaringType.FullName.StartsWith("Online.Log"))
continue;
var paras = method.GetParameters().Select(t => $"{t.ParameterType.Name} {t.Name}");
result.Add($"At {method.DeclaringType.FullName}.{method.Name}({string.Join(",", paras)}) Number({frame.GetFileLineNumber()})");
}
return result;
}
}
internal class Log
{
public long Id { get; set; }
public DateTime LogTime { get; set; }
public LogLevel Level { get; set; }
public string SecretKey { get; set; }
public string TraceId { get; set; }
public string Message { get; set; }
public List<string> Stack { get; set; }
public List<string> Tag { get; set; }
}
internal enum LogLevel
{
All = 0,
Trace = 1,
Debug = 2,
Information = 3,
Warning = 4,
Error = 5,
Fatal = 6
}
internal class SnowflakeId
{
public const long Twepoch = 1288834974657L;
private const int WorkerIdBits = 5;
private const int DatacenterIdBits = 5;
private const int SequenceBits = 12;
private const long MaxWorkerId = -1L ^ (-1L << WorkerIdBits);
private const long MaxDatacenterId = -1L ^ (-1L << DatacenterIdBits);
private const int WorkerIdShift = SequenceBits;
private const int DatacenterIdShift = SequenceBits + WorkerIdBits;
public const int TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits;
private const long SequenceMask = -1L ^ (-1L << SequenceBits);
private static SnowflakeId _snowflakeId;
private readonly object _lock = new object();
private static readonly object SLock = new object();
private long _lastTimestamp = -1L;
public SnowflakeId(long workerId, long datacenterId, long sequence = 0L)
{
WorkerId = workerId;
DatacenterId = datacenterId;
Sequence = sequence;
// sanity check for workerId
if (workerId > MaxWorkerId || workerId < 0)
throw new ArgumentException($"worker Id can't be greater than {MaxWorkerId} or less than 0");
if (datacenterId > MaxDatacenterId || datacenterId < 0)
throw new ArgumentException($"datacenter Id can't be greater than {MaxDatacenterId} or less than 0");
}
public long WorkerId { get; protected set; }
public long DatacenterId { get; protected set; }
public long Sequence { get; internal set; }
public static SnowflakeId Default()
{
lock (SLock)
{
if (_snowflakeId != null)
{
return _snowflakeId;
}
var random = new Random();
if (!int.TryParse(Environment.GetEnvironmentVariable("CAP_WORKERID", EnvironmentVariableTarget.Machine), out var workerId))
{
workerId = random.Next((int)MaxWorkerId);
}
if (!int.TryParse(Environment.GetEnvironmentVariable("CAP_DATACENTERID", EnvironmentVariableTarget.Machine), out var datacenterId))
{
datacenterId = random.Next((int)MaxDatacenterId);
}
return _snowflakeId = new SnowflakeId(workerId, datacenterId);
}
}
public virtual long NextId()
{
lock (_lock)
{
var timestamp = TimeGen();
if (timestamp < _lastTimestamp)
throw new Exception(
$"InvalidSystemClock: Clock moved backwards, Refusing to generate id for {_lastTimestamp - timestamp} milliseconds");
if (_lastTimestamp == timestamp)
{
Sequence = (Sequence + 1) & SequenceMask;
if (Sequence == 0) timestamp = TilNextMillis(_lastTimestamp);
}
else
{
Sequence = 0;
}
_lastTimestamp = timestamp;
var id = ((timestamp - Twepoch) << TimestampLeftShift) |
(DatacenterId << DatacenterIdShift) |
(WorkerId << WorkerIdShift) | Sequence;
return id;
}
}
protected virtual long TilNextMillis(long lastTimestamp)
{
var timestamp = TimeGen();
while (timestamp <= lastTimestamp) timestamp = TimeGen();
return timestamp;
}
protected virtual long TimeGen()
{
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
}
}
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="CSRedisCore" Version="3.0.45" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Http.Abstractions">
<HintPath>C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.http.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNetCore.Http.Features">
<HintPath>C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.http.features\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll</HintPath>
</Reference>
......
......@@ -76,10 +76,16 @@ public void ExtractData(int allotId, string mail, sys_hospital hospital)
var scriptList = perforExtractRepository.GetEntities(t => t.HospitalId == hospital.ID);
if (configList == null || !configList.Any())
{
LogHelper.Error("暂不支持自动提取绩效数据", "提取绩效数据");
throw new PerformanceException($"暂不支持自动提取绩效数据");
}
if (scriptList == null || !scriptList.Any())
{
LogHelper.Error($"暂无该医院的配置信息和执行sql,无法进行数据提取", "提取绩效数据");
throw new PerformanceException($"暂无该医院的配置信息和执行sql,无法进行数据提取");
}
var hospitalConfig = configList.First();
string originalPath = "";
......@@ -102,7 +108,10 @@ public void ExtractData(int allotId, string mail, sys_hospital hospital)
originalPath = allot.Path;
}
else
{
LogHelper.Error($"历史绩效未上传文件", "提取绩效数据");
throw new PerformanceException($"历史绩效未上传文件");
}
}
var dpath = Path.Combine(environment.ContentRootPath, "Files", $"{hospital.ID}", "autoextract");
FileHelper.CreateDirectory(dpath);
......@@ -121,11 +130,13 @@ public void ExtractData(int allotId, string mail, sys_hospital hospital)
catch (PerformanceException ex)
{
logger.LogError(ex.ToString());
LogHelper.Error(ex.ToString(), "提取绩效数据", "异常");
SendEmail(mail, "", $"{hospital.HosName}HIS数据提取失败", $"{hospital.HosName}提取数据失败,{ex.Message}!");
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
LogHelper.Error(ex.ToString(), "提取绩效数据", "异常");
SendEmail(mail, "", $"{hospital.HosName}HIS数据提取失败", $"{hospital.HosName}提取数据过程中出现异常情况,我们将尽快解决问题。给您带来的不便我们深感歉意!");
}
}
......@@ -138,16 +149,16 @@ public void ExtractData(int allotId, string mail, sys_hospital hospital)
/// <param name="body"></param>
private void SendEmail(string mail, string path, string subject, string body)
{
//var message = new EmailMessage
//{
// To = new List<string> { mail },
// DisplayName = "溯直健康",
// Subject = subject,
// Body = body
//};
//if (!string.IsNullOrEmpty(path))
// message.Attachments = new List<string> { path };
//emailService.Send(message);
var message = new EmailMessage
{
To = new List<string> { mail },
DisplayName = "溯直健康",
Subject = subject,
Body = body
};
if (!string.IsNullOrEmpty(path))
message.Attachments = new List<string> { path };
emailService.Send(message);
}
/// <summary>
......@@ -164,7 +175,10 @@ private void SendEmail(string mail, string path, string subject, string body)
private bool WriteExcel(string newpath, string originalPath, List<PerSheet> sheetList, sys_hospitalconfig hospitalConfig, int hospitalId, out string filepath)
{
if (string.IsNullOrEmpty(originalPath))
{
LogHelper.Error($"{originalPath}文件路径无效", "提取绩效数据");
throw new PerformanceException($"{originalPath}文件路径无效");
}
var scriptList = perforExtractRepository.GetEntities(t => t.HospitalId == hospitalId);
......@@ -342,7 +356,7 @@ private List<PerSheet> GetFileData(string path)
IWorkbook workbook = null;
try
{
fs = new FileStream(path, FileMode.Open);
fs = new FileStream(path, FileMode.Open, FileAccess.Read);
var version = FileHelper.GetExtension(path) == ".xlsx" ? ExcelVersion.xlsx : ExcelVersion.xls;
workbook = (version == ExcelVersion.xlsx) ? (IWorkbook)(new XSSFWorkbook(fs)) : (IWorkbook)(new HSSFWorkbook(fs));
for (int i = 0; i < workbook.NumberOfSheets; i++)
......@@ -373,7 +387,6 @@ private List<PerSheet> GetFileData(string path)
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
throw ex;
}
finally
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment