org.evosuite.utils.LoggingUtils Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2010-2018 Gordon Fraser, Andrea Arcuri and EvoSuite
* contributors
*
* This file is part of EvoSuite.
*
* EvoSuite is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* EvoSuite 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
* Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with EvoSuite. If not, see .
*/
package org.evosuite.utils;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.evosuite.PackageInfo;
import org.evosuite.Properties;
import org.evosuite.runtime.util.AtMostOnceLogger;
import org.evosuite.runtime.util.Inputs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;
/**
* this class is used to get help on some customization of logging facility
*
* @author arcuri
*/
public class LoggingUtils {
private static final Logger logger = LoggerFactory.getLogger(LoggingUtils.class);
/** Constant DEFAULT_OUT
*/
public static final PrintStream DEFAULT_OUT = System.out;
/** Constant DEFAULT_ERR
*/
public static final PrintStream DEFAULT_ERR = System.err;
public static final String USE_DIFFERENT_LOGGING_XML_PARAMETER = "use_different_logback";
private static final String EVO_LOGGER = "evo_logger";
/** Constant latestOut
*/
protected static PrintStream latestOut = null;
/** Constant latestErr
*/
protected static PrintStream latestErr = null;
/** Constant LOG_TARGET="log.target"
*/
public static final String LOG_TARGET = "log.target";
/** Constant LOG_LEVEL="log.level"
*/
public static final String LOG_LEVEL = "log.level";
private static volatile boolean alreadyMuted = false;
private ServerSocket serverSocket;
private final ExecutorService logConnections = Executors.newSingleThreadExecutor();
private final ExecutorService logHandler = Executors.newCachedThreadPool();
/**
*
* Constructor for LoggingUtils.
*
*/
public LoggingUtils() {
}
/**
* Rather use AtMostOnceLogger directly
*
* @param logger
* @param message
*/
@Deprecated
public static void logWarnAtMostOnce(Logger logger, String message){
AtMostOnceLogger.warn(logger, message);
}
/**
* Rather use AtMostOnceLogger directly
*
* @param logger
* @param message
*/
@Deprecated
public static void logErrorAtMostOnce(Logger logger, String message){
AtMostOnceLogger.error(logger, message);
}
/**
*
* getEvoLogger
*
*
* @return a {@link org.slf4j.Logger} object.
*/
public static Logger getEvoLogger() {
return LoggerFactory.getLogger(EVO_LOGGER);
}
/**
*
* startLogServer
*
*
* @return a boolean.
*/
public boolean startLogServer() {
try {
serverSocket = new ServerSocket();
serverSocket.bind(null);
logConnections.submit(new Callable() {
@Override
public Void call() throws Exception {
while (!isServerClosed()) {
final Socket socket = serverSocket.accept();
logHandler.submit(new Callable() {
@Override
public Void call() {
try {
ObjectInputStream ois = new ObjectInputStream(
new BufferedInputStream(
socket.getInputStream()));
while (socket != null && socket.isConnected()
&& !isServerClosed()) {
ILoggingEvent event = (ILoggingEvent) ois.readObject();
/*
* We call the appender regardless of level in the master (ie, if the level was
* set in the client and we receive a log message, then we just print it).
* Note: we use
* the local logger with same name just for formatting reasons
*/
ch.qos.logback.classic.Logger remoteLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(event.getLoggerName());
remoteLogger.callAppenders(event);
}
} catch (java.net.SocketException se) {
/*
* FIXME: this can happen if client dies or is stopped by master with "destroy" in Windows. It is not a big problem,
* but anyway how we stop clients will need to be refactored.
* It can also happen if client just crash. As we already report such info in ExternalProcessHandler, we do not need to
* log it here
*/
} catch (java.io.UTFDataFormatException utfe) {
//as above
} catch (java.io.EOFException eof) {
//this is normal, do nothing
} catch (java.io.InvalidClassException ice) {
/*
* TODO: unclear why it happens... need more investigation
*/
logger.error("Error in de-serialized log event: " + ice.getMessage());
} catch (Exception e) {
logger.error("Problem in reading loggings", e);
}
return null;
}
});
}
return null;
}
});
return true;
} catch (Exception e) {
logger.error("Can't start log server", e);
return false;
}
}
/**
*
* isServerClosed
*
*
* @return a boolean.
*/
public boolean isServerClosed() {
return serverSocket == null || serverSocket.isClosed() || !serverSocket.isBound();
}
/**
*
* getLogServerPort
*
*
* @return a {@link java.lang.Integer} object.
*/
public Integer getLogServerPort() {
if (isServerClosed()) {
return null;
}
return serverSocket.getLocalPort();
}
/**
*
* closeLogServer
*
*/
public void closeLogServer() {
if (serverSocket != null && !serverSocket.isClosed()) {
try {
serverSocket.close();
} catch (IOException e) {
logger.error("Error in closing log server", e);
}
serverSocket = null;
}
}
/**
* Redirect current System.out and System.err to a buffer
*/
public static void muteCurrentOutAndErrStream() {
if (alreadyMuted) {
return;
}
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
PrintStream outStream = new PrintStream(byteStream);
latestOut = System.out;
latestErr = System.err;
System.setOut(outStream);
System.setErr(outStream);
alreadyMuted = true;
}
/**
* Allow again printing to previous streams that were muted
*/
public static void restorePreviousOutAndErrStream() {
if (!alreadyMuted) {
return;
}
System.setOut(latestOut);
System.setErr(latestErr);
alreadyMuted = false;
}
/**
* Allow again printing to System.out and System.err
*/
public static void restoreDefaultOutAndErrStream() {
System.setOut(DEFAULT_OUT);
System.setErr(DEFAULT_ERR);
}
/**
* If the application is using a SLF4 compliant logging framework, check
* if it has been configured. If so, keep the logging as it is.
* On the other hand, if no configuration/framework is used, then mute
* the default logging (Logback) of the EvoSuite modules.
*
*/
public static void setLoggingForJUnit(){
if(Properties.ENABLE_ASSERTS_FOR_EVOSUITE){
//if we are debugging, we don't want to switch off the logging
return;
}
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
if(isDefaultLoggingConfiguration(context)){
Logger root = LoggerFactory.getLogger(PackageInfo.getEvoSuitePackage());
if(root != null && root instanceof ch.qos.logback.classic.Logger){
((ch.qos.logback.classic.Logger) root).setLevel(Level.OFF);
}
}
}
private static boolean isDefaultLoggingConfiguration(LoggerContext context){
// TODO: Find better way to find out the default configuration
return context.getName().equals("default");
}
/**
* Load the EvoSuite xml configuration file for Logback, unless a
* non-default one is already in use. The file has to be on the classpath.
*/
public static boolean loadLogbackForEvoSuite() {
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
boolean isOK = true;
// Only overrule default configurations
if (isDefaultLoggingConfiguration(context)) {
isOK = changeLogbackFile(getLogbackFileName());
StatusPrinter.printInCaseOfErrorsOrWarnings(context);
}
return isOK;
}
public static boolean changeLogbackFile(String resourceFilePath){
Inputs.checkNull(resourceFilePath);
if(!resourceFilePath.endsWith(".xml")){
throw new IllegalArgumentException("Logback file name does not terminate with '.xml'");
}
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
try {
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(context);
final String xmlFileName = resourceFilePath;
InputStream f = null;
if (LoggingUtils.class.getClassLoader() != null) {
f = LoggingUtils.class.getClassLoader().getResourceAsStream(xmlFileName);
} else {
// If the classloader is null, then that means EvoSuite.class was loaded
// with the bootstrap classloader, so let's try that as well
f = ClassLoader.getSystemClassLoader().getResourceAsStream(xmlFileName);
}
if (f == null) {
String msg = xmlFileName + " not found on classpath";
System.err.println(msg);
logger.error(msg);
return false;
} else {
context.reset();
configurator.doConfigure(f);
}
} catch (JoranException je) {
// StatusPrinter will handle this
return false;
}
return true;
}
public static String getLogbackFileName() {
return System.getProperty(USE_DIFFERENT_LOGGING_XML_PARAMETER, "logback-evosuite.xml");
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy