/*
* Copyright to the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rioproject.logging.logback;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.AppenderBase;
import org.rioproject.logging.ServiceLogEventHandler;
import org.rioproject.logging.ServiceLogEventPublisher;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.LogRecord;
/**
* An implementation of the {@link org.rioproject.logging.ServiceLogEventHandler} for Logback.
*
* @author Dennis Reedy
*/
@SuppressWarnings("unused")
public class LogbackServiceLogEventHandler extends AppenderBase<ILoggingEvent> implements ServiceLogEventHandler {
private Level publishOnLevel = Level.ERROR;
private final Collection<String> publishableLoggers = Collections.synchronizedCollection(new ArrayList<String>());
private ServiceLogEventPublisher eventPublisher;
private final BlockingQueue<ILoggingEvent> eventQ = new LinkedBlockingQueue<ILoggingEvent>();
public LogbackServiceLogEventHandler() {
Executor eventExecutor = Executors.newSingleThreadExecutor();
eventExecutor.execute(new CheckThenPublish());
start();
}
@Override
public void setServiceLogEventPublisher(ServiceLogEventPublisher publisher) {
this.eventPublisher = publisher;
}
@Override
public ServiceLogEventPublisher getServiceLogEventPublisher() {
return eventPublisher;
}
@Override
public void setPublishOnLevel(String sLevel) {
this.publishOnLevel = Level.toLevel(sLevel);
}
@Override
public void addPublishableLogger(String publishableLogger) {
publishableLoggers.add(publishableLogger);
}
@Override
protected void append(ILoggingEvent loggingEvent) {
if(eventPublisher==null)
return;
try {
eventQ.put(loggingEvent);
} catch (InterruptedException e) {
System.err.println(String.format("[%d] %s interrupted",
Thread.currentThread().getId(),
LogbackServiceLogEventHandler.class.getName()));
}
}
private String getJULLevel(Level level) {
String julLevel;
switch (level.levelInt) {
case Level.TRACE_INT:
julLevel = java.util.logging.Level.FINEST.getName();
break;
case Level.DEBUG_INT:
julLevel = java.util.logging.Level.FINE.getName();
break;
case Level.WARN_INT:
julLevel = java.util.logging.Level.WARNING.getName();
break;
case Level.ERROR_INT:
julLevel = java.util.logging.Level.SEVERE.getName();
break;
default:
julLevel = java.util.logging.Level.INFO.getName();
}
return julLevel;
}
class CheckThenPublish implements Runnable {
public void run() {
while(!Thread.currentThread().isInterrupted()) {
ILoggingEvent loggingEvent;
try {
loggingEvent = eventQ.take();
} catch (InterruptedException e) {
break;
}
if(loggingEvent!=null) {
boolean publish = false;
if(loggingEvent.getThrowableProxy()!=null) {
publish = true;
} else if(loggingEvent.getLevel().levelInt>=publishOnLevel.levelInt &&
loggingEvent.getLevel()!= Level.OFF) {
for(String logger : publishableLoggers) {
if(loggingEvent.getLoggerName().startsWith(logger)) {
publish = true;
break;
}
}
}
if(publish) {
LogRecord logRecord = new LogRecord(java.util.logging.Level.parse(getJULLevel(loggingEvent.getLevel())),
loggingEvent.getFormattedMessage());
logRecord.setMillis(loggingEvent.getTimeStamp());
if(loggingEvent.getThrowableProxy()!=null) {
if(loggingEvent.getThrowableProxy() instanceof ThrowableProxy) {
logRecord.setThrown((((ThrowableProxy) loggingEvent.getThrowableProxy()).getThrowable()));
}
}
eventPublisher.publish(logRecord);
}
}
}
}
}
}