Search code examples
spring-integrationspring-kafkaspring-cloud-stream-binder-kafka

Configure logginghandler (of spring integration) in spring-cloud-stream-binder-kafka


I have a follow up question on this question
is there a way to customise the LoggingHandler of Spring Integration module in spring cloud stream ? i.e. setting shouldLogFullMessage to false or logExpression to something minimal? ca it be done in the binder/binding configuration in application.yaml. cos right now even though the DLQ has been set up and the error-handler-definition is setup, the logginghandler logs the message with full payload. do not want to mute the log by setting the log level. just want to reduce the log content of logginghandler may be for @sobychacko

  • looked for documentation to configure the logginghandler but didnt find it in Spring Cloud Stream docs
  • however it mentioned some error handling needs to be configured at Container level so checked here too it gives customisation for Spring Kafka .. I am assuming some customisation can be done here to replace the logginghandler with some other handler but not sure how!

Solution

  • Spring Cloud Stream fully relies on whatever Spring Integration provided on that matter. So, Spring Integration creates an errorChannel if that does not exist yet, and subscribe to it a LoggingHandler with some defaults:

            this.registry.registerBeanDefinition(errorLoggerBeanName,
                    BeanDefinitionBuilder.genericBeanDefinition(LoggingHandler.class)
                            .addConstructorArgValue(LoggingHandler.Level.ERROR)
                            .addPropertyValue(IntegrationNamespaceUtils.ORDER, Ordered.LOWEST_PRECEDENCE - 100)
                            .getBeanDefinition());
    

    So, yeah, you are right: there is no way to customize that default LoggingHandler. Feel free to raise a GH issue for Spring Integration: we need to think if this default LoggingHandler has to be customized via configuration properties.

    Right now the solution is like this:

        @Bean
        PublishSubscribeChannel errorChannel() {
            return new PublishSubscribeChannel();
        }
    
        @Bean
        @ServiceActivator(inputChannel = "errorChannel")
        LoggingHandler errorLoggingHandler() {
            LoggingHandler loggingHandler = new LoggingHandler(LoggingHandler.Level.ERROR);
            loggingHandler.setLogExpression(new FunctionExpression<ErrorMessage>(m -> m.getPayload().getMessage()));
            return loggingHandler;
        }
    

    This way we just override whatever could be done there in Spring Integration by default. Also, pay attention how it is more clear to do this in Java, rather we would try to determine what could be wrong with an expression from the configuration properties. Therefore I'm not very convinced yet that we should expose those properties instead of long-lived solution via bean overriding: https://docs.spring.io/spring-integration/reference/error-handling.html