xxxxxxxxxx
// pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
// log4j.properties
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n
// application.properties
logging.level.org.springframework=debug
// ApplicationConfig.java
@Configuration
@PropertySource("classpath:application.properties")
@ComponentScan(basePackages = "com.frankmoley.lil.fid")
@EnableAspectJAutoProxy // Enable AOP
public class ApplicationConfig {
}
// Loggable annotation
@Target(ElementType.METHOD) // annotation should work on methods
@Retention(RetentionPolicy.RUNTIME) // annotation should be loaded during runtime
public @interface Loggable {
}
// Service
@Service
public class GreetingService {
@Value("${app.greeting}")
private String greeting;
public GreetingService(){ super(); }
@Loggable // This is the joinpoint : Where the aspected behavior is stitched
public String getGreeting(String name){
return greeting + " " + name; }
}
// Aspect class
@Component
@Aspect // ensure for component scanning
public class LoggingAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingAspect.class);
@Pointcut("@annotation(Loggable)") // connect with the annotation. The annotation is the pointcut (will trigger this aspect)
public void executeLogging(){} // The original Advise : the logic that will run when annotation is called
@Before(value = "executeLogging()") // Pre-Advise: the logic that will run before execution of original advise
public void logMethodCall(JoinPoint joinPoint){
StringBuilder message = new StringBuilder("Method: "); // *root-start
message.append(joinPoint.getSignature().getName());
Object[] args = joinPoint.getArgs();
if (null!=args && args.length>0){
Arrays.asList(args).forEach(arg->{
message.append(arg).append(" | ");
}); // *root-end
}
LOGGER.info(message.toString());
}
@AfterReturning(value = "executeLogging()", returning = "returnValue") // Post-Advise: the logic that will run after execution of original advise
public void logMethodCall(JoinPoint joinPoint, Object returnValue){
// same as *root-start to *root-end
// .. just work with returnValue
if(returnValue instanceof Collection){ // *return-start
message.append(", returning: ").append(((Collection)returnValue).size()).append(" instance(s)");
}else{
message.append(", returning: ").append(returnValue.toString());
}
LOGGER.info(message.toString()); // *return-end
}
@Around(value = "executeLogging()") // Most Flexible : Anything before original advise, anything after original advise returning value, anything after original advise returning exception
public Object logMethodCall(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object returnValue = joinPoint.proceed();
long totalTime = System.currentTimeMillis()-startTime;
// same as *root-start to *root-end
// same as *return-start to *return-end
return returnValue;
}
}
xxxxxxxxxx
logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE
xxxxxxxxxx
logging.level.org.springframework.web=INFO
logging.level.org.hibernate=ERROR
logging.level.net.guides=DEBUG
xxxxxxxxxx
// pom.xml
// If you are using spring-boot-starter-web, logging is automatically included with "spring-boot-starter-logging" jar
// application.properties
logging.level.org.springframework=debug // everything else will print as debug level
logging.level.[com.package.name]=trace // only this package will print as trace level
// Controlller
@Controller
public class SayHelloController {
private Logger logger = LoggerFactory.getLogger(getClass());
@RequestMapping("say-hello-jsp")
// @RequestParam lets the url take a value as argument to a parameter payload
// "ModelMap" helps to pass data from controller to the specified view
public String sayHelloJsp(@RequestParam(value="name", required = false)String name, ModelMap model){
model.put("name",name); // the name variable now can be accessed in the view with "name" keyword
// what you want to log
System.out.println(name); // This is NOT RECOMMENDED in prod environment
logger.debug(name); // debug level logging
logger.info("This will print on info level"); // info level logging
logger.warn("This will print on warn level"); // warn level logging
logger.trace("This will print on trace level"); // warn level logging
return "sayHello"; // the jsp file name
}
}
xxxxxxxxxx
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApp {
private static final Logger logger = LoggerFactory.getLogger(MyApp.class);
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
// Logging example
logger.trace("This is a TRACE level message.");
logger.debug("This is a DEBUG level message.");
logger.info("This is an INFO level message.");
logger.warn("This is a WARN level message.");
logger.error("This is an ERROR level message.");
}
}
xxxxxxxxxx
@RestController
public class LoggingController {
Logger logger = LoggerFactory.getLogger(LoggingController.class);
@RequestMapping("/")
public String index() {
logger.trace("A TRACE Message");
logger.debug("A DEBUG Message");
logger.info("An INFO Message");
logger.warn("A WARN Message");
logger.error("An ERROR Message");
return "Howdy! Check out the Logs to see the output...";
}
}
xxxxxxxxxx
Lombok has annotations for that.
Annotate your class with @Slf4j and a static log fiedl will be generated.