Skip to content

Instantly share code, notes, and snippets.

@jyeary
Created August 4, 2014 01:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jyeary/a55148ee7e14322b890d to your computer and use it in GitHub Desktop.
Save jyeary/a55148ee7e14322b890d to your computer and use it in GitHub Desktop.
An InterceptorBinding for method interception that indicates a method is capable of being logged.
/*
* Copyright 2012-2014 John Yeary <jyeary@bluelotussoftware.com>.
*
* 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 com.bluelotussoftware.logging;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
import javax.enterprise.util.Nonbinding;
import javax.interceptor.InterceptorBinding;
/**
* An {@link InterceptorBinding} that indicates that a class, or method is
* capable of being logged.
*
* @author John Yeary
* @version 1.0
*/
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface Loggable {
/**
* Sets the {@link LoggingLevel}. The default is set to {@link LoggingLevel#INFO}.
* @return the set {@link LoggingLevel}, or default {@link LoggingLevel#INFO}.
*/
@Nonbinding
public LoggingLevel logLevel() default LoggingLevel.INFO;
}
/*
* Copyright 2012-2014 John Yeary <jyeary@bluelotussoftware.com>.
*
* 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 com.bluelotussoftware.logging;
import com.bluelotussoftware.cdi.integration.ApplicationInitializer;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
/**
* <p>
* An implementation of {@link Loggable} that intercepts method calls and prints
* out arguments and result based on the {@link LoggingLevel} set in the
* {@link Loggable} annotation.</p>
* <p>
* The logging level is controlled by setting the {@literal logLevel} context
* parameter in the web.xml</p>
* <pre>
* &lt;context-param&gt;
* &lt;description&gt;
* This sets the logging level. The options are:
* ALL, CONFIG, FINE, FINER, FINEST, INFO, OFF (default), SEVERE, and WARNING.
* &lt;/description&gt;
* &lt;param-name&gt;logLevel&lt;/param-name&gt;
* &lt;param-value&gt;INFO&lt;/param-value&gt;
* &lt;/context-param&gt;</pre>
*
* @author John Yeary
* @version 1.0
*/
@Loggable
@Interceptor
public class MethodInterceptor implements Serializable {
private static final long serialVersionUID = 5772153473108384443L;
@Inject
private ApplicationInitializer applicationInitializer;
@AroundInvoke
public Object log(final InvocationContext context) throws Exception {
Logger logger = Logger.getLogger(context.getTarget().getClass().getName());
logger.setUseParentHandlers(true);
setLoggingLevel(logger);
Level currentLevel = getAnnotation(context.getMethod()).logLevel().getLevel();
if (logger.isLoggable(currentLevel)) {
logger.log(Level.FINER, "Before call to {0} with args {1}", new Object[]{context.getMethod(), Arrays.toString(context.getParameters())});
Object result = context.proceed();
logger.log(Level.FINER, "After call to {0} returned {1}", new Object[]{context.getMethod(), result});
return result;
} else {
return context.proceed();
}
}
private Loggable getAnnotation(final Class clazz) {
Loggable loggable = null;
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
if (annotation instanceof Loggable) {
loggable = (Loggable) annotation;
break;
}
}
return loggable;
}
private Loggable getAnnotation(final Method method) {
for (Annotation annotation : method.getAnnotations()) {
if (annotation instanceof Loggable) {
// short circuit and return
return (Loggable) annotation;
}
}
// Check for annotations on the parent
return getAnnotation(method.getDeclaringClass());
}
private void setLoggingLevel(Logger logger) {
logger.setLevel(Level.OFF);
String logLevel = applicationInitializer.getServletContext().getInitParameter("logLevel");
try {
if (logLevel != null) {
logger.setLevel(LoggingLevel.valueOf(logLevel).getLevel());
}
} catch (IllegalArgumentException e) {
logger.log(Level.WARNING, "The init parameter was incorrect. The options are: ALL, CONFIG, FINE, FINER, FINEST, INFO, OFF, SEVERE, and WARNING.", e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment