前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >企业级日志组件实现

企业级日志组件实现

作者头像
小蜜蜂
发布于 2019-07-15 07:53:11
发布于 2019-07-15 07:53:11
36100
代码可运行
举报
文章被收录于专栏:明丰随笔明丰随笔
运行总次数:0
代码可运行

企业级日志组件应该包含哪些信息?如下:

1. Severity:严重程度

2. AppDomain:应用程序域

3. ExceptionName:异常类型名

4. Message:异常消息

5. Source:异常来源

6. StackTrace:异常堆栈信息

7. Assembly:异常来自的程序集

8. Method:异常来自的方法

9. Machine:异常来自的机器

10. UserName:异常来自的用户名

11. ThreadName:异常来自的线程名

12. CreationDatetime:异常发生的时间

我们定义ExceptionEnvironmentInfo类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ExceptionEnvironmentInfo
{
  public string MachineName;
  public DateTime TimeStamp;
  public string AppDomainName;
  public string ThreadIdentity;
  public string WindowsIdentity;
  public string Method;
  public string AssemblyName;
  public string AssemblyFullName;
  public StackFrame[] StackTrace;
  public string GetStackTrace()
  {
    if (this.StackTrace == null || this.StackTrace.Length == 0)
    {
      return string.Empty;
    }
    try
    {
      var sb = new StringBuilder();
      bool hasFileInfo = !string.IsNullOrEmpty(this.StackTrace[0].GetFileName());
      foreach (var frame in StackTrace)
      {
        var method = frame.GetMethod();
        sb.AppendFormat("at {0}.{1}", method.DeclaringType.FullName, method.Name);
        if (hasFileInfo)
        {
          sb.AppendFormat(" in {0}:line {1}", frame.GetFileName(), frame.GetFileLineNumber());
        }
        sb.AppendLine();
      }
      return sb.ToString();
    }
    catch (Exception ex)
    {
      return "Error getting stack trace: " + ex.Message;
    }
  }
}

定义一个ExceptionInfo类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ExceptionInfo
{
  public readonly Exception Exception;
  public readonly ExceptionEnvironmentInfo EnvironmentInfo;
  public ExceptionInfo(Exception ex, ExceptionEnvironmentInfo envInfo)
  {
    this.Exception = ex;
    this.EnvironmentInfo = envInfo;
  }
}

通过这两个类可以保存所有我们关心的信息。

我们现在对上面列出来的信息,如何获取,进行一一讨论。

1. Severity:严重程度

这个信息是用户在记录异常的时候,由用户决定的。

2. AppDomain:应用程序域

AppDomain.CurrentDomain.FriendlyName;

3. ExceptionName:异常类型名

ex.GetType().Name;

4. Message:异常消息

ex.Message;

5. Source:异常来源

ex.Source;

6. StackTrace:异常堆栈信息

ex.StackTrace;

7. Assembly:异常来自的程序集

8. Method:异常来自的方法

这两个信息需要使用StackTrace来计算出来,具体看后面的ExceptionManager类的实现。

9. Machine:异常来自的机器

Environment.MachineName;

10. UserName:异常来自的用户名

System.Security.Principal.WindowsIdentity.GetCurrent().Name;

11. ThreadName:异常来自的线程名

System.Threading.Thread.CurrentPrincipal.Identity.Name;

12. CreationDatetime:异常发生的时间

DateTime.Now;

ExceptionManager类的实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ExceptionManager
{
  private Type _callerStackBoundaryDeclaringType = typeof(ExceptionManager);
  public void Publish(Exception ex)
  {
    ExceptionEnvironmentInfo envInfo = GetEnvironmentInfo();
    var exInfo = new ExceptionInfo(ex, envInfo);
    //TODO: save the exInfo in database.
    //...
  }
  private ExceptionEnvironmentInfo GetEnvironmentInfo()
  {
    ExceptionEnvironmentInfo envInfo = new ExceptionEnvironmentInfo();
    this.GetCallerInfo(envInfo);
    // Add environment information to the information collection.
    envInfo.MachineName = Environment.MachineName;
    envInfo.TimeStamp = DateTime.Now;
    envInfo.AppDomainName = AppDomain.CurrentDomain.FriendlyName;

    envInfo.ThreadIdentity = System.Threading.Thread.CurrentPrincipal.Identity.Name;
    envInfo.WindowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
    return envInfo;
  }
  private void GetCallerInfo(ExceptionEnvironmentInfo envInfo)
  {
    bool fNeedFileInfo = false;
#if DEBUG
    fNeedFileInfo = true;
#endif
    var st = new StackTrace(fNeedFileInfo);
    try
    {
      var index = 0;
      // 首先根据堆栈信息定位到ExceptionManager的调用帧信息
      while (index < st.FrameCount)
      {
        var frame = st.GetFrame(index);
        if (frame != null && frame.GetMethod().DeclaringType == _callerStackBoundaryDeclaringType)
        {
          index++;
          break;
        }
        index++;
      }
      // 然后过滤掉所有来自ExceptionManager的调用帧信息,因为ExceptionManager是底层通用组件,需要过滤掉
      while (index < st.FrameCount)
      {
        var frame = st.GetFrame(index);
        if (frame != null && frame.GetMethod().DeclaringType != _callerStackBoundaryDeclaringType)
        {
          break;
        }
        index++;
      }
      // 这个是异常出现的真实位置,记录来它的所有的帧
      if (index < st.FrameCount)
      {
        var frames = new StackFrame[st.FrameCount - index];
        for (int i = 0; i + index < st.FrameCount; i++)
        {
          frames[i] = st.GetFrame(i + index);
        }
        var method = frames[0].GetMethod();
        var declaringType = method.DeclaringType;
        var callingAssembly = declaringType.Assembly;
        var callingAssemblyName = declaringType.Assembly.GetName();
        envInfo.StackTrace = frames;
        envInfo.AssemblyName = callingAssemblyName.Name;
        envInfo.AssemblyFullName = callingAssemblyName.FullName;
        envInfo.Method = string.Format("{0}.{1} ({2})", declaringType.FullName, method.Name, envInfo.AssemblyName);
      }
    }
    catch (Exception e)
    {
      envInfo.Method = "(unobtainable)(error: " + e.Message + ")";
    }
  }
}

