在线管理框架
在工作中遇到这么两个问题,然后根据对应问题编写了这么一个框架,用于管理日志
- 线上日志为info级别,但是我想看我的那块debug代码打印的日志,不想重启代码怎么办?
- 线上出现问题不好排查,想查看某个函数的出入参,不想重启代码怎么办?
1.0.0版本提供功能
- 日志在线管理(基于logback):动态修改root级别,以及相关logger级别
- 环境变量在线管理:动态修改以及查看环境变量
<dependency>
<groupId>com.github.simonalong</groupId>
<artifactId>troy</artifactId>
<version>1.0.0</version>
</dependency>
配置使用 可以不配置,都有默认值
troy:
log:
# api前缀。默认为:/api/troy/log/
prefix: /api/troy/log/
# 是否启用。默认启用
enable: true
输出:
{
"help":{
"help 查询:命令列表":"curl http://localhost:port/api/app/log/help",
"help 查询:修改ip和port":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/help?ip={ip}&port={port}'"
},
"分组":{
"查询:分组列表":"curl 'http://localhost:port/api/app/log/group/list'",
"查询:分组函数列表":"curl 'http://localhost:port/api/app/log/group/fun/list?group={group}'",
"变更:更新分组信息":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/group?group={group}&printLogLevel={logLevel}&enable={enable}'",
"变更:某个函数更新":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/group/fun/change?funId={funId}&printLogLevel={logLevel}&enable={enable}'"
},
"分组-日志":{
"日志查询:分组某个函数信息":"curl 'http://localhost:port/api/app/log/group/fun/info/one/logger?logFunId={funId}'",
"日志查询:分组函数全部信息":"curl 'http://localhost:port/api/app/log/group/fun/info/all?group={group}'"
},
"分组-输出":{
"输出变更:添加分组输出":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/group/(console或者all)?group={group}&printLogLevel={logLevel}&enable={enable}'",
"输出变更:添加函数输出":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/group/fun/print/(console或者all)?funId={funId}&printLogLevel={logLevel}&enable={enable}'"
},
"logger":{
"查询:logger列表":"curl 'http://localhost:port/api/app/log/logger'",
"查询:logger搜索":"curl 'http://localhost:port/api/app/log/logger/{loggerName}'",
"更新:logger更新并输出":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/logger/appender/(console或者all)?loggerName={loggerName}&logLevel={logLevel}'",
"更新:logger处理恢复":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/logger/restore/all/info?loggerName={loggerName}&logLevel={logLevel}'"
},
"appender":{
"更新:添加输出器":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/appender/(console或者all)?loggerName={loggerName}&logLevel={logLevel}'",
"删除:删除某个输出器":"curl -X DELETE 'http://localhost:port/api/app/log/appender?loggerName={loggerName}'",
"删除:删除输出器":"curl -X DELETE 'http://localhost:port/api/app/log/appender/(console或者all)?loggerName={loggerName}'"
},
"环境变量":{
"设置:环境变量":"curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/en/set?key={key}&value={value}'",
"查询:环境变量":"curl 'http://localhost:port/api/app/log/en/get?key={key}'"
}
}
对于该框架有如下几种用法
这里对代码有侵入,提供注解@Watcher
,修饰类和函数,函数会覆盖类的使用。
对于一些平常不需要打印日志,但是在定位问题时候,就需要知道某个函数的出入参这种,就可以使用
@Watcher(group = "business")
@RequestMapping("api/sample/biz")
@RestController
public class BusinessController {
@Autowired
private BusinessService businessService;
@Watcher(group = "insert")
@PostMapping("troyTest")
public FunRsp troyTest(@RequestBody Fun1Req fun1Req) {
return businessService.troyTest(fun1Req);
}
// ... 省略更多 ...
}
提示:修饰函数,则函数会覆盖类的注解
输出:
[
"business",
"insert"
]
提示: 其中host和port都是自己业务的,以下都一样
curl http://localhost:port/api/troy/log/group/fun/list?group={group}
输出:
[
"fun: d6290cf8bd8a0c8ac01c4531374e77462ff5d5838c4ff3b1689c76bc41e33b4a = com.github.simonalong.sample.controller.BusinessController#troyTest(com.github.simonalong.sample.vo.req.Fun1Req)",
"fun: 53cb4ea3745bdb87bc3e8dcd915e98ed4e1128965ce0e3b1dd5d48fc7b05fa59 = com.github.simonalong.sample.service.BusinessService#troyTest(com.github.simonalong.sample.vo.req.Fun1Req)"
]
提示: 其中前面是funId,后面是对应的函数展示
curl http://localhost:port/api/troy/log/group/fun/info/all?group={group}
输出:
{
"d6290cf8bd8a0c8ac01c4531374e77462ff5d5838c4ff3b1689c76bc41e33b4a": {
"logFunName": "com.github.simonalong.sample.controller.BusinessController#troyTest(com.github.simonalong.sample.vo.req.Fun1Req)",
"loggerName": "com.github.simonalong.sample.controller.BusinessController",
"logLevel": "INFO",
"loggerEnable": false
},
"53cb4ea3745bdb87bc3e8dcd915e98ed4e1128965ce0e3b1dd5d48fc7b05fa59": {
"logFunName": "com.github.simonalong.sample.service.BusinessService#troyTest(com.github.simonalong.sample.vo.req.Fun1Req)",
"loggerName": "com.github.simonalong.sample.service.BusinessService",
"logLevel": "INFO",
"loggerEnable": false
}
}
curl http://localhost:port/api/troy/log/group/fun/info/one/logger?group={group}&logFunId={funId}
输出:
{
"logFunName": "com.github.simonalong.sample.controller.BusinessController#troyTest(com.github.simonalong.sample.vo.req.Fun1Req)",
"logLevel": "INFO",
"loggerEnable": false
}
将分组的所有的函数的日志信息更新
curl -X POST http://localhost:port/api/troy/log/group?group={group}&printLogLevel={logLevel}&enable={enable}
输出(个数): n
将分组的所有函数日志信息更新,并添加控制台的appender,输出到控制台
curl -X POST http://localhost:port/api/troy/log/group/console?group={group}&printLogLevel={logLevel}&enable={enable}
输出(个数): n
将分组的所有函数日志信息更新,并添加文件的appender,输出到文件
curl -X POST http://localhost:port/api/troy/log/group/file?group={group}&printLogLevel={logLevel}&enable={enable}
输出(个数): n
将分组的所有函数日志信息更新,并添加控制台和文件的appender,输出到控制台和文件
curl -X POST http://localhost:port/api/troy/log/group/all?group={group}&printLogLevel={logLevel}&enable={enable}
输出(个数): n
将分组内的某个函数的日志信息更新
curl -X POST http://localhost:port/api/troy/log/group/fun/change?funId={funId}&printLogLevel={logLevel}&enable={enable}
输出(个数): n
将分组的所有函数日志信息更新,并添加控制台的appender,输出到控制台
curl -X POST http://localhost:port/api/troy/log/group/fun/print/console?group={group}&printLogLevel={logLevel}&enable={enable}
输出(个数): n
将分组的所有函数日志信息更新,并添加文件的appender,输出到文件
curl -X POST http://localhost:port/api/troy/log/group/fun/print/file?group={group}&printLogLevel={logLevel}&enable={enable}
输出(个数): n
将分组的所有函数日志信息更新,并添加控制台和文件的appender,输出到控制台和文件
curl -X POST http://localhost:port/api/troy/log/group/fun/print/all?group={group}&printLogLevel={logLevel}&enable={enable}
输出(个数): n
输出:
[
{
"loggerName": "ROOT",
"logLevelStr": "INFO",
"appenderList": [
{
"appenderName": "STDOUT",
"appenderPattern": "%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) %black(shizi-2.local) %highlight(%p) --- %cyan([troy-sample]) %yellow([%X{traceId}]) %black(%c) %black(%M) %black([%t@42976]) : %green(%m%n)"
},{
"more": ".....更多...."
}
]
}
]
模糊匹配匹配到的logger
输出:
[
{
"loggerName": "com.github.simonalong.sample.service.BusinessService",
"logLevelStr": "INFO",
"appenderList": []
}
]
loggerName如果为root,则为修改root日志级别
curl -X POST http://localhost:port/api/troy/log/logger?loggerName={loggerName}&logLevel={logLevel}
输出(个数): n
curl -X POST http://localhost:port/api/troy/log/logger/name/console?loggerName={loggerName}&logLevel={logLevel}
输出(个数): n
curl -X POST http://localhost:port/api/troy/log/logger/name/file?loggerName={loggerName}&logLevel={logLevel}
输出(个数): n
变更并输出到文件和控制台
curl -X POST http://localhost:port/api/troy/log/logger/name/all?loggerName={loggerName}&logLevel={logLevel}
输出(个数): n
该appender主要就是用于将日志搜集之后如何处理使用的(不常用)
添加某个logger的appender到控制台
curl -X POST http://localhost:port/api/troy/log/appender/console?loggerName={loggerName}&logLevel={logLevel}
输出(个数): n
添加某个logger的appender到文件
curl -X POST http://localhost:port/api/troy/log/appender/file?loggerName={loggerName}&logLevel={logLevel}
输出(个数): n
添加某个logger的appender到文件也到控制台
curl -X POST http://localhost:port/api/troy/log/appender/all?loggerName={loggerName}&logLevel={logLevel}
输出(个数): n
curl -X DELETE http://localhost:port/api/troy/log/appender?loggerName={LoggerName}
输出(个数): n
curl -X DELETE http://localhost:port/api/troy/log/appender/file?loggerName={LoggerName}
输出(个数): n
curl -X DELETE http://localhost:port/api/troy/log/appender/console?loggerName={LoggerName}
输出(个数): n
这里会删除文件也会删除控制台
curl -X DELETE http://localhost:port/api/troy/log/appender/all?loggerName={LoggerName}
输出(个数): n
本工具也提供对环境变量的修改,可以动态的修改一些环境变量,在排查问题时候非常有帮助
// 代码中使用如下
System.getProperty("xxx")
设置环境变量
curl -X POST -H 'Content-Type: application/json' 'http://localhost:port/api/app/log/en/set?key={key}&value={value}'
查询环境变量
curl 'http://localhost:port/api/app/log/en/get?key={key}'