diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java index 9832729..923a64f 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java @@ -1435,6 +1435,14 @@ private static void addDeprecatedKeys() { public static final String APPLICATION_HISTORY_STORE = APPLICATION_HISTORY_PREFIX + "store-class"; + /** Save container meta-info in the application history store. */ + @Private + public static final String APPLICATION_HISTORY_SAVE_CONTAINER_META_INFO = + APPLICATION_HISTORY_PREFIX + "save-container-meta-info"; + @Private + public static final boolean + DEFAULT_APPLICATION_HISTORY_SAVE_CONTAINER_META_INFO = true; + /** URI for FileSystemApplicationHistoryStore */ @Private public static final String FS_APPLICATION_HISTORY_STORE_URI = diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java index eec32b2..4b3d310 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java @@ -267,8 +267,10 @@ protected void generateApplicationTable(Block html, public ContainerReport run() throws Exception { ContainerReport report = null; try { - report = appBaseProt.getContainerReport(request) - .getContainerReport(); + if (request.getContainerId() != null) { + report = appBaseProt.getContainerReport(request) + .getContainerReport(); + } } catch (ContainerNotFoundException ex) { LOG.warn(ex.getMessage()); } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainerImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainerImpl.java index f7d3f56..8637ebc 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainerImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainerImpl.java @@ -38,6 +38,7 @@ import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.ResourceRequest; +import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.event.EventHandler; import org.apache.hadoop.yarn.server.api.protocolrecords.NMContainerStatus; import org.apache.hadoop.yarn.server.resourcemanager.RMContext; @@ -173,6 +174,8 @@ public RMContainerImpl(Container container, .currentTimeMillis(), ""); } + private static boolean storeContainerMetaInfo; + public RMContainerImpl(Container container, ApplicationAttemptId appAttemptId, NodeId nodeId, String user, RMContext rmContext, String nodeLabelExpression) { @@ -201,9 +204,18 @@ public RMContainerImpl(Container container, this.readLock = lock.readLock(); this.writeLock = lock.writeLock(); + storeContainerMetaInfo = rmContext.getYarnConfiguration().getBoolean( + YarnConfiguration.APPLICATION_HISTORY_SAVE_CONTAINER_META_INFO, + YarnConfiguration.DEFAULT_APPLICATION_HISTORY_SAVE_CONTAINER_META_INFO); + rmContext.getRMApplicationHistoryWriter().containerStarted(this); - rmContext.getSystemMetricsPublisher().containerCreated( - this, this.creationTime); + + // Store system metrics for all containers only when storeContainerMetaInfo + // is true. + if (storeContainerMetaInfo) { + rmContext.getSystemMetricsPublisher().containerCreated( + this, this.creationTime); + } } @Override @@ -376,6 +388,13 @@ public void setAMContainer(boolean isAMContainer) { } finally { writeLock.unlock(); } + + // Even if storeContainerMetaInfo is not true, the AM container's system + // metrics still needs to be saved so that the AM's logs can be accessed. + if (!storeContainerMetaInfo && this.isAMContainer) { + rmContext.getSystemMetricsPublisher().containerCreated( + this, this.creationTime); + } } @Override @@ -526,8 +545,12 @@ public void transition(RMContainerImpl container, RMContainerEvent event) { container.rmContext.getRMApplicationHistoryWriter().containerFinished( container); - container.rmContext.getSystemMetricsPublisher().containerFinished( - container, container.finishTime); + + if (storeContainerMetaInfo || container.isAMContainer()) { + container.rmContext.getSystemMetricsPublisher().containerFinished( + container, container.finishTime); + } + } private static void updateAttemptMetrics(RMContainerImpl container) { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/TestRMContainerImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/TestRMContainerImpl.java index 21aba3b..f70a8b0 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/TestRMContainerImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/TestRMContainerImpl.java @@ -19,12 +19,14 @@ package org.apache.hadoop.yarn.server.resourcemanager.rmcontainer; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyLong; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -270,4 +272,76 @@ public void testExistenceOfResourceRequestInRMContainer() throws Exception { Assert.assertNull(scheduler.getRMContainer(containerId2) .getResourceRequests()); } + + @Test (timeout = 180000) + public void testStoreAllContainerMetrics() throws Exception { + Configuration conf = new Configuration(); + conf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS, 1); + MockRM rm1 = new MockRM(conf); + + SystemMetricsPublisher publisher = mock(SystemMetricsPublisher.class); + rm1.getRMContext().setSystemMetricsPublisher(publisher); + + rm1.start(); + MockNM nm1 = rm1.registerNode("unknownhost:1234", 8000); + RMApp app1 = rm1.submitApp(1024); + MockAM am1 = MockRM.launchAndRegisterAM(app1, rm1, nm1); + nm1.nodeHeartbeat(am1.getApplicationAttemptId(), 1, ContainerState.RUNNING); + + // request a container. + am1.allocate("127.0.0.1", 1024, 1, new ArrayList()); + ContainerId containerId2 = ContainerId.newContainerId( + am1.getApplicationAttemptId(), 2); + rm1.waitForState(nm1, containerId2, RMContainerState.ALLOCATED); + am1.allocate(new ArrayList(), new ArrayList()) + .getAllocatedContainers(); + rm1.waitForState(nm1, containerId2, RMContainerState.ACQUIRED); + nm1.nodeHeartbeat(am1.getApplicationAttemptId(), 2, ContainerState.RUNNING); + nm1.nodeHeartbeat(am1.getApplicationAttemptId(), 2, ContainerState.COMPLETE); + nm1.nodeHeartbeat(am1.getApplicationAttemptId(), 1, ContainerState.COMPLETE); + rm1.waitForState(nm1, containerId2, RMContainerState.COMPLETED); + rm1.stop(); + + // RMContainer should be publishing system metrics for all containers. + // Since there is 1 AM container and 1 non-AM container, there should be 2 + // container created events and 2 container finished events. + verify(publisher, times(2)).containerCreated(any(RMContainer.class), anyLong()); + verify(publisher, times(2)).containerFinished(any(RMContainer.class), anyLong()); + } + + @Test (timeout = 180000) + public void testStoreOnlyAMContainerMetrics() throws Exception { + Configuration conf = new Configuration(); + conf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS, 1); + conf.setBoolean( + YarnConfiguration.APPLICATION_HISTORY_SAVE_CONTAINER_META_INFO, false); + MockRM rm1 = new MockRM(conf); + + SystemMetricsPublisher publisher = mock(SystemMetricsPublisher.class); + rm1.getRMContext().setSystemMetricsPublisher(publisher); + + rm1.start(); + MockNM nm1 = rm1.registerNode("unknownhost:1234", 8000); + RMApp app1 = rm1.submitApp(1024); + MockAM am1 = MockRM.launchAndRegisterAM(app1, rm1, nm1); + nm1.nodeHeartbeat(am1.getApplicationAttemptId(), 1, ContainerState.RUNNING); + + // request a container. + am1.allocate("127.0.0.1", 1024, 1, new ArrayList()); + ContainerId containerId2 = ContainerId.newContainerId( + am1.getApplicationAttemptId(), 2); + rm1.waitForState(nm1, containerId2, RMContainerState.ALLOCATED); + am1.allocate(new ArrayList(), new ArrayList()) + .getAllocatedContainers(); + rm1.waitForState(nm1, containerId2, RMContainerState.ACQUIRED); + nm1.nodeHeartbeat(am1.getApplicationAttemptId(), 2, ContainerState.RUNNING); + nm1.nodeHeartbeat(am1.getApplicationAttemptId(), 2, ContainerState.COMPLETE); + nm1.nodeHeartbeat(am1.getApplicationAttemptId(), 1, ContainerState.COMPLETE); + rm1.waitForState(nm1, containerId2, RMContainerState.COMPLETED); + rm1.stop(); + + // RMContainer should be publishing system metrics only for AM container. + verify(publisher, times(1)).containerCreated(any(RMContainer.class), anyLong()); + verify(publisher, times(1)).containerFinished(any(RMContainer.class), anyLong()); + } }