diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java index 863b5a1..9fae6d0 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java @@ -413,13 +413,13 @@ public static boolean isAclEnabled(Configuration conf) { public static final boolean DEFAULT_SYSTEM_METRICS_PUBLISHER_ENABLED = false; /** - * The setting that controls whether yarn container metrics is published to - * the timeline server or not by RM. This configuration setting is for ATS + * The setting that controls whether yarn container events are published to + * the timeline service or not by RM. This configuration setting is for ATS * V2 */ - public static final String RM_PUBLISH_CONTAINER_METRICS_ENABLED = YARN_PREFIX + public static final String RM_PUBLISH_CONTAINER_EVENTS_ENABLED = YARN_PREFIX + "rm.system-metrics-publisher.emit-container-events"; - public static final boolean DEFAULT_RM_PUBLISH_CONTAINER_METRICS_ENABLED = + public static final boolean DEFAULT_RM_PUBLISH_CONTAINER_EVENTS_ENABLED = false; public static final String RM_SYSTEM_METRICS_PUBLISHER_DISPATCHER_POOL_SIZE = diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml index 31b897b..88ffaf8 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml @@ -785,9 +785,9 @@ - The setting that controls whether yarn container metrics is - published to the timeline server or not by RM. This configuration setting is - for ATS V2. + The setting that controls whether yarn container events are + published to the timeline service or not by RM. This configuration setting + is for ATS V2. yarn.rm.system-metrics-publisher.emit-container-events false diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/metrics/TimelineServiceV2Publisher.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/metrics/TimelineServiceV2Publisher.java index 14073d1..b7ece5f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/metrics/TimelineServiceV2Publisher.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/metrics/TimelineServiceV2Publisher.java @@ -68,7 +68,7 @@ private static final Log LOG = LogFactory.getLog(TimelineServiceV2Publisher.class); private RMTimelineCollectorManager rmTimelineCollectorManager; - private boolean publishContainerMetrics; + private boolean publishContainerEvents; public TimelineServiceV2Publisher(RMContext rmContext) { super("TimelineserviceV2Publisher"); @@ -80,14 +80,14 @@ protected void serviceInit(Configuration conf) throws Exception { super.serviceInit(conf); getDispatcher().register(SystemMetricsEventType.class, new TimelineV2EventHandler()); - publishContainerMetrics = getConfig().getBoolean( - YarnConfiguration.RM_PUBLISH_CONTAINER_METRICS_ENABLED, - YarnConfiguration.DEFAULT_RM_PUBLISH_CONTAINER_METRICS_ENABLED); + publishContainerEvents = getConfig().getBoolean( + YarnConfiguration.RM_PUBLISH_CONTAINER_EVENTS_ENABLED, + YarnConfiguration.DEFAULT_RM_PUBLISH_CONTAINER_EVENTS_ENABLED); } @VisibleForTesting - boolean isPublishContainerMetrics() { - return publishContainerMetrics; + boolean isPublishContainerEvents() { + return publishContainerEvents; } @SuppressWarnings("unchecked") @@ -285,7 +285,7 @@ private static ApplicationAttemptEntity createAppAttemptEntity( @SuppressWarnings("unchecked") @Override public void containerCreated(RMContainer container, long createdTime) { - if (publishContainerMetrics) { + if (publishContainerEvents) { TimelineEntity entity = createContainerEntity(container.getContainerId()); entity.setCreatedTime(createdTime); @@ -320,7 +320,7 @@ public void containerCreated(RMContainer container, long createdTime) { @SuppressWarnings("unchecked") @Override public void containerFinished(RMContainer container, long finishedTime) { - if (publishContainerMetrics) { + if (publishContainerEvents) { TimelineEntity entity = createContainerEntity(container.getContainerId()); TimelineEvent tEvent = new TimelineEvent(); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/metrics/TestSystemMetricsPublisherForV2.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/metrics/TestSystemMetricsPublisherForV2.java index 7a018ca..13c67f8 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/metrics/TestSystemMetricsPublisherForV2.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/metrics/TestSystemMetricsPublisherForV2.java @@ -140,7 +140,7 @@ private static Configuration getTimelineV2Conf() { conf.setBoolean(YarnConfiguration.SYSTEM_METRICS_PUBLISHER_ENABLED, true); conf.setInt( YarnConfiguration.RM_SYSTEM_METRICS_PUBLISHER_DISPATCHER_POOL_SIZE, 2); - conf.setBoolean(YarnConfiguration.RM_PUBLISH_CONTAINER_METRICS_ENABLED, + conf.setBoolean(YarnConfiguration.RM_PUBLISH_CONTAINER_EVENTS_ENABLED, true); try { conf.set(FileSystemTimelineWriterImpl.TIMELINE_SERVICE_STORAGE_DIR_ROOT, @@ -160,12 +160,12 @@ public void testSystemMetricPublisherInitialization() { new TimelineServiceV2Publisher(mock(RMContext.class)); try { Configuration conf = getTimelineV2Conf(); - conf.setBoolean(YarnConfiguration.RM_PUBLISH_CONTAINER_METRICS_ENABLED, - YarnConfiguration.DEFAULT_RM_PUBLISH_CONTAINER_METRICS_ENABLED); + conf.setBoolean(YarnConfiguration.RM_PUBLISH_CONTAINER_EVENTS_ENABLED, + YarnConfiguration.DEFAULT_RM_PUBLISH_CONTAINER_EVENTS_ENABLED); metricsPublisher.init(conf); assertFalse( - "Default configuration should not publish container Metrics from RM", - metricsPublisher.isPublishContainerMetrics()); + "Default configuration should not publish container events from RM", + metricsPublisher.isPublishContainerEvents()); metricsPublisher.stop(); @@ -174,10 +174,10 @@ public void testSystemMetricPublisherInitialization() { metricsPublisher.init(conf); assertTrue("Expected to have registered event handlers and set ready to " + "publish events after init", - metricsPublisher.isPublishContainerMetrics()); + metricsPublisher.isPublishContainerEvents()); metricsPublisher.start(); - assertTrue("Expected to publish container Metrics from RM", - metricsPublisher.isPublishContainerMetrics()); + assertTrue("Expected to publish container events from RM", + metricsPublisher.isPublishContainerEvents()); } finally { metricsPublisher.stop(); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/TimelineServer.md b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/TimelineServer.md index 3e589d3..1851a88 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/TimelineServer.md +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/TimelineServer.md @@ -87,7 +87,7 @@ Current status Future Plans 1. Future releases will introduce a next generation timeline service -which is scalable and reliable, "Timeline Server v2". +which is scalable and reliable, ["Timeline Service v2"](./TimelineServiceV2.html). 1. The expanded features of this service *may not* be available to applications using the Timeline Server v1 REST API. That includes extended data structures as well as the ability of the client to failover between Timeline Server instances. diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/TimelineServiceV2.md b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/TimelineServiceV2.md new file mode 100644 index 0000000..acf3d87 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/TimelineServiceV2.md @@ -0,0 +1,548 @@ + + +The YARN Timeline Service v.2 +======================== + +* [Overview](#Overview) + * [Introduction](#Introduction) + * [Architecture](#Architecture) + * [Current Status](#Current_Status) +* [Deployment](#Deployment) + * [Configurations](#Configurations) + * [Enabling the Timeline Service v.2](#Enabling_Timeline_Service_v2) +* [Publishing of application specific data](#Publishing_of_application_specific_data) +* [Timeline Service v.2 REST API](#Timeline_Service_REST_API_v2) + +#Overview + +### Introduction + +YARN Timeline Service v.2 is the next major iteration of Timeline Server, following v.1 and v.1.5. +V.2 is created to address two major challenges of v.1. + +#### Scalability +V.1 is limited to a single instance of writer/reader and storage, and does not scale well beyond +small clusters. V.2 uses a more scalable distributed writer architecture and a scalable backend +storage. + +YARN Timeline Service v.2 separates the collection (writes) of data from serving (reads) of data. +It uses distributed collectors, essentially one collector for each YARN application. The readers +are separate instances that are dedicated to serving queries via REST API. + +YARN Timeline Service v.2 chooses Apache HBase as the primary backing storage, as Apache HBase +scales well to a large size while maintaining good response times for reads and writes. + +#### Usability improvements +In many cases, users are interested in information at the level of "flows" or logical groups of +YARN applications. It is much more common to launch a set or series of YARN applications to +complete a logic application. Timeline Service v.2 supports the notion of flows explicitly. In +addition, it supports aggregating metrics at the flow level. + +Also, information such as configuration and metrics is treated and supported as a first-class +citizen. + +###Architecture + +YARN Timeline Service v.2 uses a set of collectors (writers) to write data to the backend storage. +The collectors are distributed and co-located with the application masters to which they are +dedicated. All data that belong to that application are sent to the application level timeline +collectors with the exception of the resource manager timeline collector. + +The resource manager also maintains its own timeline collector. It emits only YARN-generic +lifecycle events to keep its volume of writes reasonable. + +The timeline readers are separate daemons separate from the timeline collectors, and they are +dedicated to serving queries via REST API. + +The following diagram illustrates the design at a high level. + +![Timeline Service v.2 architecture](./images/timeline_v2.jpg) + +### Current Status and Future Plans + +YARN Timeline Service v.2 is currently in alpha. It is very much work in progress, and many things +can and will change rapidly. Users should enable Timeline Service v.2 only on a test or +experimental cluster to test the feature. + +A complete end-to-end flow of writes and reads should be functional, with Apache HBase as the +backend. You should be able to start generating data. When enabled, all YARN-generic events are +published as well as YARN system metrics such as CPU and memory. Furthermore, some applications +including Distributed Shell and MapReduce write per-framework data to YARN Timeline Service v.2. + +The REST API comes with a good number of useful and flexible query patterns (see below for more +information). + +Although the basic mode of accessing data is via REST, it also comes with a basic web UI based on +the proposed new YARN UI framework. Currently there is no support for command line access, however. + +The collectors (writers) are currently embedded in the node managers as auxiliary services. The +resource manager also has its dedicated in-process collector. The reader is currently a single +instance. Currently, it is not possible to write to Timeline Service outside the context of a YARN +application (i.e. no off-cluster client). + +When YARN Timeline Service v.2 is disabled, one should expect no functional or performance impact +on any other existing functionality. + +The work to make it production-ready continues. Some key items include + +* More robust storage fault tolerance +* Security +* Support for off-cluster clients +* More complete and integrated web UI +* Better support for long-running apps +* Offline (time-based periodic) aggregation for flows, users, and queues for reporting and +analysis +* Timeline collectors as separate instances from node managers +* Clustering of the readers +* Migration and compatibility with v.1 + + +#Deployment + +###Configurations + +#### Basic configuration + +| Configuration Property | new | Description | +|:---- |:---- |:---- | +| `yarn.timeline-service.enabled` | | Indicate to clients whether Timeline service is enabled or not. If enabled, the `TimelineClient` library used by applications will post entities and events to the Timeline server. Defaults to `false`. | +| `yarn.timeline-service.version` | | Indicate what is the current version of the running timeline service. For example, if "yarn.timeline-service.version" is 1.5, and "yarn.timeline-service.enabled" is true, it means the cluster will and should bring up the timeline service v.1.5 (and nothing else). On the client side, if the client uses the same version of timeline service, it should succeed. If the client chooses to use a smaller version in spite of this, then depending on how robust the compatibility story is between versions, the results may vary. Defaults to `1.0f`. | +| `yarn.timeline-service.writer.class` | x | The class for the backend storage writer. Defaults to a filesystem storage writer, therefore it should be overridden. | +| `yarn.timeline-service.reader.class` | x | The class for the backend storage reader. Defaults to a filesystem storage reader, therefore it should be overridden. | +| `yarn.system-metrics-publisher.enabled` | | The setting that controls whether yarn system metrics is published on the Timeline service or not by RM And NM. Defaults to `false`. | +| `yarn.rm.system-metrics-publisher.emit-container-events` | | The setting that controls whether yarn container metrics is published to the timeline server or not by RM. This configuration setting is for ATS V2. Defaults to `false`. | + +#### Advanced configuration + +| Configuration Property | new | Description | +|:---- |:---- |:---- | +| `yarn.timeline-service.hostname` | | The hostname of the Timeline service web application. Defaults to `0.0.0.0` | +| `yarn.timeline-service.address` | | Address for the Timeline server to start the RPC server. Defaults to `${yarn.timeline-service.hostname}:10200`. | +| `yarn.timeline-service.webapp.address` | | The http address of the Timeline service web application. Defaults to `${yarn.timeline-service.hostname}:8188`. | +| `yarn.timeline-service.webapp.https.address` | | The https address of the Timeline service web application. Defaults to `${yarn.timeline-service.hostname}:8190`. | +| `yarn.timeline-service.writer.flush-interval-seconds` | x | The setting that controls how often the timeline collector flushes the timeline writer. Defaults to `60`. | +| `yarn.timeline-service.app-collector.linger-period.ms` | x | Time period till which the application collector will be alive in NM, after the application master container finishes. Defaults to `1000` (1 second). | +| `yarn.timeline-service.timeline-client.number-of-async-entities-to-merge` | x | Time line V2 client tries to merge these many number of async entities (if available) and then call the REST ATS V2 API to submit. Defaults to `10`. | +| `yarn.timeline-service.coprocessor.app-final-value-retention-milliseconds` | x | The setting that controls how long the final value of a metric of a completed app is retained before merging into the flow sum. Defaults to `259200000` (3 days). | + + + +### Enabling the Timeline Service v.2 + +#### Preparing Apache HBase cluster for storage +The first part is to set up or pick an Apache HBase cluster to use as the storage cluster. Once +you have an HBase cluster ready to use for this purpose, run the schema creator tool to create the +necessary tables: + + bin/hbase org.apache.hadoop.yarn.server.timelineservice.storage.TimelineSchemaCreator + +The `TimelineSchemaCreator` tool supports a few options that may come handy especially when you +are testing. For example, you can use `-skipExistingTable` (`-s` for short) to skip existing tables +and continue to create other tables rather than failing the schema creation. + +#### Enabling Timeline Service v.2 +Following are the basic configurations to start Timeline service v.2: + +``` + + yarn.timeline-service.version + 2.0f + + + + yarn.timeline-service.enabled + true + + + + yarn.timeline-service.writer.class + org.apache.hadoop.yarn.server.timelineservice.storage.HBaseTimelineWriterImpl + + + + yarn.timeline-service.reader.class + org.apache.hadoop.yarn.server.timelineservice.storage.HBaseTimelineReaderImpl + + + + yarn.nodemanager.aux-services + mapreduce_shuffle,timeline_collector + + + + yarn.nodemanager.aux-services.timeline_collector.class + org.apache.hadoop.yarn.server.timelineservice.collector.PerNodeTimelineCollectorsAuxService + + + + The setting that controls whether yarn system metrics is + published on the Timeline service or not by RM And NM. + yarn.system-metrics-publisher.enabled + true + + + + The setting that controls whether yarn container events are + published to the timeline service or not by RM. This configuration setting + is for ATS V2. + yarn.rm.system-metrics-publisher.emit-container-events + true + +``` + +In addition, you may want to set the YARN cluster name to a reasonably unique name in case you +are using multiple clusters to store data in the same Apache HBase storage: + +``` + + yarn.resourcemanager.cluster-id + my_research_test_cluster + +``` + +Also, add the `hbase-site.xml` configuration file to the client Hadoop cluster configuration so +that it can write data to the Apache HBase cluster you are using. + +#### Running Timeline Service v.2 +Restart the resource manager as well as the node managers to pick up the new configuration. The +collectors start within the resource manager and the node managers in an embedded manner. + +The Timeline Service reader is a separate YARN daemon, and it can be started using the following +syntax: + + $ yarn-daemon.sh start timelinereader + +#### Enabling MapReduce to write to Timeline Service v.2 +To write MapReduce framework data to Timeline Service v.2, enable the following configuration: + +``` + + mapreduce.job.emit-timeline-data + true + +``` + +### Publishing application specific data + +This section is for YARN application developers that want to integrate with Timeline Service v.2. + +Developers can continue to use the `TimelineClient` API to publish per-framework data to the +Timeline Service v.2. You only need to instantiate the right type of the client to write to v.2. +On the other hand, the entity/object API for v.2 is different than v.1 as the object model is +significantly changed. The v.2 timeline entity class is `org.apache.hadoop.yarn.api.records.timelineservice.TimelineEntity` +whereas the v.1 class is `org.apache.hadoop.yarn.api.records.timeline.TimelineEntity`. The methods +on `TimelineClient` suitable for writing to the Timeline Service v.2 are clearly delineated, and +they use the v.2 types as arguments. + +Timeline Service v.2 `putEntities` methods come in 2 varieties: `putEntities` and +`putEntitiesAsync`. The former is a blocking operation which should be used for writing more +critical data (e.g. lifecycle events). The latter is a non-blocking operation. Note that neither +has a return value. + +Creating a `TimelineClient` for v.2 involves passing in the application id to the factory method. + +For example: + + + // Create and start the Timeline client v.2 + TimelineClient client = TimelineClient.createTimelineClient(appId); + client.init(conf); + client.start(); + + try { + TimelineEntity myEntity = new TimelineEntity(); + myEntity.setEntityType("MY_APPLICATION"); + myEntity.setEntityId("MyApp1") + // Compose other entity info + + // Blocking write + client.putEntities(entity); + + TimelineEntity myEntity2 = new TimelineEntity(); + // Compose other info + + // Non-blocking write + timelineClient.putEntitiesAsync(entity); + + } catch (IOException e) { + // Handle the exception + } catch (RuntimeException e) { + // In Hadoop 2.6, if attempts submit information to the Timeline Server fail more than the retry limit, + // a RuntimeException will be raised. This may change in future releases, being + // replaced with a IOException that is (or wraps) that which triggered retry failures. + } catch (YarnException e) { + // Handle the exception + } finally { + // Stop the Timeline client + client.stop(); + } + +As evidenced above, you need to specify the YARN application id to be able to write to the Timeline +Service v.2. Note that currently you need to be on the cluster to be able to write to the Timeline +Service. For example, an application master or code in the container can write to the Timeline +Service, while an off-cluster MapReduce job submitter cannot. + +You can create and publish your own entities, events, and metrics as with previous versions. + +Application frameworks should set the "flow context" whenever possible in order to take advantage +of the flow support Timeline Service v.2 provides. The flow context consists of the following: + +* Flow name: a string that identifies the high-level flow (e.g. "distributed grep" or any +identifiable name that can uniquely represent the app) +* Flow run id: a monotonically-increasing sequence of numbers that distinguish different runs of +the same flow +* (optional) Flow version: a string identifier that denotes a version of the flow + +If the flow context is not specified, defaults are supplied for these attributes: + +* Flow name: the YARN application name (or the application id if the name is not set) +* Flow run id: the application start time in Unix time (milliseconds) +* Flow version: "1" + +You can provide the flow context via YARN application tags: + + ApplicationSubmissionContext appContext = app.getApplicationSubmissionContext(); + + // set the flow context as YARN application tags + Set tags = new HashSet<>(); + tags.add(TimelineUtils.generateFlowNameTag("distributed grep")); + tags.add(Timelineutils.generateFlowVersionTag("3df8b0d6100530080d2e0decf9e528e57c42a90a")); + tags.add(TimelineUtils.generateFlowRunIdTag(System.currentTimeMillis())); + + appContext.setApplicationTags(tags); + +# Timeline Service v.2 REST API + +Querying the Timeline Service v.2 is currently only supported via REST API; there is no API +client implemented in the YARN libraries. + +The v.2 REST API is implemented at under the path, `/ws/v2/timeline/` on the Timeline Service web +service. + +Here is an informal description of the API. + +### Root path + + GET /ws/v2/timeline/ + +Returns a JSON object describing the service instance and version information. + + { + "About":"Timeline Reader API", + "timeline-service-version":"3.0.0-SNAPSHOT", + "timeline-service-build-version":"3.0.0-SNAPSHOT from fb0acd08e6f0b030d82eeb7cbfa5404376313e60 by sjlee source checksum be6cba0e42417d53be16459e1685e7", + "timeline-service-version-built-on":"2016-04-11T23:15Z", + "hadoop-version":"3.0.0-SNAPSHOT", + "hadoop-build-version":"3.0.0-SNAPSHOT from fb0acd08e6f0b030d82eeb7cbfa5404376313e60 by sjlee source checksum ee968fd0aedcc7384230ee3ca216e790", + "hadoop-version-built-on":"2016-04-11T23:14Z" + } + +### Request Examples + +The following shows some of the supported queries on the REST API. For example, to get the most +recent flow activities, + +HTTP request: + + GET /ws/v2/timeline/clusters/{cluster name}/flows/ + +Response: + + [ + { + "metrics": [], + "events": [], + "id": "test-cluster/1460419200000/sjlee@ds-date", + "type": "YARN_FLOW_ACTIVITY", + "createdtime": 0, + "flowruns": [ + { + "metrics": [], + "events": [], + "id": "sjlee@ds-date/1460420305659", + "type": "YARN_FLOW_RUN", + "createdtime": 0, + "info": { + "SYSTEM_INFO_FLOW_VERSION": "1", + "SYSTEM_INFO_FLOW_RUN_ID": 1460420305659, + "SYSTEM_INFO_FLOW_NAME": "ds-date", + "SYSTEM_INFO_USER": "sjlee" + }, + "isrelatedto": {}, + "relatesto": {} + }, + { + "metrics": [], + "events": [], + "id": "sjlee@ds-date/1460420587974", + "type": "YARN_FLOW_RUN", + "createdtime": 0, + "info": { + "SYSTEM_INFO_FLOW_VERSION": "1", + "SYSTEM_INFO_FLOW_RUN_ID": 1460420587974, + "SYSTEM_INFO_FLOW_NAME": "ds-date", + "SYSTEM_INFO_USER": "sjlee" + }, + "isrelatedto": {}, + "relatesto": {} + } + ], + "info": { + "SYSTEM_INFO_CLUSTER": "test-cluster", + "UID": "test-cluster!sjlee!ds-date", + "SYSTEM_INFO_FLOW_NAME": "ds-date", + "SYSTEM_INFO_DATE": 1460419200000, + "SYSTEM_INFO_USER": "sjlee" + }, + "isrelatedto": {}, + "relatesto": {} + } + ] + +It returns the flows that had runs (specific instances of the flows) most recently. + +You can drill further down to get the runs (specific instances) of a given flow. + +HTTP request: + + GET /ws/v2/timeline/users/{user name}/flows/{flow name}/runs/ + +Response: + + [ + { + "metrics": [], + "events": [], + "id": "sjlee@ds-date/1460420587974", + "type": "YARN_FLOW_RUN", + "createdtime": 1460420587974, + "info": { + "UID": "test-cluster!sjlee!ds-date!1460420587974", + "SYSTEM_INFO_FLOW_RUN_ID": 1460420587974, + "SYSTEM_INFO_FLOW_NAME": "ds-date", + "SYSTEM_INFO_FLOW_RUN_END_TIME": 1460420595198, + "SYSTEM_INFO_USER": "sjlee" + }, + "isrelatedto": {}, + "relatesto": {} + }, + { + "metrics": [], + "events": [], + "id": "sjlee@ds-date/1460420305659", + "type": "YARN_FLOW_RUN", + "createdtime": 1460420305659, + "info": { + "UID": "test-cluster!sjlee!ds-date!1460420305659", + "SYSTEM_INFO_FLOW_RUN_ID": 1460420305659, + "SYSTEM_INFO_FLOW_NAME": "ds-date", + "SYSTEM_INFO_FLOW_RUN_END_TIME": 1460420311966, + "SYSTEM_INFO_USER": "sjlee" + }, + "isrelatedto": {}, + "relatesto": {} + } + ] + +This returns the most recent runs that belong to the given flow. + +You can provide a `limit` query parameter to limit the number of entries that returned in a query. +If you want to limit the number of flow runs in the above query, you can do the following: + +HTTP request: + + GET /ws/v2/timeline/users/{user name}/flows/{flow name}/runs?limit=1 + +Response: + + [ + { + "metrics": [], + "events": [], + "id": "sjlee@ds-date/1460420587974", + "type": "YARN_FLOW_RUN", + "createdtime": 1460420587974, + "info": { + "UID": "test-cluster!sjlee!ds-date!1460420587974", + "SYSTEM_INFO_FLOW_RUN_ID": 1460420587974, + "SYSTEM_INFO_FLOW_NAME": "ds-date", + "SYSTEM_INFO_FLOW_RUN_END_TIME": 1460420595198, + "SYSTEM_INFO_USER": "sjlee" + }, + "isrelatedto": {}, + "relatesto": {} + } + ] + +Most queries in the v.2 REST API support the following query parameters: + +* `limit` +* `createdtimestart` +* `createdtimeend` +* `relatesto` +* `isrelatedto` +* `infofilters` +* `conffilters` +* `metricfilters` +* `eventfilters` +* `fields` + +Given a flow run, you can query all the YARN applications that are part of that flow run: + +HTTP request: + + GET /ws/v2/timeline/users/{user name}/flows/{flow name}/runs/{run id}/apps/ + +Response: + + [ + { + "metrics": [], + "events": [], + "id": "application_1460419579913_0002", + "type": "YARN_APPLICATION", + "createdtime": 0, + "info": { + "UID": "test-cluster!sjlee!ds-date!1460420587974!application_1460419579913_0002" + }, + "configs": {}, + "isrelatedto": {}, + "relatesto": {} + } + ] + +You can also provide per-framework entity type to query for them. For example, + +HTTP request: + + GET /ws/v2/timeline/clusters/{cluster name}/apps/{app id}/entities/DS_APP_ATTEMPT + +Response: + + [ + { + "metrics": [], + "events": [], + "id": "appattempt_1460419579913_0002_000001", + "type": "DS_APP_ATTEMPT", + "createdtime": 0, + "info": { + "UID": "test-cluster!application_1460419579913_0002!DS_APP_ATTEMPT!appattempt_1460419579913_0002_000001" + }, + "configs": {}, + "isrelatedto": {}, + "relatesto": {} + } + ] diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/resources/images/timeline_v2.jpg b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/resources/images/timeline_v2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b4f970949fc3cc7fe4b920fc78a8509780fb952f GIT binary patch literal 37683 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 xd85)n*M9}P$bY=EkYfPXo_55H}yQ(QSeKX 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 fwl?W<@0NdCH|URDB-Gy^Y`