001/** 002* Licensed to the Apache Software Foundation (ASF) under one 003* or more contributor license agreements. See the NOTICE file 004* distributed with this work for additional information 005* regarding copyright ownership. The ASF licenses this file 006* to you under the Apache License, Version 2.0 (the 007* "License"); you may not use this file except in compliance 008* with the License. You may obtain a copy of the License at 009* 010* http://www.apache.org/licenses/LICENSE-2.0 011* 012* Unless required by applicable law or agreed to in writing, software 013* distributed under the License is distributed on an "AS IS" BASIS, 014* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015* See the License for the specific language governing permissions and 016* limitations under the License. 017*/ 018 019package org.apache.hadoop.yarn.client.cli; 020 021import java.io.IOException; 022import java.io.StringReader; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Collections; 026import java.util.List; 027 028import javax.ws.rs.core.MediaType; 029import javax.xml.parsers.DocumentBuilder; 030import javax.xml.parsers.DocumentBuilderFactory; 031 032import org.apache.commons.cli.CommandLine; 033import org.apache.commons.cli.CommandLineParser; 034import org.apache.commons.cli.GnuParser; 035import org.apache.commons.cli.HelpFormatter; 036import org.apache.commons.cli.Option; 037import org.apache.commons.cli.Options; 038import org.apache.commons.cli.ParseException; 039import org.apache.commons.lang.StringUtils; 040import org.apache.hadoop.classification.InterfaceAudience.Public; 041import org.apache.hadoop.classification.InterfaceStability.Evolving; 042import org.apache.hadoop.conf.Configuration; 043import org.apache.hadoop.conf.Configured; 044import org.apache.hadoop.security.UserGroupInformation; 045import org.apache.hadoop.util.Tool; 046import org.apache.hadoop.yarn.api.records.ApplicationId; 047import org.apache.hadoop.yarn.api.records.ApplicationReport; 048import org.apache.hadoop.yarn.api.records.ContainerReport; 049import org.apache.hadoop.yarn.api.records.YarnApplicationState; 050import org.apache.hadoop.yarn.client.api.YarnClient; 051import org.apache.hadoop.yarn.conf.YarnConfiguration; 052import org.apache.hadoop.yarn.exceptions.YarnException; 053import org.apache.hadoop.yarn.logaggregation.LogCLIHelpers; 054import org.apache.hadoop.yarn.util.ConverterUtils; 055import org.apache.hadoop.yarn.util.Times; 056import org.apache.hadoop.yarn.webapp.util.WebAppUtils; 057import org.codehaus.jettison.json.JSONArray; 058import org.codehaus.jettison.json.JSONException; 059import org.codehaus.jettison.json.JSONObject; 060 061import com.google.common.annotations.VisibleForTesting; 062import com.sun.jersey.api.client.Client; 063import com.sun.jersey.api.client.ClientHandlerException; 064import com.sun.jersey.api.client.ClientResponse; 065import com.sun.jersey.api.client.UniformInterfaceException; 066import com.sun.jersey.api.client.WebResource; 067import org.w3c.dom.Document; 068import org.w3c.dom.NodeList; 069import org.xml.sax.InputSource; 070 071@Public 072@Evolving 073public class LogsCLI extends Configured implements Tool { 074 075 private static final String CONTAINER_ID_OPTION = "containerId"; 076 private static final String APPLICATION_ID_OPTION = "applicationId"; 077 private static final String NODE_ADDRESS_OPTION = "nodeAddress"; 078 private static final String APP_OWNER_OPTION = "appOwner"; 079 private static final String AM_CONTAINER_OPTION = "am"; 080 private static final String CONTAINER_LOG_FILES = "logFiles"; 081 public static final String HELP_CMD = "help"; 082 083 @Override 084 public int run(String[] args) throws Exception { 085 086 Options opts = new Options(); 087 opts.addOption(HELP_CMD, false, "Displays help for all commands."); 088 Option appIdOpt = 089 new Option(APPLICATION_ID_OPTION, true, "ApplicationId (required)"); 090 appIdOpt.setRequired(true); 091 opts.addOption(appIdOpt); 092 opts.addOption(CONTAINER_ID_OPTION, true, "ContainerId. " 093 + "By default, it will only print syslog if the application is runing." 094 + " Work with -logFiles to get other logs."); 095 opts.addOption(NODE_ADDRESS_OPTION, true, "NodeAddress in the format " 096 + "nodename:port"); 097 opts.addOption(APP_OWNER_OPTION, true, 098 "AppOwner (assumed to be current user if not specified)"); 099 Option amOption = new Option(AM_CONTAINER_OPTION, true, 100 "Prints the AM Container logs for this application. " 101 + "Specify comma-separated value to get logs for related AM Container. " 102 + "For example, If we specify -am 1,2, we will get the logs for " 103 + "the first AM Container as well as the second AM Container. " 104 + "To get logs for all AM Containers, use -am ALL. " 105 + "To get logs for the latest AM Container, use -am -1. " 106 + "By default, it will only print out syslog. Work with -logFiles " 107 + "to get other logs"); 108 amOption.setValueSeparator(','); 109 amOption.setArgs(Option.UNLIMITED_VALUES); 110 amOption.setArgName("AM Containers"); 111 opts.addOption(amOption); 112 Option logFileOpt = new Option(CONTAINER_LOG_FILES, true, 113 "Work with -am/-containerId and specify comma-separated value " 114 + "to get specified container log files. Use \"ALL\" to fetch all the " 115 + "log files for the container."); 116 logFileOpt.setValueSeparator(','); 117 logFileOpt.setArgs(Option.UNLIMITED_VALUES); 118 logFileOpt.setArgName("Log File Name"); 119 opts.addOption(logFileOpt); 120 121 opts.getOption(APPLICATION_ID_OPTION).setArgName("Application ID"); 122 opts.getOption(CONTAINER_ID_OPTION).setArgName("Container ID"); 123 opts.getOption(NODE_ADDRESS_OPTION).setArgName("Node Address"); 124 opts.getOption(APP_OWNER_OPTION).setArgName("Application Owner"); 125 opts.getOption(AM_CONTAINER_OPTION).setArgName("AM Containers"); 126 127 Options printOpts = new Options(); 128 printOpts.addOption(opts.getOption(HELP_CMD)); 129 printOpts.addOption(opts.getOption(CONTAINER_ID_OPTION)); 130 printOpts.addOption(opts.getOption(NODE_ADDRESS_OPTION)); 131 printOpts.addOption(opts.getOption(APP_OWNER_OPTION)); 132 printOpts.addOption(opts.getOption(AM_CONTAINER_OPTION)); 133 printOpts.addOption(opts.getOption(CONTAINER_LOG_FILES)); 134 135 if (args.length < 1) { 136 printHelpMessage(printOpts); 137 return -1; 138 } 139 if (args[0].equals("-help")) { 140 printHelpMessage(printOpts); 141 return 0; 142 } 143 CommandLineParser parser = new GnuParser(); 144 String appIdStr = null; 145 String containerIdStr = null; 146 String nodeAddress = null; 147 String appOwner = null; 148 boolean getAMContainerLogs = false; 149 String[] logFiles = null; 150 List<String> amContainersList = new ArrayList<String>(); 151 try { 152 CommandLine commandLine = parser.parse(opts, args, true); 153 appIdStr = commandLine.getOptionValue(APPLICATION_ID_OPTION); 154 containerIdStr = commandLine.getOptionValue(CONTAINER_ID_OPTION); 155 nodeAddress = commandLine.getOptionValue(NODE_ADDRESS_OPTION); 156 appOwner = commandLine.getOptionValue(APP_OWNER_OPTION); 157 getAMContainerLogs = commandLine.hasOption(AM_CONTAINER_OPTION); 158 if (getAMContainerLogs) { 159 String[] amContainers = commandLine.getOptionValues(AM_CONTAINER_OPTION); 160 for (String am : amContainers) { 161 boolean errorInput = false; 162 if (!am.trim().equalsIgnoreCase("ALL")) { 163 try { 164 int id = Integer.parseInt(am.trim()); 165 if (id != -1 && id <= 0) { 166 errorInput = true; 167 } 168 } catch (NumberFormatException ex) { 169 errorInput = true; 170 } 171 if (errorInput) { 172 System.err.println( 173 "Invalid input for option -am. Valid inputs are 'ALL', -1 " 174 + "and any other integer which is larger than 0."); 175 printHelpMessage(printOpts); 176 return -1; 177 } 178 amContainersList.add(am.trim()); 179 } else { 180 amContainersList.add("ALL"); 181 break; 182 } 183 } 184 } 185 if (commandLine.hasOption(CONTAINER_LOG_FILES)) { 186 logFiles = commandLine.getOptionValues(CONTAINER_LOG_FILES); 187 } 188 } catch (ParseException e) { 189 System.err.println("options parsing failed: " + e.getMessage()); 190 printHelpMessage(printOpts); 191 return -1; 192 } 193 194 if (appIdStr == null) { 195 System.err.println("ApplicationId cannot be null!"); 196 printHelpMessage(printOpts); 197 return -1; 198 } 199 200 ApplicationId appId = null; 201 try { 202 appId = ConverterUtils.toApplicationId(appIdStr); 203 } catch (Exception e) { 204 System.err.println("Invalid ApplicationId specified"); 205 return -1; 206 } 207 208 LogCLIHelpers logCliHelper = new LogCLIHelpers(); 209 logCliHelper.setConf(getConf()); 210 211 if (appOwner == null || appOwner.isEmpty()) { 212 appOwner = UserGroupInformation.getCurrentUser().getShortUserName(); 213 } 214 215 YarnApplicationState appState = YarnApplicationState.NEW; 216 try { 217 appState = getApplicationState(appId); 218 if (appState == YarnApplicationState.NEW 219 || appState == YarnApplicationState.NEW_SAVING 220 || appState == YarnApplicationState.SUBMITTED) { 221 System.out.println("Logs are not avaiable right now."); 222 return -1; 223 } 224 } catch (IOException | YarnException e) { 225 System.err.println("Unable to get ApplicationState." 226 + " Attempting to fetch logs directly from the filesystem."); 227 } 228 229 // To get am logs 230 if (getAMContainerLogs) { 231 // if we do not specify the value for CONTAINER_LOG_FILES option, 232 // we will only output syslog 233 if (logFiles == null || logFiles.length == 0) { 234 logFiles = new String[] { "syslog" }; 235 } 236 // If the application is running, we will call the RM WebService 237 // to get the AppAttempts which includes the nodeHttpAddress 238 // and containerId for all the AM Containers. 239 // After that, we will call NodeManager webService to get the 240 // related logs 241 if (appState == YarnApplicationState.ACCEPTED 242 || appState == YarnApplicationState.RUNNING) { 243 return printAMContainerLogs(getConf(), appIdStr, amContainersList, 244 logFiles, logCliHelper, appOwner, false); 245 } else { 246 // If the application is in the final state, we will call RM webservice 247 // to get all AppAttempts information first. If we get nothing, 248 // we will try to call AHS webservice to get related AppAttempts 249 // which includes nodeAddress for the AM Containers. 250 // After that, we will use nodeAddress and containerId 251 // to get logs from HDFS directly. 252 if (getConf().getBoolean(YarnConfiguration.APPLICATION_HISTORY_ENABLED, 253 YarnConfiguration.DEFAULT_APPLICATION_HISTORY_ENABLED)) { 254 return printAMContainerLogs(getConf(), appIdStr, amContainersList, 255 logFiles, logCliHelper, appOwner, true); 256 } else { 257 System.out 258 .println( 259 "Can not get AMContainers logs for the application:" + appId); 260 System.out.println("This application:" + appId + " is finished." 261 + " Please enable the application history service. Or Using " 262 + "yarn logs -applicationId <appId> -containerId <containerId> " 263 + "--nodeAddress <nodeHttpAddress> to get the container logs"); 264 return -1; 265 } 266 } 267 } 268 269 int resultCode = 0; 270 if (containerIdStr != null) { 271 // if we provide the node address and the application is in the final 272 // state, we could directly get logs from HDFS. 273 if (nodeAddress != null && isApplicationFinished(appState)) { 274 // if user specified "ALL" as the logFiles param, pass null 275 // to logCliHelper so that it fetches all the logs 276 List<String> logs; 277 if (logFiles == null) { 278 logs = null; 279 } else if (fetchAllLogFiles(logFiles)) { 280 logs = null; 281 } else { 282 logs = Arrays.asList(logFiles); 283 } 284 return logCliHelper.dumpAContainersLogsForALogType(appIdStr, 285 containerIdStr, nodeAddress, appOwner, logs); 286 } 287 try { 288 // If the nodeAddress is not provided, we will try to get 289 // the ContainerReport. In the containerReport, we could get 290 // nodeAddress and nodeHttpAddress 291 ContainerReport report = getContainerReport(containerIdStr); 292 String nodeHttpAddress = 293 report.getNodeHttpAddress().replaceFirst( 294 WebAppUtils.getHttpSchemePrefix(getConf()), ""); 295 String nodeId = report.getAssignedNode().toString(); 296 // If the application is not in the final state, 297 // we will provide the NodeHttpAddress and get the container logs 298 // by calling NodeManager webservice. 299 if (!isApplicationFinished(appState)) { 300 if (logFiles == null || logFiles.length == 0) { 301 logFiles = new String[] { "syslog" }; 302 } 303 printContainerLogsFromRunningApplication(getConf(), appIdStr, 304 containerIdStr, nodeHttpAddress, nodeId, logFiles, logCliHelper, 305 appOwner); 306 } else { 307 String [] requestedLogFiles = logFiles; 308 if(fetchAllLogFiles(logFiles)) { 309 requestedLogFiles = null; 310 } 311 // If the application is in the final state, we will directly 312 // get the container logs from HDFS. 313 printContainerLogsForFinishedApplication(appIdStr, containerIdStr, 314 nodeId, requestedLogFiles, logCliHelper, appOwner); 315 } 316 return resultCode; 317 } catch (IOException | YarnException ex) { 318 System.err.println("Unable to get logs for this container:" 319 + containerIdStr + "for the application:" + appId); 320 if (!getConf().getBoolean(YarnConfiguration.APPLICATION_HISTORY_ENABLED, 321 YarnConfiguration.DEFAULT_APPLICATION_HISTORY_ENABLED)) { 322 System.out.println("Please enable the application history service. Or "); 323 } 324 System.out.println("Using " 325 + "yarn logs -applicationId <appId> -containerId <containerId> " 326 + "--nodeAddress <nodeHttpAddress> to get the container logs"); 327 return -1; 328 } 329 } else { 330 if (nodeAddress == null) { 331 resultCode = 332 logCliHelper.dumpAllContainersLogs(appId, appOwner, System.out); 333 } else { 334 System.out.println("Should at least provide ContainerId!"); 335 printHelpMessage(printOpts); 336 resultCode = -1; 337 } 338 } 339 return resultCode; 340 } 341 342 private YarnApplicationState getApplicationState(ApplicationId appId) 343 throws IOException, YarnException { 344 YarnClient yarnClient = createYarnClient(); 345 346 try { 347 ApplicationReport appReport = yarnClient.getApplicationReport(appId); 348 return appReport.getYarnApplicationState(); 349 } finally { 350 yarnClient.close(); 351 } 352 } 353 354 @VisibleForTesting 355 protected YarnClient createYarnClient() { 356 YarnClient yarnClient = YarnClient.createYarnClient(); 357 yarnClient.init(getConf()); 358 yarnClient.start(); 359 return yarnClient; 360 } 361 362 public static void main(String[] args) throws Exception { 363 Configuration conf = new YarnConfiguration(); 364 LogsCLI logDumper = new LogsCLI(); 365 logDumper.setConf(conf); 366 int exitCode = logDumper.run(args); 367 System.exit(exitCode); 368 } 369 370 private void printHelpMessage(Options options) { 371 System.out.println("Retrieve logs for completed YARN applications."); 372 HelpFormatter formatter = new HelpFormatter(); 373 formatter.printHelp("yarn logs -applicationId <application ID> [OPTIONS]", new Options()); 374 formatter.setSyntaxPrefix(""); 375 formatter.printHelp("general options are:", options); 376 } 377 378 private List<JSONObject> getAMContainerInfoForRMWebService( 379 Configuration conf, String appId) throws ClientHandlerException, 380 UniformInterfaceException, JSONException { 381 Client webServiceClient = Client.create(); 382 String webAppAddress = 383 WebAppUtils.getWebAppBindURL(conf, YarnConfiguration.RM_BIND_HOST, 384 WebAppUtils.getRMWebAppURLWithScheme(conf)); 385 WebResource webResource = webServiceClient.resource(webAppAddress); 386 387 ClientResponse response = 388 webResource.path("ws").path("v1").path("cluster").path("apps") 389 .path(appId).path("appattempts").accept(MediaType.APPLICATION_JSON) 390 .get(ClientResponse.class); 391 JSONObject json = 392 response.getEntity(JSONObject.class).getJSONObject("appAttempts"); 393 JSONArray requests = json.getJSONArray("appAttempt"); 394 List<JSONObject> amContainersList = new ArrayList<JSONObject>(); 395 for (int i = 0; i < requests.length(); i++) { 396 amContainersList.add(requests.getJSONObject(i)); 397 } 398 return amContainersList; 399 } 400 401 private List<JSONObject> getAMContainerInfoForAHSWebService(Configuration conf, 402 String appId) throws ClientHandlerException, UniformInterfaceException, 403 JSONException { 404 Client webServiceClient = Client.create(); 405 String webAppAddress = 406 WebAppUtils.getHttpSchemePrefix(conf) 407 + WebAppUtils.getAHSWebAppURLWithoutScheme(conf); 408 WebResource webResource = webServiceClient.resource(webAppAddress); 409 410 ClientResponse response = 411 webResource.path("ws").path("v1").path("applicationhistory").path("apps") 412 .path(appId).path("appattempts").accept(MediaType.APPLICATION_JSON) 413 .get(ClientResponse.class); 414 JSONObject json = response.getEntity(JSONObject.class); 415 JSONArray requests = json.getJSONArray("appAttempt"); 416 List<JSONObject> amContainersList = new ArrayList<JSONObject>(); 417 for (int i = 0; i < requests.length(); i++) { 418 amContainersList.add(requests.getJSONObject(i)); 419 } 420 Collections.reverse(amContainersList); 421 return amContainersList; 422 } 423 424 private boolean fetchAllLogFiles(String[] logFiles) { 425 if(logFiles != null) { 426 List<String> logs = Arrays.asList(logFiles); 427 if(logs.contains("ALL")) { 428 return true; 429 } 430 } 431 return false; 432 } 433 434 private String[] getContainerLogFiles(Configuration conf, 435 String containerIdStr, String nodeHttpAddress) throws IOException { 436 List<String> logFiles = new ArrayList<>(); 437 Client webServiceClient = Client.create(); 438 try { 439 WebResource webResource = webServiceClient 440 .resource(WebAppUtils.getHttpSchemePrefix(conf) + nodeHttpAddress); 441 ClientResponse response = 442 webResource.path("ws").path("v1").path("node").path("containers") 443 .path(containerIdStr).accept(MediaType.APPLICATION_XML) 444 .get(ClientResponse.class); 445 if (response.getClientResponseStatus().equals(ClientResponse.Status.OK)) { 446 try { 447 String xml = response.getEntity(String.class); 448 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 449 DocumentBuilder db = dbf.newDocumentBuilder(); 450 InputSource is = new InputSource(); 451 is.setCharacterStream(new StringReader(xml)); 452 Document dom = db.parse(is); 453 NodeList elements = dom.getElementsByTagName("containerLogFiles"); 454 for (int i = 0; i < elements.getLength(); i++) { 455 logFiles.add(elements.item(i).getTextContent()); 456 } 457 } catch (Exception e) { 458 System.out.println("Unable to parse xml from webservice. Error:"); 459 System.out.println(e.getMessage()); 460 throw new IOException(e); 461 } 462 } 463 464 } catch (ClientHandlerException | UniformInterfaceException ex) { 465 System.out.println("Unable to fetch log files list"); 466 throw new IOException(ex); 467 } 468 return logFiles.toArray(new String[0]); 469 } 470 471 private void printContainerLogsFromRunningApplication(Configuration conf, 472 String appId, String containerIdStr, String nodeHttpAddress, 473 String nodeId, String[] logFiles, LogCLIHelpers logCliHelper, 474 String appOwner) throws IOException { 475 String [] requestedLogFiles = logFiles; 476 // fetch all the log files for the container 477 if (fetchAllLogFiles(logFiles)) { 478 requestedLogFiles = 479 getContainerLogFiles(getConf(), containerIdStr, nodeHttpAddress); 480 } 481 Client webServiceClient = Client.create(); 482 String containerString = "\n\nContainer: " + containerIdStr; 483 System.out.println(containerString); 484 System.out.println(StringUtils.repeat("=", containerString.length())); 485 486 for (String logFile : requestedLogFiles) { 487 System.out.println("LogType:" + logFile); 488 System.out.println("Log Upload Time:" 489 + Times.format(System.currentTimeMillis())); 490 System.out.println("Log Contents:"); 491 try { 492 WebResource webResource = 493 webServiceClient.resource(WebAppUtils.getHttpSchemePrefix(conf) 494 + nodeHttpAddress); 495 ClientResponse response = 496 webResource.path("ws").path("v1").path("node") 497 .path("containerlogs").path(containerIdStr).path(logFile) 498 .accept(MediaType.TEXT_PLAIN).get(ClientResponse.class); 499 System.out.println(response.getEntity(String.class)); 500 System.out.println("End of LogType:" + logFile); 501 } catch (ClientHandlerException | UniformInterfaceException ex) { 502 System.out.println("Can not find the log file:" + logFile 503 + " for the container:" + containerIdStr + " in NodeManager:" 504 + nodeId); 505 } 506 } 507 // for the case, we have already uploaded partial logs in HDFS 508 logCliHelper.dumpAContainersLogsForALogType(appId, containerIdStr, nodeId, 509 appOwner, Arrays.asList(requestedLogFiles)); 510 } 511 512 private void printContainerLogsForFinishedApplication(String appId, 513 String containerId, String nodeAddress, String[] logFiles, 514 LogCLIHelpers logCliHelper, String appOwner) throws IOException { 515 String containerString = "\n\nContainer: " + containerId; 516 System.out.println(containerString); 517 System.out.println(StringUtils.repeat("=", containerString.length())); 518 logCliHelper.dumpAContainersLogsForALogType(appId, containerId, 519 nodeAddress, appOwner, logFiles != null ? Arrays.asList(logFiles) : null); 520 } 521 522 private ContainerReport getContainerReport(String containerIdStr) 523 throws YarnException, IOException { 524 YarnClient yarnClient = createYarnClient(); 525 try { 526 return yarnClient.getContainerReport(ConverterUtils 527 .toContainerId(containerIdStr)); 528 } finally { 529 yarnClient.close(); 530 } 531 } 532 533 private boolean isApplicationFinished(YarnApplicationState appState) { 534 return appState == YarnApplicationState.FINISHED 535 || appState == YarnApplicationState.FAILED 536 || appState == YarnApplicationState.KILLED; 537 } 538 539 private int printAMContainerLogs(Configuration conf, String appId, 540 List<String> amContainers, String[] logFiles, LogCLIHelpers logCliHelper, 541 String appOwner, boolean applicationFinished) throws Exception { 542 List<JSONObject> amContainersList = null; 543 List<AMLogsRequest> requests = new ArrayList<AMLogsRequest>(); 544 boolean getAMContainerLists = false; 545 String errorMessage = ""; 546 try { 547 amContainersList = getAMContainerInfoForRMWebService(conf, appId); 548 if (amContainersList != null && !amContainersList.isEmpty()) { 549 getAMContainerLists = true; 550 for (JSONObject amContainer : amContainersList) { 551 AMLogsRequest request = new AMLogsRequest(applicationFinished); 552 request.setAmContainerId(amContainer.getString("containerId")); 553 request.setNodeHttpAddress(amContainer.getString("nodeHttpAddress")); 554 request.setNodeId(amContainer.getString("nodeId")); 555 requests.add(request); 556 } 557 } 558 } catch (Exception ex) { 559 errorMessage = ex.getMessage(); 560 if (applicationFinished) { 561 try { 562 amContainersList = getAMContainerInfoForAHSWebService(conf, appId); 563 if (amContainersList != null && !amContainersList.isEmpty()) { 564 getAMContainerLists = true; 565 for (JSONObject amContainer : amContainersList) { 566 AMLogsRequest request = new AMLogsRequest(applicationFinished); 567 request.setAmContainerId(amContainer.getString("amContainerId")); 568 requests.add(request); 569 } 570 } 571 } catch (Exception e) { 572 errorMessage = e.getMessage(); 573 } 574 } 575 } 576 577 if (!getAMContainerLists) { 578 System.err.println("Unable to get AM container informations " 579 + "for the application:" + appId); 580 System.err.println(errorMessage); 581 return -1; 582 } 583 584 if (amContainers.contains("ALL")) { 585 for (AMLogsRequest request : requests) { 586 outputAMContainerLogs(request, conf, appId, logFiles, logCliHelper, 587 appOwner); 588 } 589 System.out.println(); 590 System.out.println("Specified ALL for -am option. " 591 + "Printed logs for all am containers."); 592 } else { 593 for (String amContainer : amContainers) { 594 int amContainerId = Integer.parseInt(amContainer.trim()); 595 if (amContainerId == -1) { 596 outputAMContainerLogs(requests.get(requests.size() - 1), conf, appId, 597 logFiles, logCliHelper, appOwner); 598 } else { 599 if (amContainerId <= requests.size()) { 600 outputAMContainerLogs(requests.get(amContainerId - 1), conf, appId, 601 logFiles, logCliHelper, appOwner); 602 } 603 } 604 } 605 } 606 return 0; 607 } 608 609 private void outputAMContainerLogs(AMLogsRequest request, Configuration conf, 610 String appId, String[] logFiles, LogCLIHelpers logCliHelper, 611 String appOwner) throws Exception { 612 String nodeHttpAddress = request.getNodeHttpAddress(); 613 String containerId = request.getAmContainerId(); 614 String nodeId = request.getNodeId(); 615 616 if (request.isAppFinished()) { 617 if (containerId != null && !containerId.isEmpty()) { 618 if (nodeId == null || nodeId.isEmpty()) { 619 try { 620 nodeId = 621 getContainerReport(containerId).getAssignedNode().toString(); 622 } catch (Exception ex) { 623 System.err.println(ex); 624 nodeId = null; 625 } 626 } 627 if (nodeId != null && !nodeId.isEmpty()) { 628 String [] requestedLogFilesList = null; 629 if(!fetchAllLogFiles(logFiles)) { 630 requestedLogFilesList = logFiles; 631 } 632 printContainerLogsForFinishedApplication(appId, containerId, nodeId, 633 requestedLogFilesList, logCliHelper, appOwner); 634 } 635 } 636 } else { 637 if (nodeHttpAddress != null && containerId != null 638 && !nodeHttpAddress.isEmpty() && !containerId.isEmpty()) { 639 String [] requestedLogFiles = logFiles; 640 // fetch all the log files for the AM 641 if (fetchAllLogFiles(logFiles)) { 642 requestedLogFiles = 643 getContainerLogFiles(getConf(), containerId, nodeHttpAddress); 644 } 645 printContainerLogsFromRunningApplication(conf, appId, containerId, 646 nodeHttpAddress, nodeId, requestedLogFiles, logCliHelper, appOwner); 647 } 648 } 649 } 650 651 private static class AMLogsRequest { 652 private String amContainerId; 653 private String nodeId; 654 private String nodeHttpAddress; 655 private final boolean isAppFinished; 656 657 AMLogsRequest(boolean isAppFinished) { 658 this.isAppFinished = isAppFinished; 659 this.setAmContainerId(""); 660 this.setNodeId(""); 661 this.setNodeHttpAddress(""); 662 } 663 664 public String getAmContainerId() { 665 return amContainerId; 666 } 667 668 public void setAmContainerId(String amContainerId) { 669 this.amContainerId = amContainerId; 670 } 671 672 public String getNodeId() { 673 return nodeId; 674 } 675 676 public void setNodeId(String nodeId) { 677 this.nodeId = nodeId; 678 } 679 680 public String getNodeHttpAddress() { 681 return nodeHttpAddress; 682 } 683 684 public void setNodeHttpAddress(String nodeHttpAddress) { 685 this.nodeHttpAddress = nodeHttpAddress; 686 } 687 688 public boolean isAppFinished() { 689 return isAppFinished; 690 } 691 } 692}