azkaban-developers

Redirect System out and err to log4j (#841) Created a class

12/5/2016 6:51:29 PM
3.12.0

Details

diff --git a/azkaban-common/src/main/java/azkaban/utils/StdOutErrRedirect.java b/azkaban-common/src/main/java/azkaban/utils/StdOutErrRedirect.java
new file mode 100644
index 0000000..f921267
--- /dev/null
+++ b/azkaban-common/src/main/java/azkaban/utils/StdOutErrRedirect.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2016 LinkedIn Corp.
+ *
+ * Licensed 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 azkaban.utils;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+/**
+ * A class to encapsulate the redirection of stdout and stderr to log4j
+ * This allows us to catch messages written to the console (although we should
+ * not be using System.out to write out).
+ */
+
+public class StdOutErrRedirect {
+  private static final Logger logger = Logger.getLogger(StdOutErrRedirect.class);
+  private static final PrintStream infoStream = createStream(System.out, Level.INFO);
+  private static final PrintStream errorStream = createStream(System.out, Level.ERROR);
+
+  public static void redirectOutAndErrToLog() {
+    System.setOut(infoStream);
+    System.setErr(errorStream);
+  }
+
+  private static PrintStream createStream(PrintStream stream, Level level) {
+    return new LogStream(stream, level);
+  };
+
+  private static class LogStream extends PrintStream {
+    private final Level level;
+
+    public LogStream(OutputStream out, Level level) {
+      super(out);
+      this.level = level;
+    }
+
+    // Underlying mechanism to log to log4j - all print methods will use this
+    private void write(String string) {
+      logger.log(level, string);
+    }
+
+    // String
+    @Override
+    public void println(final String string) {
+      print(string);
+    }
+
+    @Override
+    public void print(final String string) {
+      write(string);
+    }
+
+    // Boolean
+    @Override
+    public void println(final boolean bool) {
+        print(bool);
+    }
+
+    @Override
+    public void print(final boolean bool) {
+        write(String.valueOf(bool));
+    }
+
+    // Int
+    @Override
+    public void println(final int i) {
+        print(i);
+    }
+
+    @Override
+    public void print(final int i) {
+        write(String.valueOf(i));
+    }
+
+    // Float
+    @Override
+    public void println(final float f) {
+        print(f);
+    }
+
+    @Override
+    public void print(final float f) {
+        write(String.valueOf(f));
+    }
+
+    // Char
+    @Override
+    public void println(final char c) {
+        print(c);
+    }
+
+    @Override
+    public void print(final char c) {
+        write(String.valueOf(c));
+    }
+
+    // Long
+    @Override
+    public void println(final long l) {
+        print(l);
+    }
+
+    @Override
+    public void print(final long l) {
+        write(String.valueOf(l));
+    }
+
+    // Double
+    @Override
+    public void println(final double d) {
+        print(d);
+    }
+
+    @Override
+    public void print(final double d) {
+        write(String.valueOf(d));
+    }
+
+    // Char []
+    @Override
+    public void println(final char[] c) {
+        print(c);
+    }
+
+    @Override
+    public void print(final char[] c) {
+        write(new String(c));
+    }
+
+    // Object
+    @Override
+    public void println(final Object o) {
+        print(o);
+    }
+
+    @Override
+    public void print(final Object o) {
+        write(o.toString());
+    }
+  }
+}
diff --git a/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecutorServer.java b/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecutorServer.java
index 0a69dc4..3dfc4c3 100644
--- a/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecutorServer.java
+++ b/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecutorServer.java
@@ -70,6 +70,7 @@ import azkaban.project.JdbcProjectLoader;
 import azkaban.project.ProjectLoader;
 import azkaban.server.AzkabanServer;
 import azkaban.utils.Props;
+import azkaban.utils.StdOutErrRedirect;
 import azkaban.utils.SystemMemoryInfo;
 import azkaban.utils.Utils;
 import azkaban.metrics.MetricsManager;
@@ -356,6 +357,9 @@ public class AzkabanExecutorServer {
    * @throws IOException
    */
   public static void main(String[] args) throws Exception {
+    // Redirect all std out and err messages into log4j
+    StdOutErrRedirect.redirectOutAndErrToLog();
+
     logger.info("Starting Jetty Azkaban Executor...");
     Props azkabanSettings = AzkabanServer.loadProps(args);
 
diff --git a/azkaban-solo-server/src/main/resources/log4j.properties b/azkaban-solo-server/src/main/resources/log4j.properties
index b67828a..705b927 100644
--- a/azkaban-solo-server/src/main/resources/log4j.properties
+++ b/azkaban-solo-server/src/main/resources/log4j.properties
@@ -1,7 +1,5 @@
 log4j.rootLogger=INFO, Console
-log4j.logger.azkaban.webapp=INFO, server
-log4j.logger.azkaban.execapp=INFO, server
-log4j.logger.azkaban.soloserver=INFO, server
+log4j.logger.azkaban=INFO, server
 
 log4j.appender.server=org.apache.log4j.RollingFileAppender
 log4j.appender.server.layout=org.apache.log4j.PatternLayout
diff --git a/azkaban-web-server/src/main/java/azkaban/webapp/AzkabanWebServer.java b/azkaban-web-server/src/main/java/azkaban/webapp/AzkabanWebServer.java
index c5d2ff9..2053f0b 100644
--- a/azkaban-web-server/src/main/java/azkaban/webapp/AzkabanWebServer.java
+++ b/azkaban-web-server/src/main/java/azkaban/webapp/AzkabanWebServer.java
@@ -89,6 +89,7 @@ import azkaban.utils.Emailer;
 import azkaban.utils.FileIOUtils;
 import azkaban.utils.Props;
 import azkaban.utils.PropsUtils;
+import azkaban.utils.StdOutErrRedirect;
 import azkaban.utils.Utils;
 import azkaban.webapp.plugin.PluginRegistry;
 import azkaban.webapp.plugin.TriggerPlugin;
@@ -690,6 +691,9 @@ public class AzkabanWebServer extends AzkabanServer {
    * @param args
    */
   public static void main(String[] args) throws Exception {
+    // Redirect all std out and err messages into log4j
+    StdOutErrRedirect.redirectOutAndErrToLog();
+
     logger.info("Starting Jetty Azkaban Web Server...");
     Props azkabanSettings = AzkabanServer.loadProps(args);