Code Monkey home page Code Monkey logo

autologging's Introduction

AutoLogging 监控日志框架

一个非常强大的监控日志输出框架,主要功能包含

  • 方法监控日志输出
  • 应用内调用链路追踪

可以通过

  • SpringAOP
  • 动态字节码运行时注入

两种方式引入,只要一个注解即可开启所有功能,而且具有强大的可扩展性

背景

在开发过程中,我们常常会看到这样的代码:

@GetMapping("{id}")
public ReturnDTO<User> getById(int id) {
    log.info("根据主键id查询用户, id: {}", id);
    long startTime = System.currentTimeMillis();
    try {
        ReturnDTO<User> rs =  ResultUtil.successResult(userService.getById(id));
        log.debug("根据主键id查询用户成功, id: {}, 耗时: {}", id, (System.currentTimeMills() - startTime));
        return rs;
    } catch (Exception e) {
        log.error("据主键id查询用户发生异常, id: {}, 耗时: {}", id, (System.currentTimeMills() - startTime), e);
        return ResultUtil.errorResult("据主键id查询用户发生异常, id: " + id);
    }
}

这种写法有以下几个问题:

  • 代码冗余,不易维护
  • 日志格式不统一,难以自动化分析
  • 容易遗漏或者写错日志信息,问题排查艰难

这些问题都给开发、测试和线上排查问题造成困扰

想象一下,整个项目当中,我们有多少个像这样的方法?DRY!

特点

只需要添加 maven 依赖,然后给全局打上一个注解,就能开启所有功能,我们就可以去掉所有监控日志,由框架统一输出:

@GetMapping("{id}")
public ReturnDTO<User> getById(int id) {
    return ResultUtil.successResult(userService.getById(id));
}

自动日志框架会自动输出方法的监控日志

效果展示

2020-03-01 13:38:46.483  INFO 54635 --- [           main] c.g.d.a.c.l.LocalLogTraceListener        : 121361440260956160 | 2 | Repository |  | com.github.dadiyang.autologging.test.user.UserMapperFakeImpl | getById | [830293] | {"id":830293,"username":"张三"} | 4
2020-03-01 13:38:46.484  INFO 54635 --- [           main] c.g.d.a.c.l.LocalLogTraceListener        : 121361440260956160 | 1 | Service |  | com.github.dadiyang.autologging.test.user.UserServiceImpl | getById | [830293] | {"id":830293,"username":"张三"} | 27
2020-03-01 13:38:46.485  INFO 54635 --- [           main] c.g.d.a.c.l.LocalLogTraceListener        : 121361440260956160 | 0 | Controller | GET 127.0.0.1 http://localhost/user/getById   | com.github.dadiyang.autologging.test.user.UserController | getById | [830293] | {"id":830293,"username":"张三"} | 39
2020-03-01 13:38:46.528 ERROR 54635 --- [           main] c.g.d.a.c.l.LocalLogTraceListener        : 121361440592306176 | 2 | Repository | | com.github.dadiyang.autologging.test.user.UserMapperFakeImpl | updateById | [{"id":830293,"username":"张三"}] | 0 | java.lang.UnsupportedOperationException: 模拟抛出异常
	at com.github.dadiyang.autologging.test.user.UserMapperFakeImpl.updateById(UserMapperFakeImpl.java:14)
	at com.github.dadiyang.autologging.test.user.UserMapperFakeImpl$$FastClassBySpringCGLIB$$8b95b1d3.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)

项目结构

本框架分为 core、aop、aop-jvm-sandbox、test 四个项目,其中

  • core 核心模块,包含配置和上报相关的日志监听器的定义;
  • aop 通过 SpringAOP 打印和上报方法执行的监控信息,包括对 Controller、 Service 和 Mapper 层的监控日志,以及统一异常处理;
  • aop-jvm-sandbox 基于 jvm-sandbox 框架实现的无侵入的 AOP 日志实现,它提供了一个能力,让应用完全无感的情况下,在运行时动态将监控日志相关代码织入到目标应用中,使之拥有输入监控日志的能力
  • test 用于测试

快速开始

基于 aop 的方法级监控日志

以 SpringBoot 环境使用为例

maven 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>com.github.dadiyang</groupId>
    <artifactId>autologging-aop</artifactId>
    <version>1.0.0</version>
</dependency>

注解

在 Application 类上添加 @EnableServiceLog 注解开启 Service 层的监控

各个切面有预置的注解,可以根据需要挑选添加:

