All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.artos.framework.infra.OrganisedLog Maven / Gradle / Ivy

Go to download

The Artos "ART OF SYSTEM TESTING" is a framework designed for regression, functional, integration, end to end and/or unit testing.

There is a newer version: 1.0.02
Show newest version
/*******************************************************************************
 * Copyright (C) 2018-2019 Arpit Shah and Artos Contributors
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/
package com.artos.framework.infra;

import java.io.File;
import java.util.List;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.AppenderRefComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;

import com.artos.framework.FWStaticStore;
import com.artos.framework.parser.TestSuite;

/**
 * This class is responsible for initialising all log streams which may require
 * during test suite execution
 */
class OrganisedLog {

	private LoggerContext loggerContext;
	private String logBaseDir;
	public static String GENERAL_LOGGER_NAME_STX = "General_";
	public static String SUMMARY_LOGGER_NAME_STX = "Summary_";
	public static String REALTIME_LOGGER_NAME_STX = "RealTime_";

	/**
	 * Constructor responsible for creating log base directory and Log4J
	 * loggerContext using Framework configuration and TestSuite information
	 * 
	 * @param logDirPath
	 *            Log base directory absolute or reference path
	 * @param testCaseFQCN
	 *            Test case fully qualified class name (Example :
	 *            com.test.unit.Abc)
	 * @param enableLogDecoration
	 *            Enables/disable log decoration (Time-stamp, source package,
	 *            thread number etc..)
	 * @param enableTextLog
	 *            Enables/disable text log
	 * @param enableHTMLLog
	 *            Enable/disable HTML log
	 * @param testSuiteList
	 *            list of testSuite (if any) or pass null
	 */
	public OrganisedLog(String logDirPath, String testCaseFQCN, boolean enableLogDecoration, boolean enableTextLog, boolean enableHTMLLog,
			List testSuiteList) {

		// System.setProperty("log4j.configurationFile",
		// "./conf/log4j2.properties");
		
		if(null == logDirPath){
			logDirPath = FWStaticStore.LOG_BASE_DIR;
		}

		if (!logDirPath.endsWith("/") && !logDirPath.endsWith("\\")) {
			logDirPath = logDirPath + File.separator;
		}
		
		setLogBaseDir(logDirPath + testCaseFQCN + File.separator);
		setLoggerContext(dynamicallyConfigureLog4J(getLogBaseDir(), testCaseFQCN, enableLogDecoration, enableTextLog, enableHTMLLog, testSuiteList));
	}

