在发布此问题之前,我尝试进行多次搜索.如果这是重复,请告诉我,我将删除它.
我的问题围绕处理通过我们的Web应用程序产生的错误的正确方法.我们目前通过log4j记录所有内容.如果发生错误,它只是说"发生了错误.已经通知IT部门,并将在屏幕上尽快纠正此错误".这告诉用户没什么......但是当我们尝试重现错误时,它也没有告诉开发人员任何事情.我们必须转到错误日志文件夹并尝试查找此错误.我还要提一下,该文件夹中充满了过去一周的日志.每次出现错误时,都会为该用户创建一个日志文件,并将电子邮件发送给分配给处理错误的IT人员.此电子邮件未提及日志文件名,但它是日志文件中写入的相同错误文本的副本.
因此,如果Alicia在7:15遇到问题,但在同一分钟发生了10个其他错误,我必须通过每个日志文件试图找到她的.
我向同事们提出的建议是在数据库中添加一个错误日志表.这会为每个错误写一条记录,记录它的用户,错误,它发生的页面等等.这样做的好处是我们可以从表中返回主键值(error_log_id)和显示在页面上有一条消息,例如"错误参考ID(1337)已被记录,并且已通知正确的IT人员.请保留此参考ID,以备将来使用".当我们收到电子邮件时,它会告诉我们错误的ID以便快速参考.或者如果用户是持久的,他们可以使用id与我们联系,我们可以很快找到错误.
你如何设置错误记录?顺便说一句,我们的系统使用连接到SQL Server数据库的Java Servlet.
我在这里回答了类似的问题,但我会根据你的问题调整答案.
我们为此目的使用requestID - 在处理的最开始(在过滤器中)为每个传入(HTTP)请求分配一个请求ID,然后在每个日志行上记录该请求ID,这样您可以稍后通过该ID轻松地对这些日志进行grep找到所有相关的行.
如果您认为将该ID添加到每个日志语句非常繁琐,那么您并不孤单 - 使用映射诊断上下文(MDC)(至少log4j和logback具有此功能),Java日志框架已使其透明.
RequestID也可以作为一个方便的参考号,在发生错误时吐出(如你所建议的那样).但是,正如其他人所评论的那样,将这些细节加载到数据库并不明智 - 更好地使用文件系统.或者,最简单的方法是只使用requestID - 然后您不需要在发生错误时执行任何特殊操作.它只是帮助您找到正确的日志文件并在该文件中搜索.
一个requestID怎么样?
我们使用以下模式:
<实例>:
<计数器>
由以下变量组成:
instanceName唯一标识特定部署环境中的特定JVM.
currentTimeInMillis是不言自明的.我们选择以人类可读的格式"yyyyMMddHHmmssSSS"来表示它,因此很容易从中读取请求的开始时间(注意:SimpleDateFormat不是线程安全的,因此您需要同步它或在每个请求上创建一个新的).
计数器是特定毫秒的请求计数器 - 在极少数情况下,您可能需要在一毫秒内生成多个请求ID
正如您所看到的,ID格式的设置方式使得currentTimeInMillis.counter组合在特定的JVM中保证是唯一的,并且整个ID保证是全局唯一的(好吧,不是真正意义上的"全局") ",但它足以满足我们的目的),而不需要涉及数据库或其他一些中心节点.此外,使用instanceName变量可以限制以后需要查找的日志文件数以查找该请求.
然后,最后一个问题:"在单JVM解决方案中这很好用,但是如何将其扩展到几个JVM,通过某些网络协议进行通信?"
当我们使用Spring Remoting进行远程处理时,我们实现了自定义RemoteInvocationFactory(从上下文获取请求ID并将其保存到RemoteInvocation属性)和RemoteInvocationExecutor(从属性获取请求ID并将其添加到其他JVM中的诊断上下文).
不确定如何使用plain-RMI或其他远程方法实现它.