You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@falcon.apache.org by ra...@apache.org on 2014/09/10 23:27:11 UTC
git commit: FALCON-696 Pull oozie logs at the end of tests.
Contributed by Raghav Kumar Gautam
Repository: incubator-falcon
Updated Branches:
refs/heads/master e82042def -> 5836d352c
FALCON-696 Pull oozie logs at the end of tests. Contributed by Raghav Kumar Gautam
Project: http://git-wip-us.apache.org/repos/asf/incubator-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-falcon/commit/5836d352
Tree: http://git-wip-us.apache.org/repos/asf/incubator-falcon/tree/5836d352
Diff: http://git-wip-us.apache.org/repos/asf/incubator-falcon/diff/5836d352
Branch: refs/heads/master
Commit: 5836d352c2cff32ead3019157735658cd86ec3ac
Parents: e82042d
Author: Raghav Kumar Gautam <ra...@apache.org>
Authored: Wed Sep 10 14:26:41 2014 -0700
Committer: Raghav Kumar Gautam <ra...@apache.org>
Committed: Wed Sep 10 14:26:41 2014 -0700
----------------------------------------------------------------------
falcon-regression/CHANGES.txt | 2 +
.../falcon/regression/core/util/Config.java | 3 +
.../falcon/regression/core/util/LogUtil.java | 321 +++++++++++++++++++
.../falcon/regression/TestngListener.java | 39 ++-
4 files changed, 356 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/5836d352/falcon-regression/CHANGES.txt
----------------------------------------------------------------------
diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt
index b74a4ee..d360e9b 100644
--- a/falcon-regression/CHANGES.txt
+++ b/falcon-regression/CHANGES.txt
@@ -9,6 +9,8 @@ Trunk (Unreleased)
via Samarth Gupta)
IMPROVEMENTS
+ FALCON-696 Pull oozie logs at the end of tests (Raghav Kumar Gautam)
+
FALCON-675 Request URLS moved from parameters into methods in falcon-regression (Ruslan
Ostafiychuk)
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/5836d352/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Config.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Config.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Config.java
index a897661..9ae3f0b 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Config.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/Config.java
@@ -52,4 +52,7 @@ public final class Config {
return INSTANCE.confObj.getString(key, defaultValue);
}
+ public static boolean getBoolean(String key, boolean defaultValue) {
+ return INSTANCE.confObj.getBoolean(key, defaultValue);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/5836d352/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/LogUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/LogUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/LogUtil.java
new file mode 100644
index 0000000..42583fa
--- /dev/null
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/LogUtil.java
@@ -0,0 +1,321 @@
+/**
+ * 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.falcon.regression.core.util;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.falcon.regression.core.helpers.ColoHelper;
+import org.apache.log4j.Logger;
+import org.apache.oozie.client.BundleJob;
+import org.apache.oozie.client.CoordinatorAction;
+import org.apache.oozie.client.CoordinatorJob;
+import org.apache.oozie.client.OozieClient;
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.client.WorkflowAction;
+import org.apache.oozie.client.WorkflowJob;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.List;
+
+public class LogUtil {
+ private static final Logger logger = Logger.getLogger(LogUtil.class);
+ private static final char nl = '\n';
+ private static final String hr = StringUtils.repeat("-", 80);
+ private static final String hr2 = StringUtils.repeat("-", 120);
+ private static final String hr3 = StringUtils.repeat("-", 160);
+
+ private LogUtil() {
+ throw new AssertionError("Instantiating utility class...");
+ }
+
+ private enum OozieDump {
+ BundleDump {
+ @Override
+ void writeLogs(OozieClient oozieClient, String location, Collection<File> filter) {
+ final List<BundleJob> bundleJobsInfo;
+ try {
+ bundleJobsInfo = oozieClient.getBundleJobsInfo("", 0, 1000000);
+ } catch (OozieClientException e) {
+ logger.error("Couldn't fetch list of bundles. Exception: " + e);
+ return;
+ }
+ for (BundleJob oneJobInfo : bundleJobsInfo) {
+ final String bundleJobId = oneJobInfo.getId();
+ writeOneJobInfo(oozieClient, bundleJobId, location, filter);
+ writeOneJobLog(oozieClient, bundleJobId, location, filter);
+ }
+ }
+
+ /**
+ * Pull and dump info of one job.
+ * @param oozieClient oozie client that will be used for pulling log
+ * @param bundleJobId job id of the bundle job
+ * @param location local location where logs will be dumped
+ * @param filter list of files that have already been dumped
+ */
+ private void writeOneJobInfo(OozieClient oozieClient, String bundleJobId,
+ String location, Collection<File> filter) {
+ final String fileName = OSUtil.getPath(location, bundleJobId + "-info.log");
+ final File file = new File(fileName);
+ if (filter != null && filter.contains(file)) {
+ return;
+ }
+ final BundleJob info;
+ try {
+ info = oozieClient.getBundleJobInfo(bundleJobId);
+ } catch (OozieClientException e) {
+ logger.error("Couldn't fetch bundle info for " + bundleJobId + ". " +
+ "Exception: " + e);
+ return;
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("Bundle ID : ").append(info.getId()).append(nl);
+ sb.append(hr).append(nl);
+ sb.append("Bundle Name : ").append(info.getAppName()).append(nl);
+ sb.append("App Path : ").append(info.getAppPath()).append(nl);
+ sb.append("Status : ").append(info.getStatus()).append(nl);
+ sb.append("User : ").append(info.getUser()).append(nl);
+ sb.append("Created : ").append(info.getCreatedTime()).append(nl);
+ sb.append("Started : ").append(info.getStartTime()).append(nl);
+ sb.append("EndTime : ").append(info.getEndTime()).append(nl);
+ sb.append("Kickoff time : ").append(info.getKickoffTime()).append(nl);
+ sb.append(hr2).append(nl);
+ final String format = "%-40s %-10s %-5s %-10s %-30s %-20s";
+ sb.append(String.format(format,
+ "Job ID", "Status", "Freq", "Unit", "Started", "Next Materialized")).append(nl);
+ sb.append(hr2).append(nl);
+ for (CoordinatorJob cj : info.getCoordinators()) {
+ sb.append(String.format(format,
+ cj.getId(), cj.getStatus(), cj.getFrequency(), cj.getTimeUnit(), cj.getStartTime(),
+ cj.getNextMaterializedTime())).append(nl);
+ }
+ sb.append(hr2).append(nl);
+ try {
+ FileUtils.writeStringToFile(file, sb.toString());
+ } catch (IOException e) {
+ logger.error("Couldn't write bundle info for " + bundleJobId + ". " +
+ "Exception: " + e);
+ }
+ }
+ },
+
+ CoordDump {
+ @Override
+ void writeLogs(OozieClient oozieClient, String location, Collection<File> filter) {
+ final List<CoordinatorJob> coordJobsInfo;
+ try {
+ coordJobsInfo = oozieClient.getCoordJobsInfo("", 0, 1000000);
+ } catch (OozieClientException e) {
+ logger.error("Couldn't fetch list of bundles. Exception: " + e);
+ return;
+ }
+ for (CoordinatorJob oneJobInfo : coordJobsInfo) {
+ final String coordJobId = oneJobInfo.getId();
+ writeOneJobInfo(oozieClient, coordJobId, location, filter);
+ writeOneJobLog(oozieClient, coordJobId, location, filter);
+ }
+ }
+
+ /**
+ * Pull and dump info of one job.
+ * @param oozieClient oozie client that will be used for pulling log
+ * @param coordJobId job id of the coordinator job
+ * @param location local location where logs will be dumped
+ * @param filter list of files that have already been dumped
+ */
+ private void writeOneJobInfo(OozieClient oozieClient, String coordJobId,
+ String location, Collection<File> filter) {
+ final String fileName = OSUtil.getPath(location, coordJobId + "-info.log");
+ final File file = new File(fileName);
+ if (filter != null && filter.contains(file)) {
+ return;
+ }
+ final CoordinatorJob info;
+ try {
+ info = oozieClient.getCoordJobInfo(coordJobId);
+ } catch (OozieClientException e) {
+ logger.error("Couldn't fetch bundle info for " + coordJobId + ". " +
+ "Exception: " + e);
+ return;
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("Coordinator Job ID : ").append(info.getId()).append(nl);
+ sb.append(hr).append(nl);
+ sb.append("Job Name : ").append(info.getAppName()).append(nl);
+ sb.append("App Path : ").append(info.getAppPath()).append(nl);
+ sb.append("Status : ").append(info.getStatus()).append(nl);
+ sb.append("User : ").append(info.getUser()).append(nl);
+ sb.append("Started : ").append(info.getStartTime()).append(nl);
+ sb.append("EndTime : ").append(info.getEndTime()).append(nl);
+ sb.append(hr3).append(nl);
+ final String format = "%-40s %-10s %-40s %-10s %-30s %-30s";
+ sb.append(String.format(format,
+ "Job ID", "Status", "Ext ID", "Err Code", "Created","Nominal Time")).append(nl);
+ sb.append(hr3).append(nl);
+ for (CoordinatorAction cj : info.getActions()) {
+ sb.append(String.format(format,
+ cj.getId(), cj.getStatus(), cj.getExternalId(), cj.getErrorCode(),
+ cj.getCreatedTime(), cj.getNominalTime())).append(nl);
+ }
+ sb.append(hr3).append(nl);
+ try {
+ FileUtils.writeStringToFile(file, sb.toString());
+ } catch (IOException e) {
+ logger.error("Couldn't write coord job info for " + coordJobId + ". " +
+ "Exception: " + e);
+ }
+ }
+ },
+
+ WfDump {
+ @Override
+ void writeLogs(OozieClient oozieClient, String location, Collection<File> filter) {
+ final List<WorkflowJob> wfJobsInfo;
+ try {
+ wfJobsInfo = oozieClient.getJobsInfo("", 0, 1000000);
+ } catch (OozieClientException e) {
+ logger.error("Couldn't fetch list of bundles. Exception: " + e);
+ return;
+ }
+ for (WorkflowJob oneJobInfo : wfJobsInfo) {
+ final String wfJobId = oneJobInfo.getId();
+ writeOneJobInfo(oozieClient, wfJobId, location, filter);
+ writeOneJobLog(oozieClient, wfJobId, location, filter);
+ }
+ }
+
+ /**
+ * Pull and dump info of one job.
+ * @param oozieClient oozie client that will be used for pulling log
+ * @param wfJobId job id of the workflow job
+ * @param location local location where logs will be dumped
+ * @param filter list of files that have already been dumped
+ */
+ private void writeOneJobInfo(OozieClient oozieClient, String wfJobId,
+ String location, Collection<File> filter) {
+ final String fileName = OSUtil.getPath(location, wfJobId + "-info.log");
+ final File file = new File(fileName);
+ if (filter != null && filter.contains(file)) {
+ return;
+ }
+ final WorkflowJob info;
+ try {
+ info = oozieClient.getJobInfo(wfJobId);
+ } catch (OozieClientException e) {
+ logger.error("Couldn't fetch bundle info for " + wfJobId + ". Exception: " + e);
+ return;
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("Workflow Job ID : ").append(info.getId()).append(nl);
+ sb.append(hr).append(nl);
+ sb.append("Wf Name : ").append(info.getAppName()).append(nl);
+ sb.append("App Path : ").append(info.getAppPath()).append(nl);
+ sb.append("Status : ").append(info.getStatus()).append(nl);
+ sb.append("Run : ").append(info.getRun()).append(nl);
+ sb.append("User : ").append(info.getUser()).append(nl);
+ sb.append("Group : ").append(info.getGroup()).append(nl);
+ sb.append("Created : ").append(info.getCreatedTime()).append(nl);
+ sb.append("Started : ").append(info.getStartTime()).append(nl);
+ sb.append("Last Modified : ").append(info.getLastModifiedTime()).append(nl);
+ sb.append("EndTime : ").append(info.getEndTime()).append(nl);
+ sb.append("External ID : ").append(info.getExternalId()).append(nl);
+ sb.append(nl).append("Actions").append(nl);
+ sb.append(hr3).append(nl);
+ final String format = "%-80s %-10s %-40s %-15s %-10s";
+ sb.append(String.format(format,
+ "Job ID", "Status", "Ext ID", "Ext Status", "Err Code")).append(nl);
+ sb.append(hr3).append(nl);
+ for (WorkflowAction cj : info.getActions()) {
+ sb.append(String.format(format,
+ cj.getId(), cj.getStatus(), cj.getExternalId(), cj.getExternalStatus(),
+ cj.getErrorCode())).append(nl);
+ }
+ sb.append(hr3).append(nl);
+ try {
+ FileUtils.writeStringToFile(file, sb.toString());
+ } catch (IOException e) {
+ logger.error("Couldn't write wf job info for " + wfJobId + ". Exception: " + e);
+ }
+ }
+ },
+ ;
+
+ /**
+ * Pull and dump info and log of all jobs of a type
+ * @param oozieClient oozie client that will be used for pulling log
+ * @param location local location where logs will be dumped
+ * @param filter list of files that have already been dumped
+ */
+ abstract void writeLogs(OozieClient oozieClient, String location, Collection<File> filter);
+
+ /**
+ * Pull and dump log of one job.
+ * @param oozieClient oozie client that will be used for pulling log
+ * @param jobId job id of the job
+ * @param location local location where logs will be dumped
+ * @param filter list of files that have already been dumped
+ */
+ private static void writeOneJobLog(OozieClient oozieClient, String jobId,
+ String location, Collection<File> filter) {
+ final String fileName = OSUtil.getPath(location, jobId + ".log");
+ assert fileName != null;
+ final File file = new File(fileName);
+ if (filter != null && filter.contains(file)) {
+ return;
+ }
+ try {
+ oozieClient.getJobLog(jobId, "", "", new PrintStream(file));
+ } catch (OozieClientException e) {
+ logger.error("Couldn't fetch log for " + jobId + ". Exception: " + e);
+ } catch (FileNotFoundException e) {
+ logger.error("Couldn't write log for " + jobId + ". Exception: " + e);
+ }
+ }
+ }
+
+ /**
+ * Pulls and dumps oozie logs at a configured location.
+ * @param coloHelper coloHelper of the cluster from which oozie logs are going to be pulled
+ * @param logLocation local location at which logs are going to be dumped
+ */
+ public static void writeOozieLogs(ColoHelper coloHelper, String logLocation) {
+ final OozieClient oozieClient = coloHelper.getFeedHelper().getOozieClient();
+ final String hostname = coloHelper.getClusterHelper().getQaHost();
+ final String oozieLogLocation = OSUtil.getPath(logLocation + "oozie_logs", hostname);
+ assert oozieLogLocation != null;
+ final File directory = new File(oozieLogLocation);
+ if (!directory.exists()) {
+ try {
+ FileUtils.forceMkdir(directory);
+ } catch (IOException e) {
+ logger.error("Directory creation failed for: " + directory + ". Exception: " + e);
+ return;
+ }
+ }
+ final Collection<File> filter = FileUtils.listFiles(directory, null, true);
+ for (OozieDump oozieDump : OozieDump.values()) {
+ oozieDump.writeLogs(oozieClient, oozieLogLocation, filter);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/5836d352/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
index 5cba005..e3af96d 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/TestngListener.java
@@ -20,12 +20,17 @@ package org.apache.falcon.regression;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.falcon.regression.core.helpers.ColoHelper;
+import org.apache.falcon.regression.core.util.Config;
+import org.apache.falcon.regression.core.util.LogUtil;
import org.apache.falcon.regression.core.util.OSUtil;
import org.apache.falcon.regression.testHelper.BaseUITestClass;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
+import org.testng.IExecutionListener;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
@@ -34,29 +39,25 @@ import java.io.File;
import java.io.IOException;
import java.util.Arrays;
-public class TestngListener implements ITestListener {
+public class TestngListener implements ITestListener, IExecutionListener {
private static final Logger logger = Logger.getLogger(TestngListener.class);
+ private final String hr = StringUtils.repeat("-", 100);
@Override
public void onTestStart(ITestResult result) {
- logLine();
+ logger.info(hr);
logger.info(
String.format("Testing going to start for: %s.%s(%s)", result.getTestClass().getName(),
result.getName(), Arrays.toString(result.getParameters())));
NDC.push(result.getName());
}
- private void logLine() {
- logger.info(
- "-----------------------------------------------------------------------------------------------");
- }
-
private void logEndOfTest(ITestResult result, String outcome) {
logger.info(
String.format("Testing going to end for: %s.%s(%s) %s", result.getTestClass().getName(),
result.getName(), Arrays.toString(result.getParameters()), outcome));
NDC.pop();
- logLine();
+ logger.info(hr);
}
@Override
@@ -80,7 +81,7 @@ public class TestngListener implements ITestListener {
}
logger.info(ExceptionUtils.getStackTrace(result.getThrowable()));
- logLine();
+ logger.info(hr);
}
@Override
@@ -100,4 +101,24 @@ public class TestngListener implements ITestListener {
@Override
public void onFinish(ITestContext context) {
}
+
+ @Override
+ public void onExecutionStart() {
+ }
+
+ @Override
+ public void onExecutionFinish() {
+ if (!Config.getBoolean("log.capture.oozie", false)) {
+ logger.info("oozie log capturing is disabled");
+ return;
+ }
+ final String logLocation = Config.getProperty("log.capture.location", "./");
+ final String[] serverNames = Config.getStringArray("servers");
+ for (final String serverName : serverNames) {
+ final ColoHelper coloHelper = new ColoHelper(serverName.trim());
+ LogUtil.writeOozieLogs(coloHelper, logLocation);
+ }
+ }
+
+
}