¶Ô±ÈÐÂÎļþ |
| | |
| | | using Castle.DynamicProxy; |
| | | using Microsoft.AspNetCore.Http; |
| | | using Microsoft.AspNetCore.SignalR; |
| | | using Newtonsoft.Json; |
| | | using StackExchange.Profiling; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | | using System.Linq; |
| | | using System.Reflection; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core.Helper; |
| | | using WIDESEA_Core.LogHelper; |
| | | |
| | | namespace WIDESEA_Core.AOP |
| | | { |
| | | /// <summary> |
| | | /// æ¦æªå¨BlogLogAOP ç»§æ¿IInterceptoræ¥å£ |
| | | /// </summary> |
| | | public class LogAOP : IInterceptor |
| | | { |
| | | private readonly IHttpContextAccessor _accessor; |
| | | |
| | | public LogAOP(IHttpContextAccessor accessor) |
| | | { |
| | | _accessor = accessor; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å®ä¾åIInterceptorå¯ä¸æ¹æ³ |
| | | /// </summary> |
| | | /// <param name="invocation">å
å«è¢«æ¦æªæ¹æ³çä¿¡æ¯</param> |
| | | public void Intercept(IInvocation invocation) |
| | | { |
| | | string UserName = _accessor.HttpContext?.User?.Identity?.Name; |
| | | string json; |
| | | try |
| | | { |
| | | if (invocation.Arguments.Any()) |
| | | { |
| | | json = JsonConvert.SerializeObject(invocation.Arguments); |
| | | } |
| | | else |
| | | { |
| | | json = "æ åæ°"; |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | json = "æ æ³åºååï¼å¯è½æ¯å
°å§è¾¾è¡¨è¾¾å¼çåå é æï¼æç
§æ¡æ¶ä¼å代ç " + ex.ToString(); |
| | | } |
| | | |
| | | DateTime startTime = DateTime.Now; |
| | | AOPLogInfo apiLogAopInfo = new AOPLogInfo |
| | | { |
| | | RequestTime = startTime.ToString("yyyy-MM-dd hh:mm:ss fff"), |
| | | OpUserName = "ãå½åæä½ç¨æ·ãï¼" + UserName, |
| | | RequestMethodName = "ãå½åæ§è¡æ¹æ³ãï¼" + invocation.Method.Name, |
| | | RequestParamsName = "ãæºå¸¦çåæ°æãï¼" + string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()), |
| | | RequestParamsData = json |
| | | }; |
| | | |
| | | var dataIntercept = $""; |
| | | |
| | | try |
| | | { |
| | | MiniProfiler.Current.Step($"æ§è¡{invocation.InvocationTarget}.{invocation.Method.Name}()æ¹æ³ -> "); |
| | | //å¨è¢«æ¦æªçæ¹æ³æ§è¡å®æ¯å ç»§ç»æ§è¡å½åæ¹æ³ï¼æ³¨ææ¯è¢«æ¦æªçæ¯å¼æ¥ç |
| | | invocation.Proceed(); |
| | | |
| | | // 弿¥è·åå¼å¸¸ï¼å
æ§è¡ |
| | | if (IsAsyncMethod(invocation.Method)) |
| | | { |
| | | #region æ¹æ¡ä¸ |
| | | |
| | | //Wait task execution and modify return value |
| | | if (invocation.Method.ReturnType == typeof(Task)) |
| | | { |
| | | invocation.ReturnValue = InternalAsyncHelper.AwaitTaskWithPostActionAndFinally( |
| | | (Task)invocation.ReturnValue, |
| | | async () => await SuccessAction(invocation, apiLogAopInfo, startTime), /*æåæ¶æ§è¡*/ |
| | | ex => |
| | | { |
| | | LogEx(ex, apiLogAopInfo); |
| | | }); |
| | | } |
| | | //Task<TResult> |
| | | else |
| | | { |
| | | invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithPostActionAndFinallyAndGetResult( |
| | | invocation.Method.ReturnType.GenericTypeArguments[0], |
| | | invocation.ReturnValue, |
| | | //async () => await SuccessAction(invocation, dataIntercept),/*æåæ¶æ§è¡*/ |
| | | async (o) => await SuccessAction(invocation, apiLogAopInfo, startTime, o), /*æåæ¶æ§è¡*/ |
| | | ex => |
| | | { |
| | | LogEx(ex, apiLogAopInfo); |
| | | }); |
| | | } |
| | | |
| | | #endregion æ¹æ¡ä¸ |
| | | |
| | | // å¦ææ¹æ¡ä¸ä¸è¡ï¼è¯è¯è¿ä¸ªæ¹æ¡ |
| | | //#region æ¹æ¡äº |
| | | |
| | | //var type = invocation.Method.ReturnType; |
| | | //var resultProperty = type.GetProperty("Result"); |
| | | //DateTime endTime = DateTime.Now; |
| | | //string ResponseTime = (endTime - startTime).Milliseconds.ToString(); |
| | | //apiLogAopInfo.ResponseTime = endTime.ToString("yyyy-MM-dd hh:mm:ss fff"); |
| | | //apiLogAopInfo.ResponseIntervalTime = ResponseTime + "ms"; |
| | | //apiLogAopInfo.ResponseJsonData = JsonConvert.SerializeObject(resultProperty.GetValue(invocation.ReturnValue)); |
| | | |
| | | ////dataIntercept += ($"ãååºæ¶é´ãï¼{ResponseTime}ms\r\n"); |
| | | ////dataIntercept += ($"ãæ§è¡å®ææ¶é´ãï¼{endTime.ToString("yyyy-MM-dd hh:mm:ss fff")}\r\n"); |
| | | ////dataIntercept += ($"ãæ§è¡å®æç»æãï¼{JsonConvert.SerializeObject(resultProperty.GetValue(invocation.ReturnValue))}\r\n"); |
| | | |
| | | //Parallel.For(0, 1, e => |
| | | //{ |
| | | // //LogLock.OutLogAOP("AOPLog", new string[] { dataIntercept }); |
| | | // LogLock.OutLogAOP("AOPLog", new string[] { apiLogAopInfo.GetType().ToString() + " - ResponseJsonDataType:" + type, JsonConvert.SerializeObject(apiLogAopInfo) }); |
| | | //}); |
| | | |
| | | //#endregion |
| | | } |
| | | else |
| | | { |
| | | // 忥1 |
| | | string jsonResult; |
| | | try |
| | | { |
| | | jsonResult = JsonConvert.SerializeObject(invocation.ReturnValue); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | jsonResult = "æ æ³åºååï¼å¯è½æ¯å
°å§è¾¾è¡¨è¾¾å¼çåå é æï¼æç
§æ¡æ¶ä¼å代ç " + ex.ToString(); |
| | | } |
| | | |
| | | var type = invocation.Method.ReturnType; |
| | | var resultProperty = type.GetProperty("Result"); |
| | | DateTime endTime = DateTime.Now; |
| | | string ResponseTime = (endTime - startTime).Milliseconds.ToString(); |
| | | apiLogAopInfo.ResponseTime = endTime.ToString("yyyy-MM-dd hh:mm:ss fff"); |
| | | apiLogAopInfo.ResponseIntervalTime = ResponseTime + "ms"; |
| | | apiLogAopInfo.ResponseJsonData = jsonResult; |
| | | Parallel.For(0, 1, e => |
| | | { |
| | | LogLock.OutLogAOP("AOPLog", new string[] { apiLogAopInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopInfo) }); |
| | | }); |
| | | } |
| | | } |
| | | catch (Exception ex) // 忥2 |
| | | { |
| | | LogEx(ex, apiLogAopInfo); |
| | | throw; |
| | | } |
| | | } |
| | | |
| | | private async Task SuccessAction(IInvocation invocation, AOPLogInfo apiLogAopInfo, DateTime startTime, object o = null) |
| | | { |
| | | DateTime endTime = DateTime.Now; |
| | | string ResponseTime = (endTime - startTime).Milliseconds.ToString(); |
| | | apiLogAopInfo.ResponseTime = endTime.ToString("yyyy-MM-dd hh:mm:ss fff"); |
| | | apiLogAopInfo.ResponseIntervalTime = ResponseTime + "ms"; |
| | | apiLogAopInfo.ResponseJsonData = JsonConvert.SerializeObject(o); |
| | | |
| | | await Task.Run(() => |
| | | { |
| | | Parallel.For(0, 1, e => |
| | | { |
| | | //LogLock.OutSql2Log("AOPLog", new string[] { JsonConvert.SerializeObject(apiLogAopInfo) }); |
| | | LogLock.OutLogAOP("AOPLog", new string[] { apiLogAopInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopInfo) }); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | private void LogEx(Exception ex, AOPLogInfo dataIntercept) |
| | | { |
| | | if (ex != null) |
| | | { |
| | | //æ§è¡ç service ä¸ï¼æ¶å½å¼å¸¸ |
| | | MiniProfiler.Current.CustomTiming("Errorsï¼", ex.Message); |
| | | //æ§è¡ç service ä¸ï¼æè·å¼å¸¸ |
| | | AOPLogExInfo apiLogAopExInfo = new AOPLogExInfo |
| | | { |
| | | ExMessage = ex.Message, |
| | | InnerException = "InnerException-å
é¨å¼å¸¸:\r\n" + (ex.InnerException == null ? "" : ex.InnerException.InnerException.ToString()) + |
| | | "\r\nStackTrace-å æ è·è¸ª:\r\n" + (ex.StackTrace == null ? "" : ex.StackTrace.ToString()), |
| | | ApiLogAopInfo = dataIntercept |
| | | }; |
| | | // å¼å¸¸æ¥å¿éæè¯¦ç»çå æ ä¿¡æ¯ |
| | | Parallel.For(0, 1, e => |
| | | { |
| | | LogLock.OutLogAOP("AOPLogEx", new string[] { apiLogAopExInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopExInfo) }); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | public static bool IsAsyncMethod(MethodInfo method) |
| | | { |
| | | return |
| | | method.ReturnType == typeof(Task) || |
| | | method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>) |
| | | ; |
| | | } |
| | | } |
| | | |
| | | internal static class InternalAsyncHelper |
| | | { |
| | | public static async Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue, Func<Task> postAction, Action<Exception> finalAction) |
| | | { |
| | | Exception exception = null; |
| | | |
| | | try |
| | | { |
| | | await actualReturnValue; |
| | | await postAction(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | exception = ex; |
| | | } |
| | | finally |
| | | { |
| | | finalAction(exception); |
| | | } |
| | | } |
| | | |
| | | public static async Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue, Func<object, Task> postAction, |
| | | Action<Exception> finalAction) |
| | | { |
| | | Exception exception = null; |
| | | try |
| | | { |
| | | var result = await actualReturnValue; |
| | | await postAction(result); |
| | | return result; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | exception = ex; |
| | | throw; |
| | | } |
| | | finally |
| | | { |
| | | finalAction(exception); |
| | | } |
| | | } |
| | | |
| | | public static object CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType, object actualReturnValue, |
| | | Func<object, Task> action, Action<Exception> finalAction) |
| | | { |
| | | return typeof(InternalAsyncHelper) |
| | | .GetMethod("AwaitTaskWithPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static) |
| | | .MakeGenericMethod(taskReturnType) |
| | | .Invoke(null, new object[] { actualReturnValue, action, finalAction }); |
| | | } |
| | | } |
| | | |
| | | public class AOPLogInfo |
| | | { |
| | | /// <summary> |
| | | /// è¯·æ±æ¶é´ |
| | | /// </summary> |
| | | [Description("è¯·æ±æ¶é´")] |
| | | public string RequestTime { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// æä½äººå |
| | | /// </summary> |
| | | [Description("æä½äººå")] |
| | | public string OpUserName { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// è¯·æ±æ¹æ³å |
| | | /// </summary> |
| | | [Description("è¯·æ±æ¹æ³å")] |
| | | public string RequestMethodName { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// 请æ±åæ°å |
| | | /// </summary> |
| | | [Description("请æ±åæ°å")] |
| | | public string RequestParamsName { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// 请æ±åæ°æ°æ®JSON |
| | | /// </summary> |
| | | [Description("请æ±åæ°æ°æ®JSON")] |
| | | public string RequestParamsData { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// 请æ±ååºé´éæ¶é´ |
| | | /// </summary> |
| | | [Description("请æ±ååºé´éæ¶é´")] |
| | | public string ResponseIntervalTime { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// ååºæ¶é´ |
| | | /// </summary> |
| | | [Description("ååºæ¶é´")] |
| | | public string ResponseTime { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// ååºç»æ |
| | | /// </summary> |
| | | [Description("ååºç»æ")] |
| | | public string ResponseJsonData { get; set; } = string.Empty; |
| | | } |
| | | |
| | | public class AOPLogExInfo |
| | | { |
| | | public AOPLogInfo ApiLogAopInfo { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å¼å¸¸ |
| | | /// </summary> |
| | | [Description("å¼å¸¸")] |
| | | public string InnerException { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// å¼å¸¸ä¿¡æ¯ |
| | | /// </summary> |
| | | [Description("å¼å¸¸ä¿¡æ¯")] |
| | | public string ExMessage { get; set; } = string.Empty; |
| | | } |
| | | } |