This is an automated email from the ASF dual-hosted git repository.

guoyp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/griffin.git


The following commit(s) were added to refs/heads/master by this push:
     new ee2c7ac  [GRIFFIN-244] get metrics by instance
ee2c7ac is described below

commit ee2c7acad7c58ca16d35c4887656f71dea6989d9
Author: Rodion Gorkovenko <[email protected]>
AuthorDate: Sun Apr 14 08:45:07 2019 +0800

    [GRIFFIN-244] get metrics by instance
    
    This is just a squashed version of #491
    
    Author: Rodion Gorkovenko <[email protected]>
    Author: rodion <[email protected]>
    
    Closes #492 from RodionGork/griffin-244-squashed.
---
 griffin-doc/service/api-guide.md                   |  39 ++++++
 griffin-doc/service/postman/griffin.json           | 146 ++++++++++++++++++++-
 .../griffin/measure/context/MetricWrapper.scala    |   4 +-
 .../measure/context/MetricWrapperTest.scala        |   5 +-
 .../core/exception/GriffinExceptionMessage.java    |   2 +
 .../griffin/core/job/entity/JobInstanceBean.java   |   7 +
 .../griffin/core/metric/MetricController.java      |   6 +
 .../apache/griffin/core/metric/MetricService.java  |   2 +
 .../griffin/core/metric/MetricServiceImpl.java     |  22 ++++
 .../apache/griffin/core/metric/MetricStore.java    |   2 +
 .../griffin/core/metric/MetricStoreImpl.java       |  28 +++-
 .../griffin/core/metric/model/MetricValue.java     |  44 +++++++
 .../apache/griffin/core/job/JobControllerTest.java |  11 ++
 .../griffin/core/metric/MetricServiceImplTest.java |  44 +++++++
 .../griffin/core/metric/MetricStoreImplTest.java   |  79 ++++++++++-
 service/src/test/resources/metricvalue.json        |  51 +++++++
 16 files changed, 475 insertions(+), 17 deletions(-)

