package com.ejie.x38.log; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.ejie.x38.dto.JQGridResponseDto; import com.ejie.x38.log.model.LogModel; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Appender; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Gestion del cambio de logs en runtime * * @author Urko Guinea * */ @Service(value = "LoggingEditor") public class LoggingEditor { private static final String LOGBACK_CLASSIC = "ch.qos.logback.classic"; private static final String LOGBACK_CLASSIC_LOGGER = "ch.qos.logback.classic.Logger"; private static final String LOGBACK_CLASSIC_LEVEL = "ch.qos.logback.classic.Level"; private static final Logger logger = LoggerFactory.getLogger(LoggingEditor.class); /** * Cambio en runtime del nivel de logger * * @param loggerName Nombre del logger a cambiar su nivel. Si blank, se usara el root logger. * @param logLevel Uno de los niveles de logs soportado: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, * OFF. {@code null} se considera 'OFF'. */ public static boolean setLogLevel(String loggerName, String logLevel) { String logLevelUpper = (logLevel == null) ? "OFF" : logLevel.toUpperCase(); try { Package logbackPackage = Package.getPackage(LOGBACK_CLASSIC); if (logbackPackage == null) { logger.info("Logback no esta en el classpath!"); return false; } // usa el root logger en caso de que llegue vacio if ((loggerName == null) || loggerName.trim().isEmpty()) { loggerName = (String) getFieldVaulue(LOGBACK_CLASSIC_LOGGER, "ROOT_LOGGER_NAME"); } // Obtener el logger por su nombre Logger loggerObtained = LoggerFactory.getLogger(loggerName); if (loggerObtained == null) { // I don't know if this case occurs logger.warn("No existe un logger con tal nombre: {}", loggerName); return false; } Object logLevelObj = getFieldVaulue(LOGBACK_CLASSIC_LEVEL, logLevelUpper); if (logLevelObj == null) { logger.warn("No existe tal log level: {}", logLevelUpper); return false; } Class<?>[] paramTypes = { logLevelObj.getClass() }; Object[] params = { logLevelObj }; Class<?> clz = Class.forName(LOGBACK_CLASSIC_LOGGER); Method method = clz.getMethod("setLevel", paramTypes); method.invoke(loggerObtained, params); logger.debug("Log level cambiado a {} para el logger '{}'", logLevelUpper, loggerName); return true; } catch (Exception e) { logger.warn("No se pudo asignar el log level a {} para el logger '{}'", logLevelUpper, loggerName); return false; } } /** * Obtener un logger concreto * * @return Logger */ public static LogModel getLogger(final String loggerName) { final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); ch.qos.logback.classic.Logger aux; LogModel result = new LogModel(); aux= lc.getLogger(loggerName); result.setLevelLog(aux.getEffectiveLevel().toString()); result.setNameLog(aux.getName()); return result; } /** * Devuelto todos los loggers configurados. * * @param showAll para devolver todos los loggers, no solo los configurados. * @return list de LogModel */ public static List<LogModel> getLoggers(final LoggerContext logContext ,final boolean showAll) { final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); final List<LogModel> loggers = new ArrayList<LogModel>(); LogModel aux; for (ch.qos.logback.classic.Logger log : lc.getLoggerList()) { if(showAll == false) { if(log.getLevel() != null || hasAppenders(log)) { aux= new LogModel(); aux.setLevelLog(log.getEffectiveLevel().toString()); aux.setNameLog(log.getName()); loggers.add(aux); } } else { aux= new LogModel(); aux.setLevelLog(log.getEffectiveLevel().toString()); aux.setNameLog(log.getName()); loggers.add(aux); } } return loggers; } /** * Comprueba si el logger seleccionado tiene appender * * @param logger el logger a probar * @return true si el logger tiene appenders. */ public static boolean hasAppenders(Logger logger) { Iterator<Appender<ILoggingEvent>> it =((ch.qos.logback.classic.Logger) logger).iteratorForAppenders(); return it.hasNext(); } private static Object getFieldVaulue(String fullClassName, String fieldName) { try { Class<?> clazz = Class.forName(fullClassName); Field field = clazz.getField(fieldName); return field.get(null); } catch (Exception ex) { return null; } } public static JQGridResponseDto<LogModel> getLoggersFiltered(LogModel filterLogModel ) { JQGridResponseDto<LogModel> resultado= new JQGridResponseDto<LogModel>(); List<LogModel> listalogs=getLoggers((LoggerContext) LoggerFactory.getILoggerFactory() ,false); List<LogModel> resulList= new ArrayList<LogModel>(); LogModel model; for (int i=0;i<listalogs.size();i++){ if (filterLogModel.getLevelLog()==null && filterLogModel.getNameLog()==null){ model= new LogModel(); model.setNameLog(listalogs.get(i).getNameLog()); model.setLevelLog(listalogs.get(i).getLevelLog()); resulList.add(model); }else if (filterLogModel.getLevelLog()!=null && filterLogModel.getNameLog()==null){ if(filterLogModel.getLevelLog().equalsIgnoreCase(listalogs.get(i).getLevelLog())){ model= new LogModel(); model.setNameLog(listalogs.get(i).getNameLog()); model.setLevelLog(listalogs.get(i).getLevelLog()); resulList.add(model); } }else if(filterLogModel.getLevelLog()==null && filterLogModel.getNameLog()!=null){ if (listalogs.get(i).getNameLog().toLowerCase().contains(filterLogModel.getNameLog().toLowerCase()) || listalogs.get(i).getNameLog().toLowerCase().contains(filterLogModel.getNameLog().toLowerCase())){ model= new LogModel(); model.setNameLog(listalogs.get(i).getNameLog()); model.setLevelLog(listalogs.get(i).getLevelLog()); resulList.add(model); } }else if (filterLogModel.getLevelLog()!=null && filterLogModel.getNameLog()!=null){ if (listalogs.get(i).getNameLog().toLowerCase().contains(filterLogModel.getNameLog().toLowerCase()) && filterLogModel.getLevelLog().equalsIgnoreCase(listalogs.get(i).getLevelLog())){ model= new LogModel(); model.setNameLog(listalogs.get(i).getNameLog()); model.setLevelLog(listalogs.get(i).getLevelLog()); resulList.add(model); } } } resultado.setRows(resulList); resultado.setRecords(resulList.size()); resultado.setTotal(new Long(resulList.size()), new Long(resulList.size())); return resultado; } }