Skip to content

Commit

Permalink
fixes #1102 update the LoggerGetLogContentHandler to return map and h… (
Browse files Browse the repository at this point in the history
#1103)

* fixes #1102 update the LoggerGetLogContentHandler to return map and handle parsing exception

* change the return to map of maps and filter record by level and loggerName
  • Loading branch information
stevehu authored Feb 7, 2022
1 parent d9a76ab commit a29824e
Showing 1 changed file with 53 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.networknt.logging.model.LoggerConfig;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.Headers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
Expand All @@ -26,32 +27,43 @@
*
*/
public class LoggerGetLogContentsHandler implements LightHttpHandler {

private static final Logger logger = LoggerFactory.getLogger(LoggerGetLogContentsHandler.class);
public static final String CONFIG_NAME = "logging";
private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ";
static final String STATUS_LOGGER_INFO_DISABLED = "ERR12108";
static final String STATUS_LOGGER_FILE_INVALID = "ERR12110";
static final String TIMESTAMP_LOG_KEY = "timestamp";
static final String LEVEL_LOG_KEY = "level";
static final String LOGGER_LOG_KEY = "logger";
static final String ROOT_LOGGER_NAME = "ROOT";
public static final int DEFAULT_LIMIT = 100;
public static final int DEFAULT_OFFSET = 0;

private static final ObjectMapper mapper = Config.getInstance().getMapper();

@Override
public void handleRequest(HttpServerExchange exchange) throws IOException, ParseException {
LoggerConfig config = (LoggerConfig) Config.getInstance().getJsonObjectConfig(CONFIG_NAME, LoggerConfig.class);
long requestTimeRangeStart = System.currentTimeMillis()- config.getLogStart();
long requestTimeRangeEnd = System.currentTimeMillis();
int limit = DEFAULT_LIMIT;
int offset = DEFAULT_OFFSET;

Map<String, Deque<String>> parameters = exchange.getQueryParameters();
String loggerName = parameters.containsKey("loggerName")? parameters.get("loggerName").getFirst() : null;
Level loggerLevel = parameters.containsKey("loggerLevel")? Level.toLevel(parameters.get("loggerLevel").getFirst(), Level.ERROR): Level.ERROR;

if (config.isEnabled()) {

if(parameters.containsKey("limit"))
limit = Integer.parseInt(parameters.get("limit").getFirst());
if(parameters.containsKey("offset"))
offset = Integer.parseInt(parameters.get("offset").getFirst());
if(parameters.containsKey("startTime"))
requestTimeRangeStart = Long.parseLong(parameters.get("startTime").getFirst());
if(parameters.containsKey("endTime"))
requestTimeRangeEnd = Long.parseLong(parameters.get("endTime").getFirst());

this.getLogEntries(requestTimeRangeStart, requestTimeRangeEnd, exchange, loggerName, loggerLevel);
if(logger.isDebugEnabled()) logger.debug("startTime = " + requestTimeRangeStart + " endTime = " + requestTimeRangeEnd + " loggerName = " + loggerName + " loggerLevel = " + loggerLevel + " offset = " + offset + " limit = " + limit);
this.getLogEntries(requestTimeRangeStart, requestTimeRangeEnd, exchange, loggerName, loggerLevel, offset, limit);
} else {
logger.error("Logging is disabled in logging.yml");
setExchangeStatus(exchange, STATUS_LOGGER_INFO_DISABLED);
Expand All @@ -67,17 +79,17 @@ public void handleRequest(HttpServerExchange exchange) throws IOException, Parse
* @param endTime - the request end time range when grabbing log entries
* @param exchange - HttpServer exchange
*/
private void getLogEntries(long startTime, long endTime, HttpServerExchange exchange, String loggerName, Level loggerLevel) throws IOException, ParseException {
List<Object> logContent = new ArrayList<>();
private void getLogEntries(long startTime, long endTime, HttpServerExchange exchange, String loggerName, Level loggerLevel, int offset, int limit) throws IOException, ParseException {
// the return is a map of list with key is the loggerName. There might be multiple of loggers in the logback.xml file.
Map<String, Map<String, Object>> logContent = new HashMap<>();

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
for (ch.qos.logback.classic.Logger log : lc.getLoggerList()) {

/* only parse the context if the log is valid */
if (log.getLevel() != null && log.getLevel().isGreaterOrEqual(loggerLevel) && (loggerName==null || log.getName().equalsIgnoreCase(loggerName))) {
List<Map<String, Object>> logs = this.parseLogContents(startTime, endTime, log);
if(!logs.isEmpty())
logContent.addAll(logs);
if (loggerName == null || log.getName().equalsIgnoreCase(loggerName)) {
Map<String, Object> logMap = this.parseLogContents(startTime, endTime, log, loggerLevel, offset, limit);
if(logMap.size() > 0 && (Integer)logMap.get("total") > 0)
logContent.put(log.getName(), logMap);
}
}
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, ContentType.APPLICATION_JSON.value());
Expand All @@ -91,16 +103,14 @@ private void getLogEntries(long startTime, long endTime, HttpServerExchange exch
* @param log - the log context
* @return - returns the string response for log entry request.
*/
private List<Map<String, Object>> parseLogContents(long startTime, long endTime, ch.qos.logback.classic.Logger log) throws IOException, ParseException {
List<Map<String, Object>> res = new ArrayList<>();
private Map<String, Object> parseLogContents(long startTime, long endTime, ch.qos.logback.classic.Logger log, Level loggerLevel, int offset, int limit) throws IOException, ParseException {
Map<String, Object> res = new HashMap<>();
for(Iterator<Appender<ILoggingEvent>> it = log.iteratorForAppenders(); it.hasNext();) {
Appender<ILoggingEvent> logEvent = it.next();
if(logEvent.getClass().equals(RollingFileAppender.class)) {
FileReader reader = new FileReader(((RollingFileAppender<ILoggingEvent>) logEvent).getFile());
BufferedReader bufferedReader = new BufferedReader(reader);
List<Map<String, Object>> parsedLogLines = this.parseAppenderFile(bufferedReader, startTime, endTime);
if(!parsedLogLines.isEmpty())
res.addAll(parsedLogLines);
res = this.parseAppenderFile(bufferedReader, startTime, endTime, log, loggerLevel, offset, limit);
}
}
return res;
Expand All @@ -116,23 +126,36 @@ private List<Map<String, Object>> parseLogContents(long startTime, long endTime,
* @throws ParseException - exception when parsing the file
* @throws IOException - exception when trying to load the file
*/
private List<Map<String, Object>> parseAppenderFile(BufferedReader bufferedReader, long startTime, long endTime) throws ParseException, IOException {
List<Map<String, Object>> res = new ArrayList<>();
private Map<String, Object> parseAppenderFile(BufferedReader bufferedReader, long startTime, long endTime, ch.qos.logback.classic.Logger log, Level loggerLevel, int offset, int limit) throws ParseException, IOException {
Map<String, Object> logMap = new HashMap<>();
List<Map<String, Object>> logs = new ArrayList<>();
int index = 0;
String currentLine;
while((currentLine=bufferedReader.readLine()) != null) {

@SuppressWarnings("unchecked")
Map<String,Object> logLine = mapper.readValue(currentLine, Map.class);

/* Grab the log entry as a map, and check to see if the timestamp falls within range of startTime and endTime */
if(logLine != null && logLine.containsKey(TIMESTAMP_LOG_KEY)) {
SimpleDateFormat timestampFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);
long logTime = timestampFormat.parse(logLine.get(TIMESTAMP_LOG_KEY).toString()).toInstant().toEpochMilli();
if(logTime > startTime && logTime < endTime) {
res.add(logLine);
try {
while ((currentLine = bufferedReader.readLine()) != null) {
@SuppressWarnings("unchecked")
Map<String, Object> logLine = mapper.readValue(currentLine, Map.class);
/* Grab the log entry as a map, and check to see if the timestamp falls within range of startTime and endTime */
if (logLine != null && logLine.containsKey(TIMESTAMP_LOG_KEY) && logLine.containsKey(LEVEL_LOG_KEY) && logLine.containsKey(LOGGER_LOG_KEY)) {
SimpleDateFormat timestampFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);
long logTime = timestampFormat.parse(logLine.get(TIMESTAMP_LOG_KEY).toString()).toInstant().toEpochMilli();
String levelStr = (String)logLine.get(LEVEL_LOG_KEY);
Level logLevel = Level.valueOf(levelStr.trim());
String logLogger = (String)logLine.get(LOGGER_LOG_KEY);
if (logTime > startTime && logTime < endTime && logLevel.isGreaterOrEqual(loggerLevel) && (log.getName().equals(ROOT_LOGGER_NAME) || logLogger.startsWith(log.getName()))) {
if(index >= offset && logs.size() < limit) {
logs.add(logLine);
}
// the total number of entries between the startTime and endTime.
index++;
}
}
}
} catch (Exception e) {
// any exception here might be the format is not JSON for the logger. For example Audit logger etc. Ignore it.
}
return res;
logMap.put("total", index);
logMap.put("logs", logs);
return logMap;
}
}

0 comments on commit a29824e

Please sign in to comment.