/* * Copyright (c) 2002 Cunningham & Cunningham, Inc. * Copyright (c) 2009-2015 by Jochen Wierum & Cologne Intelligence * * This file is part of FitGoodies. * * FitGoodies is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FitGoodies is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with FitGoodies. If not, see <http://www.gnu.org/licenses/>. */ package de.cologneintelligence.fitgoodies.log4j; import de.cologneintelligence.fitgoodies.Fixture; import de.cologneintelligence.fitgoodies.htmlparser.FitCell; import de.cologneintelligence.fitgoodies.util.FitUtils; import org.apache.log4j.Appender; import org.apache.log4j.spi.AppenderAttachable; import java.util.List; import java.util.Map; /** * Fixture to analyze captured log data. Log messages can be analyzed by searing * strings in their messages and exception information.<br> * The fixture contains 4 rows: the name of the logger, the name of the appender, * a command which can have parameters, and a expression to search. The parameter * column supports Cross References. * Only captured loggers can be analyzed. To capture loggers, see {@link SetupFixture}. * <p> * The root logger is named "rootLogger". * Valid parameters are "Thread" and "MinLevel". * <p> * Example: * <table border="1" summary=""><tr><td>fitgoodies.log4j.LogFixture</td></tr> * <tr><td>rootLogger</td><td>R</td><td>contains</td><td>successfully initialized</td></tr> * <tr><td>rootLogger</td><td>R</td><td>notContains</td><td>critical error</td></tr> * <tr> * <td>org.example.MyClass</td> * <td>stdout</td> * <td>containsException</td> * <td>IllegalArgumentException</td> * </tr> * <tr> * <td>org.example.MyClass</td> * <td>stdout</td> * <td>notContainsException</td> * <td>not found</td> * </tr> * <tr> * <td>org.example.MyClass</td> * <td>stdout</td> * <td>contains[Thread = main, MinLevel = Error]</td> * <td>timeout</td> * </tr> * </table> */ public class LogFixture extends Fixture { private final LoggerProvider loggerProvider; private final LogEventAnalyzerFactory logEventAnalyzerFactory; private static final int LOGGER_COLUMN = 0; private static final int APPENDER_COLUMN = 1; private static final int COMMAND_COLUMN = 2; private static final int CHECK_EXPRESSION_COLUMN = 3; private CaptureAppender appender; private List<FitCell> cells; /** * Initializes a new {@code LogFixture} using a {@link LoggerProvider} * and a {@link LogEventAnalyzerFactory}. * * @see #LogFixture(LoggerProvider, LogEventAnalyzerFactory) * LogFixture(LoggerProvider, CellArgumentParserFactory, LogEventAnalyzerFactory) */ public LogFixture() { this(new LoggerProvider(), new LogEventAnalyzerFactory()); } /** * Initializes a new LogFixture. * * @param logs {@code LoggerProvider} to receive loggers. * @param logEventAnalyzerFactory {@code LogEventAnalyzerFactory} * to analyze log entries */ public LogFixture(final LoggerProvider logs, final LogEventAnalyzerFactory logEventAnalyzerFactory) { this.loggerProvider = logs; this.logEventAnalyzerFactory = logEventAnalyzerFactory; } /** * Processes the table row {@code cells}. * * @param cells row to parse and process */ @Override protected void doCells(List<FitCell> cells) { this.cells = cells; this.appender = getAppender(); if (appender != null) { try { executeCommand(); } catch (final IllegalArgumentException e) { cells.get(COMMAND_COLUMN).exception("Illegal Format"); } } } private void executeCommand() { Map<String, String> parameters = FitUtils.extractCellParameterMap(cells.get(COMMAND_COLUMN)); String command = cells.get(COMMAND_COLUMN).getFitValue(); getExpressionCellContent(); dispatchCommand(command, parameters); } private String getExpressionCellContent() { FitCell cell = cells.get(CHECK_EXPRESSION_COLUMN); return validator.preProcess(cell); } private CaptureAppender getAppender() { String loggerName = cells.get(LOGGER_COLUMN).getFitValue(); AppenderAttachable logger = getLogger(loggerName); if (logger == null) { cells.get(LOGGER_COLUMN).exception("Invalid logger"); return null; } String appenderName = cells.get(APPENDER_COLUMN).getFitValue(); String captureAppenderName = CaptureAppender.getAppenderNameFor(appenderName); final Appender appender = logger.getAppender(captureAppenderName); if (appender == null) { cells.get(APPENDER_COLUMN).exception("Invalid appender or appender not captured"); return null; } return (CaptureAppender) appender; } private AppenderAttachable getLogger(String loggerName) { if ("rootLogger".equalsIgnoreCase(loggerName)) { return loggerProvider.getRootLogger(); } else { return loggerProvider.getLogger(loggerName); } } private void dispatchCommand(String command, Map<String, String> parameters) { FitCell cell = cells.get(CHECK_EXPRESSION_COLUMN); LogEventAnalyzer analyzer = logEventAnalyzerFactory.getLogEventAnalyzerFor( validator, cell, appender.getAllEvents()); if ("contains".equalsIgnoreCase(command)) { analyzer.processContains(parameters); } else if ("notContains".equalsIgnoreCase(command)) { analyzer.processNotContains(parameters); } else if ("containsException".equalsIgnoreCase(command)) { analyzer.processContainsException(parameters); } else if ("notContainsException".equalsIgnoreCase(command)) { analyzer.processNotContainsException(parameters); } else { cells.get(COMMAND_COLUMN).exception("unknown command"); } } }