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.File; 022import java.io.IOException; 023import java.io.InputStream; 024import java.io.PrintStream; 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collection; 028import java.util.Collections; 029import java.util.HashSet; 030import java.util.List; 031import java.util.Map; 032import java.util.Set; 033import java.util.TreeMap; 034import java.util.regex.Pattern; 035 036import javax.ws.rs.core.MediaType; 037 038import org.apache.commons.cli.CommandLine; 039import org.apache.commons.cli.CommandLineParser; 040import org.apache.commons.cli.GnuParser; 041import org.apache.commons.cli.HelpFormatter; 042import org.apache.commons.cli.Option; 043import org.apache.commons.cli.Options; 044import org.apache.commons.cli.ParseException; 045import org.apache.commons.io.IOUtils; 046import org.apache.commons.lang.StringUtils; 047import org.apache.hadoop.classification.InterfaceAudience.Private; 048import org.apache.hadoop.classification.InterfaceAudience.Public; 049import org.apache.hadoop.classification.InterfaceStability.Evolving; 050import org.apache.hadoop.conf.Configuration; 051import org.apache.hadoop.conf.Configured; 052import org.apache.hadoop.security.UserGroupInformation; 053import org.apache.hadoop.util.Tool; 054import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport; 055import org.apache.hadoop.yarn.api.records.ApplicationId; 056import org.apache.hadoop.yarn.api.records.ApplicationReport; 057import org.apache.hadoop.yarn.api.records.ContainerId; 058import org.apache.hadoop.yarn.api.records.ContainerReport; 059import org.apache.hadoop.yarn.api.records.ContainerState; 060import org.apache.hadoop.yarn.api.records.YarnApplicationState; 061import org.apache.hadoop.yarn.client.api.YarnClient; 062import org.apache.hadoop.yarn.conf.YarnConfiguration; 063import org.apache.hadoop.yarn.exceptions.YarnException; 064import org.apache.hadoop.yarn.logaggregation.ContainerLogsRequest; 065import org.apache.hadoop.yarn.logaggregation.LogCLIHelpers; 066import org.apache.hadoop.yarn.util.Times; 067import org.apache.hadoop.yarn.webapp.util.WebAppUtils; 068import org.codehaus.jettison.json.JSONArray; 069import org.codehaus.jettison.json.JSONException; 070import org.codehaus.jettison.json.JSONObject; 071 072import com.google.common.annotations.VisibleForTesting; 073import com.sun.jersey.api.client.Client; 074import com.sun.jersey.api.client.ClientHandlerException; 075import com.sun.jersey.api.client.ClientResponse; 076import com.sun.jersey.api.client.UniformInterfaceException; 077import com.sun.jersey.api.client.WebResource; 078 079@Public 080@Evolving 081public class LogsCLI extends Configured implements Tool { 082 083 private static final String CONTAINER_ID_OPTION = "containerId"; 084 private static final String APPLICATION_ID_OPTION = "applicationId"; 085 private static final String NODE_ADDRESS_OPTION = "nodeAddress"; 086 private static final String APP_OWNER_OPTION = "appOwner"; 087 private static final String AM_CONTAINER_OPTION = "am"; 088 private static final String PER_CONTAINER_LOG_FILES_OPTION = "log_files"; 089 private static final String PER_CONTAINER_LOG_FILES_REGEX_OPTION 090 = "log_files_pattern"; 091 private static final String LIST_NODES_OPTION = "list_nodes"; 092 private static final String SHOW_APPLICATION_LOG_INFO 093 = "show_application_log_info"; 094 private static final String SHOW_CONTAINER_LOG_INFO 095 = "show_container_log_info"; 096 private static final String OUT_OPTION = "out"; 097 private static final String SIZE_OPTION = "size"; 098 public static final String HELP_CMD = "help"; 099 private PrintStream outStream = System.out; 100 private YarnClient yarnClient = null; 101 102 @Override 103 public int run(String[] args) throws Exception { 104 try { 105 yarnClient = createYarnClient(); 106 return runCommand(args); 107 } finally { 108 if (yarnClient != null) { 109 yarnClient.close(); 110 } 111 } 112 } 113 114 private int runCommand(String[] args) throws Exception { 115 Options opts = createCommandOpts(); 116 Options printOpts = createPrintOpts(opts); 117 if (args.length < 1) { 118 printHelpMessage(printOpts); 119 return -1; 120 } 121 if (args[0].equals("-help")) { 122 printHelpMessage(printOpts); 123 return 0; 124 } 125 CommandLineParser parser = new GnuParser(); 126 String appIdStr = null; 127 String containerIdStr = null; 128 String nodeAddress = null; 129 String appOwner = null; 130 boolean getAMContainerLogs = false; 131 boolean nodesList = false; 132 boolean showApplicationLogInfo = false; 133 boolean showContainerLogInfo = false; 134 boolean useRegex = false; 135 String[] logFiles = null; 136 String[] logFilesRegex = null; 137 List<String> amContainersList = new ArrayList<String>(); 138 String localDir = null; 139 long bytes = Long.MAX_VALUE; 140 try { 141 CommandLine commandLine = parser.parse(opts, args, true); 142 appIdStr = commandLine.getOptionValue(APPLICATION_ID_OPTION); 143 containerIdStr = commandLine.getOptionValue(CONTAINER_ID_OPTION); 144 nodeAddress = commandLine.getOptionValue(NODE_ADDRESS_OPTION); 145 appOwner = commandLine.getOptionValue(APP_OWNER_OPTION); 146 getAMContainerLogs = commandLine.hasOption(AM_CONTAINER_OPTION); 147 nodesList = commandLine.hasOption(LIST_NODES_OPTION); 148 localDir = commandLine.getOptionValue(OUT_OPTION); 149 showApplicationLogInfo = commandLine.hasOption( 150 SHOW_APPLICATION_LOG_INFO); 151 showContainerLogInfo = commandLine.hasOption(SHOW_CONTAINER_LOG_INFO); 152 if (getAMContainerLogs) { 153 try { 154 amContainersList = parseAMContainer(commandLine, printOpts); 155 } catch (NumberFormatException ex) { 156 System.err.println(ex.getMessage()); 157 return -1; 158 } 159 } 160 if (commandLine.hasOption(PER_CONTAINER_LOG_FILES_OPTION)) { 161 logFiles = commandLine.getOptionValues(PER_CONTAINER_LOG_FILES_OPTION); 162 } 163 if (commandLine.hasOption(PER_CONTAINER_LOG_FILES_REGEX_OPTION)) { 164 logFilesRegex = commandLine.getOptionValues( 165 PER_CONTAINER_LOG_FILES_REGEX_OPTION); 166 useRegex = true; 167 } 168 if (commandLine.hasOption(SIZE_OPTION)) { 169 bytes = Long.parseLong(commandLine.getOptionValue(SIZE_OPTION)); 170 } 171 } catch (ParseException e) { 172 System.err.println("options parsing failed: " + e.getMessage()); 173 printHelpMessage(printOpts); 174 return -1; 175 } 176 177 if (appIdStr == null && containerIdStr == null) { 178 System.err.println("Both applicationId and containerId are missing, " 179 + " one of them must be specified."); 180 printHelpMessage(printOpts); 181 return -1; 182 } 183 184 ApplicationId appId = null; 185 if (appIdStr != null) { 186 try { 187 appId = ApplicationId.fromString(appIdStr); 188 } catch (Exception e) { 189 System.err.println("Invalid ApplicationId specified"); 190 return -1; 191 } 192 } 193 194 if (containerIdStr != null) { 195 try { 196 ContainerId containerId = ContainerId.fromString(containerIdStr); 197 if (appId == null) { 198 appId = containerId.getApplicationAttemptId().getApplicationId(); 199 } else if (!containerId.getApplicationAttemptId().getApplicationId() 200 .equals(appId)) { 201 System.err.println("The Application:" + appId 202 + " does not have the container:" + containerId); 203 return -1; 204 } 205 } catch (Exception e) { 206 System.err.println("Invalid ContainerId specified"); 207 return -1; 208 } 209 } 210 211 if (showApplicationLogInfo && showContainerLogInfo) { 212 System.err.println("Invalid options. Can only accept one of " 213 + "show_application_log_info/show_container_log_info."); 214 return -1; 215 } 216 217 if (logFiles != null && logFiles.length > 0 && logFilesRegex != null 218 && logFilesRegex.length > 0) { 219 System.err.println("Invalid options. Can only accept one of " 220 + "log_files/log_files_pattern."); 221 return -1; 222 } 223 if (localDir != null) { 224 File file = new File(localDir); 225 if (file.exists() && file.isFile()) { 226 System.err.println("Invalid value for -out option. " 227 + "Please provide a directory."); 228 return -1; 229 } 230 } 231 232 LogCLIHelpers logCliHelper = new LogCLIHelpers(); 233 logCliHelper.setConf(getConf()); 234 235 YarnApplicationState appState = YarnApplicationState.NEW; 236 ApplicationReport appReport = null; 237 try { 238 appReport = getApplicationReport(appId); 239 appState = appReport.getYarnApplicationState(); 240 if (appState == YarnApplicationState.NEW 241 || appState == YarnApplicationState.NEW_SAVING 242 || appState == YarnApplicationState.SUBMITTED) { 243 System.err.println("Logs are not avaiable right now."); 244 return -1; 245 } 246 } catch (IOException | YarnException e) { 247 // If we can not get appReport from either RM or ATS 248 // We will assume that this app has already finished. 249 appState = YarnApplicationState.FINISHED; 250 System.err.println("Unable to get ApplicationState." 251 + " Attempting to fetch logs directly from the filesystem."); 252 } 253 254 if (appOwner == null || appOwner.isEmpty()) { 255 appOwner = guessAppOwner(appReport, appId); 256 if (appOwner == null) { 257 System.err.println("Can not find the appOwner. " 258 + "Please specify the correct appOwner"); 259 System.err.println("Could not locate application logs for " + appId); 260 return -1; 261 } 262 } 263 264 Set<String> logs = new HashSet<String>(); 265 if (fetchAllLogFiles(logFiles, logFilesRegex)) { 266 logs.add("ALL"); 267 } else if (logFiles != null && logFiles.length > 0) { 268 logs.addAll(Arrays.asList(logFiles)); 269 } else if (logFilesRegex != null && logFilesRegex.length > 0) { 270 logs.addAll(Arrays.asList(logFilesRegex)); 271 } 272 273 ContainerLogsRequest request = new ContainerLogsRequest(appId, 274 isApplicationFinished(appState), appOwner, nodeAddress, null, 275 containerIdStr, localDir, logs, bytes, null); 276 277 if (showContainerLogInfo) { 278 return showContainerLogInfo(request, logCliHelper); 279 } 280 281 if (nodesList) { 282 return showNodeLists(request, logCliHelper); 283 } 284 285 if (showApplicationLogInfo) { 286 return showApplicationLogInfo(request, logCliHelper); 287 } 288 // To get am logs 289 if (getAMContainerLogs) { 290 return fetchAMContainerLogs(request, amContainersList, 291 logCliHelper, useRegex); 292 } 293 294 int resultCode = 0; 295 if (containerIdStr != null) { 296 return fetchContainerLogs(request, logCliHelper, useRegex); 297 } else { 298 if (nodeAddress == null) { 299 resultCode = fetchApplicationLogs(request, logCliHelper, useRegex); 300 } else { 301 System.err.println("Should at least provide ContainerId!"); 302 printHelpMessage(printOpts); 303 resultCode = -1; 304 } 305 } 306 return resultCode; 307 } 308 309 private ApplicationReport getApplicationReport(ApplicationId appId) 310 throws IOException, YarnException { 311 return yarnClient.getApplicationReport(appId); 312 } 313 314 @VisibleForTesting 315 protected YarnClient createYarnClient() { 316 YarnClient client = YarnClient.createYarnClient(); 317 client.init(getConf()); 318 client.start(); 319 return client; 320 } 321 322 public static void main(String[] args) throws Exception { 323 Configuration conf = new YarnConfiguration(); 324 LogsCLI logDumper = new LogsCLI(); 325 logDumper.setConf(conf); 326 int exitCode = logDumper.run(args); 327 System.exit(exitCode); 328 } 329 330 private void printHelpMessage(Options options) { 331 outStream.println("Retrieve logs for YARN applications."); 332 HelpFormatter formatter = new HelpFormatter(); 333 formatter.printHelp("yarn logs -applicationId <application ID> [OPTIONS]", 334 new Options()); 335 formatter.setSyntaxPrefix(""); 336 formatter.printHelp("general options are:", options); 337 } 338 339 protected List<JSONObject> getAMContainerInfoForRMWebService( 340 Configuration conf, String appId) throws ClientHandlerException, 341 UniformInterfaceException, JSONException { 342 Client webServiceClient = Client.create(); 343 String webAppAddress = WebAppUtils.getRMWebAppURLWithScheme(conf); 344 345 WebResource webResource = webServiceClient.resource(webAppAddress); 346 347 ClientResponse response = 348 webResource.path("ws").path("v1").path("cluster").path("apps") 349 .path(appId).path("appattempts").accept(MediaType.APPLICATION_JSON) 350 .get(ClientResponse.class); 351 JSONObject json = 352 response.getEntity(JSONObject.class).getJSONObject("appAttempts"); 353 JSONArray requests = json.getJSONArray("appAttempt"); 354 List<JSONObject> amContainersList = new ArrayList<JSONObject>(); 355 for (int i = 0; i < requests.length(); i++) { 356 amContainersList.add(requests.getJSONObject(i)); 357 } 358 return amContainersList; 359 } 360 361 private List<JSONObject> getAMContainerInfoForAHSWebService( 362 Configuration conf, String appId) throws ClientHandlerException, 363 UniformInterfaceException, JSONException { 364 Client webServiceClient = Client.create(); 365 String webAppAddress = 366 WebAppUtils.getHttpSchemePrefix(conf) 367 + WebAppUtils.getAHSWebAppURLWithoutScheme(conf); 368 WebResource webResource = webServiceClient.resource(webAppAddress); 369 370 ClientResponse response = 371 webResource.path("ws").path("v1").path("applicationhistory") 372 .path("apps").path(appId).path("appattempts") 373 .accept(MediaType.APPLICATION_JSON) 374 .get(ClientResponse.class); 375 JSONObject json = response.getEntity(JSONObject.class); 376 JSONArray requests = json.getJSONArray("appAttempt"); 377 List<JSONObject> amContainersList = new ArrayList<JSONObject>(); 378 for (int i = 0; i < requests.length(); i++) { 379 amContainersList.add(requests.getJSONObject(i)); 380 } 381 Collections.reverse(amContainersList); 382 return amContainersList; 383 } 384 385 private boolean fetchAllLogFiles(String[] logFiles, String[] logFilesRegex) { 386 387 // If no value is specified for the PER_CONTAINER_LOG_FILES_OPTION option 388 // and PER_CONTAINER_LOG_FILES_REGEX_OPTION 389 // we will assume all logs. 390 if ((logFiles == null || logFiles.length == 0) && ( 391 logFilesRegex == null || logFilesRegex.length == 0)) { 392 return true; 393 } 394 395 if (logFiles != null && logFiles.length > 0) { 396 List<String> logs = Arrays.asList(logFiles); 397 if (logs.contains("ALL") || logs.contains("*")) { 398 return true; 399 } 400 } 401 402 if (logFilesRegex != null && logFilesRegex.length > 0) { 403 List<String> logsRegex = Arrays.asList(logFilesRegex); 404 if (logsRegex.contains(".*")) { 405 return true; 406 } 407 } 408 409 return false; 410 } 411 412 private List<PerLogFileInfo> getContainerLogFiles(Configuration conf, 413 String containerIdStr, String nodeHttpAddress) throws IOException { 414 List<PerLogFileInfo> logFileInfos = new ArrayList<>(); 415 Client webServiceClient = Client.create(); 416 try { 417 WebResource webResource = webServiceClient 418 .resource(WebAppUtils.getHttpSchemePrefix(conf) + nodeHttpAddress); 419 ClientResponse response = 420 webResource.path("ws").path("v1").path("node").path("containers") 421 .path(containerIdStr).path("logs") 422 .accept(MediaType.APPLICATION_JSON) 423 .get(ClientResponse.class); 424 if (response.getStatusInfo().getStatusCode() == 425 ClientResponse.Status.OK.getStatusCode()) { 426 try { 427 JSONObject json = response.getEntity(JSONObject.class); 428 JSONArray array = json.getJSONArray("containerLogInfo"); 429 for (int i = 0; i < array.length(); i++) { 430 String fileName = array.getJSONObject(i).getString("fileName"); 431 String fileSize = array.getJSONObject(i).getString("fileSize"); 432 logFileInfos.add(new PerLogFileInfo(fileName, fileSize)); 433 } 434 } catch (Exception e) { 435 System.err.println("Unable to parse json from webservice. Error:"); 436 System.err.println(e.getMessage()); 437 throw new IOException(e); 438 } 439 } 440 441 } catch (ClientHandlerException | UniformInterfaceException ex) { 442 System.err.println("Unable to fetch log files list"); 443 throw new IOException(ex); 444 } 445 return logFileInfos; 446 } 447 448 @Private 449 @VisibleForTesting 450 public int printContainerLogsFromRunningApplication(Configuration conf, 451 ContainerLogsRequest request, LogCLIHelpers logCliHelper, 452 boolean useRegex) throws IOException { 453 String containerIdStr = request.getContainerId().toString(); 454 String localDir = request.getOutputLocalDir(); 455 String nodeHttpAddress = request.getNodeHttpAddress(); 456 if (nodeHttpAddress == null || nodeHttpAddress.isEmpty()) { 457 System.err.println("Can not get the logs for the container: " 458 + containerIdStr); 459 System.err.println("The node http address is required to get container " 460 + "logs for the Running application."); 461 return -1; 462 } 463 String nodeId = request.getNodeId(); 464 PrintStream out = logCliHelper.createPrintStream(localDir, nodeId, 465 containerIdStr); 466 try { 467 Set<String> matchedFiles = getMatchedContainerLogFiles(request, 468 useRegex); 469 if (matchedFiles.isEmpty()) { 470 System.err.println("Can not find any log file matching the pattern: " 471 + request.getLogTypes() + " for the container: " + containerIdStr 472 + " within the application: " + request.getAppId()); 473 return -1; 474 } 475 ContainerLogsRequest newOptions = new ContainerLogsRequest(request); 476 newOptions.setLogTypes(matchedFiles); 477 478 Client webServiceClient = Client.create(); 479 String containerString = String.format( 480 LogCLIHelpers.CONTAINER_ON_NODE_PATTERN, containerIdStr, nodeId); 481 out.println(containerString); 482 out.println(StringUtils.repeat("=", containerString.length())); 483 boolean foundAnyLogs = false; 484 byte[] buffer = new byte[65536]; 485 for (String logFile : newOptions.getLogTypes()) { 486 out.println("LogType:" + logFile); 487 out.println("Log Upload Time:" 488 + Times.format(System.currentTimeMillis())); 489 out.println("Log Contents:"); 490 InputStream is = null; 491 try { 492 ClientResponse response = getResponeFromNMWebService(conf, 493 webServiceClient, request, logFile); 494 if (response != null && response.getStatusInfo().getStatusCode() == 495 ClientResponse.Status.OK.getStatusCode()) { 496 is = response.getEntityInputStream(); 497 int len = 0; 498 while((len = is.read(buffer)) != -1) { 499 out.write(buffer, 0, len); 500 } 501 out.println(); 502 } else { 503 out.println("Can not get any logs for the log file: " + logFile); 504 String msg = "Response from the NodeManager:" + nodeId + 505 " WebService is " + ((response == null) ? "null": 506 "not successful," + " HTTP error code: " + 507 response.getStatus() + ", Server response:\n" + 508 response.getEntity(String.class)); 509 out.println(msg); 510 } 511 StringBuilder sb = new StringBuilder(); 512 sb.append("End of LogType:" + logFile + "."); 513 if (request.getContainerState() == ContainerState.RUNNING) { 514 sb.append(" This log file belongs" 515 + " to a running container (" + containerIdStr + ") and so may" 516 + " not be complete."); 517 } 518 out.println(sb.toString()); 519 out.flush(); 520 foundAnyLogs = true; 521 } catch (ClientHandlerException | UniformInterfaceException ex) { 522 System.err.println("Can not find the log file:" + logFile 523 + " for the container:" + containerIdStr + " in NodeManager:" 524 + nodeId); 525 } finally { 526 IOUtils.closeQuietly(is); 527 } 528 } 529 // for the case, we have already uploaded partial logs in HDFS 530 int result = logCliHelper.dumpAContainerLogsForLogType( 531 newOptions, false); 532 if (result == 0 || foundAnyLogs) { 533 return 0; 534 } else { 535 return -1; 536 } 537 } finally { 538 logCliHelper.closePrintStream(out); 539 } 540 } 541 542 private int printContainerLogsForFinishedApplication( 543 ContainerLogsRequest request, LogCLIHelpers logCliHelper, 544 boolean useRegex) throws IOException { 545 ContainerLogsRequest newOptions = getMatchedLogOptions( 546 request, logCliHelper, useRegex); 547 if (newOptions == null) { 548 System.err.println("Can not find any log file matching the pattern: " 549 + request.getLogTypes() + " for the container: " 550 + request.getContainerId() + " within the application: " 551 + request.getAppId()); 552 return -1; 553 } 554 return logCliHelper.dumpAContainerLogsForLogType(newOptions); 555 } 556 557 private int printContainerLogsForFinishedApplicationWithoutNodeId( 558 ContainerLogsRequest request, LogCLIHelpers logCliHelper, 559 boolean useRegex) throws IOException { 560 ContainerLogsRequest newOptions = getMatchedLogOptions( 561 request, logCliHelper, useRegex); 562 if (newOptions == null) { 563 System.err.println("Can not find any log file matching the pattern: " 564 + request.getLogTypes() + " for the container: " 565 + request.getContainerId() + " within the application: " 566 + request.getAppId()); 567 return -1; 568 } 569 return logCliHelper.dumpAContainerLogsForLogTypeWithoutNodeId( 570 newOptions); 571 } 572 573 @Private 574 @VisibleForTesting 575 public ContainerReport getContainerReport(String containerIdStr) 576 throws YarnException, IOException { 577 return yarnClient.getContainerReport( 578 ContainerId.fromString(containerIdStr)); 579 } 580 581 private boolean isApplicationFinished(YarnApplicationState appState) { 582 return appState == YarnApplicationState.FINISHED 583 || appState == YarnApplicationState.FAILED 584 || appState == YarnApplicationState.KILLED; 585 } 586 587 private int printAMContainerLogs(Configuration conf, 588 ContainerLogsRequest request, List<String> amContainers, 589 LogCLIHelpers logCliHelper, boolean useRegex) throws Exception { 590 List<JSONObject> amContainersList = null; 591 List<ContainerLogsRequest> requests = 592 new ArrayList<ContainerLogsRequest>(); 593 boolean getAMContainerLists = false; 594 String appId = request.getAppId().toString(); 595 StringBuilder errorMessage = new StringBuilder(); 596 // We will call RM webservice to get all AppAttempts information. 597 // If we get nothing, we will try to call AHS webservice to get AppAttempts 598 // which includes nodeAddress for the AM Containers. 599 try { 600 amContainersList = getAMContainerInfoForRMWebService(conf, appId); 601 if (amContainersList != null && !amContainersList.isEmpty()) { 602 getAMContainerLists = true; 603 for (JSONObject amContainer : amContainersList) { 604 ContainerLogsRequest amRequest = new ContainerLogsRequest(request); 605 amRequest.setContainerId(amContainer.getString("containerId")); 606 String httpAddress = amContainer.getString("nodeHttpAddress"); 607 if (httpAddress != null && !httpAddress.isEmpty()) { 608 amRequest.setNodeHttpAddress(httpAddress); 609 } 610 amRequest.setNodeId(amContainer.getString("nodeId")); 611 requests.add(amRequest); 612 } 613 } 614 } catch (Exception ex) { 615 errorMessage.append(ex.getMessage() + "\n"); 616 if (request.isAppFinished()) { 617 if (!conf.getBoolean(YarnConfiguration.TIMELINE_SERVICE_ENABLED, 618 YarnConfiguration.DEFAULT_TIMELINE_SERVICE_ENABLED)) { 619 errorMessage.append("Please enable the timeline service " 620 + "and make sure the timeline server is running."); 621 } else { 622 try { 623 amContainersList = getAMContainerInfoForAHSWebService(conf, appId); 624 if (amContainersList != null && !amContainersList.isEmpty()) { 625 getAMContainerLists = true; 626 for (JSONObject amContainer : amContainersList) { 627 ContainerLogsRequest amRequest = new ContainerLogsRequest( 628 request); 629 amRequest.setContainerId( 630 amContainer.getString("amContainerId")); 631 requests.add(amRequest); 632 } 633 } 634 } catch (Exception e) { 635 errorMessage.append(e.getMessage()); 636 } 637 } 638 } 639 } 640 641 if (!getAMContainerLists) { 642 System.err.println("Unable to get AM container informations " 643 + "for the application:" + appId); 644 System.err.println(errorMessage); 645 System.err.println("Can not get AMContainers logs for " 646 + "the application:" + appId + " with the appOwner:" 647 + request.getAppOwner()); 648 return -1; 649 } 650 651 if (amContainers.contains("ALL")) { 652 for (ContainerLogsRequest amRequest : requests) { 653 outputAMContainerLogs(amRequest, conf, logCliHelper, useRegex); 654 } 655 outStream.println(); 656 outStream.println("Specified ALL for -am option. " 657 + "Printed logs for all am containers."); 658 } else { 659 for (String amContainer : amContainers) { 660 int amContainerId = Integer.parseInt(amContainer.trim()); 661 if (amContainerId == -1) { 662 outputAMContainerLogs(requests.get(requests.size() - 1), conf, 663 logCliHelper, useRegex); 664 } else { 665 if (amContainerId <= requests.size()) { 666 outputAMContainerLogs(requests.get(amContainerId - 1), conf, 667 logCliHelper, useRegex); 668 } else { 669 System.err.println(String.format("ERROR: Specified AM containerId" 670 + " (%s) exceeds the number of AM containers (%s).", 671 amContainerId, requests.size())); 672 return -1; 673 } 674 } 675 } 676 } 677 return 0; 678 } 679 680 private void outputAMContainerLogs(ContainerLogsRequest request, 681 Configuration conf, LogCLIHelpers logCliHelper, boolean useRegex) 682 throws Exception { 683 String nodeHttpAddress = request.getNodeHttpAddress(); 684 String containerId = request.getContainerId(); 685 String nodeId = request.getNodeId(); 686 687 if (request.isAppFinished()) { 688 if (containerId != null && !containerId.isEmpty()) { 689 if (nodeId != null && !nodeId.isEmpty()) { 690 printContainerLogsForFinishedApplication(request, 691 logCliHelper, useRegex); 692 } else { 693 printContainerLogsForFinishedApplicationWithoutNodeId( 694 request, logCliHelper, useRegex); 695 } 696 } 697 } else { 698 if (nodeHttpAddress != null && containerId != null 699 && !nodeHttpAddress.isEmpty() && !containerId.isEmpty()) { 700 ContainerState containerState = getContainerReport(containerId) 701 .getContainerState(); 702 request.setContainerState(containerState); 703 printContainerLogsFromRunningApplication(conf, 704 request, logCliHelper, useRegex); 705 } 706 } 707 } 708 709 private int showContainerLogInfo(ContainerLogsRequest request, 710 LogCLIHelpers logCliHelper) throws IOException, YarnException { 711 if (!request.isAppFinished()) { 712 return printContainerInfoFromRunningApplication(request); 713 } else { 714 return logCliHelper.printAContainerLogMetadata( 715 request, System.out, System.err); 716 } 717 } 718 719 private int showNodeLists(ContainerLogsRequest request, 720 LogCLIHelpers logCliHelper) throws IOException { 721 if (!request.isAppFinished()) { 722 System.err.println("The -list_nodes command can be only used with " 723 + "finished applications"); 724 return -1; 725 } else { 726 logCliHelper.printNodesList(request, System.out, System.err); 727 return 0; 728 } 729 } 730 731 private int showApplicationLogInfo(ContainerLogsRequest request, 732 LogCLIHelpers logCliHelper) throws IOException, YarnException { 733 String appState = "Application State: " 734 + (request.isAppFinished() ? "Completed." : "Running."); 735 if (!request.isAppFinished()) { 736 List<ContainerReport> reports = 737 getContainerReportsFromRunningApplication(request); 738 List<ContainerReport> filterReports = filterContainersInfo( 739 request, reports); 740 if (filterReports.isEmpty()) { 741 System.err.println("Can not find any containers for the application:" 742 + request.getAppId() + "."); 743 return -1; 744 } 745 outStream.println(appState); 746 for (ContainerReport report : filterReports) { 747 outStream.println(String.format(LogCLIHelpers.CONTAINER_ON_NODE_PATTERN, 748 report.getContainerId(), report.getAssignedNode())); 749 } 750 return 0; 751 } else { 752 outStream.println(appState); 753 logCliHelper.printContainersList(request, System.out, System.err); 754 return 0; 755 } 756 } 757 758 private Options createCommandOpts() { 759 Options opts = new Options(); 760 opts.addOption(HELP_CMD, false, "Displays help for all commands."); 761 Option appIdOpt = 762 new Option(APPLICATION_ID_OPTION, true, "ApplicationId (required)"); 763 opts.addOption(appIdOpt); 764 opts.addOption(CONTAINER_ID_OPTION, true, "ContainerId. " 765 + "By default, it will print all available logs." 766 + " Work with -log_files to get only specific logs. If specified, the" 767 + " applicationId can be omitted"); 768 opts.addOption(NODE_ADDRESS_OPTION, true, "NodeAddress in the format " 769 + "nodename:port"); 770 opts.addOption(APP_OWNER_OPTION, true, 771 "AppOwner (assumed to be current user if not specified)"); 772 Option amOption = new Option(AM_CONTAINER_OPTION, true, 773 "Prints the AM Container logs for this application. " 774 + "Specify comma-separated value to get logs for related AM " 775 + "Container. For example, If we specify -am 1,2, we will get " 776 + "the logs for the first AM Container as well as the second " 777 + "AM Container. To get logs for all AM Containers, use -am ALL. " 778 + "To get logs for the latest AM Container, use -am -1. " 779 + "By default, it will print all available logs. Work with -log_files " 780 + "to get only specific logs."); 781 amOption.setValueSeparator(','); 782 amOption.setArgs(Option.UNLIMITED_VALUES); 783 amOption.setArgName("AM Containers"); 784 opts.addOption(amOption); 785 Option logFileOpt = new Option(PER_CONTAINER_LOG_FILES_OPTION, true, 786 "Specify comma-separated value " 787 + "to get exact matched log files. Use \"ALL\" or \"*\" to " 788 + "fetch all the log files for the container."); 789 logFileOpt.setValueSeparator(','); 790 logFileOpt.setArgs(Option.UNLIMITED_VALUES); 791 logFileOpt.setArgName("Log File Name"); 792 opts.addOption(logFileOpt); 793 Option logFileRegexOpt = new Option(PER_CONTAINER_LOG_FILES_REGEX_OPTION, 794 true, "Specify comma-separated value " 795 + "to get matched log files by using java regex. Use \".*\" to " 796 + "fetch all the log files for the container."); 797 logFileRegexOpt.setValueSeparator(','); 798 logFileRegexOpt.setArgs(Option.UNLIMITED_VALUES); 799 logFileRegexOpt.setArgName("Log File Pattern"); 800 opts.addOption(logFileRegexOpt); 801 opts.addOption(SHOW_CONTAINER_LOG_INFO, false, 802 "Show the container log metadata, " 803 + "including log-file names, the size of the log files. " 804 + "You can combine this with --containerId to get log metadata for " 805 + "the specific container, or with --nodeAddress to get log metadata " 806 + "for all the containers on the specific NodeManager."); 807 opts.addOption(SHOW_APPLICATION_LOG_INFO, false, "Show the " 808 + "containerIds which belong to the specific Application. " 809 + "You can combine this with --nodeAddress to get containerIds " 810 + "for all the containers on the specific NodeManager."); 811 opts.addOption(LIST_NODES_OPTION, false, 812 "Show the list of nodes that successfully aggregated logs. " 813 + "This option can only be used with finished applications."); 814 opts.addOption(OUT_OPTION, true, "Local directory for storing individual " 815 + "container logs. The container logs will be stored based on the " 816 + "node the container ran on."); 817 opts.addOption(SIZE_OPTION, true, "Prints the log file's first 'n' bytes " 818 + "or the last 'n' bytes. Use negative values as bytes to read from " 819 + "the end and positive values as bytes to read from the beginning."); 820 opts.getOption(APPLICATION_ID_OPTION).setArgName("Application ID"); 821 opts.getOption(CONTAINER_ID_OPTION).setArgName("Container ID"); 822 opts.getOption(NODE_ADDRESS_OPTION).setArgName("Node Address"); 823 opts.getOption(APP_OWNER_OPTION).setArgName("Application Owner"); 824 opts.getOption(AM_CONTAINER_OPTION).setArgName("AM Containers"); 825 opts.getOption(OUT_OPTION).setArgName("Local Directory"); 826 opts.getOption(SIZE_OPTION).setArgName("size"); 827 return opts; 828 } 829 830 private Options createPrintOpts(Options commandOpts) { 831 Options printOpts = new Options(); 832 printOpts.addOption(commandOpts.getOption(HELP_CMD)); 833 printOpts.addOption(commandOpts.getOption(CONTAINER_ID_OPTION)); 834 printOpts.addOption(commandOpts.getOption(NODE_ADDRESS_OPTION)); 835 printOpts.addOption(commandOpts.getOption(APP_OWNER_OPTION)); 836 printOpts.addOption(commandOpts.getOption(AM_CONTAINER_OPTION)); 837 printOpts.addOption(commandOpts.getOption(PER_CONTAINER_LOG_FILES_OPTION)); 838 printOpts.addOption(commandOpts.getOption(LIST_NODES_OPTION)); 839 printOpts.addOption(commandOpts.getOption(SHOW_APPLICATION_LOG_INFO)); 840 printOpts.addOption(commandOpts.getOption(SHOW_CONTAINER_LOG_INFO)); 841 printOpts.addOption(commandOpts.getOption(OUT_OPTION)); 842 printOpts.addOption(commandOpts.getOption(SIZE_OPTION)); 843 printOpts.addOption(commandOpts.getOption( 844 PER_CONTAINER_LOG_FILES_REGEX_OPTION)); 845 return printOpts; 846 } 847 848 private List<String> parseAMContainer(CommandLine commandLine, 849 Options printOpts) throws NumberFormatException { 850 List<String> amContainersList = new ArrayList<String>(); 851 String[] amContainers = commandLine.getOptionValues(AM_CONTAINER_OPTION); 852 for (String am : amContainers) { 853 boolean errorInput = false; 854 if (!am.trim().equalsIgnoreCase("ALL")) { 855 try { 856 int id = Integer.parseInt(am.trim()); 857 if (id != -1 && id <= 0) { 858 errorInput = true; 859 } 860 } catch (NumberFormatException ex) { 861 errorInput = true; 862 } 863 if (errorInput) { 864 String errMessage = 865 "Invalid input for option -am. Valid inputs are 'ALL', -1 " 866 + "and any other integer which is larger than 0."; 867 printHelpMessage(printOpts); 868 throw new NumberFormatException(errMessage); 869 } 870 amContainersList.add(am.trim()); 871 } else { 872 amContainersList.add("ALL"); 873 break; 874 } 875 } 876 return amContainersList; 877 } 878 879 private int fetchAMContainerLogs(ContainerLogsRequest request, 880 List<String> amContainersList, LogCLIHelpers logCliHelper, 881 boolean useRegex) throws Exception { 882 return printAMContainerLogs(getConf(), request, amContainersList, 883 logCliHelper, useRegex); 884 } 885 886 private int fetchContainerLogs(ContainerLogsRequest request, 887 LogCLIHelpers logCliHelper, boolean useRegex) throws IOException { 888 int resultCode = 0; 889 String appIdStr = request.getAppId().toString(); 890 String containerIdStr = request.getContainerId(); 891 String nodeAddress = request.getNodeId(); 892 String appOwner = request.getAppOwner(); 893 boolean isAppFinished = request.isAppFinished(); 894 // if the application is in the final state, 895 // we could directly get logs from HDFS. 896 if (isAppFinished) { 897 // if user specified "ALL" as the logFiles param, pass empty list 898 // to logCliHelper so that it fetches all the logs 899 if (nodeAddress != null && !nodeAddress.isEmpty()) { 900 return printContainerLogsForFinishedApplication( 901 request, logCliHelper, useRegex); 902 } else { 903 return printContainerLogsForFinishedApplicationWithoutNodeId( 904 request, logCliHelper, useRegex); 905 } 906 } 907 String nodeHttpAddress = null; 908 String nodeId = null; 909 try { 910 // If the nodeAddress is not provided, we will try to get 911 // the ContainerReport. In the containerReport, we could get 912 // nodeAddress and nodeHttpAddress 913 ContainerReport report = getContainerReport(containerIdStr); 914 nodeHttpAddress = report.getNodeHttpAddress(); 915 if (nodeHttpAddress != null && !nodeHttpAddress.isEmpty()) { 916 nodeHttpAddress = nodeHttpAddress.replaceFirst( 917 WebAppUtils.getHttpSchemePrefix(getConf()), ""); 918 request.setNodeHttpAddress(nodeHttpAddress); 919 } 920 nodeId = report.getAssignedNode().toString(); 921 request.setNodeId(nodeId); 922 request.setContainerState(report.getContainerState()); 923 } catch (IOException | YarnException ex) { 924 if (isAppFinished) { 925 return printContainerLogsForFinishedApplicationWithoutNodeId( 926 request, logCliHelper, useRegex); 927 } else { 928 System.err.println("Unable to get logs for this container:" 929 + containerIdStr + "for the application:" + appIdStr 930 + " with the appOwner: " + appOwner); 931 System.err.println("The application: " + appIdStr 932 + " is still running, and we can not get Container report " 933 + "for the container: " + containerIdStr +". Please try later " 934 + "or after the application finishes."); 935 return -1; 936 } 937 } 938 // If the application is not in the final state, 939 // we will provide the NodeHttpAddress and get the container logs 940 // by calling NodeManager webservice. 941 if (!isAppFinished) { 942 resultCode = printContainerLogsFromRunningApplication(getConf(), request, 943 logCliHelper, useRegex); 944 } else { 945 // If the application is in the final state, we will directly 946 // get the container logs from HDFS. 947 resultCode = printContainerLogsForFinishedApplication( 948 request, logCliHelper, useRegex); 949 } 950 return resultCode; 951 } 952 953 private int fetchApplicationLogs(ContainerLogsRequest options, 954 LogCLIHelpers logCliHelper, boolean useRegex) throws IOException, 955 YarnException { 956 // If the application has finished, we would fetch the logs 957 // from HDFS. 958 // If the application is still running, we would get the full 959 // list of the containers first, then fetch the logs for each 960 // container from NM. 961 int resultCode = -1; 962 if (options.isAppFinished()) { 963 ContainerLogsRequest newOptions = getMatchedLogOptions( 964 options, logCliHelper, useRegex); 965 if (newOptions == null) { 966 System.err.println("Can not find any log file matching the pattern: " 967 + options.getLogTypes() + " for the application: " 968 + options.getAppId()); 969 } else { 970 resultCode = 971 logCliHelper.dumpAllContainersLogs(newOptions); 972 } 973 } else { 974 List<ContainerLogsRequest> containerLogRequests = 975 getContainersLogRequestForRunningApplication(options); 976 for (ContainerLogsRequest container : containerLogRequests) { 977 int result = printContainerLogsFromRunningApplication(getConf(), 978 container, logCliHelper, useRegex); 979 if (result == 0) { 980 resultCode = 0; 981 } 982 } 983 } 984 if (resultCode == -1) { 985 System.err.println("Can not find the logs for the application: " 986 + options.getAppId() + " with the appOwner: " 987 + options.getAppOwner()); 988 } 989 return resultCode; 990 } 991 992 private String guessAppOwner(ApplicationReport appReport, 993 ApplicationId appId) throws IOException { 994 String appOwner = null; 995 if (appReport != null) { 996 //always use the app owner from the app report if possible 997 appOwner = appReport.getUser(); 998 } else { 999 appOwner = UserGroupInformation.getCurrentUser().getShortUserName(); 1000 appOwner = LogCLIHelpers.getOwnerForAppIdOrNull( 1001 appId, appOwner, getConf()); 1002 } 1003 return appOwner; 1004 } 1005 1006 private ContainerLogsRequest getMatchedLogOptions( 1007 ContainerLogsRequest request, LogCLIHelpers logCliHelper, 1008 boolean useRegex) throws IOException { 1009 ContainerLogsRequest newOptions = new ContainerLogsRequest(request); 1010 if (request.getLogTypes() != null && !request.getLogTypes().isEmpty()) { 1011 Set<String> matchedFiles = new HashSet<String>(); 1012 if (!request.getLogTypes().contains("ALL")) { 1013 Set<String> files = logCliHelper.listContainerLogs(request); 1014 matchedFiles = getMatchedLogFiles(request, files, useRegex); 1015 if (matchedFiles.isEmpty()) { 1016 return null; 1017 } 1018 } 1019 newOptions.setLogTypes(matchedFiles); 1020 } 1021 return newOptions; 1022 } 1023 1024 private Set<String> getMatchedLogFiles(ContainerLogsRequest options, 1025 Collection<String> candidate, boolean useRegex) throws IOException { 1026 Set<String> matchedFiles = new HashSet<String>(); 1027 Set<String> filePattern = options.getLogTypes(); 1028 if (options.getLogTypes().contains("ALL")) { 1029 return new HashSet<String>(candidate); 1030 } 1031 for (String file : candidate) { 1032 if (useRegex) { 1033 if (isFileMatching(file, filePattern)) { 1034 matchedFiles.add(file); 1035 } 1036 } else { 1037 if (filePattern.contains(file)) { 1038 matchedFiles.add(file); 1039 } 1040 } 1041 } 1042 return matchedFiles; 1043 } 1044 1045 private boolean isFileMatching(String fileType, 1046 Set<String> logTypes) { 1047 for (String logType : logTypes) { 1048 Pattern filterPattern = Pattern.compile(logType); 1049 boolean match = filterPattern.matcher(fileType).find(); 1050 if (match) { 1051 return true; 1052 } 1053 } 1054 return false; 1055 } 1056 1057 private List<ContainerLogsRequest> 1058 getContainersLogRequestForRunningApplication( 1059 ContainerLogsRequest options) throws YarnException, IOException { 1060 List<ContainerLogsRequest> newOptionsList = 1061 new ArrayList<ContainerLogsRequest>(); 1062 List<ContainerReport> reports = 1063 getContainerReportsFromRunningApplication(options); 1064 for (ContainerReport container : reports) { 1065 ContainerLogsRequest newOptions = new ContainerLogsRequest(options); 1066 newOptions.setContainerId(container.getContainerId().toString()); 1067 newOptions.setNodeId(container.getAssignedNode().toString()); 1068 String httpAddress = container.getNodeHttpAddress(); 1069 if (httpAddress != null && !httpAddress.isEmpty()) { 1070 newOptions.setNodeHttpAddress(httpAddress 1071 .replaceFirst(WebAppUtils.getHttpSchemePrefix(getConf()), "")); 1072 } 1073 newOptions.setContainerState(container.getContainerState()); 1074 newOptionsList.add(newOptions); 1075 } 1076 return newOptionsList; 1077 } 1078 1079 private List<ContainerReport> getContainerReportsFromRunningApplication( 1080 ContainerLogsRequest options) throws YarnException, IOException { 1081 List<ContainerReport> reports = new ArrayList<ContainerReport>(); 1082 List<ApplicationAttemptReport> attempts = 1083 yarnClient.getApplicationAttempts(options.getAppId()); 1084 Map<ContainerId, ContainerReport> containerMap = new TreeMap< 1085 ContainerId, ContainerReport>(); 1086 for (ApplicationAttemptReport attempt : attempts) { 1087 List<ContainerReport> containers = yarnClient.getContainers( 1088 attempt.getApplicationAttemptId()); 1089 for (ContainerReport container : containers) { 1090 if (!containerMap.containsKey(container.getContainerId())) { 1091 containerMap.put(container.getContainerId(), container); 1092 } 1093 } 1094 } 1095 reports.addAll(containerMap.values()); 1096 return reports; 1097 } 1098 1099 // filter the containerReports based on the nodeId and ContainerId 1100 private List<ContainerReport> filterContainersInfo( 1101 ContainerLogsRequest options, List<ContainerReport> containers) { 1102 List<ContainerReport> filterReports = new ArrayList<ContainerReport>( 1103 containers); 1104 String nodeId = options.getNodeId(); 1105 boolean filterBasedOnNodeId = (nodeId != null && !nodeId.isEmpty()); 1106 String containerId = options.getContainerId(); 1107 boolean filterBasedOnContainerId = (containerId != null 1108 && !containerId.isEmpty()); 1109 1110 if (filterBasedOnNodeId || filterBasedOnContainerId) { 1111 // filter the reports based on the containerId and.or nodeId 1112 for(ContainerReport report : containers) { 1113 if (filterBasedOnContainerId) { 1114 if (!report.getContainerId().toString() 1115 .equalsIgnoreCase(containerId)) { 1116 filterReports.remove(report); 1117 } 1118 } 1119 1120 if (filterBasedOnNodeId) { 1121 if (!report.getAssignedNode().toString().equalsIgnoreCase(nodeId)) { 1122 filterReports.remove(report); 1123 } 1124 } 1125 } 1126 } 1127 return filterReports; 1128 } 1129 1130 private int printContainerInfoFromRunningApplication( 1131 ContainerLogsRequest options) throws YarnException, IOException { 1132 String containerIdStr = options.getContainerId(); 1133 String nodeIdStr = options.getNodeId(); 1134 List<ContainerReport> reports = 1135 getContainerReportsFromRunningApplication(options); 1136 List<ContainerReport> filteredReports = filterContainersInfo( 1137 options, reports); 1138 if (filteredReports.isEmpty()) { 1139 StringBuilder sb = new StringBuilder(); 1140 if (containerIdStr != null && !containerIdStr.isEmpty()) { 1141 sb.append("Trying to get container with ContainerId: " 1142 + containerIdStr + "\n"); 1143 } 1144 if (nodeIdStr != null && !nodeIdStr.isEmpty()) { 1145 sb.append("Trying to get container from NodeManager: " 1146 + nodeIdStr + "\n"); 1147 } 1148 sb.append("Can not find any matched containers for the application: " 1149 + options.getAppId()); 1150 System.err.println(sb.toString()); 1151 return -1; 1152 } 1153 for (ContainerReport report : filteredReports) { 1154 String nodeId = report.getAssignedNode().toString(); 1155 String nodeHttpAddress = report.getNodeHttpAddress().replaceFirst( 1156 WebAppUtils.getHttpSchemePrefix(getConf()), ""); 1157 String containerId = report.getContainerId().toString(); 1158 String containerString = String.format( 1159 LogCLIHelpers.CONTAINER_ON_NODE_PATTERN, containerId, nodeId); 1160 outStream.println(containerString); 1161 outStream.println(StringUtils.repeat("=", containerString.length())); 1162 outStream.printf(LogCLIHelpers.PER_LOG_FILE_INFO_PATTERN, 1163 "LogType", "LogLength"); 1164 outStream.println(StringUtils.repeat("=", containerString.length())); 1165 List<PerLogFileInfo> infos = getContainerLogFiles( 1166 getConf(), containerId, nodeHttpAddress); 1167 for (PerLogFileInfo info : infos) { 1168 outStream.printf(LogCLIHelpers.PER_LOG_FILE_INFO_PATTERN, 1169 info.getFileName(), info.getFileLength()); 1170 } 1171 } 1172 return 0; 1173 } 1174 1175 private static class PerLogFileInfo { 1176 private String fileName; 1177 private String fileLength; 1178 public PerLogFileInfo(String fileName, String fileLength) { 1179 setFileName(fileName); 1180 setFileLength(fileLength); 1181 } 1182 1183 public String getFileName() { 1184 return fileName; 1185 } 1186 1187 public void setFileName(String fileName) { 1188 this.fileName = fileName; 1189 } 1190 1191 public String getFileLength() { 1192 return fileLength; 1193 } 1194 1195 public void setFileLength(String fileLength) { 1196 this.fileLength = fileLength; 1197 } 1198 } 1199 1200 @VisibleForTesting 1201 public Set<String> getMatchedContainerLogFiles(ContainerLogsRequest request, 1202 boolean useRegex) throws IOException { 1203 // fetch all the log files for the container 1204 // filter the log files based on the given -log_files pattern 1205 List<PerLogFileInfo> allLogFileInfos= 1206 getContainerLogFiles(getConf(), request.getContainerId(), 1207 request.getNodeHttpAddress()); 1208 List<String> fileNames = new ArrayList<String>(); 1209 for (PerLogFileInfo fileInfo : allLogFileInfos) { 1210 fileNames.add(fileInfo.getFileName()); 1211 } 1212 return getMatchedLogFiles(request, fileNames, 1213 useRegex); 1214 } 1215 1216 @VisibleForTesting 1217 public ClientResponse getResponeFromNMWebService(Configuration conf, 1218 Client webServiceClient, ContainerLogsRequest request, String logFile) { 1219 WebResource webResource = 1220 webServiceClient.resource(WebAppUtils.getHttpSchemePrefix(conf) 1221 + request.getNodeHttpAddress()); 1222 return webResource.path("ws").path("v1").path("node") 1223 .path("containers").path(request.getContainerId()).path("logs") 1224 .path(logFile) 1225 .queryParam("size", Long.toString(request.getBytes())) 1226 .accept(MediaType.TEXT_PLAIN).get(ClientResponse.class); 1227 } 1228}