java agent开发 日志打印
简介目前java 打印日志用的比较多的就是slf4j配合log4j/logback进行日志打印,但是呢agent是独立的jar包,使用slf4j就需要将包引入agent中,这样就可能和业务自身的slf4j log4j日志产生冲突而且在agent包使用slf4j-api包后,需要保证agent的classLoader和业务的classLoader保持一致,否则找不到需求agent的日志打印可以不依赖
·
简介
目前java 打印日志用的比较多的就是slf4j配合log4j/logback进行日志打印,但是呢agent是独立的jar包,
使用slf4j就需要将包引入agent中,这样就可能和业务自身的slf4j log4j日志产生冲突
而且在agent包使用slf4j-api包后,需要保证agent的classLoader和业务的classLoader保持一致,否则找不到
需求
- agent的日志打印可以不依赖于业务日志,如果用户有日志包依赖,也可以使用业务日志
- agent的日志设置,用户可以在环境变量设置
问题
- 有时候出现包冲突,导致日志打印不出来
- spring boot项目的classLoder和agent的classLoader不一致,sf4j相关包找不到。因为spring boot打包出来后是一个独立的jar包,jar包内部的依赖包由spring 自己的类加载器处理
- 在ide调试的时候没有问题,在linux环境运行就有问题。因为在ide调试的时候所有包都在一个classLoader下,可以找到相关的类
解决方案
-
spring boot的问题可以通过字节码增强的方式,把agent相关的包路径加到spring boot的classLoader(JarLauncher) 搜索路径中
-
agent日志打印方式使用Java.util.logging (jdk原生的打印),jul-to-slf4j包可以把 原生的log和sf4结合起来。这时候不管有没有slf4j相关包都可以打印日志。有就走slf4j,没有就是jdk自己的打印
-
ide调试的问题没有好的解决方案,只能说在本地shell进行一次独立运行测试
相关代码封装实例
public class AgentLogger {
static Logger logger = Logger.getLogger("AgentLogger");
static String defaultLogName = "";
public static Logger getLogger(){
return logger;
}
public static void log(Level level, String msg, Object...param){
if(param != null && param.length >0){
String message = String.format(msg,param);
logger.log(level,message);
}else {
logger.log(level,msg);
}
}
public static void info( String msg, Object...param){
log(Level.INFO,msg,param);
}
public static void init(){
// Logger tlogger = Logger.getLogger("plough");
// Logger clogger = Logger.getLogger("governance-client");
//
// tlogger.setLevel(Level.SEVERE);
// clogger.setLevel(Level.SEVERE);
setLevel();
String agentLogNames = EnvUtil.getEnv("agent_console_log_name",defaultLogName);
List<String> agentLogNameList = StringUtil.StringToList(agentLogNames);
// 给某个logger 手动添加日志打印, 防止某种情况打印不出日志
for (String agentLogName : agentLogNameList){
Logger logger = Logger.getLogger(agentLogName);
Handler[] handlers = logger.getHandlers();
if (handlers != null && handlers.length == 0){
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.ALL);
logger.addHandler(consoleHandler);
}
}
}
//可以通过环境变量设置日志级别
public static void setLevel(){
Map<String,String> envMap = System.getenv();
Properties properties = System.getProperties();
properties.putAll(envMap);
Set<Object> keySet = properties.keySet();
for (Object envKey : keySet){
String envKeyStr = envKey.toString();
if (envKeyStr.startsWith("agent_log_level_")){
envKeyStr = envKeyStr.replace("agent_log_level_","");
Logger logger = Logger.getLogger(envKeyStr);
String level = properties.getProperty(envKey.toString());
if ("error".equals(level)) {
logger.setLevel(Level.SEVERE);
}else if ("info".equals(level)){
logger.setLevel(Level.INFO);
}else if ("debug".equals(level)){
logger.setLevel(Level.ALL);
}
}
}
}
更多推荐
所有评论(0)