diff --git a/griffin-doc/service/api-guide.md b/griffin-doc/service/api-guide.md
index 95113af..17bca5b 100644
--- a/griffin-doc/service/api-guide.md
+++ b/griffin-doc/service/api-guide.md
@@ -42,12 +42,14 @@ Apache Griffin default `BASE_PATH` is `http://<your 
ip>:8080`.
     - [Get Job Instances](#34)
     - [Get Job Healthy Statistics](#35)
     - [Download Sample Records](#36)
+    - [Get Job Instance by Id](#38)
 
 - [Metrics](#4)
     - [Get Metrics](#41)
     - [Add Metric Value](#42)
     - [Get Metric Value](#43)
     - [Remove Metric Value](#44)
+    - [Get Metric Value by Job Instance Id](#45)
 
 - [Hive MetaStore](#5)
     - [Get Table Metadata](#51)
@@ -747,6 +749,17 @@ curl -k -G -X GET 
http://127.0.0.1:8080/api/v1/jobs/download \
 ```
 If successful, this method returns missing records in the response body, 
maximum record count is 100.
 
+<div id = "38"></div>
+
+### Get Job Instance by Id
+`GET /api/v1/jobs/instances/{jobInstanceId}`
+
+#### API Example
+```
+curl -k -G -X GET http://127.0.0.1:8080/api/v1/jobs/instances/1
+```
+If successful, this method returns job instance description for the given job 
instance id. If there is no instance with given id found, returns Griffin 
Exception.
+
 <h2 id = "4"></h2>
 
 ## Metrics
@@ -927,6 +940,32 @@ curl -k -H "Accept: application/json" \
 }
 ```
 
+<div id = "45"></div>
+
+### Get Metric Value by Job Instance Id
+`GET http://127.0.0.1:8080/api/v1/metrics/values/:jobInstanceId`
+#### API Example
+```
+curl -k -G -X GET http://127.0.0.1:8080/api/v1/metrics/values/{304}
+{
+    "name": "some_job",
+    "tmst": 1553526960000,
+    "value": {
+        "total": 74,
+        "miss": 31,
+        "matched": 43,
+        "matchedFraction": 0.581081081081081
+    },
+    "metadata": {
+        "applicationId": "\"application_1549876136110_0237\"",
+    }
+}
+```
+
+
+
+
+
 <h2 id = "5"></h2>
 
 ### Hive MetaStore
diff --git a/griffin-doc/service/postman/griffin.json 
b/griffin-doc/service/postman/griffin.json
index e789121..55d7bac 100644
--- a/griffin-doc/service/postman/griffin.json
+++ b/griffin-doc/service/postman/griffin.json
@@ -1406,7 +1406,7 @@
                                                                "health"
                                                        ]
                                                },
-                                               "description": "`GET 
/api/v1/jobs/health`\n\n#### Response Body Sample\n```\n{\n  
\"healthyJobCount\": 1,\n  \"jobCount\": 2\n}\n```"
+                                               "description": "`GET 
/api/v1/jobs/health`\n\n#### Response Body Sample\n```\n{\n  \"job instance 
info\"\n}\n```"
                                        },
                                        "response": [
                                                {
@@ -1430,7 +1430,7 @@
                                                                                
"health"
                                                                        ]
                                                                },
-                                                               "description": 
"`GET /api/v1/jobs/health`\n\n#### Response Body Sample\n```\n{\n  
\"healthyJobCount\": 1,\n  \"jobCount\": 2\n}\n```"
+                                                               "description": 
"`GET /api/v1/jobs/health`\n\n#### Response Body Sample\n```\n{\n  \"job 
instance info\"\n}\n```"
                                                        },
                                                        "status": "OK",
                                                        "code": 200,
@@ -1838,6 +1838,75 @@
                                                        "body": ""
                                                }
                                        ]
+                               },
+                               {
+                                       "name": "Get Job Instance by Id",
+                                       "request": {
+                                               "method": "GET",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": ""
+                                               },
+                                               "url": {
+                                                       "raw": 
"{{BASE_PATH}}/api/v1/jobs/instances/:id",
+                                                       "host": [
+                                                               "{{BASE_PATH}}"
+                                                       ],
+                                                       "path": [
+                                                               "api",
+                                                               "v1",
+                                                               "jobs",
+                                                               "instances",
+                                                               ":id"
+                                                       ],
+                                                       "variable": [
+                                                               {
+                                                                       "key": 
"id",
+                                                                       
"value": "2"
+                                                               }
+                                                       ]
+                                               },
+                                               "description": "`GET 
/api/v1/jobs/instances/{id}`\n\n#### Response Body Sample\n```\n{\n  \"job 
instance info\"\n}\n```"
+                                       },
+                                       "response": [
+                                               {
+                                                       "name": "Get Job 
Instance by Id",
+                                                       "originalRequest": {
+                                                               "method": "GET",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": 
"raw",
+                                                                       "raw": 
""
+                                                               },
+                                                               "url": {
+                                                                       "raw": 
"{{BASE_PATH}}/api/v1/jobs/instances/:id",
+                                                                       "host": 
[
+                                                                               
"{{BASE_PATH}}"
+                                                                       ],
+                                                                       "path": 
[
+                                                                               
"api",
+                                                                               
"v1",
+                                                                               
"jobs",
+                                                                               
"instances",
+                                                                               
":id"
+                                                                       ],
+                                                                       
"variable": [
+                                                                               
{
+                                                                               
        "key": "id",
+                                                                               
        "value": "2"
+                                                                               
}
+                                                                       ]
+                                                               },
+                                                               "description": 
"`GET /api/v1/jobs/instances/{id}`\n\n#### Response Body Sample\n```\n{\n  
\"job instance info\"\n}\n```"
+                                                       },
+                                                       "status": "OK",
+                                                       "code": 200,
+                                                       
"_postman_previewlanguage": "json",
+                                                       "cookie": [],
+                                                       "body": "{\n    
\"healthyJobCount\": 1,\n    \"jobCount\": 2\n}"
+                                               }
+                                       ]
                                }
                        ]
                },
@@ -2080,7 +2149,7 @@
                                                ],
                                                "body": {
                                                        "mode": "raw",
-                                                       "raw": 
"[\n\t{\n\t\t\"name\" : \"metricName\",\n\t\t\"tmst\" : 
1509599811123,\n\t\t\"value\" : {\n\t\t\t\"__tmst\" : 
1509599811123,\n\t\t\t\"miss\" : 11,\n\t\t\t\"total\" : 
125000,\n\t\t\t\"matched\" : 124989\n\t\t}\n   }\n]"
+                                                       "raw": 
"[\n\t{\n\t\t\"name\" : \"metricName\",\n\t\t\"tmst\" : 
1509599811123,\n\t\t\"applicationId\" : \"app_1\",\n\t\t\"value\" : 
{\n\t\t\t\"__tmst\" : 1509599811123,\n\t\t\t\"miss\" : 11,\n\t\t\t\"total\" : 
125000,\n\t\t\t\"matched\" : 124989\n\t\t}\n   }\n]"
                                                },
                                                "url": {
                                                        "raw": 
"{{BASE_PATH}}/api/v1/metrics/values",
@@ -2109,7 +2178,7 @@
                                                                ],
                                                                "body": {
                                                                        "mode": 
"raw",
-                                                                       "raw": 
"[\n\t{\n\t\t\"name\" : \"metricName\",\n\t\t\"tmst\" : 
1509599811123,\n\t\t\"value\" : {\n\t\t\t\"__tmst\" : 
1509599811123,\n\t\t\t\"miss\" : 11,\n\t\t\t\"total\" : 
125000,\n\t\t\t\"matched\" : 124989\n\t\t}\n   }\n]"
+                                                                       "raw": 
"[\n\t{\n\t\t\"name\" : \"metricName\",\n\t\t\"tmst\" : 
1509599811123,\n\t\t\"applicationId\" : \"app_1\",\n\t\t\"value\" : 
{\n\t\t\t\"__tmst\" : 1509599811123,\n\t\t\t\"miss\" : 11,\n\t\t\t\"total\" : 
125000,\n\t\t\t\"matched\" : 124989\n\t\t}\n   }\n]"
                                                                },
                                                                "url": {
                                                                        "raw": 
"{{BASE_PATH}}/api/v1/metrics/values",
@@ -2307,6 +2376,75 @@
                                                        "body": 
"{\"took\":363,\"timed_out\":false,\"total\":5,\"deleted\":5,\"batches\":1,\"version_conflicts\":0,\"noops\":0,\"retries\":{\"bulk\":0,\"search\":0},\"throttled_millis\":0,\"requests_per_second\":-1.0,\"throttled_until_millis\":0,\"failures\":[]}"
                                                }
                                        ]
+                               },
+                               {
+                                       "name": "Get Metrics Value by Job 
Instance Id",
+                                       "request": {
+                                               "method": "GET",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": ""
+                                               },
+                                               "url": {
+                                                       "raw": 
"{{BASE_PATH}}/api/v1/metrics/values/:jobInstanceId",
+                                                       "host": [
+                                                               "{{BASE_PATH}}"
+                                                       ],
+                                                       "path": [
+                                                               "api",
+                                                               "v1",
+                                                               "metrics",
+                                                               "values",
+                                                               ":jobInstanceId"
+                                                       ],
+                                                       "variable": [
+                                                               {
+                                                                       "key": 
"jobInstanceId",
+                                                                       
"value": "304"
+                                                               }
+                                                       ]
+                                               },
+                                               "description": "`GET 
/api/v1/metrics/values/{jobInstanceId}`\n\n#### Response Body Sample\n```\n{\n  
\"metric value\"\n}\n```"
+                                       },
+                                       "response": [
+                                               {
+                                                       "name": "Get Metrics 
Value by Job Instance Id",
+                                                       "originalRequest": {
+                                                               "method": "GET",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": 
"raw",
+                                                                       "raw": 
""
+                                                               },
+                                                               "url": {
+                                                                       "raw": 
"{{BASE_PATH}}/api/v1/metrics/values/:jobInstanceId",
+                                                                       "host": 
[
+                                                                               
"{{BASE_PATH}}"
+                                                                       ],
+                                                                       "path": 
[
+                                                                               
"api",
+                                                                               
"v1",
+                                                                               
"metrics",
+                                                                               
"values",
+                                                                               
":jobInstanceId"
+                                                                       ],
+                                                                       
"variable": [
+                                                                               
{
+                                                                               
        "key": "jobInstanceId",
+                                                                               
        "value": "304"
+                                                                               
}
+                                                                       ]
+                                                               },
+                                                               "description": 
"`GET /api/v1/metrics/values/{jobInstanceId}`\n\n#### Response Body 
Sample\n```\n{\n  \"metric value\"\n}\n```"
+                                                       },
+                                                       "status": "OK",
+                                                       "code": 200,
+                                                       
"_postman_previewlanguage": "json",
+                                                       "cookie": [],
+                                                       "body": "{\n    
\"name\": some_job,\n    \"tmst\": 1553526960000\n    \"applicationId\": 
application_1549876136110_0237\n    \"value\": {\n    \"total\": 74}}"
+                                               }
+                                       ]
                                }
                        ]
                },
