文档章节

日志分级输出到指定文件

嘴角轻扬30
 嘴角轻扬30
发布于 01/18 18:01
字数 738
阅读 8
收藏 0

 log4j.properties文件

#根设置,输出级别为DEBUG级别, 输出文件为 ERRORA,stdout,DEBUGA
log4j.rootLogger=DEBUG,ERRORA,stdout,DEBUGA

#过滤掉spring框架下的额外日志
#log4j.category.org.springframework = WARN

#输出到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %-5p %c{1}:%L - %m%n

#输出DEBUG信息到指定文件
log4j.appender.DEBUGA=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DEBUGA.layout=org.apache.log4j.PatternLayout
log4j.appender.DEBUGA.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
log4j.appender.DEBUGA.datePattern=yyyy-MM-dd'.log'
log4j.appender.DEBUGA.Threshold = DEBUG
log4j.appender.DEBUGA.append=true
log4j.appender.DEBUGA.File=d:/log/debug_log.log
log4j.appender.DEBUGA.filter.F1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.DEBUGA.filter.F1.LevelMin=DEBUG
log4j.appender.DEBUGA.filter.F1.LevelMax=INFO

#输出error到指定文件
log4j.appender.ERRORA=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ERRORA.layout=org.apache.log4j.PatternLayout
log4j.appender.ERRORA.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
log4j.appender.ERRORA.datePattern=yyyy-MM-dd'.log'
log4j.appender.ERRORA.Threshold = ERROR
log4j.appender.ERRORA.append=true
log4j.appender.ERRORA.File=d:/errorlog/error_log.log

#打印sql语句
log4j.logger.com.ibatis=DEBUG
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

 

为了对每个请求的进行日志输出,我们需要配置拦截器

<!-- 拦截器配置,拦截顺序:先执行后定义的,排在第一位的最后执行。-->
<mvc:interceptors>
    <!-- API访问日志记录拦截器 -->
    <mvc:interceptor>
        <mvc:mapping path="/user/**" />
        <bean class="com.utils.ApiLogInterceptor" />
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/childs/**" />
        <bean class="com.utils.ApiLogInterceptor" />
    </mvc:interceptor>

</mvc:interceptors>

开发自定义的拦截器,实现 HandlerInterceptor 接口

public class ApiLogInterceptor  implements HandlerInterceptor {

   private static final Logger logger = org.apache.log4j.Logger.getLogger(ApiLogInterceptor.class);

   private static final ThreadLocal<Long> startTimeThreadLocal =
         new NamedThreadLocal<Long>("ThreadLocal StartTime");
   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
      if (logger.isDebugEnabled()){
         long beginTime = System.currentTimeMillis();//1、开始时间  
           startTimeThreadLocal.set(beginTime);      //线程绑定变量(该数据只有当前请求的线程可见)  
           logger.debug("开始计时: {"+new SimpleDateFormat("HH:mm:ss.SSS").format(beginTime)+"}  URI: {"+request.getRequestURI()+"}");
      }
      return true;
   }

   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
      if (modelAndView != null){
         logger.info("ViewName: " + modelAndView.getViewName());
      }
   }

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {

      logger.debug("Header: " + request.getHeader("user-agent"));
      logger.debug("RequestURI: " + request.getRequestURI());
      logger.debug("Method: " + request.getMethod());
      logger.debug("ParameterMap: " + request.getParameterMap().toString());

      // 打印JVM信息
      if (logger.isDebugEnabled()){
         long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)  
         long endTime = System.currentTimeMillis();     //2、结束时间  
         logger.debug("计时结束:{"+new SimpleDateFormat("HH:mm:ss.SSS").format(endTime)+"}  耗时:{"+DateUtils.formatDateTime(endTime - beginTime)+"}  URI: {"+request.getRequestURI()+"}  最大内存: {"+(Runtime.getRuntime().maxMemory()/1024/1024)+"}m  已分配内存: {"+(Runtime.getRuntime().totalMemory()/1024/1024)+"}m  已分配内存中的剩余空间: {"+(Runtime.getRuntime().freeMemory()/1024/1024+"}m  最大可用内存: {"+(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024)+"}m") ;
      }
   }
}

 

自定义拦截器会针对 /user/** 和 /childs/** 的请求进行拦截,输出日志。

测试后发现,错误日志既没有在控制台打印出来也没有输出到文件,因为我们需要配置spring-mvc的全局异常处理器,实现 HandlerExceptionResolver  接口

public class DefaultExceptionHandler implements HandlerExceptionResolver {

    private static final Logger logger = org.apache.log4j.Logger.getLogger(DefaultExceptionHandler.class);

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        logger.error("异常信息", ex);

        String url = request.getRequestURL().toString();

        if (url.contains("api")) {
            try {
                /**
                 * 来自app的请求异常处理
                 */
                response.setStatus(HttpStatus.OK.value());
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(new Gson().toJson("系统错误"));
            } catch (IOException e) {
                logger.error("", e);
            }
        } else {
            ModelAndView mv = new ModelAndView();
            mv.setViewName("error");
            return mv;
        }

        return null;
    }

}

