You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ao...@apache.org on 2019/06/27 11:16:06 UTC

[ambari] branch branch-2.7 updated (54dc60b -> 9e9ddf7)

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

aonishuk pushed a change to branch branch-2.7
in repository https://gitbox.apache.org/repos/asf/ambari.git.


    from 54dc60b  [AMBARI-25324] : Upgrade commons-lang/lang3 to latest versions (branch-2.7) (#3031)
     new f206398  AMBARI-25320 Backport AMBARI-24872 and AMBARI-24723 for ambari 2.7.4 (ihor lukianov)
     new 9e9ddf7  AMBARI-25320 Backport AMBARI-24872 and AMBARI-24723 for ambari 2.7.4 - small adjustment(ihor lukianov)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../ambari-metrics/datasource.js                   |   4 +
 .../core/timeline/PhoenixHBaseAccessor.java        | 101 +++++++++++++++++
 .../discovery/TimelineMetricMetadataManager.java   | 123 +++++++++++++--------
 .../timeline/query/MetadataQueryCondition.java     |  82 ++++++++++++++
 .../core/timeline/query/PhoenixTransactSQL.java    |  50 +++++++++
 .../timeline/query/TransientMetricCondition.java   |  29 ++++-
 .../timeline/discovery/TestMetadataManager.java    |  82 +++++++++++++-
 7 files changed, 422 insertions(+), 49 deletions(-)
 create mode 100644 ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/MetadataQueryCondition.java


[ambari] 02/02: AMBARI-25320 Backport AMBARI-24872 and AMBARI-24723 for ambari 2.7.4 - small adjustment(ihor lukianov)

Posted by ao...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aonishuk pushed a commit to branch branch-2.7
in repository https://gitbox.apache.org/repos/asf/ambari.git

commit 9e9ddf752f36aa9340d6dfdc23ecccfcd646fc53
Author: Ihor Lukianov <ih...@cloudera.com>
AuthorDate: Thu Jun 27 12:37:11 2019 +0300

    AMBARI-25320 Backport AMBARI-24872 and AMBARI-24723 for ambari 2.7.4 - small adjustment(ihor lukianov)
---
 ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js
index a5796b3..ec5ee10 100644
--- a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js
+++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js
@@ -259,7 +259,7 @@ define([
             var instanceId = typeof target.templatedCluster == 'undefined'  ? '' : '&instanceId=' + target.templatedCluster;
             var appId = target.app;
             if ((appId === 'nifi' || appId === 'druid') && (!instanceId || instanceId === '&instanceId=')) {
-                instanceId = "%"
+                instanceId = "&instanceId=%"
             }
             var precision = target.precision === 'default' || typeof target.precision == 'undefined'  ? '' : '&precision='
             + target.precision;


[ambari] 01/02: AMBARI-25320 Backport AMBARI-24872 and AMBARI-24723 for ambari 2.7.4 (ihor lukianov)

Posted by ao...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aonishuk pushed a commit to branch branch-2.7
in repository https://gitbox.apache.org/repos/asf/ambari.git

commit f2063984190b932e5a77220c4a80f4665e0617fa
Author: Ihor Lukianov <ih...@cloudera.com>
AuthorDate: Thu Jun 20 12:40:50 2019 +0300

    AMBARI-25320 Backport AMBARI-24872 and AMBARI-24723 for ambari 2.7.4 (ihor lukianov)
---
 .../ambari-metrics/datasource.js                   |   4 +
 .../core/timeline/PhoenixHBaseAccessor.java        | 101 +++++++++++++++++
 .../discovery/TimelineMetricMetadataManager.java   | 123 +++++++++++++--------
 .../timeline/query/MetadataQueryCondition.java     |  82 ++++++++++++++
 .../core/timeline/query/PhoenixTransactSQL.java    |  50 +++++++++
 .../timeline/query/TransientMetricCondition.java   |  29 ++++-
 .../timeline/discovery/TestMetadataManager.java    |  82 +++++++++++++-
 7 files changed, 422 insertions(+), 49 deletions(-)

diff --git a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js
index e7cd850..a5796b3 100644
--- a/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js
+++ b/ambari-metrics/ambari-metrics-grafana/ambari-metrics/datasource.js
@@ -257,6 +257,10 @@ define([
           // To speed up querying on templatized dashboards.
           var getAllHostData = function(target) {
             var instanceId = typeof target.templatedCluster == 'undefined'  ? '' : '&instanceId=' + target.templatedCluster;
+            var appId = target.app;
+            if ((appId === 'nifi' || appId === 'druid') && (!instanceId || instanceId === '&instanceId=')) {
+                instanceId = "%"
+            }
             var precision = target.precision === 'default' || typeof target.precision == 'undefined'  ? '' : '&precision='
             + target.precision;
             var metricAggregator = target.aggregator === "none" ? '' : '._' + target.aggregator;
diff --git a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/PhoenixHBaseAccessor.java b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/PhoenixHBaseAccessor.java
index c0427e7..b6ff202 100644
--- a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/PhoenixHBaseAccessor.java
+++ b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/PhoenixHBaseAccessor.java
@@ -121,6 +121,7 @@ import org.apache.ambari.metrics.core.timeline.discovery.TimelineMetricMetadataK
 import org.apache.ambari.metrics.core.timeline.discovery.TimelineMetricMetadataManager;
 import org.apache.ambari.metrics.core.timeline.query.Condition;
 import org.apache.ambari.metrics.core.timeline.query.DefaultPhoenixDataSource;
+import org.apache.ambari.metrics.core.timeline.query.MetadataQueryCondition;
 import org.apache.ambari.metrics.core.timeline.query.PhoenixConnectionProvider;
 import org.apache.ambari.metrics.core.timeline.query.PhoenixTransactSQL;
 import org.apache.ambari.metrics.core.timeline.query.SplitByMetricNamesCondition;
@@ -1990,6 +1991,106 @@ public class PhoenixHBaseAccessor {
     return metadataMap;
   }
 
+  public List<TimelineMetricMetadata> scanMetricMetadataForWildCardRequest(Collection<String> metricNames,
+                                                                           String appId,
+                                                                           String instanceId) throws SQLException {
+    List<TimelineMetricMetadata> metadataList = new ArrayList<>();
+    Connection conn = getConnection();
+    PreparedStatement stmt = null;
+    ResultSet rs = null;
+
+    MetadataQueryCondition metadataQueryCondition = new MetadataQueryCondition(new ArrayList<>(metricNames), appId, instanceId);
+    stmt = PhoenixTransactSQL.prepareScanMetricMetadataSqlStmt(conn, metadataQueryCondition);
+    try {
+      if (stmt != null) {
+        rs = stmt.executeQuery();
+        while (rs.next()) {
+          TimelineMetricMetadata metadata = new TimelineMetricMetadata(
+            rs.getString("METRIC_NAME"),
+            rs.getString("APP_ID"),
+            rs.getString("INSTANCE_ID"),
+            null,
+            null,
+            null,
+            false,
+            true
+          );
+
+          metadata.setUuid(rs.getBytes("UUID"));
+          metadataList.add(metadata);
+        }
+      }
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException e) {
+          // Ignore
+        }
+      }
+      if (stmt != null) {
+        try {
+          stmt.close();
+        } catch (SQLException e) {
+          // Ignore
+        }
+      }
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (SQLException sql) {
+          // Ignore
+        }
+      }
+    }
+
+    return metadataList;
+  }
+
+  public List<byte[]> scanHostMetadataForWildCardRequest(List<String> hostnames) throws SQLException {
+    List<byte[]> uuidList = new ArrayList<>();
+    Connection conn = getConnection();
+    PreparedStatement stmt;
+    ResultSet rs = null;
+
+    MetadataQueryCondition metadataQueryCondition = new MetadataQueryCondition(hostnames);
+    stmt = PhoenixTransactSQL.prepareScanMetricMetadataSqlStmt(conn, metadataQueryCondition);
+    try {
+      if (stmt != null) {
+        rs = stmt.executeQuery();
+        while (rs.next()) {
+          byte[] uuid = rs.getBytes("UUID");
+          if (uuid != null) {
+            uuidList.add(uuid);
+          }
+        }
+      }
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException e) {
+          // Ignore
+        }
+      }
+      if (stmt != null) {
+        try {
+          stmt.close();
+        } catch (SQLException e) {
+          // Ignore
+        }
+      }
+      if (conn != null) {
+        try {
+          conn.close();
+        } catch (SQLException sql) {
+          // Ignore
+        }
+      }
+    }
+    return uuidList;
+  }
+
   // No filter criteria support for now.
   public Map<TimelineMetricMetadataKey, TimelineMetricMetadata> getTimelineMetricMetadataV1() throws SQLException {
     Map<TimelineMetricMetadataKey, TimelineMetricMetadata> metadataMap = new HashMap<>();
diff --git a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/discovery/TimelineMetricMetadataManager.java b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/discovery/TimelineMetricMetadataManager.java
index 1c95c20..8d5edd6 100644
--- a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/discovery/TimelineMetricMetadataManager.java
+++ b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/discovery/TimelineMetricMetadataManager.java
@@ -361,7 +361,8 @@ public class TimelineMetricMetadataManager {
   }
 
   boolean isDistributedModeEnabled() {
-    return metricsConf.get("timeline.metrics.service.operation.mode").equals("distributed");
+    String mode = metricsConf.get("timeline.metrics.service.operation.mode");
+    return (mode != null) && mode.equals("distributed");
   }
 
   /**
@@ -632,69 +633,94 @@ public class TimelineMetricMetadataManager {
     Collection<String> sanitizedMetricNames = new HashSet<>();
     List<byte[]> uuids = new ArrayList<>();
 
+    boolean metricNameHasWildcard = false;
+
     for (String metricName : metricNames) {
-      if (metricName.contains("%")) {
-        String metricRegEx = getJavaRegexFromSqlRegex(metricName);
-        for (TimelineMetricMetadataKey key : METADATA_CACHE.keySet()) {
-          String metricNameFromMetadata = key.getMetricName();
-          if (metricNameFromMetadata.matches(metricRegEx)) {
-            sanitizedMetricNames.add(metricNameFromMetadata);
-          }
-        }
-      } else {
-        sanitizedMetricNames.add(metricName);
+      if (hasWildCard(metricName)) {
+        metricNameHasWildcard = true;
+        break;
       }
     }
 
-    if(sanitizedMetricNames.isEmpty()) {
-      return uuids;
+    boolean hostNameHasWildcard = false;
+    if (CollectionUtils.isNotEmpty(hostnames)) {
+      for (String hostname : hostnames) {
+        if (hasWildCard(hostname)) {
+          hostNameHasWildcard = true;
+          break;
+        }
+      }
     }
 
-    Set<String> sanitizedHostNames = getSanitizedHostnames(hostnames);
-
-    if (CollectionUtils.isNotEmpty(sanitizedHostNames)) {
-      if (CollectionUtils.isNotEmpty(sanitizedMetricNames)) {
+    if (hasWildCard(instanceId) || hasWildCard(appId) || hostNameHasWildcard || metricNameHasWildcard) {
+      try {
+        List<TimelineMetricMetadata> metricMetadataFromStore = hBaseAccessor.scanMetricMetadataForWildCardRequest(metricNames,
+          appId, instanceId);
+        List<byte[]> hostUuidsFromStore = hBaseAccessor.scanHostMetadataForWildCardRequest(hostnames);
+
+        for (TimelineMetricMetadata matchedEntry : metricMetadataFromStore) {
+          if (matchedEntry.getUuid() != null) {
+            if (CollectionUtils.isNotEmpty(hostnames)) {
+              for (byte[] hostUuidEntry : hostUuidsFromStore) {
+                uuids.add(ArrayUtils.addAll(matchedEntry.getUuid(), hostUuidEntry));
+              }
+            } else {
+              uuids.add(matchedEntry.getUuid());
+            }
+          } else if (isTransientMetric(matchedEntry.getMetricName(), matchedEntry.getAppId())) {
+            transientMetricNames.add(matchedEntry.getMetricName());
+          }
+        }
+        return uuids;
+      } catch (SQLException e) {
+        LOG.error("Unable to query metadata table to check satisfying metric keys for wildcard request : " + e);
+        return uuids;
+      }
+    } else {
 
-        //Skip getting UUID if it is a transient metric.
-        //An attempt to get it will also be OK as we don't add null UUIDs.
-        for (String metricName : sanitizedMetricNames) {
-          if (isTransientMetric(metricName, appId)) {
-            transientMetricNames.add(metricName);
-            continue;
+      if (CollectionUtils.isNotEmpty(hostnames)) {
+        if (CollectionUtils.isNotEmpty(metricNames)) {
+          //Skip getting UUID if it is a transient metric.
+          //An attempt to get it will also be OK as we don't add null UUIDs.
+          for (String metricName : metricNames) {
+            if (isTransientMetric(metricName, appId)) {
+              transientMetricNames.add(metricName);
+              continue;
+            }
+            TimelineMetric metric = new TimelineMetric();
+            metric.setMetricName(metricName);
+            metric.setAppId(appId);
+            metric.setInstanceId(instanceId);
+            for (String hostname : hostnames) {
+              metric.setHostName(hostname);
+              byte[] uuid = getUuid(metric, false);
+              if (uuid != null) {
+                uuids.add(uuid);
+              }
+            }
           }
-          TimelineMetric metric = new TimelineMetric();
-          metric.setMetricName(metricName);
-          metric.setAppId(appId);
-          metric.setInstanceId(instanceId);
-          for (String hostname : sanitizedHostNames) {
-            metric.setHostName(hostname);
-            byte[] uuid = getUuid(metric, false);
+        } else {
+          for (String hostname : hostnames) {
+            byte[] uuid = getUuidForHostname(hostname, false);
             if (uuid != null) {
               uuids.add(uuid);
             }
           }
         }
       } else {
-        for (String hostname : sanitizedHostNames) {
-          byte[] uuid = getUuidForHostname(hostname, false);
+        for (String metricName : metricNames) {
+          //Skip getting UUID if it is a transient metric. An attempt to get it will also be OK as we don't add null UUIDs.
+          if (isTransientMetric(metricName, appId)) {
+            transientMetricNames.add(metricName);
+            continue;
+          }
+          TimelineClusterMetric metric = new TimelineClusterMetric(metricName, appId, instanceId, -1l);
+          byte[] uuid = getUuid(metric, false);
           if (uuid != null) {
             uuids.add(uuid);
           }
         }
       }
-    } else {
-      for (String metricName : sanitizedMetricNames) {
-        //Skip getting UUID if it is a transient metric. An attempt to get it will also be OK as we don't add null UUIDs.
-        if (isTransientMetric(metricName, appId)) {
-          transientMetricNames.add(metricName);
-          continue;
-        }
-        TimelineClusterMetric metric = new TimelineClusterMetric(metricName, appId, instanceId, -1l);
-        byte[] uuid = getUuid(metric, false);
-        if (uuid != null) {
-          uuids.add(uuid);
-        }
-      }
     }
 
     return uuids;
@@ -830,9 +856,16 @@ public class TimelineMetricMetadataManager {
    * Run TimelineMetricMetadataSync once
    */
   public void forceMetricsMetadataSync() {
+    if (metricMetadataSync == null) {
+      metricMetadataSync = new TimelineMetricMetadataSync(this);
+    }
     metricMetadataSync.run();
   }
 
+  private boolean hasWildCard(String key) {
+    return StringUtils.isNotEmpty(key) && key.contains("%");
+  }
+
   public void updateMetadataCacheUsingV1Tables() throws SQLException {
     Map<TimelineMetricMetadataKey, TimelineMetricMetadata> metadataV1Map = getMetadataFromStoreV1();
     for (TimelineMetricMetadataKey key: METADATA_CACHE.keySet()) {
diff --git a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/MetadataQueryCondition.java b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/MetadataQueryCondition.java
new file mode 100644
index 0000000..a3e034e
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/MetadataQueryCondition.java
@@ -0,0 +1,82 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.metrics.core.timeline.query;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+
+public class MetadataQueryCondition extends TransientMetricCondition {
+
+  private boolean isMetricMetadataCondition = true;
+
+  public MetadataQueryCondition(List<String> metricNames, String appId, String instanceId) {
+    super(metricNames, Collections.EMPTY_LIST, appId, instanceId, null, null, null , null, true, null);
+    this.hostnames = Collections.EMPTY_LIST;
+  }
+
+  public MetadataQueryCondition(List<String> hostnames) {
+    super(Collections.EMPTY_LIST, hostnames, StringUtils.EMPTY, StringUtils.EMPTY, null, null, null , null, true, null);
+    isMetricMetadataCondition = false;
+  }
+
+  public StringBuilder getConditionClause() {
+    StringBuilder sb = new StringBuilder();
+
+    boolean appendConjunction = false;
+    if (CollectionUtils.isNotEmpty(metricNames)) {
+      appendConjunction = appendMetricNameClause(sb);
+    }
+
+    if (CollectionUtils.isNotEmpty(hostnames)) {
+      appendConjunction = appendHostnameClause(sb, appendConjunction);
+    }
+
+    String appId = getAppId();
+    if (StringUtils.isNotEmpty(appId)) {
+      if (appId.contains("%")) {
+        appendConjunction = append(sb, appendConjunction, appId, " APP_ID LIKE ?");
+      } else {
+        appendConjunction = append(sb, appendConjunction, appId, " APP_ID = ?");
+      }
+    }
+
+    String instanceId = getInstanceId();
+    if (StringUtils.isNotEmpty(instanceId) && !"%".equals(instanceId)) {
+      if (instanceId.contains("%")) {
+        appendConjunction = append(sb, appendConjunction, instanceId, " INSTANCE_ID LIKE ?");
+      } else {
+        appendConjunction = append(sb, appendConjunction, instanceId, " INSTANCE_ID = ?");
+      }
+    }
+
+    return sb;
+  }
+
+  @Override
+  public String getInstanceId() {
+    return instanceId == null || "%".equals(instanceId) || instanceId.isEmpty() ? null : instanceId;
+  }
+
+  public boolean isMetricMetadataCondition() {
+    return isMetricMetadataCondition;
+  }
+}
\ No newline at end of file
diff --git a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/PhoenixTransactSQL.java b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/PhoenixTransactSQL.java
index 6a1d03f..99ea38a 100644
--- a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/PhoenixTransactSQL.java
+++ b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/PhoenixTransactSQL.java
@@ -47,6 +47,16 @@ public class PhoenixTransactSQL {
 
   public static final String METRICS_RECORD_TABLE_NAME = "METRIC_RECORD_UUID";
 
+  public static final String SCAN_METRIC_METADATA_SQL = "SELECT METRIC_NAME, APP_ID, INSTANCE_ID, UUID FROM %s";
+
+  public static final String SCAN_HOST_METADATA_SQL = "SELECT HOSTNAME, UUID FROM %s";
+
+  public static final String METRICS_METADATA_TABLE_NAME =
+    "METRICS_METADATA_UUID";
+
+  public static final String HOST_METADATA_TABLE_NAME =
+    "HOSTED_APPS_METADATA_UUID";
+
   public static final String CREATE_METRICS_TABLE_SQL = "CREATE TABLE IF NOT " +
     "EXISTS " + METRICS_RECORD_TABLE_NAME + " (UUID BINARY(20) NOT NULL, " +
     "SERVER_TIME BIGINT NOT NULL, " +
@@ -980,6 +990,46 @@ public class PhoenixTransactSQL {
 
   }
 
+  public static PreparedStatement prepareScanMetricMetadataSqlStmt(Connection connection, MetadataQueryCondition condition)
+    throws SQLException {
+
+    String stmtStr;
+    if (condition.isMetricMetadataCondition()) {
+      stmtStr = String.format(SCAN_METRIC_METADATA_SQL, METRICS_METADATA_TABLE_NAME);
+    } else {
+      stmtStr = String.format(SCAN_HOST_METADATA_SQL, HOST_METADATA_TABLE_NAME);
+    }
+
+    StringBuilder sb = new StringBuilder(stmtStr);
+
+    sb.append(" WHERE ");
+    sb.append(condition.getConditionClause());
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("SQL: " + sb.toString() + ", condition: " + condition);
+    }
+
+    PreparedStatement stmt = null;
+    try {
+      stmt = connection.prepareStatement(sb.toString());
+      int pos = 1;
+      if (condition.isMetricMetadataCondition()) {
+        pos = addMetricNames(condition, pos, stmt);
+        pos = addAppId(condition, pos, stmt);
+        pos = addInstanceId(condition, pos, stmt);
+      } else {
+        pos = addHostNames(condition, pos, stmt);
+      }
+
+    } catch (SQLException e) {
+      if (stmt != null) {
+        stmt.close();
+      }
+      throw e;
+    }
+    return stmt;
+  }
+
   public static String getTargetTableUsingPrecision(Precision precision, boolean withHosts) {
 
     String inputTable = null;
diff --git a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/TransientMetricCondition.java b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/TransientMetricCondition.java
index c26d18d..bb43f28 100644
--- a/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/TransientMetricCondition.java
+++ b/ambari-metrics/ambari-metrics-timelineservice/src/main/java/org/apache/ambari/metrics/core/timeline/query/TransientMetricCondition.java
@@ -42,6 +42,17 @@ public class TransientMetricCondition extends DefaultCondition {
     }
   }
 
+  public TransientMetricCondition(List<String> metricNames, List<String> hostnames, String appId,
+                                  String instanceId, Long startTime, Long endTime, Precision precision,
+                                  Integer limit, boolean grouped, List<String> transientMetricNames) {
+    super(metricNames, hostnames, appId, instanceId, startTime, endTime, precision, limit, grouped);
+    this.transientMetricNames = transientMetricNames;
+    if (CollectionUtils.isEmpty(hostnames)) {
+      this.hostnames = Collections.singletonList("%");
+    }
+  }
+
+
   public StringBuilder getTransientConditionClause() {
     StringBuilder sb = new StringBuilder();
 
@@ -49,15 +60,27 @@ public class TransientMetricCondition extends DefaultCondition {
 
     appendConjunction = appendHostnameClause(sb, appendConjunction);
 
-    appendConjunction = append(sb, appendConjunction, getAppId(), " APP_ID = ?");
-    appendConjunction = append(sb, appendConjunction, getInstanceId(), " INSTANCE_ID = ?");
+    String appId = getAppId();
+    if (appId.contains("%")) {
+      appendConjunction = append(sb, appendConjunction, getAppId(), " APP_ID LIKE ?");
+    } else {
+      appendConjunction = append(sb, appendConjunction, getAppId(), " APP_ID = ?");
+    }
+
+    String instanceId = getInstanceId();
+    if (instanceId.contains("%")) {
+      appendConjunction = append(sb, appendConjunction, getInstanceId(), " INSTANCE_ID LIKE ?");
+    } else {
+      appendConjunction = append(sb, appendConjunction, getInstanceId(), " INSTANCE_ID = ?");
+    }
+
     appendConjunction = append(sb, appendConjunction, getStartTime(), " SERVER_TIME >= ?");
     append(sb, appendConjunction, getEndTime(), " SERVER_TIME < ?");
 
     return sb;
   }
 
-  private boolean appendMetricNameClause(StringBuilder sb) {
+  protected boolean appendMetricNameClause(StringBuilder sb) {
     boolean appendConjunction = false;
     List<String> metricsLike = new ArrayList<>();
     List<String> metricsIn = new ArrayList<>();
diff --git a/ambari-metrics/ambari-metrics-timelineservice/src/test/java/org/apache/ambari/metrics/core/timeline/discovery/TestMetadataManager.java b/ambari-metrics/ambari-metrics-timelineservice/src/test/java/org/apache/ambari/metrics/core/timeline/discovery/TestMetadataManager.java
index 90def86..0d9c3e5 100644
--- a/ambari-metrics/ambari-metrics-timelineservice/src/test/java/org/apache/ambari/metrics/core/timeline/discovery/TestMetadataManager.java
+++ b/ambari-metrics/ambari-metrics-timelineservice/src/test/java/org/apache/ambari/metrics/core/timeline/discovery/TestMetadataManager.java
@@ -181,7 +181,7 @@ public class TestMetadataManager extends AbstractMiniHBaseClusterTest {
   }
 
   @Test
-  public void testWildcardSanitization() throws IOException, SQLException, URISyntaxException {
+  public void testMetricHostWildcardSanitization() throws IOException, SQLException, URISyntaxException {
     // Initialize new manager
     metadataManager = new TimelineMetricMetadataManager(new Configuration(), hdb);
     hdb.setMetadataInstance(metadataManager);
@@ -234,6 +234,7 @@ public class TestMetadataManager extends AbstractMiniHBaseClusterTest {
     replay(configuration);
 
     hdb.insertMetricRecordsWithMetadata(metadataManager, timelineMetrics, true);
+    metadataManager.forceMetricsMetadataSync();
 
     List<byte[]> uuids = metadataManager.getUuidsForGetMetricQuery(Collections.singletonList("dummy_m%"),
       Collections.singletonList("dummy_host2"), "dummy_app1", null);
@@ -255,6 +256,85 @@ public class TestMetadataManager extends AbstractMiniHBaseClusterTest {
   }
 
   @Test
+  public void testAppInstanceWildcardSanitization() throws IOException, SQLException, URISyntaxException {
+    // Initialize new manager
+    metadataManager = new TimelineMetricMetadataManager(new Configuration(), hdb);
+    hdb.setMetadataInstance(metadataManager);
+    final long now = System.currentTimeMillis();
+
+    TimelineMetrics timelineMetrics = new TimelineMetrics();
+
+    TimelineMetric metric1 = new TimelineMetric();
+    metric1.setMetricName("dummy_m1");
+    metric1.setHostName("dummy_host1");
+    metric1.setStartTime(now - 1000);
+    metric1.setAppId("dummy_app1");
+    metric1.setInstanceId("dummy_i1");
+    metric1.setType("Integer");
+    metric1.setMetricValues(new TreeMap<Long, Double>() {{
+      put(now - 100, 1.0);
+      put(now - 200, 2.0);
+      put(now - 300, 3.0);
+    }});
+    timelineMetrics.getMetrics().add(metric1);
+
+    TimelineMetric metric2 = new TimelineMetric();
+    metric2.setMetricName("dummy_m2");
+    metric2.setHostName("dummy_host2");
+    metric2.setStartTime(now - 1000);
+    metric2.setAppId("dummy_app2");
+    metric2.setInstanceId("dummy_i2");
+    metric2.setType("Integer");
+    metric2.setMetricValues(new TreeMap<Long, Double>() {{
+      put(now - 100, 1.0);
+      put(now - 200, 2.0);
+      put(now - 300, 3.0);
+    }});
+    timelineMetrics.getMetrics().add(metric2);
+
+    TimelineMetric metric3 = new TimelineMetric();
+    metric3.setMetricName("dummy_3");
+    metric3.setHostName("gummy_3h");
+    metric3.setStartTime(now - 1000);
+    metric3.setAppId("gummy_app3");
+    metric3.setType("Integer");
+    metric3.setMetricValues(new TreeMap<Long, Double>() {{
+      put(now - 100, 1.0);
+      put(now - 200, 2.0);
+      put(now - 300, 3.0);
+    }});
+    timelineMetrics.getMetrics().add(metric3);
+
+    Configuration metricsConf = new Configuration();
+    TimelineMetricConfiguration configuration = EasyMock.createNiceMock(TimelineMetricConfiguration.class);
+    expect(configuration.getMetricsConf()).andReturn(metricsConf).once();
+    replay(configuration);
+
+    hdb.insertMetricRecordsWithMetadata(metadataManager, timelineMetrics, true);
+    metadataManager.forceMetricsMetadataSync();
+
+    List<byte[]> uuids = metadataManager.getUuidsForGetMetricQuery(Collections.singletonList("dummy_m%"),
+      Collections.singletonList("dummy_host%"), "dummy_app%", "dummy_i%");
+    Assert.assertTrue(uuids.size() == 4);
+
+    uuids = metadataManager.getUuidsForGetMetricQuery(Collections.singletonList("dummy_m1"),
+      Collections.singletonList("dummy_host1"), "dummy_app1", "%");
+    Assert.assertTrue(uuids.size() == 1);
+
+    uuids = metadataManager.getUuidsForGetMetricQuery(Collections.singletonList("dummy_m1"),
+      Collections.singletonList("dummy_host1"), "dummy_app1", "dummy_i%");
+    Assert.assertTrue(uuids.size() == 1);
+
+    uuids = metadataManager.getUuidsForGetMetricQuery(Collections.singletonList("dummy_m1"),
+      Collections.singletonList("dummy_host1"), "dummy_app1", "dummy_i2");
+    Assert.assertTrue(uuids.size() == 0);
+
+    uuids = metadataManager.getUuidsForGetMetricQuery(Collections.singletonList("%"),
+      Collections.singletonList("%"), "%", "%");
+    Assert.assertTrue(uuids.size() == 9);
+  }
+
+  @Test
   public void testTransientMetricPatterns() {
 
     long now = System.currentTimeMillis();