no logging for PerformanceMonitorInterceptor - spring-boot

I've got this simple bean for PerformanceMonitorInterceptor
#Configuration
#EnableAspectJAutoProxy
#Aspect
public class PerfMetricsConfiguration {
/**
* Monitoring pointcut.
*/
#Pointcut("execution(* com.lapots.breed.judge.repository.*Repository.*(..))")
public void monitor() {
}
/**
* Creates instance of performance monitor interceptor.
* #return performance monitor interceptor
*/
#Bean
public PerformanceMonitorInterceptor performanceMonitorInterceptor() {
return new PerformanceMonitorInterceptor(true);
}
/**
* Creates instance of performance monitor advisor.
* #return performance monitor advisor
*/
#Bean
public Advisor performanceMonitorAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("com.lapots.breed.judge.repository.PerfMetricsConfiguration.monitor()");
return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor());
}
}
It supposed to trace any method invocation in the interfaces that ends with Repository in name.
I set logging level in application.properties
logging.level.org.springframework.aop.interceptor.PerformanceMonitorInterceptor=TRACE
But during execution it doesn't write anything in the console. What's the problem?

I was facing similar issue, after changing the useDynamicLogger to false the issue was fixed.
#Bean
public PerformanceMonitorInterceptor performanceMonitorInterceptor() {
return new PerformanceMonitorInterceptor(false);
}

Faced with the same issue. And as Manzoor suggested passing false to PerformanceMonitorInterceptor solves the problem.
Why? When you call new PerformanceMonitorInterceptor(true), the logger name used inside of PerformanceMonitorInterceptor will be: com.lapots.breed.judge.repository.SomeClass.
So in your particular case the following logging configuration is required:
logging.level.com.lapots.breed.judge.repository=TRACE, otherwise you do not see any logs, the breakpoint on PerformanceMonitorInterceptor.invokeUnderTrace() will not work and you spend lot's of time thinking you have wrong AOP configuration (while actually it's fine), but you did not set up logging level for proper class/package.

I am using spring logging (SLF4J logging). Instead of putting PerformanceMonitorInterceptor logger to TRACE , I added com.lapots.breed.judge.repository logger to TRACE.
This started printing logs for me.
I did this because the below method in AbstractTraceInterceptor is looking for TRACE enabled on the class(Repository) we executing but not on PerformanceMonitorInterceptor.
protected boolean isLogEnabled(Log logger) {
return logger.isTraceEnabled();
}

I just tried this, I simply added this to application.properties and it works:
logging.level.org.springframework.aop.interceptor.PerformanceMonitorInterceptor=trace

Related

Spring Integration - WIth AWS S3 ( Retry Strategy)

I am creating a simple integration service with AWS S3. I am facing some difficulties when an exception occurs.
My requirement is to poll an S3 Bucket periodically and to apply some transformation whenever a file is newly placed into S3 Bucket. The below code snippet works fine, but when an exception occurs it continues to retry again and again. I do not want that to happen. Can someone help me here.,
The IntegrationFlow is defined as below.,
#Configuration
public class S3Routes {
#Bean
public IntegrationFlow downloadFlow(MessageSource<InputStream> s3InboundStreamingMessageSource) {
return IntegrationFlows.from(s3InboundStreamingMessageSource)
.channel("s3Channel")
.handle("QueryServiceImpl", "processFile")
.get();
}
}
Configuration file is as below.,
#Service
public class S3AppConfiguration {
#Bean
#InboundChannelAdapter(value = "s3Channel")
public MessageSource<InputStream> s3InboundStreamingMessageSource(S3RemoteFileTemplate template) {
S3StreamingMessageSource messageSource = new S3StreamingMessageSource(template);
messageSource.setRemoteDirectory("my-bucket-name");
messageSource.setFilter(new S3PersistentAcceptOnceFileListFilter(new SimpleMetadataStore(),
"streaming"));
return messageSource;
}
#Bean
public PollableChannel s3Channel() {
return new QueueChannel();
}
#Bean
public S3RemoteFileTemplate template(AmazonS3 amazonS3) {
return new S3RemoteFileTemplate(new S3SessionFactory(amazonS3));
}
#Bean(name = "amazonS3")
public AmazonS3 nonProdAmazonS3(BasicAWSCredentials basicAWSCredentials) {
ClientConfiguration config = new ClientConfiguration();
config.setProxyHost("localhost");
config.setProxyPort(3128);
return AmazonS3ClientBuilder.standard().withRegion(Regions.fromName("ap-southeast-1"))
.withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials))
.withClientConfiguration(config)
.build();
}
#Bean
public BasicAWSCredentials basicAWSCredentials() {
return new BasicAWSCredentials("access_key", "secret_key");
}
#Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata nonProdPoller() {
return Pollers.cron("* */2 * * * *")
.get();
}
}
AcceptOnceFileList filter that I have used here, helps me to prevent handling the same file for continuous retries. But, I do not want to use AcceptOnceFileList filter, because when a file is not processed on 1st attempt, I wish to retry on next Poll (usually it happens every 1 hour in Prod region). I tried to use filter.remove() method whenever the processing fails(in case of any exception), it again results in continuous retries.
I am not sure how to disable the continuous retries on failure. Where should I configure it?
I took a look at Spring Integration ( Retry Strategy). Same scenario, but a different integration. I am not sure how to set up this for my IntegrationFlow. Can someone help here? Thanks in advance
That story is different: it talks about a listener container for AMQP. You use a source polling channel adapter - the approach might be different.
You create two source polling channel adapters: one via that #InboundChannelAdapter, another via IntegrationFlows.from(s3InboundStreamingMessageSource). Both of them produces data to the same channel. Not sure if that is really intentional.
It is not clear what is that retry in your case unless you really do that manual filter.remove() call. In this case indeed it is going to retry. But this is a single, not controlled retry. It is going to retry again only if you call that filter.remove() again. So, if you do everything yourself, why is the question?
Consider to use a RequestHandlerRetryAdvice configured for that your handle() instead: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#message-handler-advice-chain. This way you really going to pull the remote file only once and retry is going to be managed by the Spring Retry API.
UPDATE
So, after some Cron Expression learning I realized that your one is wrong:
* */2 * * * * - means every second of every even minute
Must be like this:
0 */2 * * * * - at the beginning of every even minute
Perhaps something similar is with your hourly cron expression on the prod...

