com.quartzdesk.api.agent.log.log4j.ClassicLog4jInterceptionAppender Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of quartzdesk-api Show documentation
Show all versions of quartzdesk-api Show documentation
QuartzDesk Public API library required for QuartzDesk Standard and Enterprise edition installations. This library must be placed on the classpath of the Quartz scheduler based application that is managed by QuartzDesk. It is important that this library is loaded by the same classloader that loads the Quartz scheduler API used by the application.
/*
* Copyright (c) 2013-2019 QuartzDesk.com. All Rights Reserved.
* QuartzDesk.com PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.quartzdesk.api.agent.log.log4j;
import com.quartzdesk.agent.Agent;
import com.quartzdesk.agent.api.domain.model.log.LoggingEventPriority;
import com.quartzdesk.agent.api.scheduler.common.log.IExecutingJobLoggingInterceptor;
import com.quartzdesk.api.agent.log.WorkerThreadLoggingInterceptorRegistry;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
/**
* Implementation of a Log4J appender that passes the log events to the QuartzDesk JVM agent that intercepts log
* messages produced by executed jobs.
*
* ==== Example log4j.xml ====
* ...
*
* <!--
* Appender that passes all received log events to the QuartzDesk agent to intercept
* log events produced by executed Quartz jobs.
* -->
* <appender name="QUARTZDESK_JVM_AGENT" class="com.quartzdesk.api.agent.log.log4j.ClassicLog4jInterceptionAppender">
* <param name="threshold" value="DEBUG"/>
*
* <layout class="org.apache.log4j.EnhancedPatternLayout">
* <param name="conversionPattern" value="[%d{ISO8601}] %!.1p [%t] [%C:%L] - %m%n"/>
* </layout>
* </appender>
*
* ...
*
* <root>
* <priority value="WARN"/>
* ...
* <appender-ref ref="QUARTZDESK_JVM_AGENT"/>
* </root>
*
*
* This implementation is statically bound to the QuartzDesk JVM Agent API and to the QuartzDesk domain object
* API. Therefore this appender requires a JVM with an installed QuartzDesk JVM Agent.
*
* @version $Id:$
* @see IExecutingJobLoggingInterceptor
*/
@Deprecated
public class ClassicLog4jInterceptionAppender
extends AppenderSkeleton
{
private static final LoggingEventPriority LOGGING_INTERCEPTOR_EVENT_PRIORITY =
LoggingEventPriority.INFO;
private IExecutingJobLoggingInterceptor loggingInterceptor;
/**
* Creates a new {@link ClassicLog4jInterceptionAppender} instance.
*/
public ClassicLog4jInterceptionAppender()
{
setName( "QuartzDesk-" + ClassicLog4jInterceptionAppender.class.getSimpleName() );
//LogLog.warn( "Starting " + Log4j2InterceptionAppender.class.getName() + ", name=" + getName() );
//addInfo( "Starting " + Log4jInterceptionAppender.class.getName() + " for " + agent );
loggingInterceptor = loggingInterceptor = Agent.getInstance().getRuntime().getExecutingJobLoggingInterceptor();
}
/**
* Stops this appender.
*/
@Override
public void close()
{
loggingInterceptor = null;
}
@Override
public boolean requiresLayout()
{
return true;
}
/**
* If the QuartzDesk agent's logging interceptor wishes to intercept the specified logging event, then this method
* formats the log event using the provided pattern layout and passes the result to the logging interceptor.
*
* @param event a logging event object.
*/
@Override
protected void append( LoggingEvent event )
{
/*
* The LoggingEvent object does not contain the emitter's thread ID so we assume the emitter
* is the current thread.
*/
Long threadId = Thread.currentThread().getId();
/*
* The emitter thread can be a worker thread (a thread created / used by the main job thread).
*/
Long jobThreadId = WorkerThreadLoggingInterceptorRegistry.INSTANCE.getJobThreadForWorkerThread( threadId );
if ( jobThreadId != null )
{
threadId = jobThreadId;
}
if ( loggingInterceptor != null && loggingInterceptor.isIntercepting( threadId ) )
{
com.quartzdesk.agent.api.domain.model.log.LoggingEvent loggingInterceptorEvent =
new com.quartzdesk.agent.api.domain.model.log.LoggingEvent()
.withPriority( convertLevel2Priority( event.getLevel() ) );
StringBuilder msg = new StringBuilder( getLayout().format( event ) );
/*
* If layout ignores throwable (pattern does not contain %throwable macros for custom exception
* formatting), then dump the exception as text.
*/
if ( layout.ignoresThrowable() )
{
String[] traceLines = event.getThrowableStrRep();
if ( traceLines != null )
{
for ( String traceLine : traceLines )
{
msg.append( traceLine );
msg.append( Layout.LINE_SEP );
}
}
}
loggingInterceptorEvent.setMessage( msg.toString() );
loggingInterceptor.intercept( threadId, loggingInterceptorEvent );
}
}
/**
* Returns the {@link LoggingEventPriority} for the specified Log4J level.
*
* @param level a log4j level.
* @return the {@link LoggingEventPriority} for the specified Log4J level.
*/
protected LoggingEventPriority convertLevel2Priority( Level level )
{
if ( level.equals( Level.TRACE ) )
return LoggingEventPriority.TRACE;
else if ( level.equals( Level.DEBUG ) )
return LoggingEventPriority.DEBUG;
else if ( level.equals( Level.INFO ) )
return LoggingEventPriority.INFO;
else if ( level.equals( Level.WARN ) )
return LoggingEventPriority.WARN;
else if ( level.equals( Level.ERROR ) )
return LoggingEventPriority.ERROR;
else if ( level.equals( Level.FATAL ) ) // FATAL mapped to ERROR
return LoggingEventPriority.ERROR;
else
{
LogLog.warn( "Cannot map logging level: " + level + ". Using default logging interceptor event priority: " +
LOGGING_INTERCEPTOR_EVENT_PRIORITY );
return LOGGING_INTERCEPTOR_EVENT_PRIORITY;
}
}
}