diff --git 
a/measure/src/main/scala/org/apache/griffin/measure/context/MetricWrapper.scala 
b/measure/src/main/scala/org/apache/griffin/measure/context/MetricWrapper.scala
index df162a7..484797a 100644
--- 
a/measure/src/main/scala/org/apache/griffin/measure/context/MetricWrapper.scala
+++ 
b/measure/src/main/scala/org/apache/griffin/measure/context/MetricWrapper.scala
@@ -28,7 +28,7 @@ case class MetricWrapper(name: String, applicationId: String) 
extends Serializab
   val _Name = "name"
   val _Timestamp = "tmst"
   val _Value = "value"
-  val _ApplicationId = "applicationId"
+  val _Metadata = "metadata"
 
   val metrics: MutableMap[Long, Map[String, Any]] = MutableMap()
 
@@ -47,7 +47,7 @@ case class MetricWrapper(name: String, applicationId: String) 
extends Serializab
         (_Name -> name),
         (_Timestamp -> timestamp),
         (_Value -> value),
-        (_ApplicationId -> applicationId)
+        (_Metadata -> Map("applicationId" -> applicationId))
       ))
     }
   }
diff --git 
a/measure/src/test/scala/org/apache/griffin/measure/context/MetricWrapperTest.scala
 
b/measure/src/test/scala/org/apache/griffin/measure/context/MetricWrapperTest.scala
index 8ad7d5d..4a49c75 100644
--- 
a/measure/src/test/scala/org/apache/griffin/measure/context/MetricWrapperTest.scala
+++ 
b/measure/src/test/scala/org/apache/griffin/measure/context/MetricWrapperTest.scala
@@ -35,8 +35,9 @@ class MetricWrapperTest extends FlatSpec with Matchers {
     metricWrapper.insertMetric(2, Map("miss" -> 4))
     metricWrapper.flush should be (Map(
       1L -> Map("name" -> "test", "tmst" -> 1, "value" -> Map("total" -> 10, 
"miss"-> 2, "match" -> 8),
-        "applicationId" -> "appId"),
-      2L -> Map("name" -> "test", "tmst" -> 2, "value" -> Map("total" -> 20, 
"miss"-> 4), "applicationId" -> "appId")
+        "metadata" -> Map("applicationId" -> "appId")),
+      2L -> Map("name" -> "test", "tmst" -> 2, "value" -> Map("total" -> 20, 
"miss"-> 4),
+        "metadata" -> Map("applicationId" -> "appId"))
     ))
   }
 
