Repository: camel Updated Branches: refs/heads/master fc91c5883 -> 2ab36a3db
[CAMEL-6694] Allow log EIP to use provided or registry logger Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/dba21eb2 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/dba21eb2 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/dba21eb2 Branch: refs/heads/master Commit: dba21eb2c27d936f0d903981d8dba0343335b300 Parents: fc91c58 Author: Grzegorz Grzybek <gr.grzy...@gmail.com> Authored: Fri Apr 4 13:11:32 2014 +0200 Committer: Grzegorz Grzybek <gr.grzy...@gmail.com> Committed: Fri Apr 4 13:11:32 2014 +0200 ---------------------------------------------------------------------- .../org/apache/camel/model/LogDefinition.java | 59 ++++++++- .../apache/camel/model/ProcessorDefinition.java | 37 ++++++ .../LogProcessorWithProvidedLoggerTest.java | 120 +++++++++++++++++++ camel-core/src/test/resources/log4j.properties | 7 ++ ...pringLogProcessorWithProvidedLoggerTest.java | 31 +++++ .../logProcessorWithProvidedLoggerTest.xml | 45 +++++++ 6 files changed, 294 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/dba21eb2/camel-core/src/main/java/org/apache/camel/model/LogDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/LogDefinition.java b/camel-core/src/main/java/org/apache/camel/model/LogDefinition.java index 8bc3a2c..085d0ce 100644 --- a/camel-core/src/main/java/org/apache/camel/model/LogDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/LogDefinition.java @@ -20,14 +20,20 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; import org.apache.camel.Expression; import org.apache.camel.LoggingLevel; import org.apache.camel.Processor; import org.apache.camel.processor.LogProcessor; import org.apache.camel.spi.RouteContext; +import org.apache.camel.util.CamelContextHelper; import org.apache.camel.util.CamelLogger; import org.apache.camel.util.ObjectHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; /** * Represents an XML <log/> element @@ -45,6 +51,10 @@ public class LogDefinition extends NoOutputDefinition<LogDefinition> { private String logName; @XmlAttribute private String marker; + @XmlAttribute + private String loggerRef; + @XmlTransient + private Logger logger; public LogDefinition() { } @@ -75,15 +85,38 @@ public class LogDefinition extends NoOutputDefinition<LogDefinition> { // use simple language for the message string to give it more power Expression exp = routeContext.getCamelContext().resolveLanguage("simple").createExpression(message); - String name = getLogName(); - if (name == null) { - name = routeContext.getRoute().getId(); + // get logger explicitely set in the definition + Logger logger = this.getLogger(); + + // get logger which may be set in XML definition + if (logger == null && ObjectHelper.isNotEmpty(loggerRef)) { + logger = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), loggerRef, Logger.class); + } + + if (logger == null) { + // first - try to lookup single instance in the registry, just like LogComponent + Map<String, Logger> availableLoggers = routeContext.lookupByType(Logger.class); + if (availableLoggers.size() == 1) { + logger = availableLoggers.values().iterator().next(); + } else if (availableLoggers.size() > 1) { + // we should log about this somewhere... + //LOG.info("More than one {} instance found in the registry. Falling back to creating logger by name.", Logger.class.getName()); + } + } + + if (logger == null) { + String name = getLogName(); + if (name == null) { + name = routeContext.getRoute().getId(); + } + logger = LoggerFactory.getLogger(name); } + // should be INFO by default LoggingLevel level = getLoggingLevel() != null ? getLoggingLevel() : LoggingLevel.INFO; - CamelLogger logger = new CamelLogger(name, level, getMarker()); + CamelLogger camelLogger = new CamelLogger(logger, level, getMarker()); - return new LogProcessor(exp, logger); + return new LogProcessor(exp, camelLogger); } @Override @@ -123,4 +156,20 @@ public class LogDefinition extends NoOutputDefinition<LogDefinition> { public void setMarker(String marker) { this.marker = marker; } + + public String getLoggerRef() { + return loggerRef; + } + + public void setLoggerRef(String loggerRef) { + this.loggerRef = loggerRef; + } + + public Logger getLogger() { + return logger; + } + + public void setLogger(Logger logger) { + this.logger = logger; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/dba21eb2/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java index 7e817ea..833457c 100644 --- a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinition.java @@ -1540,6 +1540,23 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type> } /** + * Creates a log message to be logged at the given level using provided logger. + * + * @param loggingLevel the logging level to use + * @param logger the logger to use + * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax) + * @return the builder + */ + @SuppressWarnings("unchecked") + public Type log(LoggingLevel loggingLevel, Logger logger, String message) { + LogDefinition answer = new LogDefinition(message); + answer.setLoggingLevel(loggingLevel); + answer.setLogger(logger); + addOutput(answer); + return (Type) this; + } + + /** * Creates a log message to be logged at the given level and name. * * @@ -1560,6 +1577,26 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type> } /** + * Creates a log message to be logged at the given level using provided logger. + * + * + * @param loggingLevel the logging level to use + * @param logger the logger to use + * @param marker log marker name + * @param message the log message, (you can use {@link org.apache.camel.language.simple.SimpleLanguage} syntax) + * @return the builder + */ + @SuppressWarnings("unchecked") + public Type log(LoggingLevel loggingLevel, Logger logger, String marker, String message) { + LogDefinition answer = new LogDefinition(message); + answer.setLoggingLevel(loggingLevel); + answer.setLogger(logger); + answer.setMarker(marker); + addOutput(answer); + return (Type) this; + } + + /** * <a href="http://camel.apache.org/content-based-router.html">Content Based Router EIP:</a> * Creates a choice of one or more predicates with an otherwise clause * http://git-wip-us.apache.org/repos/asf/camel/blob/dba21eb2/camel-core/src/test/java/org/apache/camel/processor/LogProcessorWithProvidedLoggerTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/processor/LogProcessorWithProvidedLoggerTest.java b/camel-core/src/test/java/org/apache/camel/processor/LogProcessorWithProvidedLoggerTest.java new file mode 100644 index 0000000..4aa000e --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/processor/LogProcessorWithProvidedLoggerTest.java @@ -0,0 +1,120 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.processor; + +import org.apache.camel.CamelContext; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.LoggingLevel; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.log.LogComponent; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.impl.SimpleRegistry; +import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.spi.LoggingEvent; +import org.junit.Before; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.StringWriter; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * @version + */ +public class LogProcessorWithProvidedLoggerTest extends ContextTestSupport { + + // to capture the logs + private static StringWriter sw; + // to capture the warnings from LogComponent + private static StringWriter sw2; + + private static final class CapturingAppender extends AppenderSkeleton { + private StringWriter sw; + + private CapturingAppender(StringWriter sw) { + this.sw = sw; + } + + @Override + protected void append(LoggingEvent event) { + this.sw.append(event.getLoggerName() + " " + event.getLevel().toString() + " " + event.getMessage()); + } + + @Override + public void close() { + } + + @Override + public boolean requiresLayout() { + return false; + } + } + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + sw = new StringWriter(); + Logger.getLogger("org.apache.camel.customlogger").removeAllAppenders(); + Logger.getLogger("org.apache.camel.customlogger").addAppender(new CapturingAppender(sw)); + Logger.getLogger("org.apache.camel.customlogger").setLevel(Level.TRACE); + } + + public void testLogProcessorWithRegistryLogger() throws Exception { + getMockEndpoint("mock:foo").expectedMessageCount(1); + + template.sendBody("direct:foo", "Bye World"); + + assertMockEndpointsSatisfied(); + + assertThat(sw.toString(), equalTo("org.apache.camel.customlogger INFO Got Bye World")); + } + + public void testLogProcessorWithProvidedLogger() throws Exception { + getMockEndpoint("mock:bar").expectedMessageCount(1); + + template.sendBody("direct:bar", "Bye World"); + + assertMockEndpointsSatisfied(); + + assertThat(sw.toString(), equalTo("org.apache.camel.customlogger INFO Also got Bye World")); + } + + @Override + protected CamelContext createCamelContext() throws Exception { + SimpleRegistry registry = new SimpleRegistry(); + registry.put("mylogger1", LoggerFactory.getLogger("org.apache.camel.customlogger")); + CamelContext context = new DefaultCamelContext(registry); + return context; + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:foo").routeId("foo").log(LoggingLevel.INFO, "Got ${body}").to("mock:foo"); + from("direct:bar").routeId("bar").log(LoggingLevel.INFO, LoggerFactory.getLogger("org.apache.camel.customlogger"), "Also got ${body}").to("mock:bar"); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/dba21eb2/camel-core/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/camel-core/src/test/resources/log4j.properties b/camel-core/src/test/resources/log4j.properties index 55b0834..c3eb9f7 100644 --- a/camel-core/src/test/resources/log4j.properties +++ b/camel-core/src/test/resources/log4j.properties @@ -19,6 +19,7 @@ # The logging properties used during tests.. # log4j.rootLogger=INFO, file +log4j.logger.org.apache.camel.customlogger=TRACE, file2 #log4j.logger.org.apache.camel.impl.converter=WARN #log4j.logger.org.apache.camel.management=WARN @@ -70,3 +71,9 @@ log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m # MDC #log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %-10.10X{camel.breadcrumbId} - %-10.10X{camel.exchangeId} - %-10.10X{camel.correlationId} - %-10.10X{camel.routeId} - %m%n +# File appender for logging with provided logger +log4j.appender.file2=org.apache.log4j.FileAppender +log4j.appender.file2.layout=org.apache.log4j.PatternLayout +log4j.appender.file2.file=target/custom-logger-test.log +log4j.appender.file2.append=false +log4j.appender.file2.layout.ConversionPattern=%-5p %c{1} %m%n http://git-wip-us.apache.org/repos/asf/camel/blob/dba21eb2/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringLogProcessorWithProvidedLoggerTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringLogProcessorWithProvidedLoggerTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringLogProcessorWithProvidedLoggerTest.java new file mode 100644 index 0000000..6b4ac33 --- /dev/null +++ b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringLogProcessorWithProvidedLoggerTest.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.spring.processor; + +import org.apache.camel.CamelContext; +import org.apache.camel.processor.LogProcessorTest; +import org.apache.camel.processor.LogProcessorWithProvidedLoggerTest; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +public class SpringLogProcessorWithProvidedLoggerTest extends LogProcessorWithProvidedLoggerTest { + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, + "org/apache/camel/spring/processor/logProcessorWithProvidedLoggerTest.xml"); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/dba21eb2/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/logProcessorWithProvidedLoggerTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/logProcessorWithProvidedLoggerTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/logProcessorWithProvidedLoggerTest.xml new file mode 100644 index 0000000..6039650 --- /dev/null +++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/logProcessorWithProvidedLoggerTest.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <bean id="customLogger" class="org.slf4j.LoggerFactory" factory-method="getLogger"> + <constructor-arg value="org.apache.camel.customlogger" /> + </bean> + + <camelContext trace="true" xmlns="http://camel.apache.org/schema/spring"> + + <route id="foo"> + <from uri="direct:foo"/> + <log message="Got ${body}" loggingLevel="INFO"/> + <to uri="mock:foo"/> + </route> + + <route id="bar"> + <from uri="direct:bar"/> + <log message="Also got ${body}" loggingLevel="INFO" loggerRef="customLogger"/> + <to uri="mock:bar"/> + </route> + + </camelContext> + +</beans>