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
// 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
/*
Create this class somwhere in your app directory structure
(More details on: https://www.baeldung.com/spring-http-logging - Section 5.1)
*/
@Configuration
public class RequestLoggingFilterConfig {
@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter
= new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true);
filter.setIncludePayload(true);
filter.setMaxPayloadLength(10000);
filter.setIncludeHeaders(false);
filter.setAfterMessagePrefix("REQUEST DATA: ");
return filter;
}
}
/*
Add those to your application.properties file
(More details on: https://www.tutorialworks.com/spring-boot-log-to-file/)
*/
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG
logging.file.path=/home/logs
logging.file.name=myapp.log
xxxxxxxxxx
Lombok has annotations for that.
Annotate your class with @Slf4j and a static log fiedl will be generated.