注解 释义 备注
@EnableMarkLog 启用所有带 @MarkLog 注解的类和方法 在需要监控的类或方法上添加 @MarkLog
@AutoLogAll 开启所有切面的日志监控功能,打印到本地,如果有引入 Kafka 相关配置则进行上报
@AutoLogAllLocal 开启所有切面的日志监控功能,打印到本地
@EnableControllerLog 开启 Controller 日志
@EnableServiceLog 开启 Service 的日志 带有 @Service 的类
@EnableMapperLog 开启 Mapper 层的日志 带有 @Mapper 的类
@RepositoryLogAspect 开启 Repository 的日志 带有 @Repository 的类

配置

autolog:
    # 请填写应用名称,必填!
    app-name: 

OK,搞定!启动之后应用中的各个切面方法执行的时候就会打印相关的日志了。

更多配置项请查看:autologging-aop

交个朋友

donation

autologging's People

Contributors

dadiyang avatar dependabot[bot] avatar yangziwen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

autologging's Issues

继承父类中的方法调用日志如何打出来

1、controller里面调用service -->mapper 想把mapper 里面日志打出来
2. carService 调用carBiz carBiz继承一个通用增删改查

@RestController
@RequestMapping("car/")
public class CarController extends BaseController<CarBiz, Car, Integer> {

@Autowired
CarService carService;

@RequestMapping(value = "/aadd1", method = RequestMethod.GET)
@ResponseBody
@ApiOperation("新增单个对象")
public ObjectRestResponse<Car> add1() {
    carService.insertByRandom();
    return null;
}

@RequestMapping(value = "/addDefault", method = RequestMethod.GET)
@ResponseBody
@ApiOperation("新增单个对象")
public ObjectRestResponse<Car> addDefault() {
    carService.insertByRandomDefault();
    return null;
}

}

@service
public class CarService {

@Autowired
CarBiz carBiz;

@TargetDataSource(dataSourceKey = DataSourceKey.DB_SLAVE1)
public void insertByRandom() {

    Car car = new Car();
    car.setName("ifaofa");
    car.setId(11111111);
    carBiz.insertSelective(car);

}


public void insertByRandomDefault() {

    Car car = new Car();
    car.setName("ifaofa"+ new Random().nextInt(1000));
    carBiz.insertSelective(car);

}

}

@service
public class CarBiz extends BusinessBiz<CarMapper, Car> {
}

/**

  • 基础业务类

  • @author woozoom

  • @Version 2018/1/13.
    */
    public abstract class BusinessBiz<M extends CommonMapper, T> extends BaseBiz<M, T> {
    @OverRide
    public void insertSelective(T entity) {
    EntityUtils.setCreatAndUpdatInfo(entity);
    super.insertSelective(entity);
    }

    @OverRide
    public void updateById(T entity) {
    EntityUtils.setUpdatedInfo(entity);
    super.updateById(entity);
    }

    @OverRide
    public void updateSelectiveById(T entity) {
    EntityUtils.setUpdatedInfo(entity);
    super.updateSelectiveById(entity);
    }
    }

/**

  • 这是需要打日志的mapper,继承了一个通用的增删改查
    */
    @Marklog
    public interface CarMapper extends CommonMapper {
    }

import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.ids.SelectByIdsMapper;

/**

  • 这是通用的增删改查类
    */
    public interface CommonMapper extends SelectByIdsMapper,Mapper {
    }

结合springControllerAdvice traceId如何统一

hello,请教一下如何可以同时覆盖@controller 和 @RestControllerAdvice,因为两个方法都在另一个类中,无法覆盖到,导致每次发生错误的时候会在RestControllerAdvice中的方法重新生成traceId

org.springframework.web.servlet.DispatcherServlet#doDispatch
try{
handle();
}catch(exception e){
...
}
processDispatchResult();

序列化复杂对象很容易出错

return fullMsg ? serializer.serialize(objects) : summary(objects, serializeConfig.getArgsMaxLength());

这一行经常在controller调用service的时候报错,一些传递进去的复杂对象序列化不了,不像普通的javabean。

我的项目里面每次进去都是使用的fastjson进行序列化的

我暂时也不知道如何处理这种复杂且多样的情况

MarkLogAspect中的切点定义,为何用的是EnableMarkLog注解,而不是MarkLog注解?

你好,最近在学习你写的日志框架,感觉颇有收获。这里有个小疑问想请教下。

MarkLogAspect中定义的切点,为何是基于EnableMarkLog注解(@Within(EnableMarkLog) || @annotation(EnableMarkLog)),而不是基于MarkLog注解的呢(@Within(MarkLog) || @annotation(MarkLog))?

按我理解,EnableMarkLog注解应该只是用来import诸如AutoLogConfig、MarkLogAspect等相关bean。实际在标注需要打日志的类或者方法时,应该使用MarkLog注解吧。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.