Spring boot hikaricp connection-timeout vs connectionTimeout

when I google the Hikaricp connection properties, I found two major difference, for example:
https://www.javadevjournal.com/spring-boot/spring-boot-hikari/
https://www.baeldung.com/spring-boot-hikari
spring.datasource.hikari.connection-timeout = 20000
spring.datasource.hikari.connectionTimeout=30000
when I look into https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby
I cannot find '''.connection-timeout'''
what is the difference between connection-timeout vs connectionTimeout?
this is one of the difference I found on net. 😒
Spring Boot utilized something they call relaxed binding and each of those properties would endup in the same place. The connectionTimeout property of the HikariDataSource.
In fact you could also use _ or when providing a environment variable use uppercase names.
spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.connection_timeout=20000
spring.datasource.hikari.connectionTimeout=30000
SPRING_DATASOURCE_HIKARI_CONNECTIONTIMEOUT=30000
All of the aforementioned properties would eventually be bound to the HikariDataSource.connectionTimeout property. They are all different representations of the same. The latter is mainly to overcome the limitation of not being able to use - in environment variables in Linux/Mac.
Here is the actual code in Hikari - setting up the configuration and the actual property is connectionTimeout. Spring would most likely invoke it via setter when provided this setting in Spring configuration
public class HikariConfig implements HikariConfigMXBean
{
.....................
.....................
private volatile long connectionTimeout;
/** {#inheritDoc} */
#Override
public long getConnectionTimeout()
{
return connectionTimeout;
}
/** {#inheritDoc} */
#Override
public void setConnectionTimeout(long connectionTimeoutMs)
{
if (connectionTimeoutMs == 0) {
this.connectionTimeout = Integer.MAX_VALUE;
}
else if (connectionTimeoutMs < 250) {
throw new IllegalArgumentException("connectionTimeout cannot be less than 250ms");
}
else {
this.connectionTimeout = connectionTimeoutMs;
}
}

CommonsRequestLoggingFilter not working in spring boot application

I have added this #Bean to the class I have main function in
#Bean
public CommonsRequestLoggingFilter requestLoggingFilter() {
System.out.println("inside logging filter");
CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
loggingFilter.setIncludeClientInfo(true);
loggingFilter.setIncludeQueryString(true);
loggingFilter.setIncludePayload(true);
loggingFilter.setIncludeHeaders(false);
return loggingFilter;
}
On application start,
inside logging filter
gets printed in console but I do not see any logging of requests when I call method from a RestController.
Why is that? How do I fix it?
I have already added
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG
in application.properties file
I have been the same situation and I could resolve it with removing log setting.
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG
It runs without this setting.
Also, if you want to change log level, you can define the class extends AbstractRequestLoggingFilter and write logging like this.
#Override
protected void beforeRequest(HttpServletRequest request, String message) {
logger.info(message);
}
#Override
protected void afterRequest(HttpServletRequest request, String message) {
logger.info(message);
}
In principle you just need to enable debug on the logger of choice. In effect it is hard to know what logger exatly is used by Spring. The safe way to do it is to override AbstractRequestLoggingFilter and set the logger to a logger of choice. Alternatively is is possible you just override the 'shouldLog' method to return 'true'.
Example in Kotlin
package org.ultra-marine.logging
import org.slf4j.LoggerFactory
import org.springframework.web.filter.AbstractRequestLoggingFilter
import javax.servlet.http.HttpServletRequest
class RequestLoggingFilter: AbstractRequestLoggingFilter() {
private val log = LoggerFactory.getLogger(this::class.java)
override fun shouldLog(request: HttpServletRequest): Boolean {
return log.isDebugEnabled
}
/**
* Writes a log message before the request is processed.
*/
override fun beforeRequest(request: HttpServletRequest, message: String) {
log.debug(message)
}
/**
* Writes a log message after the request is processed.
*/
override fun afterRequest(request: HttpServletRequest, message: String) {
log.debug(message)
}
}
The Filter need to be initialized using a Bean in the same way demonstrated in other places.
#Configuration
class SpringBootRequestLoggingConfiguration {
#Bean
fun requestLoggingFilter(): RequestLoggingFilter {
val filter = RequestLoggingFilter()
filter.setIncludeClientInfo(false)
filter.setIncludeQueryString(true)
filter.setIncludePayload(false)
filter.setMaxPayloadLength(8000)
filter.setIncludeHeaders(false)
return filter
}
}
Try changing the level to TRACE in your application.properties file:
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=TRACE
DEBUG didn't work for me, but TRACE did.
Fyi if you see an extra ] at the end of the json body you can remove it like this:
loggingFilter.setAfterMessageSuffix("");
you should set the MaxPayloadLength,if you use CommonsRequestLoggingFilter
filter.setMaxPayloadLength(2048);
Or you can implements Filter,then you can customize yourself Filter.
Define a MultiReadHttpServletRequest extends HttpServletRequestWrapper
slove the getInputStream problem.

