/** * Populate a {@link WireTap} for the {@link #currentMessageChannel} * with the {@link LoggingHandler} subscriber for the provided * {@link LoggingHandler.Level} logging level, logging category * and SpEL expression for the log message. * <p> When this operator is used in the end of flow, it is treated * as one-way handler without any replies to continue. * The {@link #logAndReply()} should be used for request-reply configuration. * @param level the {@link LoggingHandler.Level}. * @param category the logging category. * @param logExpression the {@link Expression} to evaluate logger message at runtime * against the request {@link Message}. * @return the current {@link IntegrationFlowDefinition}. * @see #wireTap(WireTapSpec) */ public B log(LoggingHandler.Level level, String category, Expression logExpression) { LoggingHandler loggingHandler = new LoggingHandler(level); if (StringUtils.hasText(category)) { loggingHandler.setLoggerName(category); } if (logExpression != null) { loggingHandler.setLogExpression(logExpression); } else { loggingHandler.setShouldLogFullMessage(true); } addComponent(loggingHandler); MessageChannel loggerChannel = new FixedSubscriberChannel(loggingHandler); return wireTap(loggerChannel); }
/** * Create a LoggingHandler with the given log level (case-insensitive). * <p> * The valid levels are: FATAL, ERROR, WARN, INFO, DEBUG, or TRACE * </p> * @param level The level. * @see #LoggingHandler(Level) */ public LoggingHandler(String level) { this(convertLevel(level)); }
private Object createLogMessage(Message<?> message) { Object logMessage = this.expression.getValue(this.evaluationContext, message); return logMessage instanceof Throwable ? createLogMessage((Throwable) logMessage) : logMessage; }
@Test public void assertMutuallyExclusive() { LoggingHandler loggingHandler = new LoggingHandler("INFO"); loggingHandler.setLogExpressionString("'foo'"); try { loggingHandler.setShouldLogFullMessage(true); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertEquals("Cannot set both 'expression' AND 'shouldLogFullMessage' properties", e.getMessage()); } loggingHandler = new LoggingHandler("INFO"); loggingHandler.setShouldLogFullMessage(true); try { loggingHandler.setLogExpressionString("'foo'"); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertEquals("Cannot set both 'expression' AND 'shouldLogFullMessage' properties", e.getMessage()); } }
@Test public void testChangeLevel() { LoggingHandler loggingHandler = new LoggingHandler(Level.INFO); loggingHandler.setBeanFactory(mock(BeanFactory.class)); loggingHandler.afterPropertiesSet(); DirectFieldAccessor accessor = new DirectFieldAccessor(loggingHandler); Log log = (Log) accessor.getPropertyValue("messageLogger"); log = spy(log); accessor.setPropertyValue("messageLogger", log); when(log.isInfoEnabled()).thenReturn(true); loggingHandler.handleMessage(new GenericMessage<>("foo")); verify(log, times(1)).info(Mockito.anyString()); verify(log, never()).warn(Mockito.anyString()); loggingHandler.setLevel(Level.WARN); loggingHandler.handleMessage(new GenericMessage<>("foo")); verify(log, times(1)).info(Mockito.anyString()); verify(log, times(1)).warn(Mockito.anyString()); }
@Override protected MessageHandler createHandler(Object bean, Method method, List<Annotation> annotations) { LoggingHandler.Level level = MessagingAnnotationUtils.resolveAttribute(annotations, "level", LoggingHandler.Level.class); LoggingHandler loggingHandler = new LoggingHandler(level.name()); MethodInvokingMessageProcessor<String> processor = new MethodInvokingMessageProcessor<>(bean, method); processor.setBeanFactory(this.beanFactory); loggingHandler.setLogExpression(new FunctionExpression<>(processor::processMessage)); return loggingHandler; }
@Bean @ServiceActivator(inputChannel = Sink.INPUT) public LoggingHandler logSinkHandler() { LoggingHandler loggingHandler = new LoggingHandler(this.properties.getLevel().name()); loggingHandler.setExpression(this.properties.getExpression()); loggingHandler.setLoggerName(this.properties.getName()); return loggingHandler; }
@Bean public MessageHandler loggingMessageHandler() { return new LoggingHandler(LoggingHandler.Level.DEBUG); }
@Test public void testUsageWithoutSpringInitialization() { LoggingHandler loggingHandler = new LoggingHandler("ERROR"); DirectFieldAccessor accessor = new DirectFieldAccessor(loggingHandler); Log log = (Log) accessor.getPropertyValue("messageLogger"); log = spy(log); accessor.setPropertyValue("messageLogger", log); String testPayload = "TEST_PAYLOAD"; Message<String> message = MessageBuilder.withPayload(testPayload).build(); loggingHandler.handleMessage(message); verify(log).error(testPayload); }
@Bean @ServiceActivator(inputChannel = Sink.INPUT) public LoggingHandler logSinkHandler() { LoggingHandler loggingHandler = new LoggingHandler(this.properties.getLevel().name()) { @Override protected void handleMessageInternal(Message<?> message) throws Exception { if (message.getPayload() instanceof byte[]){ String contentType = message.getHeaders().containsKey(MessageHeaders.CONTENT_TYPE) ? message.getHeaders().get(MessageHeaders.CONTENT_TYPE).toString() : BindingProperties.DEFAULT_CONTENT_TYPE.toString(); if (contentType.contains("text") || contentType.contains("json") || contentType.contains("x-spring-tuple")) { message = new MutableMessage<>(new String(((byte[]) message.getPayload())), message.getHeaders()); } } super.handleMessageInternal(message); } }; loggingHandler.setLogExpressionString(this.properties.getExpression()); loggingHandler.setLoggerName(this.properties.getName()); return loggingHandler; }
/** * Set a SpEL expression string to use. * @param expressionString the SpEL expression string to use. * @since 4.3 * @see #setLogExpression(Expression) */ public void setLogExpressionString(String expressionString) { Assert.hasText(expressionString, "'expressionString' must not be empty"); setLogExpression(EXPRESSION_PARSER.parseExpression(expressionString)); }
/** * Set the logging {@link Level} to change the behavior at runtime. * @param level the level. */ public void setLevel(Level level) { doSetLevel(level); }
@Override protected void onInit() { super.onInit(); this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory()); }
private String createLogMessage(Throwable throwable) { StringWriter stringWriter = new StringWriter(); if (throwable instanceof AggregateMessageDeliveryException) { stringWriter.append(throwable.getMessage()); for (Exception exception : ((AggregateMessageDeliveryException) throwable).getAggregatedExceptions()) { printStackTrace(exception, stringWriter); } } else { printStackTrace(throwable, stringWriter); } return stringWriter.toString(); }
@Test public void testDontEvaluateIfNotEnabled() { LoggingHandler loggingHandler = new LoggingHandler("INFO"); loggingHandler.setBeanFactory(mock(BeanFactory.class)); loggingHandler.afterPropertiesSet(); DirectFieldAccessor accessor = new DirectFieldAccessor(loggingHandler); Log log = (Log) accessor.getPropertyValue("messageLogger"); log = spy(log); accessor.setPropertyValue("messageLogger", log); Expression expression = (Expression) accessor.getPropertyValue("expression"); expression = spy(expression); accessor.setPropertyValue("expression", expression); when(log.isInfoEnabled()).thenReturn(false); loggingHandler.handleMessage(new GenericMessage<>("foo")); verify(expression, never()).getValue(Mockito.any(EvaluationContext.class), Mockito.any(Message.class)); when(log.isInfoEnabled()).thenReturn(true); loggingHandler.handleMessage(new GenericMessage<>("foo")); verify(expression, times(1)).getValue(Mockito.any(EvaluationContext.class), Mockito.any(Message.class)); }
/** * Set a SpEL expression string to use. * @param expressionString the SpEL expression string to use. * @since 4.3 * @see #setLogExpression(Expression) */ public void setLogExpressionString(String expressionString) { Assert.hasText(expressionString, "'expressionString' must not be empty"); setLogExpression(EXPRESSION_PARSER.parseExpression(expressionString)); }
/** * Create a {@link LoggingHandler} with the given log {@link Level}. * @param level the {@link Level} to use. * @since 4.3 */ public LoggingHandler(Level level) { doSetLevel(level); }
@Override protected void onInit() { super.onInit(); this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory()); }
private String createLogMessage(Throwable throwable) { StringWriter stringWriter = new StringWriter(); if (throwable instanceof AggregateMessageDeliveryException) { stringWriter.append(throwable.getMessage()); for (Exception exception : ((AggregateMessageDeliveryException) throwable).getAggregatedExceptions()) { printStackTrace(exception, stringWriter); } } else { printStackTrace(throwable, stringWriter); } return stringWriter.toString(); }
/** * Populate a {@link WireTap} for the {@link #currentMessageChannel} * with the {@link LoggingHandler} subscriber for the provided * {@link LoggingHandler.Level} logging level, logging category * and SpEL expression for the log message. * @param level the {@link LoggingHandler.Level}. * @param category the logging category. * @param logExpression the {@link Expression} to evaluate logger message at runtime * against the request {@link Message}. * @return the current {@link IntegrationFlowDefinition}. * @since 1.2 */ public B log(LoggingHandler.Level level, String category, Expression logExpression) { LoggingHandler loggingHandler = new LoggingHandler(level); if (StringUtils.hasText(category)) { loggingHandler.setLoggerName(category); } if (logExpression != null) { loggingHandler.setLogExpression(logExpression); } else { loggingHandler.setShouldLogFullMessage(true); } addComponent(loggingHandler); MessageChannel loggerChannel = new FixedSubscriberChannel(loggingHandler); return wireTap(loggerChannel); }