	/**
	 * Dynamically Generates and applies Log4J configuration XML as per test
	 * suite requirement
	 * 
	 * @param baseDir
	 *            Log file root directory
	 * @param testFQCN
	 *            Log file name
	 * @param enableLogDecoration
	 *            Enable/disable log decoration (Time-stamp, source package,
	 *            thread number etc..)
	 * @param enableTextLog
	 *            Enables/disable text log
	 * @param enableHTMLLog
	 *            Enable/disable HTML log
	 * @param testSuiteList
	 *            testSuiteLite (if any) or pass null
	 * @return {@code LoggerContext}
	 * 
	 * @see LoggerContext
	 */
	private LoggerContext dynamicallyConfigureLog4J(String baseDir, String testFQCN, boolean enableLogDecoration, boolean enableTextLog,
			boolean enableHTMLLog, List testSuiteList) {

		int numberOfAppenders = 1;

		if (!baseDir.endsWith("/") && !baseDir.endsWith("\\")) {
			baseDir = baseDir + File.separator;
		}

		if (null != testSuiteList && !testSuiteList.isEmpty()) {
			numberOfAppenders = testSuiteList.size();
		}

		ConfigurationBuilder builder = ConfigurationBuilderFactory.newConfigurationBuilder();
		builder.setStatusLevel(Level.WARN);
		builder.setConfigurationName("RollingBuilder");

		// Log Layout for general logs
		LayoutComponentBuilder logFileLayout = builder.newLayout("PatternLayout");
		// Log Layout for real time logs
		LayoutComponentBuilder realTimeLogLayout = builder.newLayout("PatternLayout");
		// Log Layout for summary file
		LayoutComponentBuilder summaryFileLayout = builder.newLayout("PatternLayout");
		/*
		* @formatter:off
		*
		* %highlight{} Highlights log levels in different colour
		* [%-5level] = Log level upto 5 char max
		* [%d{yyyy-MM-dd_HH:mm:ss.SSS}] = Date and time 
		* [%t] = Thread number
		* [%F] = File where logs are coming from
		* [%M] = Method which generated log
		* [%c{-1}] = ClassName which issued logCommand 
		* %msg = Actual msg to be logged 
		* %n = new line
		* %throwable = log exception
		* 
		* @formatter:on
		*/
		{
			if (enableLogDecoration) {
				logFileLayout.addAttribute("pattern", "[%-5level][%d{yyyy-MM-dd_HH:mm:ss.SSS}][%t][%F][%M][%c{1}] - %msg%n%throwable");
			} else {
				logFileLayout.addAttribute("pattern", "%msg%n%throwable");
			}

			realTimeLogLayout.addAttribute("pattern", "[%-5level][%d{yyyy-MM-dd_HH:mm:ss.SSS}][%t] - %msg%n%throwable");
			summaryFileLayout.addAttribute("pattern", "%msg%n%throwable");
		}

		// HTML Log Layout for general logs
		LayoutComponentBuilder htmlLogFileLayout = builder.newLayout("HTMLLayout");
		htmlLogFileLayout.addAttribute("title", "Test Logs");
		// expensive if enabled
		htmlLogFileLayout.addAttribute("locationInfo", false);
		htmlLogFileLayout.addAttribute("fontSize", "small");

		// HTML Log Layout for summary logs
		LayoutComponentBuilder htmlSummaryFileLayout = builder.newLayout("HTMLLayout");
		htmlSummaryFileLayout.addAttribute("title", "Test Summary");
		// expensive if enabled
		htmlSummaryFileLayout.addAttribute("locationInfo", false);
		htmlLogFileLayout.addAttribute("fontSize", "small");

		// HTML Log Layout for realtime logs
		LayoutComponentBuilder htmlrealTimeLogLayout = builder.newLayout("HTMLLayout");
		htmlrealTimeLogLayout.addAttribute("title", "Test Summary");
		// expensive if enabled
		htmlrealTimeLogLayout.addAttribute("locationInfo", false);
		htmlrealTimeLogLayout.addAttribute("fontSize", "small");

		// File size based rollver Trigger Policy
		ComponentBuilder triggeringPolicy = builder.newComponent("Policies");
		triggeringPolicy.addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "10MB"));

		// create a console appender
		{
			AppenderComponentBuilder appenderBuilder1 = builder.newAppender("console-log", "CONSOLE");
			appenderBuilder1.addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
			appenderBuilder1.add(logFileLayout);
			builder.add(appenderBuilder1);
		}

		for (int i = 0; i < numberOfAppenders; i++) {
			// retrieve file prefix
			String logFilePrefix = (testSuiteList != null ) ? testSuiteList.get(i).getSuiteName() + "_" : ""; 
			String logFileName = testFQCN + "_" + i + "_" + logFilePrefix + System.currentTimeMillis();

			// create a rolling file appender for general logs
			{
				// Text
				AppenderComponentBuilder appenderBuilder2 = builder.newAppender("all-log-text" + i, "RollingFile");
				appenderBuilder2.addAttribute("fileName", baseDir + logFileName + "-all.log");
				appenderBuilder2.addAttribute("filePattern", baseDir + logFileName + "-all-%d{yyyy-MM-dd_HH.mm.ss.SSS}.log");
				appenderBuilder2.add(logFileLayout);
				appenderBuilder2.addComponent(triggeringPolicy);
				if (enableTextLog) {
					builder.add(appenderBuilder2);
				}

				// HTML
				AppenderComponentBuilder appenderBuilder3 = builder.newAppender("all-log-html" + i, "RollingFile");
				appenderBuilder3.addAttribute("fileName", baseDir + logFileName + "-all.html");
				appenderBuilder3.addAttribute("filePattern", baseDir + logFileName + "-all-%d{yyyy-MM-dd_HH.mm.ss.SSS}.html");
				appenderBuilder3.add(htmlLogFileLayout);
				appenderBuilder3.addComponent(triggeringPolicy);
				if (enableHTMLLog) {
					builder.add(appenderBuilder3);
				}
			}

			// create a rolling file appender for summary
			{
				// Text
				AppenderComponentBuilder appenderBuilder6 = builder.newAppender("summary-log-text" + i, "RollingFile");
				appenderBuilder6.addAttribute("fileName", baseDir + logFileName + "-summary.log");
				appenderBuilder6.addAttribute("filePattern", baseDir + logFileName + "-summary-%d{yyyy-MM-dd_HH.mm.ss.SSS}.log");
				appenderBuilder6.add(summaryFileLayout);
				appenderBuilder6.addComponent(triggeringPolicy);
				if (enableTextLog) {
					builder.add(appenderBuilder6);
				}

				// HTML
				AppenderComponentBuilder appenderBuilder7 = builder.newAppender("summary-log-html" + i, "RollingFile");
				appenderBuilder7.addAttribute("fileName", baseDir + logFileName + "-summary.html");
				appenderBuilder7.addAttribute("filePattern", baseDir + logFileName + "-summary-%d{yyyy-MM-dd_HH.mm.ss.SSS}.html");
				appenderBuilder7.add(htmlSummaryFileLayout);
				appenderBuilder7.addComponent(triggeringPolicy);
				if (enableHTMLLog) {
					builder.add(appenderBuilder7);
				}
			}

			// create a rolling file appender for real time logs
			{
				// Text
				AppenderComponentBuilder appenderBuilder8 = builder.newAppender("realtime-log-text" + i, "RollingFile");
				appenderBuilder8.addAttribute("fileName", baseDir + logFileName + "-realtime.log");
				appenderBuilder8.addAttribute("filePattern", baseDir + logFileName + "-realtime-%d{yyyy-MM-dd_HH.mm.ss.SSS}.log");
				appenderBuilder8.add(realTimeLogLayout);
				appenderBuilder8.addComponent(triggeringPolicy);
				if (enableTextLog) {
					builder.add(appenderBuilder8);
				}

				// HTML
				AppenderComponentBuilder appenderBuilder9 = builder.newAppender("realtime-log-html" + i, "RollingFile");
				appenderBuilder9.addAttribute("fileName", baseDir + logFileName + "-realtime.html");
				appenderBuilder9.addAttribute("filePattern", baseDir + logFileName + "-realtime-%d{yyyy-MM-dd_HH.mm.ss.SSS}.html");
				appenderBuilder9.add(htmlrealTimeLogLayout);
				appenderBuilder9.addComponent(triggeringPolicy);
				if (enableHTMLLog) {
					builder.add(appenderBuilder9);
				}
			}

			String generalLoggerName = GENERAL_LOGGER_NAME_STX + i;
			String summaryLoggerName = SUMMARY_LOGGER_NAME_STX + i;
			String realtimeLoggerName = REALTIME_LOGGER_NAME_STX + i;

			// create the new logger
			Level loglevel = FWStaticStore.frameworkConfig.getLoglevelFromXML();
			LoggerComponentBuilder generalLoggerBuilder = builder.newLogger(generalLoggerName, loglevel);
			{
				generalLoggerBuilder.addAttribute("additivity", false);
				AppenderRefComponentBuilder appendRef1 = builder.newAppenderRef("console-log");
				appendRef1.addAttribute("level", Level.ALL);
				AppenderRefComponentBuilder appendRef2 = builder.newAppenderRef("all-log-text" + i);
				appendRef2.addAttribute("level", Level.ALL);
				AppenderRefComponentBuilder appendRef3 = builder.newAppenderRef("all-log-html" + i);
				appendRef3.addAttribute("level", Level.ALL);

				generalLoggerBuilder.add(appendRef1);

				if (enableTextLog) {
					generalLoggerBuilder.add(appendRef2);
				}
				if (enableHTMLLog) {
					generalLoggerBuilder.add(appendRef3);
				}
			}

			// create new logger for summary
			LoggerComponentBuilder summaryLoggerBuilder = builder.newLogger(summaryLoggerName, Level.ALL);
			summaryLoggerBuilder.addAttribute("additivity", false);
			{
				AppenderRefComponentBuilder appendRef11 = builder.newAppenderRef("summary-log-text" + i);
				appendRef11.addAttribute("level", Level.ALL);
				AppenderRefComponentBuilder appendRef12 = builder.newAppenderRef("summary-log-html" + i);
				appendRef12.addAttribute("level", Level.ALL);

				if (enableTextLog) {
					summaryLoggerBuilder.add(appendRef11);
				}
				if (enableHTMLLog) {
					summaryLoggerBuilder.add(appendRef12);
				}
			}

			// create new logger for real time logs
			LoggerComponentBuilder realTimeLoggerBuilder = builder.newLogger(realtimeLoggerName, Level.ALL);
			realTimeLoggerBuilder.addAttribute("additivity", false);
			{
				AppenderRefComponentBuilder appendRef21 = builder.newAppenderRef("realtime-log-text" + i);
				appendRef21.addAttribute("level", Level.ALL);
				AppenderRefComponentBuilder appendRef22 = builder.newAppenderRef("realtime-log-html" + i);
				appendRef22.addAttribute("level", Level.ALL);

				if (enableTextLog) {
					realTimeLoggerBuilder.add(appendRef21);
				}
				if (enableHTMLLog) {
					realTimeLoggerBuilder.add(appendRef22);
				}
			}

			builder.add(generalLoggerBuilder);
			builder.add(summaryLoggerBuilder);
			builder.add(realTimeLoggerBuilder);
		}

		// create root logger
		RootLoggerComponentBuilder rootlogggerBuilder = builder.newRootLogger(Level.ALL);
		rootlogggerBuilder.addAttribute("additivity", false);
		{
			AppenderRefComponentBuilder appendRef0 = builder.newAppenderRef("console-log");
			rootlogggerBuilder.add(appendRef0);
		}

		builder.add(rootlogggerBuilder);

		// System.out.println(builder.toXmlConfiguration().toString());

		LoggerContext loggerContext = Configurator.initialize(builder.build());
		// Print logger xml to log file
		loggerContext.getLogger(GENERAL_LOGGER_NAME_STX + 0).trace(builder.toXmlConfiguration().toString());

		return loggerContext;
	}

	/** Returns Log Files Base Directory */
	public String getLogBaseDir() {
		return logBaseDir;
	}

	/** Sets Log Files Base Directory */
	protected void setLogBaseDir(String logBaseDir) {
		this.logBaseDir = logBaseDir;
	}

	public LoggerContext getLoggerContext() {
		return loggerContext;
	}

	protected void setLoggerContext(LoggerContext loggerContext) {
		this.loggerContext = loggerContext;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy