/// <summary> /// 记录内部异常记录 /// </summary> /// <param name="e">异常信息</param> /// <param name="remark">备注信息</param> /// <param name="logSpan">日志段</param> internal static void InnerException(Exception e, string remark, LogSpan logSpan) { Task.Run(() => { try { ExceptionLog log = new ExceptionLog { CustomerInfo = new Dictionary <string, object>(), LogSpan = logSpan, ExceptionInfo = e.ToString(), LogLevel = LogLevel.Error, }; log.CustomerInfo.Add("Remark", string.IsNullOrWhiteSpace(remark) ? string.Empty : remark); if (!LogFilter(log.LogLevel)) { _logger.WriteException(log); } } catch (Exception ex) { InnerTxtLog.WriteException(ex, "记录异常日志异常,参数:" + new { e, remark }.ToJson()); } }); }
/// <summary> /// 记录debug日志 /// </summary> /// <param name="debugInfo">debug信息</param> /// <param name="args">请求参数</param> /// <param name="returnVal">返回参数</param> /// <param name="keyWord">自定义信息</param> public static void Debug(string debugInfo, object args = null, object returnVal = null, Dictionary <string, object> keyWord = null) { // 调用链+1 LogSpan logSpan = LogSpan.Extend(LogContext.Current); var functionName = GetStackTrace(); Task.Run(() => { try { LogBase log = new LogBase { CustomerInfo = keyWord ?? new Dictionary <string, object>(), LogSpan = logSpan, LogLevel = LogLevel.Warning, }; log.LogSpan.FunctionName = functionName; log.LogSpan.ParamIn = args?.ToJson() ?? string.Empty; log.LogSpan.ParamOut = returnVal?.ToJson() ?? string.Empty; log.CustomerInfo.Add("DebugInfo", string.IsNullOrWhiteSpace(debugInfo) ? string.Empty : debugInfo); if (!LogFilter(log.LogLevel)) { _logger.Write(log); } } catch (Exception ex) { InnerTxtLog.WriteException(ex, "记录Debug日志异常,参数:" + new { debugInfo, args, returnVal, keyWord }.ToJson()); } }); }
/// <summary> /// 记录异常日志 /// </summary> /// <param name="e">异常信息</param> /// <param name="remark">备注</param> /// <param name="args">请求参数</param> /// <param name="returnVal">返回参数</param> /// <param name="keyWord">自定义信息</param> public static void Exception(Exception e, string remark, object args = null, object returnVal = null, Dictionary <string, object> keyWord = null) { // 调用链+1 LogSpan logSpan = LogSpan.Extend(LogContext.Current); var functionName = GetStackTrace(); Task.Run(() => { try { ExceptionLog log = new ExceptionLog { CustomerInfo = keyWord ?? new Dictionary <string, object>(), LogSpan = logSpan, ExceptionInfo = e.ToString(), LogLevel = LogLevel.Error, }; log.LogSpan.FunctionName = functionName; log.LogSpan.ParamIn = args?.ToJson() ?? string.Empty; log.LogSpan.ParamOut = returnVal?.ToJson() ?? string.Empty; log.CustomerInfo.Add("Remark", string.IsNullOrWhiteSpace(remark) ? string.Empty : remark); if (!LogFilter(log.LogLevel)) { _logger.WriteException(log); } } catch (Exception ex) { InnerTxtLog.WriteException(ex, "记录异常日志异常,参数:" + new { e, remark, args, returnVal, keyWord }.ToJson()); } }); }
/// <summary> /// 记录info信息 /// </summary> /// <param name="logSpan">日志段</param> /// <param name="paramOut">内容</param> internal static void InnerInfo(LogSpan logSpan, string paramOut = "") { Task.Run(() => { try { LogBase log = new LogBase { CustomerInfo = new Dictionary <string, object>(), LogSpan = logSpan, LogLevel = LogLevel.Info, }; log.LogSpan.ParamOut = paramOut; log.CustomerInfo.Add("Content", logSpan.FunctionName ?? string.Empty); if (!LogFilter(log.LogLevel)) { _logger.Write(log); } } catch (Exception ex) { InnerTxtLog.WriteException(ex, "记录内部Info日志异常,参数:" + new { paramOut, logSpan }.ToJson()); } }); }
/// <summary>在将请求消息发送到服务之前,启用消息的检查或修改。</summary> /// <param name="request">要发送给服务的消息。</param> /// <param name="channel">WCF 客户端对象通道。</param> /// <returns> /// 作为 <paramref> /// <name xml:space="preserve">correlationState </name> /// </paramref> /// 方法的 <see cref="M:System.ServiceModel.Dispatcher.IClientMessageInspector.AfterReceiveReply(System.ServiceModel.Channels.Message@,System.Object)" />参数返回的对象。 /// 如果不使用关联状态,则为 <see langword="null" />。 /// 最佳做法是将它设置为 <see cref="T:System.Guid" />,以确保没有两个相同的 <paramref> /// <name>correlationState</name> /// </paramref> /// 对象。 /// </returns> public object BeforeSendRequest(ref Message request, IClientChannel channel) { string action = request.Headers.GetHeader <string>("Action", request.Headers[0].Namespace); _logSpan = LogSpan.Extend(LogContext.Current); _logSpan.FunctionName = "WCF Client :" + action; _logSpan.ParamIn = request.ToString(); MessageHeader <LogContext> contextHeader = new MessageHeader <LogContext>(LogContext.Current); request.Headers.Add(contextHeader.GetUntypedHeader(LogContext.ContextHeaderLocalName, LogContext.ContextHeaderNamespace)); return(null); }
/// <summary>实现它来参与初始化操作线程。</summary> /// <param name="instanceContext">操作的服务实例。</param> /// <param name="channel">客户端通道。</param> /// <param name="message">传入消息。</param> /// <returns> /// 作为 <see cref="M:System.ServiceModel.Dispatcher.ICallContextInitializer.AfterInvoke(System.Object)" /> 方法的参数传回的关联对象。 /// </returns> public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message) { LogContext context = message.Headers.GetHeader <LogContext>(LogContext.ContextHeaderLocalName, LogContext.ContextHeaderNamespace); string action = message.Headers.GetHeader <string>("Action", message.Headers[0].Namespace); LogContext.Current = context; LogContext.Current.SpanChain += ".0"; var _logSpan = LogSpan.Extend(LogContext.Current); _logSpanDic.Add(_logSpan.TraceId, _logSpan); _logSpan.FunctionName = "WCF Service :" + action; _logSpan.ParamIn = message.ToString(); return(LogContext.Current); }
/// <summary> /// Implements advice logic. /// Usually, advice must invoke context.Proceed() /// </summary> /// <param name="context">The method advice context.</param> public void Advise(MethodAdviceContext context) { var paramIn = GetInParam(context); // 跳过构造函数和属性(仅记录异常日志,运行日志不记录) if (context.TargetMethod.MemberType == MemberTypes.Constructor || context.TargetMethod.MemberType == MemberTypes.Property || context.TargetMethod.Name.StartsWith("set_") || context.TargetMethod.Name.StartsWith("get_")) { try { _logSpan = LogSpan.GetCurrentLogSpan(); _logSpan.FunctionName = $"{context.TargetMethod.Name}---(Constructor|Property)"; _logSpan.ParamIn = paramIn; context.Proceed(); } catch (Exception e) { // 构造函数中,如果不出现异常,则调用链不用延长,出现异常后才延长调用链 var logTmp = LogSpan.Extend(LogContext.Current); _logSpan.SpanChain = logTmp.SpanChain; _logSpan.ParamOut = $"Exception:{e}"; _logSpan.SpendTime = (DateTime.Now - _logSpan.CreateTime).TotalMilliseconds; LogManager.InnerException(e, "构造函数、属性初始化异常", _logSpan); throw; } return; } // 普通函数,运行日志和异常日志都会记录 _logSpan = LogSpan.Extend(LogContext.Current); _logSpan.FunctionName = $"{context.TargetMethod.Name}"; _logSpan.ParamIn = paramIn; context.Proceed(); _logSpan.ParamOut = GetOutParam(context); _logSpan.SpendTime = (DateTime.Now - _logSpan.CreateTime).TotalMilliseconds; LogManager.InnerRunningLog(_logSpan); }
/// <summary> /// Implements advice logic. /// Usually, advice must invoke context.Proceed() /// </summary> /// <param name="context">The method advice context.</param> public void Advise(MethodAdviceContext context) { try { var paramIn = RunningLogAttribute.GetInParam(context); _logSpan = LogSpan.Extend(LogContext.Current); _logSpan.FunctionName = $"{context.TargetMethod.Name}"; _logSpan.ParamIn = paramIn; context.Proceed(); } catch (Exception e) { _logSpan.ParamOut = $"Exception:{e}"; _logSpan.SpendTime = (DateTime.Now - _logSpan.CreateTime).TotalMilliseconds; LogManager.InnerException(e, "函数执行异常", _logSpan); if (context.HasReturnValue) { // 如果不抛异常到外层,则需要补上函数的返回值 var methodInfo = context.TargetMethod as MethodInfo; if (methodInfo == null) { throw new Exception("日志组件自动补充返回值,未找到目标方法"); } context.ReturnValue = DefaultForType(methodInfo.ReturnType, e.Message); } } finally { if (_isLogFinally) { string res = ""; if (context.HasReturnValue) { res = Newtonsoft.Json.JsonConvert.SerializeObject(context.ReturnValue); } LogManager.InnerInfo(_logSpan, res); } } }
/// <summary> /// 记录内部运行日志 /// </summary> internal static void InnerRunningLog(LogSpan logSpan) { Task.Run(() => { try { LogBase log = new LogBase { CustomerInfo = new Dictionary <string, object>(), LogSpan = logSpan, LogLevel = LogLevel.RunningLog, }; if (!LogFilter(log.LogLevel)) { _logger.Write(log); } } catch (Exception ex) { InnerTxtLog.WriteException(ex, "记录运行日志异常,参数:" + logSpan.ToJson()); } }); }
/// <summary> /// 自定义追踪id(注意,此函数会打破原调用链并新建调用链, 建议在http调用的第一个函数或者调度程序的入口函数使用此方法) /// </summary> /// <param name="traceId"></param> public static void CustomerTraceId(string traceId = "") { LogContext.Current.TraceId = LogSpan.CreateNewTraceId(traceId); LogContext.Current.SpanChain = "0"; }