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 1d52cec..4e5d0cb 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 @@ -1091,6 +1091,11 @@ public static final String DEFAULT_FS_APPLICATION_HISTORY_STORE_COMPRESSION_TYPE = "none"; + /** The setting that controls whether timeline service is enabled or not. */ + public static final String TIMELINE_SERVICE_ENABLED = + TIMELINE_SERVICE_PREFIX + "enabled"; + public static final boolean DEFAULT_TIMELINE_SERVICE_ENABLED = true; + /** host:port address for timeline service RPC APIs. */ public static final String TIMELINE_SERVICE_ADDRESS = TIMELINE_SERVICE_PREFIX + "address"; diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java index 55dc55b..64cc041 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java @@ -55,6 +55,7 @@ private Client client; private URI resURI; + private boolean isEnabled; public TimelineClientImpl() { super(TimelineClientImpl.class.getName()); @@ -64,24 +65,38 @@ public TimelineClientImpl() { } protected void serviceInit(Configuration conf) throws Exception { - if (YarnConfiguration.useHttps(conf)) { - resURI = URI - .create(JOINER.join("https://", conf.get( - YarnConfiguration.TIMELINE_SERVICE_WEBAPP_HTTPS_ADDRESS, - YarnConfiguration.DEFAULT_TIMELINE_SERVICE_WEBAPP_HTTPS_ADDRESS), - RESOURCE_URI_STR)); + isEnabled = conf.getBoolean( + YarnConfiguration.TIMELINE_SERVICE_ENABLED, + YarnConfiguration.DEFAULT_TIMELINE_SERVICE_ENABLED); + if (!isEnabled) { + LOG.info("Timeline service is not enabled"); } else { - resURI = URI.create(JOINER.join("http://", conf.get( - YarnConfiguration.TIMELINE_SERVICE_WEBAPP_ADDRESS, - YarnConfiguration.DEFAULT_TIMELINE_SERVICE_WEBAPP_ADDRESS), RESOURCE_URI_STR)); + if (YarnConfiguration.useHttps(conf)) { + resURI = URI + .create(JOINER.join("https://", conf.get( + YarnConfiguration.TIMELINE_SERVICE_WEBAPP_HTTPS_ADDRESS, + YarnConfiguration.DEFAULT_TIMELINE_SERVICE_WEBAPP_HTTPS_ADDRESS), + RESOURCE_URI_STR)); + } else { + resURI = URI.create(JOINER.join("http://", conf.get( + YarnConfiguration.TIMELINE_SERVICE_WEBAPP_ADDRESS, + YarnConfiguration.DEFAULT_TIMELINE_SERVICE_WEBAPP_ADDRESS), + RESOURCE_URI_STR)); + } + LOG.info("Timeline service address: " + resURI); } - LOG.info("Timeline service address: " + resURI); super.serviceInit(conf); } @Override public TimelinePutResponse putEntities( TimelineEntity... entities) throws IOException, YarnException { + if (!isEnabled) { + if (LOG.isDebugEnabled()) { + LOG.debug("Nothing will be put because timeline service is not enabled"); + } + return new TimelinePutResponse(); + } TimelineEntities entitiesContainer = new TimelineEntities(); entitiesContainer.addEntities(Arrays.asList(entities)); ClientResponse resp; diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestTimelineClient.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestTimelineClient.java index 0fb3f38..8f61a05 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestTimelineClient.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestTimelineClient.java @@ -49,19 +49,19 @@ @Before public void setup() { - client = spy((TimelineClientImpl) TimelineClient.createTimelineClient()); - client.init(new YarnConfiguration()); - client.start(); + client = createTimelineClient(new YarnConfiguration()); } @After public void tearDown() { - client.stop(); + if (client != null) { + client.stop(); + } } @Test public void testPostEntities() throws Exception { - mockClientResponse(ClientResponse.Status.OK, false, false); + mockClientResponse(client, ClientResponse.Status.OK, false, false); try { TimelinePutResponse response = client.putEntities(generateEntity()); Assert.assertEquals(0, response.getErrors().size()); @@ -72,7 +72,7 @@ public void testPostEntities() throws Exception { @Test public void testPostEntitiesWithError() throws Exception { - mockClientResponse(ClientResponse.Status.OK, true, false); + mockClientResponse(client, ClientResponse.Status.OK, true, false); try { TimelinePutResponse response = client.putEntities(generateEntity()); Assert.assertEquals(1, response.getErrors().size()); @@ -90,7 +90,7 @@ public void testPostEntitiesWithError() throws Exception { @Test public void testPostEntitiesNoResponse() throws Exception { mockClientResponse( - ClientResponse.Status.INTERNAL_SERVER_ERROR, false, false); + client, ClientResponse.Status.INTERNAL_SERVER_ERROR, false, false); try { client.putEntities(generateEntity()); Assert.fail("Exception is expected"); @@ -102,7 +102,7 @@ public void testPostEntitiesNoResponse() throws Exception { @Test public void testPostEntitiesConnectionRefused() throws Exception { - mockClientResponse(null, false, true); + mockClientResponse(client, null, false, true); try { client.putEntities(generateEntity()); Assert.fail("RuntimeException is expected"); @@ -111,8 +111,24 @@ public void testPostEntitiesConnectionRefused() throws Exception { } } - private ClientResponse mockClientResponse(ClientResponse.Status status, - boolean hasError, boolean hasRuntimeError) { + @Test + public void testPostEntitiesTimelineServiceNotEnabled() throws Exception { + YarnConfiguration conf = new YarnConfiguration(); + conf.setBoolean(YarnConfiguration.TIMELINE_SERVICE_ENABLED, false); + TimelineClientImpl client = createTimelineClient(conf); + mockClientResponse( + client, ClientResponse.Status.INTERNAL_SERVER_ERROR, false, false); + try { + TimelinePutResponse response = client.putEntities(generateEntity()); + Assert.assertEquals(0, response.getErrors().size()); + } catch (YarnException e) { + Assert.fail( + "putEntities should already return before throwing the exception"); + } + } + + private static ClientResponse mockClientResponse(TimelineClientImpl client, + ClientResponse.Status status, boolean hasError, boolean hasRuntimeError) { ClientResponse response = mock(ClientResponse.class); if (hasRuntimeError) { doThrow(new ClientHandlerException(new ConnectException())).when(client) @@ -157,4 +173,13 @@ private static TimelineEntity generateEntity() { return entity; } + private static TimelineClientImpl createTimelineClient( + YarnConfiguration conf) { + TimelineClientImpl client = + spy((TimelineClientImpl) TimelineClient.createTimelineClient()); + client.init(conf); + client.start(); + return client; + } + } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml index deb3c2e..c12a2f5 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml @@ -1088,6 +1088,14 @@ + Indicate to clients whether timeline service is enabled or not. + If enabled, clients will put entities and events to the timeline server. + + yarn.timeline-service.enabled + true + + + The hostname of the timeline service web application. yarn.timeline-service.hostname 0.0.0.0