You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@samza.apache.org by cr...@apache.org on 2014/08/05 18:34:54 UTC
git commit: SAMZA-350; allow dynamic log level toggling
Repository: incubator-samza
Updated Branches:
refs/heads/master e603a2794 -> 3f3d80eb4
SAMZA-350; allow dynamic log level toggling
Project: http://git-wip-us.apache.org/repos/asf/incubator-samza/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-samza/commit/3f3d80eb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-samza/tree/3f3d80eb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-samza/diff/3f3d80eb
Branch: refs/heads/master
Commit: 3f3d80eb466dc42567f3fbf07834b35bc4f958b6
Parents: e603a27
Author: Chris Riccomini <cr...@criccomi-mn.linkedin.biz>
Authored: Tue Aug 5 09:34:46 2014 -0700
Committer: Chris Riccomini <cr...@criccomi-mn.linkedin.biz>
Committed: Tue Aug 5 09:34:46 2014 -0700
----------------------------------------------------------------------
build.gradle | 9 ++
gradle/dependency-versions.gradle | 1 +
.../metrics/reporter/TestJmxReporter.scala | 2 +-
.../apache/samza/logging/log4j/JmxAppender.java | 123 +++++++++++++++++
.../samza/logging/log4j/TestJmxAppender.java | 136 +++++++++++++++++++
samza-log4j/src/test/resources/log4j.xml | 35 +++++
settings.gradle | 15 +-
7 files changed, 318 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-samza/blob/3f3d80eb/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 93ec947..ff920b7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -162,6 +162,15 @@ project(":samza-kafka_$scalaVersion") {
}
}
+project(':samza-log4j') {
+ apply plugin: 'java'
+
+ dependencies {
+ compile "log4j:log4j:$log4jVersion"
+ testCompile "junit:junit:$junitVersion"
+ }
+}
+
project(":samza-serializers_$scalaVersion") {
apply plugin: 'scala'
http://git-wip-us.apache.org/repos/asf/incubator-samza/blob/3f3d80eb/gradle/dependency-versions.gradle
----------------------------------------------------------------------
diff --git a/gradle/dependency-versions.gradle b/gradle/dependency-versions.gradle
index c8bd830..fe2e446 100644
--- a/gradle/dependency-versions.gradle
+++ b/gradle/dependency-versions.gradle
@@ -31,6 +31,7 @@
leveldbVersion = "1.8"
yarnVersion = "2.4.0"
slf4jVersion = "1.6.2"
+ log4jVersion = "1.2.17"
guavaVersion = "17.0"
commonsCodecVersion = "1.9"
}
http://git-wip-us.apache.org/repos/asf/incubator-samza/blob/3f3d80eb/samza-core/src/test/scala/org/apache/samza/metrics/reporter/TestJmxReporter.scala
----------------------------------------------------------------------
diff --git a/samza-core/src/test/scala/org/apache/samza/metrics/reporter/TestJmxReporter.scala b/samza-core/src/test/scala/org/apache/samza/metrics/reporter/TestJmxReporter.scala
index 357b290..f6c8646 100644
--- a/samza-core/src/test/scala/org/apache/samza/metrics/reporter/TestJmxReporter.scala
+++ b/samza-core/src/test/scala/org/apache/samza/metrics/reporter/TestJmxReporter.scala
@@ -44,7 +44,7 @@ object TestJmxReporter {
@BeforeClass
def beforeSetupServers {
- LocateRegistry.createRegistry(4500)
+ LocateRegistry.createRegistry(port)
val mbs = ManagementFactory.getPlatformMBeanServer()
cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs)
cs.start
http://git-wip-us.apache.org/repos/asf/incubator-samza/blob/3f3d80eb/samza-log4j/src/main/java/org/apache/samza/logging/log4j/JmxAppender.java
----------------------------------------------------------------------
diff --git a/samza-log4j/src/main/java/org/apache/samza/logging/log4j/JmxAppender.java b/samza-log4j/src/main/java/org/apache/samza/logging/log4j/JmxAppender.java
new file mode 100644
index 0000000..27c9a29
--- /dev/null
+++ b/samza-log4j/src/main/java/org/apache/samza/logging/log4j/JmxAppender.java
@@ -0,0 +1,123 @@
+/*
+ * 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.samza.logging.log4j;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.LoggingEvent;
+
+/**
+ * <p>
+ * JmxAppender is a simple class that exposes Log4J's getLevel and setLevel APIs
+ * through a JMX MBean. To enable this MBean, simply include the appender in
+ * log4j.xml:
+ * </p>
+ *
+ * <code>
+ * <appender name="jmx" class="org.apache.samza.logging.log4j.JmxAppender"/>
+ * </code>
+ *
+ * <p>
+ * And then enable it as a root logger:
+ * </p>
+ *
+ * <code>
+ * <root>
+ * <!-- ...other stuff... -->
+ * <appender-ref ref="jmx" />
+ * </root>
+ * </code>
+ */
+public class JmxAppender extends AppenderSkeleton {
+ public static final String JMX_OBJECT_DOMAIN = JmxAppender.class.getName();
+ public static final String JMX_OBJECT_TYPE = "jmx-log4j-appender";
+ public static final String JMX_OBJECT_NAME = "jmx-log4j-appender";
+
+ private static final Logger log = Logger.getLogger(JmxAppender.class.getName());
+
+ public JmxAppender() {
+ this(ManagementFactory.getPlatformMBeanServer());
+ }
+
+ /**
+ * Calling the default constructor causes this appender to register JmxLog4J
+ * as a JMX MBean.
+ */
+ public JmxAppender(MBeanServer mbeanServer) {
+ super();
+
+ try {
+ JmxLog4J mbean = new JmxLog4J();
+ ObjectName name = new ObjectName(JMX_OBJECT_DOMAIN + ":type=" + JMX_OBJECT_TYPE + ",name=" + JMX_OBJECT_NAME);
+ mbeanServer.registerMBean(mbean, name);
+ } catch (Exception e) {
+ log.error("Unable to register Log4J MBean.", e);
+ }
+ }
+
+ public void close() {
+ log.debug("Ignoring close call.");
+ }
+
+ public boolean requiresLayout() {
+ log.debug("Ignoring requresLayout call.");
+
+ return false;
+ }
+
+ protected void append(LoggingEvent event) {
+ // No op. We're just using the appender as a convenient way to start the
+ // JmxServer without introducing any dependencies anywhere for Log4J.
+ }
+
+ /**
+ * An MBean to expose Log4J's getLevel and setLevel APIs.
+ */
+ public static interface JmxLog4JMBean {
+ public void setLevel(String level);
+
+ public String getLevel();
+ }
+
+ /**
+ * An implementation of JmxLog4JMBean that calls getLevel and setLevel on the
+ * root logger.
+ */
+ public static class JmxLog4J implements JmxLog4JMBean {
+ public void setLevel(String level) {
+ try {
+ LogManager.getRootLogger().setLevel(Level.toLevel(level));
+ } catch (Exception e) {
+ log.error("Unable to set level to: " + level, e);
+ }
+ }
+
+ public String getLevel() {
+ return LogManager.getRootLogger().getLevel().toString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-samza/blob/3f3d80eb/samza-log4j/src/test/java/org/apache/samza/logging/log4j/TestJmxAppender.java
----------------------------------------------------------------------
diff --git a/samza-log4j/src/test/java/org/apache/samza/logging/log4j/TestJmxAppender.java b/samza-log4j/src/test/java/org/apache/samza/logging/log4j/TestJmxAppender.java
new file mode 100644
index 0000000..036d80c
--- /dev/null
+++ b/samza-log4j/src/test/java/org/apache/samza/logging/log4j/TestJmxAppender.java
@@ -0,0 +1,136 @@
+/*
+ * 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.samza.logging.log4j;
+
+import java.lang.management.ManagementFactory;
+import java.rmi.registry.LocateRegistry;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.LoggingEvent;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/*
+ * These tests assume that log4j.xml and log4j are both set on the classpath
+ * with the JmxAppender added as a root-level appender.
+ */
+public class TestJmxAppender {
+ public static final int port = 5500;
+ public static final JMXServiceURL url = getJmxServiceURL();
+ private static JMXConnectorServer cs = null;
+ private static final Logger log = Logger.getLogger(TestJmxAppender.class.getName());
+
+ private static JMXServiceURL getJmxServiceURL() {
+ try {
+ return new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + port + "/jmxapitestrmi");
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @BeforeClass
+ public static void beforeSetupServers() throws Exception {
+ LocateRegistry.createRegistry(port);
+ MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
+ cs.start();
+ }
+
+ @AfterClass
+ public static void afterCleanLogDirs() throws Exception {
+ if (cs != null) {
+ cs.stop();
+ }
+ }
+
+ @Test
+ public void testJmxAppender() throws Exception {
+ MBeanServerConnection mbserver = JMXConnectorFactory.connect(url).getMBeanServerConnection();
+ ObjectName objectName = new ObjectName(JmxAppender.JMX_OBJECT_DOMAIN + ":type=" + JmxAppender.JMX_OBJECT_TYPE + ",name=" + JmxAppender.JMX_OBJECT_NAME);
+ String level = null;
+ MockAppender mockAppender = new MockAppender();
+ Logger.getRootLogger().addAppender(mockAppender);
+
+ // Check INFO is set (from log4j.xml).
+ level = (String) mbserver.getAttribute(objectName, "Level");
+ assertEquals("INFO", level);
+
+ log.info("info1");
+ log.debug("debug1");
+
+ // Set to debug.
+ mbserver.setAttribute(objectName, new Attribute("Level", "debug"));
+
+ // Check DEBUG is set.
+ level = (String) mbserver.getAttribute(objectName, "Level");
+ assertEquals("DEBUG", level);
+
+ log.info("info2");
+ log.debug("debug2");
+
+ List<LoggingEvent> logLines = mockAppender.getLogLines();
+
+ // Should not have debug1 because log level is info at first.
+ Iterator<LoggingEvent> logLineIterator = logLines.iterator();
+ assertEquals(3, logLines.size());
+ assertEquals("info1", logLineIterator.next().getMessage());
+ assertEquals("info2", logLineIterator.next().getMessage());
+ assertEquals("debug2", logLineIterator.next().getMessage());
+ }
+
+ public static final class MockAppender extends AppenderSkeleton {
+ private final List<LoggingEvent> logLines;
+
+ public MockAppender() {
+ logLines = new ArrayList<LoggingEvent>();
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public boolean requiresLayout() {
+ return false;
+ }
+
+ @Override
+ protected void append(LoggingEvent event) {
+ logLines.add(event);
+ }
+
+ public List<LoggingEvent> getLogLines() {
+ return logLines;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-samza/blob/3f3d80eb/samza-log4j/src/test/resources/log4j.xml
----------------------------------------------------------------------
diff --git a/samza-log4j/src/test/resources/log4j.xml b/samza-log4j/src/test/resources/log4j.xml
new file mode 100644
index 0000000..acbbc86
--- /dev/null
+++ b/samza-log4j/src/test/resources/log4j.xml
@@ -0,0 +1,35 @@
+<?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. -->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="jmx" class="org.apache.samza.logging.log4j.JmxAppender">
+ </appender>
+
+ <appender name="console" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n" />
+ </layout>
+ </appender>
+
+ <logger name="org.apache.hadoop">
+ <level value="off" />
+ </logger>
+
+ <root>
+ <priority value="info" />
+ <appender-ref ref="console" />
+ <appender-ref ref="jmx" />
+ </root>
+
+</log4j:configuration>
http://git-wip-us.apache.org/repos/asf/incubator-samza/blob/3f3d80eb/settings.gradle
----------------------------------------------------------------------
diff --git a/settings.gradle b/settings.gradle
index db5c32b..325cac2 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -16,10 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
-include 'samza-api', 'samza-core', 'samza-kafka', 'samza-kv', 'samza-kv-inmemory', 'samza-kv-leveldb', 'samza-serializers', 'samza-shell', 'samza-yarn', 'samza-test'
+include \
+ 'samza-api',
+ 'samza-core',
+ 'samza-kafka',
+ 'samza-kv',
+ 'samza-kv-inmemory',
+ 'samza-kv-leveldb',
+ 'samza-log4j',
+ 'samza-serializers',
+ 'samza-shell',
+ 'samza-yarn',
+ 'samza-test'
rootProject.children.each {
- if (it.name != 'samza-api' && it.name != 'samza-shell') {
+ if (it.name != 'samza-api' && it.name != 'samza-shell' && it.name != 'samza-log4j') {
it.name = it.name + "_" + scalaVersion
}
}