然后在自己的业务逻辑代码里面就可以获取到所有的异常信息了,并且会正确返回程序集和方法信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void DoBiz()
{
  try
  {
    throw new Exception("Error happen!");
  }
  catch (Exception ex)
  {
    ExceptionManager manager = new ExceptionManager();
    manager.Publish(ex);
  }
}

-纸上得来终觉浅,绝知此事要躬行-

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 明丰随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
一个让人遗忘的角落—Exception(二)
在上一篇中"一个被人遗忘的角落--Exception(一)"中,跟大家简单介绍了一下Exception,也使大家充分的了解了Exception管理在一个项目中的重要性,那如何在我们的项目中处理异常呢?因为我从事的是Web开发,所以我只跟大家讨论Web的解决方案,Win的解决方式,还希望同大家一起探讨。 上一章中我们了解了异常发生的原因,同时也说了不存在没有bug的程序,任何网站都会遇到各种各样的问题,无论是大网站还是小网站都会存在,但大公司和小公司对待异常的态度全然不同,一个是主动出击,一个是守株待兔,我
脑洞的蜂蜜
2018/02/01
5090
浅谈StackTrace类
在程序中,每次调用一个函数,就会生成一个堆栈帧,并push进入堆栈中。每一次结束一个函数调用,就会从堆栈中pop一个堆栈帧。
小蜜蜂
2019/07/15
1.5K0
浅谈StackTrace类
C#项目将dll打包进exe中
想将项目用到的两个dll库文件(CryptEnDe.dll和ICSharpCode.SharpZipLib.dll)一同编译进exe中,并编译后仅一个exe程序就可以独立运行不再需要其它文件。
zls365
2021/04/07
1.3K0
基于微软企业库的AOP组件(含源码)
软件开发,离不开对日志的操作。日志可以帮助我们查找和检测问题,比较传统的日志是在方法执行前或后,手动调用日志代码保存。但自从AOP出现后,我们就可以避免这种繁琐但又必须要实现的方式。本文是在微软企业库
用户1219352
2018/02/01
5740
基于微软企业库的AOP组件(含源码)
Unity 自定义日志保存「建议收藏」
之前unity5.x在代码中写了debug.log..等等,打包之后在当前程序文件夹下会有个对应的”outlog.txt”,2017之后这个文件被移到C盘用户Appdata/LocalLow/公司名 文件夹下面。觉得不方便就自己写了个
全栈程序员站长
2022/09/14
5670
数组未必一定需从0开始,谈一下非0开始的数组
彭泽0902
2018/01/04
1K0
秒懂C#通过Emit动态生成代码
通过类型构造器定义一个方法,获取方法构造器,获得方法构造器的IL生成器,通过编写IL代码来定义方法功能。
郑子铭
2023/10/30
2820
秒懂C#通过Emit动态生成代码
使Spring.NET的IOC容器支持动态加载的程序集
当我们发布系统时,有时候希望不用关掉应用程序就能完成发布,但Spring.NET的ApplicationContext是从AppDomain.CurrentDomain中加载的程序集中创建对象的,并不支持从动态加载的程序集中创建对象,如果直接把更新后的程序集复制到bin目录,会无法替换dll或导致应用程序重启。最近我正好有这个需求,就研究了一下Spring的相关代码,需要解决的问题如下:
明年我18
2019/09/18
7300
使Spring.NET的IOC容器支持动态加载的程序集
SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)
但是在silverlight客户端用处就非常大(等会会说道为silverlight客户端自动生成实体类型,silverlight 4.0是有Entity类的)
liulun
2022/05/09
7630
SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)
C# StackTrace & StackFrame
在软件开发过程中,调试和错误追踪是非常重要的环节。C# 提供了强大的调试工具,其中 StackTrace 和 StackFrame 是用于追踪和分析代码执行路径的重要类。本文将详细介绍这两个类及其在实际开发中的应用。
JusterZhu
2025/01/23
1150
C# StackTrace & StackFrame
04Prism WPF 入门实战 - Module
源码及PPT地址:https://github.com/JusterZhu/wemail
JusterZhu
2022/12/07
4380
04Prism WPF 入门实战 - Module
AppDomain
AppDomain(应用程序域)是.NET框架中的一个重要概念,主要用于隔离、加载和执行托管代码。它提供了一种轻量级的进程内隔离机制,使得多个应用程序可以在同一个进程中运行而不互相干扰。以下是关于AppDomain的一些关键点:
JusterZhu
2025/01/23
770
AppDomain
构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(13)-系统日志和异常的处理③
上一节我们讲了如何捕获异常和记录日志,这一节我们讲,没有捕获的或者忘记捕获的异常包括404错误等,我们统一处理这个异常。 这一讲是利用 Application_Error 捕获所有异常,全局的异常处理为了减少代码,统一异常处理,Application_Error位于Global.asax里面, protected void Application_Error(object sender, EventArgs e) 当一个异常在调用堆栈中没有被处理,也没有被框架代码处理时,我们说这个异常未处理,它将被ASP.
用户1149182
2018/01/16
9820
构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(13)-系统日志和异常的处理③
C# 在自定义的控制台输出重定向类中整合调用方信息
众所周知,在 .NET 的控制台应用程序(就是那种小黑框程序)中输出信息,使用的是控制台输出方法 Console.Write ("消息") 或 Console.WriteLine ("消息"),这两个方法称为标准输出。而在 Winform、WPF、网页程序中,使用这种方法输出的信息是没有地方显示的,在这些程序中,我们一般把信息输出到相应的显示控件中,或者写入日志中。
独立观察员
2022/12/06
1.7K0
C# 在自定义的控制台输出重定向类中整合调用方信息
C#/.NET 如何获取一个异常(Exception)的关键特征,用来判断两个异常是否表示同一个异常
在 .NET / C# 程序中出现异常是很常见的事情,程序出现异常后记录日志或者收集到统一的地方可以便于分析程序中各种各样此前未知的问题。但是,有些异常表示的是同一个异常,只是因为参数不同、状态不同、用户的语言环境不同就分开成多个异常的话,分析起来会有些麻烦。
walterlv
2023/10/22
7150
ASP.NET MVC模块化开发——动态挂载外部项目
最近在开发一个MVC框架,开发过程中考虑到以后开发依托于框架的项目,为了框架的维护更新升级,代码肯定要和具体的业务工程分割开来,所以需要解决业务工程挂载在框架工程的问题,MVC与传统的ASP.NET不同,WebForm项目只需要挂在虚拟目录拷贝dll就可以访问,但是MVC不可能去引用工程项目的dll重新编译,从而产生了开发一个动态挂在MVC项目功能的想法,MVC项目挂载主要有几个问题,接下来进行详细的分析与完成解决方案
code2roc
2023/07/19
3400
ASP.NET MVC模块化开发——动态挂载外部项目
C# 很少人知道的科技
本文来告诉大家在C#很少有人会发现的科技。即使是工作了好多年的老司机也不一定会知道,如果觉得我在骗你,那么请看看下面。
林德熙
2018/09/19
6520
C# 很少人知道的科技
WPF 判断调用方法堆栈
最近遇到一个问题,经常有小伙伴在类A的构造里调用静态函数B,但是这时B依赖于A的初始化完成,于是就无限循环。所以我需要在判断小伙伴调用B时是否在A的构造方法里,如果是就给他异常。 本文告诉大家如何使用 StackTrace 获得调用堆栈,并且判断当前是否构造调用
林德熙
2022/08/04
3550
WPF 判断调用方法堆栈
最近遇到一个问题,经常有小伙伴在类A的构造里调用静态函数B,但是这时B依赖于A的初始化完成,于是就无限循环。所以我需要在判断小伙伴调用B时是否在A的构造方法里,如果是就给他异常。 本文告诉大家如何使用 StackTrace 获得调用堆栈,并且判断当前是否构造调用
林德熙
2018/09/19
6970
WPF 判断调用方法堆栈
ASP.NET MVC 巧用代码注释做权限控制以及后台导航
请先看:https://cloud.tencent.com/developer/article/1057566 权限控制需要将控制器和Action信息写入到数据库,手动添加的话比较麻烦,有没有更简单的办法呢? 那就用反射把吧,我们可以借助代码注释( 将权限控制的详细用xml注释的方式写到代码里)+反射技术来巧妙的实现 同时,还可以用来作后台导航哦 效果篇   /// <IsShow>True</IsShow>   /// <IsHeader>True</IsHeader>   /// <Title>个人信息
JadePeng
2018/03/12
2K0
ASP.NET MVC 巧用代码注释做权限控制以及后台导航
推荐阅读
相关推荐
一个让人遗忘的角落—Exception(二)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验