还需要在spring-mvc.xml中配置这个bean

<bean id="exceptionHandler" class="com.utils.DefaultExceptionHandler" />

 

再次运行项目,系统出现错误的时候,会跳转到 error.jsp,错误信息会被输出到 error_log 文件。

© 著作权归作者所有

共有 人打赏支持
嘴角轻扬30
粉丝 9
博文 69
码字总数 48746
作品 0
苏州
程序员
私信 提问
log4net 记录 总结 反思

说实话,我并不是太想写这篇文章,因为我承诺过要完成博客园的部分功能,所以一直都在积极的利用下班时间来完善这个系统, 但是我又不想让看我源代码的朋友不知道我写的代码是什么意思,所以...

架构师郭郭
2012/12/27
0
0
Java——Log4j与Log4j2

完整的软件,日志是必不可少的。程序从开发、测试、维护、运行等环节,都需要向控制台或文件等位置输出大量信息。这些信息的输出,在很多时候是System.out.println()无法完成日志信息根据用途与...

奶berber
2018/03/02
0
0
SeasLog 之企业级日志行为规范发布

注:2017年云智慧研发团队发布此《企业级日志行为规范》。这份日志规范并不涉及任何商业机密,故分享给社区,愿整个社区在日志生产和使用过程中更加规范和高效。 该规范共包括:前言、工具组...

Neeke
2018/03/27
2.3K
8
Golang中使用log(三):log模块的设计

Golang的log模块可谓是语言层面上非常基础的一层库,反应的是语言本身的特征而不是一个服务应该怎样怎样。为了方便自己写 应用,我按照自己的需求提出一些log的API并重新实现。和Golang的log...

gotaly
2014/05/14
0
0
Python logging模块

logging模块与log4j的机制是一样的,只是具体的实现细节不同。模块提供logger,handler,filter,formatter四个主要组件。 logger:提供日志接口,供应用代码使用。logger最长用的操作有两类...

China_OS
2013/04/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

学习设计模式之路

https://java-design-patterns.com/patterns/ https://www.oodesign.com/ https://www.programering.com/a/MTNxAzMwATY.html https://design-patterns.readthedocs.io/zh_CN/latest/ https:/......

晨猫
今天
1
0
JDK1.8 jar包说明

JDK 1.8 lib:access-bridge-64.jarcharsets.jarcldrdata.jardeploy.jardnsns.jarjaccess.jarjavawa.jarjce.jarjfr.jarjfxrt.jarjfxswt.jarjsse.jarlocaledata.jar......

冷基
今天
1
0
判断用户的icloud是否开启【Swift4.2】

使用icloudkit存储用户私人数据时,必须判断用户的icloud是否开启【Swift4.2】 func isICloudContainerAvailable()-> Bool { if FileManager.default.ubiquityIdentityToken != ni......

叶落花开
今天
2
0
今天的学习

1、执行git add *命令就把改动提交到了暂存区,执行git pull命令将远程仓库的数据拉到当前分支并合并,执行git checkout [branch-name]切换分支 2、执行git commit -m '说明' 命令就把改动提...

墨冥
昨天
0
0
Android4.4 及以下TextView,Button等控件使用矢量图报错

1 问题描述 最近项目开发中,图标资源我尽量使用了矢量图,然而配置了基本的兼容设置,程序在低版本中运行还是出现了问题。 xml布局文件中,在TextView中使用矢量图,比如android:drawableS...

newtrek
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部