diff --git 
a/service/src/main/java/org/apache/griffin/core/exception/GriffinExceptionMessage.java
 
b/service/src/main/java/org/apache/griffin/core/exception/GriffinExceptionMessage.java
index 6a9b9da..4f65248 100644
--- 
a/service/src/main/java/org/apache/griffin/core/exception/GriffinExceptionMessage.java
+++ 
b/service/src/main/java/org/apache/griffin/core/exception/GriffinExceptionMessage.java
@@ -76,6 +76,8 @@ public enum GriffinExceptionMessage {
 
     INSTANCE_ID_DOES_NOT_EXIST(40409, "Instance id does not exist"),
 
+    JOB_INSTANCE_NOT_FOUND(40410, "No job instances with given job instance id 
found"),
+
     //409, "Conflict"
     MEASURE_NAME_ALREADY_EXIST(40901, "Measure name already exists"),
 
diff --git 
a/service/src/main/java/org/apache/griffin/core/job/entity/JobInstanceBean.java 
b/service/src/main/java/org/apache/griffin/core/job/entity/JobInstanceBean.java
index 6fc5cf2..c3b0f1c 100644
--- 
a/service/src/main/java/org/apache/griffin/core/job/entity/JobInstanceBean.java
+++ 
b/service/src/main/java/org/apache/griffin/core/job/entity/JobInstanceBean.java
@@ -186,6 +186,13 @@ public class JobInstanceBean extends 
AbstractAuditableEntity {
     public JobInstanceBean() {
     }
 
+    public JobInstanceBean(State state, Long tms, Long expireTms, String 
appId) {
+        this.state = state;
+        this.tms = tms;
+        this.expireTms = expireTms;
+        this.appId=appId;
+    }
+
     public JobInstanceBean(State state, Long tms, Long expireTms) {
         this.state = state;
         this.tms = tms;
diff --git 
a/service/src/main/java/org/apache/griffin/core/metric/MetricController.java 
b/service/src/main/java/org/apache/griffin/core/metric/MetricController.java
index 4d39ba3..5cd43af 100644
--- a/service/src/main/java/org/apache/griffin/core/metric/MetricController.java
+++ b/service/src/main/java/org/apache/griffin/core/metric/MetricController.java
@@ -27,6 +27,7 @@ import org.apache.griffin.core.metric.model.MetricValue;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -71,4 +72,9 @@ public class MetricController {
                                                         String metricName) {
         return metricService.deleteMetricValues(metricName);
     }
+
+    @RequestMapping(value = "/metrics/values/{instanceId}", method = 
RequestMethod.GET)
+    public MetricValue getMetric(@PathVariable("instanceId") Long id){
+        return metricService.findMetric(id);
+    }
 }
diff --git 
a/service/src/main/java/org/apache/griffin/core/metric/MetricService.java 
b/service/src/main/java/org/apache/griffin/core/metric/MetricService.java
index 039b0cb..75402ff 100644
--- a/service/src/main/java/org/apache/griffin/core/metric/MetricService.java
+++ b/service/src/main/java/org/apache/griffin/core/metric/MetricService.java
@@ -37,4 +37,6 @@ public interface MetricService {
     ResponseEntity addMetricValues(List<MetricValue> values);
 
     ResponseEntity<?> deleteMetricValues(String metricName);
+
+    MetricValue findMetric(Long id);
 }
diff --git 
a/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java 
b/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java
index f817f65..beca19e 100644
--- 
a/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java
+++ 
b/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java
@@ -23,6 +23,7 @@ package org.apache.griffin.core.metric;
 import static 
org.apache.griffin.core.exception.GriffinExceptionMessage.INVALID_METRIC_RECORDS_OFFSET;
 import static 
org.apache.griffin.core.exception.GriffinExceptionMessage.INVALID_METRIC_RECORDS_SIZE;
 import static 
org.apache.griffin.core.exception.GriffinExceptionMessage.INVALID_METRIC_VALUE_FORMAT;
+import static 
org.apache.griffin.core.exception.GriffinExceptionMessage.JOB_INSTANCE_NOT_FOUND;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -36,6 +37,8 @@ import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.griffin.core.exception.GriffinException;
 import org.apache.griffin.core.job.entity.AbstractJob;
+import org.apache.griffin.core.job.entity.JobInstanceBean;
+import org.apache.griffin.core.job.repo.JobInstanceRepo;
 import org.apache.griffin.core.job.repo.JobRepo;
 import org.apache.griffin.core.measure.entity.Measure;
 import org.apache.griffin.core.measure.repo.MeasureRepo;
@@ -59,6 +62,8 @@ public class MetricServiceImpl implements MetricService {
     private JobRepo<AbstractJob> jobRepo;
     @Autowired
     private MetricStore metricStore;
+    @Autowired
+    private JobInstanceRepo jobInstanceRepo;
 
     @Override
     public Map<String, List<Metric>> getAllMetrics() {
@@ -139,6 +144,23 @@ public class MetricServiceImpl implements MetricService {
         }
     }
 
+    @Override
+    public MetricValue findMetric(Long id) {
+        JobInstanceBean jobInstanceBean = jobInstanceRepo.findByInstanceId(id);
+        if (jobInstanceBean == null){
+            LOGGER.warn("There are no job instances with id {} ", id);
+            throw new GriffinException
+                    .NotFoundException(JOB_INSTANCE_NOT_FOUND);
+        }
+        String appId = jobInstanceBean.getAppId();
+        try {
+            return metricStore.getMetric(appId);
+        } catch (IOException e) {
+            LOGGER.warn("Failed to get metric for applicationId {} ", appId);
+            throw new GriffinException.ServiceException("Failed to find 
metric", e);
+        }
+    }
+
     private void checkFormat(MetricValue value) {
         if (StringUtils.isBlank(value.getName()) || value.getTmst() == null
                 || MapUtils.isEmpty(value.getValue())) {
diff --git 
a/service/src/main/java/org/apache/griffin/core/metric/MetricStore.java 
b/service/src/main/java/org/apache/griffin/core/metric/MetricStore.java
index a452648..f85c4db 100644
--- a/service/src/main/java/org/apache/griffin/core/metric/MetricStore.java
+++ b/service/src/main/java/org/apache/griffin/core/metric/MetricStore.java
@@ -34,4 +34,6 @@ public interface MetricStore {
             throws IOException;
 
     ResponseEntity<?> deleteMetricValues(String metricName) throws IOException;
+
+    MetricValue getMetric(String applicationId) throws IOException;
 }
diff --git 
a/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java 
b/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java
index 3bff8f5..2d577bb 100644
--- a/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java
+++ b/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java
@@ -31,7 +31,9 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.griffin.core.metric.model.MetricValue;
 import org.apache.griffin.core.util.JsonUtil;
 import org.apache.http.Header;
@@ -142,14 +144,16 @@ public class MetricStoreImpl implements MetricStore {
                 .hasNonNull("hits")) {
             for (JsonNode node : jsonNode.get("hits").get("hits")) {
                 JsonNode sourceNode = node.get("_source");
-                Map<String, Object> value = JsonUtil.toEntity(sourceNode
-                                .get("value").toString(),
-                        new TypeReference<Map<String, Object>>() {
-                        });
-                MetricValue metricValue = new MetricValue(sourceNode
-                        .get("name")
-                        .asText(),
+                Map<String, Object> value = JsonUtil.toEntity(
+                        sourceNode.get("value").toString(),
+                        new TypeReference<Map<String, Object>>() {});
+                Map<String, Object> meta = JsonUtil.toEntity(
+                        Objects.toString(sourceNode.get("metadata"), null),
+                        new TypeReference<Map<String, Object>>() {});
+                MetricValue metricValue = new MetricValue(
+                        sourceNode.get("name").asText(),
                         Long.parseLong(sourceNode.get("tmst").asText()),
+                        meta,
                         value);
                 metricValues.add(metricValue);
             }
@@ -206,4 +210,14 @@ public class MetricStoreImpl implements MetricStore {
         return String.format("Basic %s", Base64.getEncoder().encodeToString(
                 auth.getBytes()));
     }
+
+    @Override
+    public MetricValue getMetric(String applicationId) throws IOException {
+        Response response = client.performRequest(
+                "GET", urlGet,
+                Collections.singletonMap(
+                        "q", "metadata.applicationId:" + applicationId));
+        List<MetricValue> metricValues = getMetricValuesFromResponse(response);
+        return metricValues.get(0);
+    }
 }
diff --git 
a/service/src/main/java/org/apache/griffin/core/metric/model/MetricValue.java 
b/service/src/main/java/org/apache/griffin/core/metric/model/MetricValue.java
index 4839f9f..4c7f386 100644
--- 
a/service/src/main/java/org/apache/griffin/core/metric/model/MetricValue.java
+++ 
b/service/src/main/java/org/apache/griffin/core/metric/model/MetricValue.java
@@ -19,7 +19,9 @@ under the License.
 
 package org.apache.griffin.core.metric.model;
 
+import java.util.Collections;
 import java.util.Map;
+import java.util.Objects;
 
 public class MetricValue {
 
@@ -27,6 +29,8 @@ public class MetricValue {
 
     private Long tmst;
 
+    private Map<String, Object> metadata;
+
     private Map<String, Object> value;
 
     public MetricValue() {
@@ -36,6 +40,15 @@ public class MetricValue {
         this.name = name;
         this.tmst = tmst;
         this.value = value;
+        this.metadata = Collections.emptyMap();
+    }
+
+
+    public MetricValue(String name, Long tmst, Map<String, Object> metadata, 
Map<String, Object> value) {
+        this.name = name;
+        this.tmst = tmst;
+        this.metadata = metadata;
+        this.value = value;
     }
 
     public String getName() {
@@ -61,4 +74,35 @@ public class MetricValue {
     public void setValue(Map<String, Object> value) {
         this.value = value;
     }
+
+    public Map<String, Object> getMetadata() {
+        return metadata;
+    }
+
+    public void setMetadata(Map<String, Object> metadata) {
+        this.metadata = metadata;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        MetricValue that = (MetricValue) o;
+        return Objects.equals(name, that.name) &&
+                Objects.equals(tmst, that.tmst) &&
+                Objects.equals(metadata, that.metadata) &&
+                Objects.equals(value, that.value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, tmst, metadata, value);
+    }
+
+    @Override
+    public String toString() {
+        return String.format(
+                "MetricValue{name=%s, ts=%s, meta=%s, value=%s}",
+                name, tmst, metadata, value);
+    }
 }
diff --git 
a/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java 
b/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java
index d9d5d80..aa10cf2 100644
--- a/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java
+++ b/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java
@@ -38,6 +38,7 @@ import java.util.Collections;
 
 import org.apache.griffin.core.exception.GriffinException;
 import org.apache.griffin.core.exception.GriffinExceptionHandler;
+import org.apache.griffin.core.exception.GriffinExceptionMessage;
 import org.apache.griffin.core.job.entity.AbstractJob;
 import org.apache.griffin.core.job.entity.JobHealth;
 import org.apache.griffin.core.job.entity.JobInstanceBean;
@@ -186,6 +187,16 @@ public class JobControllerTest {
     }
 
     @Test
+    public void testJobInstanceWithGivenIdNotFound() throws Exception {
+        Long jobInstanceId = 2L;
+        doThrow(new 
GriffinException.NotFoundException(GriffinExceptionMessage.JOB_INSTANCE_NOT_FOUND))
+                .when(service).findInstance(jobInstanceId);
+
+        mvc.perform(get(URLHelper.API_VERSION_PATH + "/jobs/instances/2"))
+                .andExpect(status().isNotFound());
+    }
+
+    @Test
     public void testGetHealthInfo() throws Exception {
         JobHealth jobHealth = new JobHealth(1, 3);
         given(service.getHealthInfo()).willReturn(jobHealth);
diff --git 
a/service/src/test/java/org/apache/griffin/core/metric/MetricServiceImplTest.java
 
b/service/src/test/java/org/apache/griffin/core/metric/MetricServiceImplTest.java
index aa55f7a..39837f0 100644
--- 
a/service/src/test/java/org/apache/griffin/core/metric/MetricServiceImplTest.java
+++ 
b/service/src/test/java/org/apache/griffin/core/metric/MetricServiceImplTest.java
@@ -33,6 +33,9 @@ import java.util.Map;
 
 import org.apache.griffin.core.exception.GriffinException;
 import org.apache.griffin.core.job.entity.AbstractJob;
+import org.apache.griffin.core.job.entity.JobInstanceBean;
+import org.apache.griffin.core.job.entity.LivySessionStates;
+import org.apache.griffin.core.job.repo.JobInstanceRepo;
 import org.apache.griffin.core.job.repo.JobRepo;
 import org.apache.griffin.core.measure.entity.Measure;
 import org.apache.griffin.core.measure.repo.MeasureRepo;
@@ -63,6 +66,8 @@ public class MetricServiceImplTest {
     private JobRepo<AbstractJob> jobRepo;
     @Mock
     private MetricStoreImpl metricStore;
+    @Mock
+    private JobInstanceRepo jobInstanceRepo;
 
     @Autowired
     private Environment env;
@@ -204,4 +209,43 @@ public class MetricServiceImplTest {
 
     }
 
+    @Test
+    public void testFindMetricSuccess() throws IOException {
+        Long id = 1L;
+        String appId = "application";
+        MetricValue expectedMetric = new MetricValue(
+                "name", 1234L, Collections.singletonMap("applicationId", 
appId), new HashMap<>());
+
+        given(jobInstanceRepo.findByInstanceId(id))
+                .willReturn(new 
JobInstanceBean(LivySessionStates.State.RUNNING, 12L, 32L, appId));
+        given(metricStore.getMetric(appId))
+                .willReturn(expectedMetric);
+        MetricValue actualMetric = service.findMetric(id);
+
+        assertEquals(expectedMetric, actualMetric);
+    }
+
+    @Test(expected = GriffinException.NotFoundException.class)
+    public void testFailedToFindJobInstance() throws IOException {
+        Long id = 1L;
+        given(jobInstanceRepo.findByInstanceId(id))
+                .willReturn(null);
+        service.findMetric(id);
+
+    }
+
+    @Test(expected = GriffinException.ServiceException.class)
+    public void testFindMetricFailure() throws IOException {
+        Long id = 1L;
+        String appId = "application";
+
+        given(jobInstanceRepo.findByInstanceId(id))
+                .willReturn(new 
JobInstanceBean(LivySessionStates.State.RUNNING, 12L, 32L, appId));
+        given(metricStore.getMetric(appId))
+                .willThrow(new GriffinException.ServiceException("", new 
RuntimeException()));
+        service.findMetric(id);
+
+    }
+
+
 }
diff --git 
a/service/src/test/java/org/apache/griffin/core/metric/MetricStoreImplTest.java 
b/service/src/test/java/org/apache/griffin/core/metric/MetricStoreImplTest.java
index d3cbfb0..b91f6ba 100644
--- 
a/service/src/test/java/org/apache/griffin/core/metric/MetricStoreImplTest.java
+++ 
b/service/src/test/java/org/apache/griffin/core/metric/MetricStoreImplTest.java
@@ -19,15 +19,55 @@ under the License.
 
 package org.apache.griffin.core.metric;
 
-import static org.junit.Assert.assertTrue;
+import org.apache.griffin.core.metric.model.MetricValue;
+import org.apache.http.HttpEntity;
+import org.elasticsearch.client.Response;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.BDDMockito.*;
 
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({RestClient.class, RestClientBuilder.class})
+@PowerMockIgnore("javax.management.*")
 public class MetricStoreImplTest {
 
+    private static final String INDEX = "griffin";
+    private static final String TYPE = "accuracy";
+
+    private static final String urlBase = String.format("/%s/%s", INDEX, TYPE);
+    private static final String urlGet = 
urlBase.concat("/_search?filter_path=hits.hits._source");
+
+    private RestClient restClientMock;
+
+    @Before
+    public void setup(){
+        PowerMockito.mockStatic(RestClient.class);
+        restClientMock = PowerMockito.mock(RestClient.class);
+        RestClientBuilder restClientBuilderMock = 
PowerMockito.mock(RestClientBuilder.class);
+
+        
given(RestClient.builder(anyVararg())).willReturn(restClientBuilderMock);
+        given(restClientBuilderMock.build()).willReturn(restClientMock);
+    }
+
     @Test
     public void testBuildBasicAuthString()
             throws NoSuchMethodException, InvocationTargetException,
@@ -40,4 +80,39 @@ public class MetricStoreImplTest {
         assertTrue(authStr.equals("Basic dXNlcjpwYXNzd29yZA=="));
     }
 
+    @Test
+    public void testMetricGetting() throws IOException, URISyntaxException {
+        //given
+        Response responseMock = PowerMockito.mock(Response.class);
+        HttpEntity httpEntityMock = PowerMockito.mock(HttpEntity.class);
+        InputStream is = Thread.currentThread().getContextClassLoader()
+                .getResourceAsStream("metricvalue.json");
+        Map<String, String> map = new HashMap<>();
+        map.put("q", "metadata.applicationId:application_1549876136110_0018");
+
+        Map<String, Object> value = new HashMap<String, Object>(){{
+            put("total", 74);
+            put("miss", 0);
+            put("matched", 74);
+            put("matchedFraction", 1);
+        }};
+        MetricValue expectedMetric = new 
MetricValue("de_demo_results_comparision",
+                1549985089648L,
+                Collections.singletonMap("applicationId", 
"application_1549876136110_0018"),
+                value);
+
+
+        given(restClientMock.performRequest(eq("GET"), eq(urlGet), eq(map), 
anyVararg())).willReturn(responseMock);
+        given(responseMock.getEntity()).willReturn(httpEntityMock);
+        given(httpEntityMock.getContent()).willReturn(is);
+
+        //when
+        MetricStoreImpl metricStore = new MetricStoreImpl("", 0, "", "", "");
+        MetricValue metric = 
metricStore.getMetric("application_1549876136110_0018");
+
+        //then
+        PowerMockito.verifyStatic();
+        assertEquals(expectedMetric, metric);
+    }
+
 }
diff --git a/service/src/test/resources/metricvalue.json 
b/service/src/test/resources/metricvalue.json
new file mode 100644
index 0000000..690c1c4
--- /dev/null
+++ b/service/src/test/resources/metricvalue.json
@@ -0,0 +1,51 @@
+{
+  "took": 47,
+  "timed_out": false,
+  "_shards": {
+    "total": 5,
+    "successful": 5,
+    "skipped": 0,
+    "failed": 0
+  },
+  "hits": {
+    "total": 17,
+    "max_score": 3.226844,
+    "hits": [
+      {
+        "_index": "griffin",
+        "_type": "accuracy",
+        "_id": "RZFP4mgBkZqzqlKSwWtJ",
+        "_score": 3.226844,
+        "_source": {
+          "name": "de_demo_results_comparision",
+          "tmst": 1549985089648,
+          "value": {
+            "total": 74,
+            "miss": 0,
+            "matched": 74,
+            "matchedFraction": 1
+          },
+          "metadata": {
+            "applicationId": "application_1549876136110_0018"
+          }
+        }
+      },
+      {
+        "_index": "griffin",
+        "_type": "accuracy",
+        "_id": "taMpvmgBfOpRJiYFj5Xg",
+        "_score": 2.4107988,
+        "_source": {
+          "name": "de_demo_results_comparision",
+          "tmst": 1549378607658,
+          "value": {
+            "total": 74,
+            "miss": 0,
+            "matched": 74,
+            "matchedFraction": 1
+          }
+        }
+      }
+    ]
+  }
+}
\ No newline at end of file

Reply via email to