Running async jobs in dropwizard, and polling their status

In dropwizard, I need to implement asynchronous jobs and poll their status.
I have 2 endpoints for this in resource:
#Path("/jobs")
#Component
public class MyController {
#POST
#Produces(MediaType.APPLICATION_JSON)
public String startJob(#Valid MyRequest request) {
return 1111;
}
#GET
#Path("/{jobId}")
#Produces(MediaType.APPLICATION_JSON)
public JobStatus getJobStatus(#PathParam("id") String jobId) {
return JobStatus.READY;
}
}
I am considering to use quartz to start job, but only single time and without repeating. And when requesting status, I will get trigger status. But the idea of using quartz for none-scheduled usage looks weird.
Is there any better approaches for this? Maybe dropwizard provides better tools itself? Will appriciate any advices.
UPDATE: I also looking at https://github.com/gresrun/jesque, but can not find any way to poll the status of running job.
You can use the Managed interface. In the snippet below I am using the ScheduledExecutorService to exuecute jobs, but you can use Quartz instead if you like. I prefer working with ScheduledExecutorService as it is simpler and easier...
first step is to register your managed service.
environment.lifecycle().manage(new JobExecutionService());
Second step is to write it.
/**
* A wrapper around the ScheduledExecutorService so all jobs can start when the server starts, and
* automatically shutdown when the server stops.
* #author Nasir Rasul {#literal nasir#rasul.ca}
*/
public class JobExecutionService implements Managed {
private final ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
#Override
public void start() throws Exception {
System.out.println("Starting jobs");
service.scheduleAtFixedRate(new HelloWorldJob(), 1, 1, TimeUnit.SECONDS);
}
#Override
public void stop() throws Exception {
System.out.println("Shutting down");
service.shutdown();
}
}
and the job itself
/**
* A very simple job which just prints the current time in millisecods
* #author Nasir Rasul {#literal nasir#rasul.ca}
*/
public class HelloWorldJob implements Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* #see Thread#run()
*/
#Override
public void run() {
System.out.println(System.currentTimeMillis());
}
}
As mentioned in the comment below, if you use Runnable, you can Thread.getState(). Please refer to Get a List of all Threads currently running in Java. You may still need some intermediary pieces depending on how you're wiring you application.

Trouble in Using Quartz with spring webapp - Not able to see errors on cosole

I am using quartz within a Spring MVC application.
I have a task class, all functionality and logic is written there. I have a separate quartz configuration file. I am just hitting a URL and in controller function initializing the quartz conf file. The job is running fine. The issue I am facing is:
In my task class, some code is running and from a point of time. I am not getting it to run and I am not able to see any error or exception. Here is the code for my task class. I am able to run the getValues() function on a timely basis with quartz. The problem is it's printing the value hi and nothing else. It's not going in if nor else and neither is showing any error or exception.
public class TeamUpdateImpl implements TeamUpdate {
// #Autowired
ReadXmlDao readXmlDao;
public void setReadXmlDao(ReadXmlDao readXmlDao) {
this.readXmlDao = readXmlDao;
}
public void getValues() {
System.out.print("Hi");
if (readXmlDao.getName().equals("Hema")) {
System.out.print("if cond");
} else {
System.out.print("else cond");
}
}
}
Please suggest a solution, some logging thing or something so that I could get at least errors on my console to fix them.
Thanks.
I guess readXmlDao or readXmlDao.getName() is null.
Try to print it.
System.out.print("readXmlDao = "+readXmlDao);
System.out.print("readXmlDao.getName() = "+readXmlDao.getName());
You will get npe on printing readXmlDao.getName() if readXmlDao is null.
Also
Try to set #Autowired on setReadXmlDao method.
#Autowired
public void setReadXmlDao(ReadXmlDao readXmlDao) {
this.readXmlDao = readXmlDao;
}

Resources