io.cloudslang.lang.logging.LoggingServiceImpl Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* (c) Copyright 2016 Hewlett-Packard Development Company, L.P.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License v2.0 which accompany this distribution.
*
* The Apache License is available at
* http://www.apache.org/licenses/LICENSE-2.0
*
*******************************************************************************/
package io.cloudslang.lang.logging;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.DisposableBean;
import javax.annotation.PostConstruct;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.Executors.newFixedThreadPool;
import static org.apache.logging.log4j.Level.DEBUG;
import static org.apache.logging.log4j.Level.ERROR;
import static org.apache.logging.log4j.Level.FATAL;
import static org.apache.logging.log4j.Level.INFO;
import static org.apache.logging.log4j.Level.TRACE;
import static org.apache.logging.log4j.Level.WARN;
/**
* Implements a logging service that is asynchronous with respect to the caller
*/
public class LoggingServiceImpl implements LoggingService, DisposableBean {
private static final Logger logger = LogManager.getLogger(LoggingServiceImpl.class);
private ThreadPoolExecutor singleThreadExecutor;
@PostConstruct
public void initialize() {
singleThreadExecutor = (ThreadPoolExecutor) newFixedThreadPool(1); // one thread only
}
@Override
public Future> logEvent(Level level, String message) {
return doLogEvent(level, message, null);
}
@Override
public Future> logEvent(Level level, String message, Throwable throwable) {
return doLogEvent(level, message, throwable);
}
@Override
public void destroy() throws Exception {
singleThreadExecutor.shutdown();
singleThreadExecutor = null;
}
private Future> doLogEvent(Level level, String message, Throwable throwable) {
try {
return doSubmit(level, message, throwable);
} catch (RejectedExecutionException rejectedExecutionException) {
try {
return doSubmit(level, message, throwable);
} catch (RejectedExecutionException rejectedExecutionException2) {
// try twice and fail
}
}
return null;
}
private Future> doSubmit(Level level, String message, Throwable throwable) {
return singleThreadExecutor.submit((throwable != null) ? new LoggingDetailsRunnable(level, message, throwable)
: new LoggingDetailsRunnable(level, message));
}
@Override
public void waitForAllLogTasksToFinish() {
try {
singleThreadExecutor.shutdown();
singleThreadExecutor.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException ignore) {
}
}
static class LoggingDetailsRunnable implements Runnable {
private final Level level;
private final String message;
private final Throwable exception;
LoggingDetailsRunnable(Level level, String message, Throwable t) {
this.level = level;
this.message = message;
this.exception = t;
}
LoggingDetailsRunnable(Level level, String message) {
this(level, message, null);
}
@Override
public void run() {
try {
String localMessage = StringUtils.isEmpty(message) ? "" : message;
final Throwable throwable = exception;
if (exception == null) {
if (level == TRACE) {
if (logger.isTraceEnabled()) {
logger.trace(localMessage);
}
} else if (level == DEBUG) {
if (logger.isDebugEnabled()) {
logger.debug(localMessage);
}
} else if (level == INFO) {
logger.info(localMessage);
} else if (level == WARN) {
logger.warn(localMessage);
} else if (level == ERROR) {
logger.error(localMessage);
} else if (level == FATAL) {
logger.fatal(localMessage);
}
} else {
if (level == TRACE) {
if (logger.isTraceEnabled()) {
logger.trace(localMessage, throwable);
}
} else if (level == DEBUG) {
if (logger.isDebugEnabled()) {
logger.debug(localMessage, throwable);
}
} else if (level == INFO) {
logger.info(localMessage, throwable);
} else if (level == WARN) {
logger.warn(localMessage, throwable);
} else if (level == ERROR) {
logger.error(localMessage, throwable);
} else if (level == FATAL) {
logger.fatal(localMessage, throwable);
}
}
} catch (Exception ignore) {
// so that this thread does not die
}
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
LoggingDetailsRunnable rhs = (LoggingDetailsRunnable) obj;
return new EqualsBuilder()
.append(this.level, rhs.level)
.append(this.message, rhs.message)
.append(this.exception, rhs.exception)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder()
.append(level)
.append(message)
.append(exception)
.toHashCode();
}
}
}