You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sa...@apache.org on 2021/04/30 05:57:21 UTC

[atlas] branch master updated: ATLAS-4106: Add REST API debug metrics to Atlas

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 8077863  ATLAS-4106: Add REST API debug metrics to Atlas
8077863 is described below

commit 8077863b2f5a9c7ee4bd140eb954e24fef684785
Author: mayanknj <ma...@freestoneinfotech.com>
AuthorDate: Thu Apr 29 22:35:34 2021 -0700

    ATLAS-4106: Add REST API debug metrics to Atlas
    
    Co-authored-by: Jayendra Parab <ja...@freestoneinfotech.com>
    
    Signed-off-by: Sarath Subramanian <sa...@apache.org>
---
 .../java/org/apache/atlas/CommonConfiguration.java |   2 +
 .../Timed.java}                                    |  36 +-
 dashboardv2/public/css/scss/override.scss          |   5 +
 dashboardv2/public/css/scss/table.scss             |  20 +-
 dashboardv2/public/js/main.js                      |   5 +-
 dashboardv2/public/js/router/Router.js             |  25 +
 .../dev_debug/DebugMetricsLayoutView_tmpl.html     |  30 +
 .../site/DebugMetricsTableLayoutView_tmpl.html     |  28 +
 dashboardv2/public/js/templates/site/Header.html   |   6 +-
 dashboardv2/public/js/utils/Globals.js             |   7 +-
 dashboardv2/public/js/utils/UrlLinks.js            |   5 +-
 dashboardv2/public/js/utils/Utils.js               |   8 +
 .../js/views/dev_debug/DebugMetricsLayoutView.js   |  86 +++
 .../js/views/site/DebugMetricsTableLayoutView.js   | 174 ++++++
 dashboardv2/public/js/views/site/Header.js         |  12 +-
 .../public/js/views/site/SideNavLayoutView.js      |   2 +-
 dashboardv3/public/css/scss/override.scss          |   4 +
 dashboardv3/public/css/scss/table.scss             |  17 +
 dashboardv3/public/js/main.js                      |   5 +-
 dashboardv3/public/js/router/Router.js             |   9 +-
 .../dev_debug/DebugMetricsLayoutView_tmpl.html     |  30 +
 .../site/DebugMetricsTableLayoutView_tmpl.html     |  28 +
 dashboardv3/public/js/templates/site/Header.html   |   5 +-
 dashboardv3/public/js/utils/Globals.js             |   7 +-
 dashboardv3/public/js/utils/UrlLinks.js            |   8 +-
 dashboardv3/public/js/utils/Utils.js               |  15 +
 .../js/views/dev_debug/DebugMetricsLayoutView.js   |  86 +++
 .../js/views/site/DebugMetricsTableLayoutView.js   | 174 ++++++
 dashboardv3/public/js/views/site/Header.js         |  12 +-
 distro/src/conf/hadoop-metrics2.properties         |  25 +
 .../java/org/apache/atlas/AtlasConfiguration.java  |   1 +
 .../org/apache/atlas/web/model/DebugMetrics.java   |  82 +++
 .../apache/atlas/web/resources/AdminResource.java  |  17 +-
 .../org/apache/atlas/web/rest/DiscoveryREST.java   |  17 +
 .../java/org/apache/atlas/web/rest/EntityREST.java |  37 ++
 .../org/apache/atlas/web/rest/GlossaryREST.java    |  32 +
 .../org/apache/atlas/web/rest/LineageREST.java     |   4 +-
 .../apache/atlas/web/rest/RelationshipREST.java    |   5 +
 .../java/org/apache/atlas/web/rest/TypesREST.java  |  21 +
 .../atlas/web/service/AtlasDebugMetricsSink.java   | 115 ++++
 .../atlas/web/service/AtlasDebugMetricsSource.java | 647 +++++++++++++++++++++
 .../atlas/web/service/DebugMetricsWrapper.java     | 190 ++++++
 .../atlas/web/service/TimedAspectInterceptor.java  |  61 ++
 .../atlas/web/integration/BaseResourceIT.java      |  10 +
 .../atlas/web/integration/DebugMetricsIT.java      |  79 +++
 .../atlas/web/resources/AdminResourceTest.java     |   4 +-
 46 files changed, 2153 insertions(+), 45 deletions(-)

diff --git a/common/src/main/java/org/apache/atlas/CommonConfiguration.java b/common/src/main/java/org/apache/atlas/CommonConfiguration.java
index 8ef9f8b..edea42b 100644
--- a/common/src/main/java/org/apache/atlas/CommonConfiguration.java
+++ b/common/src/main/java/org/apache/atlas/CommonConfiguration.java
@@ -21,8 +21,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
 
 @Configuration
+@EnableAspectJAutoProxy
 public class CommonConfiguration {
     private static final Logger LOGGER = LoggerFactory.getLogger(CommonConfiguration.class);
 
diff --git a/common/src/main/java/org/apache/atlas/CommonConfiguration.java b/common/src/main/java/org/apache/atlas/annotation/Timed.java
similarity index 51%
copy from common/src/main/java/org/apache/atlas/CommonConfiguration.java
copy to common/src/main/java/org/apache/atlas/annotation/Timed.java
index 8ef9f8b..b892a16 100644
--- a/common/src/main/java/org/apache/atlas/CommonConfiguration.java
+++ b/common/src/main/java/org/apache/atlas/annotation/Timed.java
@@ -6,33 +6,27 @@
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *     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.atlas;
+package org.apache.atlas.annotation;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
 
-@Configuration
-public class CommonConfiguration {
-    private static final Logger LOGGER = LoggerFactory.getLogger(CommonConfiguration.class);
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
-    @Bean
-    public org.apache.commons.configuration.Configuration getAtlasConfig() throws AtlasException {
-        try {
-            return ApplicationProperties.get();
-        } catch (AtlasException e) {
-            LOGGER.warn("AtlasConfig init failed", e);
-            throw e;
-        }
-    }
-}
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface Timed {
+    String value() default "";
+}
\ No newline at end of file
diff --git a/dashboardv2/public/css/scss/override.scss b/dashboardv2/public/css/scss/override.scss
index 69ac36d..c593619 100644
--- a/dashboardv2/public/css/scss/override.scss
+++ b/dashboardv2/public/css/scss/override.scss
@@ -254,6 +254,10 @@
     overflow: initial;
 }
 
+.tab-content>.tab-pane.active.debug-metrics {
+    padding: 5px 20px 15px 20px;
+}
+
 .advancedInfo {
     margin-left: 5px;
     cursor: pointer;
@@ -550,6 +554,7 @@ div.columnmanager-dropdown-container {
         }
     }
 }
+
 .dropzone .dz-preview .dz-details .dz-filename {
     padding-top: 20px;
 }
\ No newline at end of file
diff --git a/dashboardv2/public/css/scss/table.scss b/dashboardv2/public/css/scss/table.scss
index 2eae3e5..121769b 100644
--- a/dashboardv2/public/css/scss/table.scss
+++ b/dashboardv2/public/css/scss/table.scss
@@ -122,7 +122,8 @@ tr.empty {
 
     .debuggging-table-header {
         padding-right: 0px !important;
-        button{
+
+        button {
             float: right;
         }
     }
@@ -314,4 +315,21 @@ td {
     &>div {
         flex-grow: 1;
     }
+}
+
+.debug-metrics-table table {
+
+    tr th:not(:first-child),
+    tr td:not(:first-child) {
+        text-align: center !important;
+
+        button {
+            margin: 0 auto;
+        }
+    }
+}
+
+.debug-btn-wrapper {
+    margin-bottom: 5px;
+    z-index: 2;
 }
\ No newline at end of file
diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js
index 85f3d82..14d9e0f 100644
--- a/dashboardv2/public/js/main.js
+++ b/dashboardv2/public/js/main.js
@@ -280,6 +280,9 @@ require(['App',
                 if (response['atlas.ui.date.timezone.format.enabled'] !== undefined) {
                     Globals.isTimezoneFormatEnabled = response['atlas.ui.date.timezone.format.enabled'];
                 }
+                if (response['atlas.debug.metrics.enabled'] !== undefined) {
+                    Globals.isDebugMetricsEnabled = response["atlas.debug.metrics.enabled"];
+                }
             }
             --that.asyncFetchCounter;
             startApp();
@@ -359,4 +362,4 @@ require(['App',
             startApp();
         }
     });
-});
\ No newline at end of file
+});
diff --git a/dashboardv2/public/js/router/Router.js b/dashboardv2/public/js/router/Router.js
index 84fb42b..ea26bf5 100644
--- a/dashboardv2/public/js/router/Router.js
+++ b/dashboardv2/public/js/router/Router.js
@@ -46,6 +46,8 @@ define([
             //Administrator page
             '!/administrator': 'administrator',
             '!/administrator/businessMetadata/:id': 'businessMetadataDetailPage',
+            //Debug Metrics
+            '!/debugMetrics': 'debugMetrics',
             // Default
             '*actions': 'defaultAction'
         },
@@ -355,6 +357,29 @@ define([
                 App.rNContent.show(new AdministratorLayoutView(_.extend({ value: paramObj, guid: null }, options)));
             });
         },
+        debugMetrics: function() {
+            var that = this;
+            require(["views/site/Header", "views/site/SideNavLayoutView", 'views/dev_debug/DebugMetricsLayoutView'], function(Header, SideNavLayoutView, DebugMetricsLayoutView) {
+                var paramObj = Utils.getUrlState.getQueryParams(),
+                    options = _.extend({}, that.preFetchedCollectionLists, that.sharedObj, that.ventObj);
+                that.renderViewIfNotExists(that.getHeaderOptions(Header));
+                that.renderViewIfNotExists({
+                    view: App.rSideNav,
+                    manualRender: function() {
+                        this.view.currentView.selectTab();
+                        if (Utils.getUrlState.isTagTab()) {
+                            this.view.currentView.RTagLayoutView.currentView.manualRender();
+                        } else if (Utils.getUrlState.isGlossaryTab()) {
+                            this.view.currentView.RGlossaryLayoutView.currentView.manualRender(_.extend({ "isTrigger": true, "value": paramObj }));
+                        }
+                    },
+                    render: function() {
+                        return new SideNavLayoutView(options);
+                    }
+                });
+                App.rNContent.show(new DebugMetricsLayoutView(options));
+            });
+        },
         businessMetadataDetailPage: function(guid) {
             var that = this;
             require(["views/site/Header", "views/site/SideNavLayoutView", "views/business_metadata/BusinessMetadataContainerLayoutView", ], function(Header, SideNavLayoutView, BusinessMetadataContainerLayoutView) {
diff --git a/dashboardv2/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html b/dashboardv2/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html
new file mode 100644
index 0000000..78d91bf
--- /dev/null
+++ b/dashboardv2/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html
@@ -0,0 +1,30 @@
+<!--
+ * 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.
+-->
+<div class="row" style=" margin:0px;">
+    <div class="col-sm-12 default-tab">
+        <ul class="nav nav-tabs" data-id="tab-list">
+            <li role="debugMetrics" class="tab active"><a href="#tab-debugMetrics" aria-controls="tab-debugMetrics" role="tab" data-toggle="tab">REST API Metrics</a> </li>
+        </ul>
+    </div>
+</div>
+<div class="tab-content admin-details">
+    <div id="tab-debugMetrics" role="debugMetrics" class="tab-pane active animated fadeIn debug-metrics">
+        <div id="r_debugMetricsLayoutView">
+        </div>
+    </div>
+</div>
+</div>
\ No newline at end of file
diff --git a/dashboardv2/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html
new file mode 100644
index 0000000..43a38c2
--- /dev/null
+++ b/dashboardv2/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html
@@ -0,0 +1,28 @@
+<!--
+ * 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.
+-->
+<div class="metrics-details" data-id="metricsTablePage">
+    <div class="col-sm-12 debug-btn-wrapper">
+        <button type="button" class="btn btn-action btn-sm pull-right typeLOV" title="" data-id="refreshMetricsBtn" data-original-title="Refresh"><i class="fa fa-refresh"></i></button>
+    </div>
+    <div class="position-relative">
+        <div class="tableOverlay"></div>
+        <div class='attr-filter-overlay hide'></div>
+        <div class="debug-metrics-table  metrics-details">
+            <div id="r_debugMetricsTableLayoutView"></div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/dashboardv2/public/js/templates/site/Header.html b/dashboardv2/public/js/templates/site/Header.html
index c2835ca..981f393 100644
--- a/dashboardv2/public/js/templates/site/Header.html
+++ b/dashboardv2/public/js/templates/site/Header.html
@@ -33,7 +33,6 @@
                 </div>
             </td>
             <td>
-                <!-- <div class="btn-group pull-right header-menu"> -->
                 <table class="header-menu">
                     <tr>
                         <td><a class="show-stat" href="javascript:void(0);" title="Statistics"><i class="fa fa-bar-chart"></i></a></td>
@@ -66,6 +65,9 @@
                                         <li><a target="_blank" href="http://atlas.apache.org/">Documentation</a></li>
                                         <li><a target="_blank" href="{{apiDocUrl}}">API Documentation</a></li>
                                         <li class="aboutAtlas"><a href="javascript:void(0)">About</a></li>
+                                        {{#if isDebugMetricsEnabled}}
+                                            <li class="show-debug"><a href="javascript:void(0)" data-id="showDebug">Debug</a></li>
+                                        {{/if}}    
                                     </ul>
                                 </li>
                                 <li role="separator" class="divider"></li>
@@ -80,4 +82,4 @@
             </td>
         </tr>
     </table>
-</header>
\ No newline at end of file
+</header>
diff --git a/dashboardv2/public/js/utils/Globals.js b/dashboardv2/public/js/utils/Globals.js
index 56c155c..8ae89eb 100644
--- a/dashboardv2/public/js/utils/Globals.js
+++ b/dashboardv2/public/js/utils/Globals.js
@@ -29,7 +29,8 @@ define(["require"], function(require) {
             tagUrl: "#!/tag",
             searchUrl: "#!/search",
             glossaryUrl: "#!/glossary",
-            administratorUrl: "#!/administrator"
+            administratorUrl: "#!/administrator",
+            debugMetricsUrl: "#!/debugMetrics"
         },
         detailPageState: {}
     };
@@ -46,5 +47,7 @@ define(["require"], function(require) {
     Globals.dateFormat = "MM/DD/YYYY";
     Globals.isTimezoneFormatEnabled = true;
 
+    Globals.isDebugMetricsEnabled = false;
+
     return Globals;
-});
\ No newline at end of file
+});
diff --git a/dashboardv2/public/js/utils/UrlLinks.js b/dashboardv2/public/js/utils/UrlLinks.js
index 7d53abb..58a65f1 100644
--- a/dashboardv2/public/js/utils/UrlLinks.js
+++ b/dashboardv2/public/js/utils/UrlLinks.js
@@ -46,6 +46,9 @@ define(['require', 'utils/Enums', 'utils/Utils', 'underscore'], function(require
         metricsApiUrl: function() {
             return this.baseUrl + '/admin/metrics'
         },
+        debugMetricsApiUrl: function() {
+            return this.baseUrl + '/admin/debug/metrics'
+        },
         migrationStatusApiUrl: function() {
             return this.baseUrl + '/admin/status'
         },
@@ -260,4 +263,4 @@ define(['require', 'utils/Enums', 'utils/Utils', 'underscore'], function(require
     });
 
     return UrlLinks;
-});
\ No newline at end of file
+});
diff --git a/dashboardv2/public/js/utils/Utils.js b/dashboardv2/public/js/utils/Utils.js
index 04f6fdc..f426b6c 100644
--- a/dashboardv2/public/js/utils/Utils.js
+++ b/dashboardv2/public/js/utils/Utils.js
@@ -341,6 +341,8 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
                     urlUpdate['glossaryUrl'] = options.url;
                 } else if (Utils.getUrlState.isAdministratorTab(options.url)) {
                     urlUpdate['administratorUrl'] = options.url;
+                } else if (Utils.getUrlState.isDebugMetricsTab(options.url)) {
+                    urlUpdate['debugMetricsUrl'] = options.url;
                 }
                 $.extend(Globals.saveApplicationState.tabState, urlUpdate);
             }
@@ -392,6 +394,12 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
                 matchString: "administrator"
             });
         },
+        isDebugMetricsTab: function(url) {
+            return this.checkTabUrl({
+                url: url,
+                matchString: "debugMetrics"
+            });
+        },
         isGlossaryTab: function(url) {
             return this.checkTabUrl({
                 url: url,
diff --git a/dashboardv2/public/js/views/dev_debug/DebugMetricsLayoutView.js b/dashboardv2/public/js/views/dev_debug/DebugMetricsLayoutView.js
new file mode 100644
index 0000000..375d551
--- /dev/null
+++ b/dashboardv2/public/js/views/dev_debug/DebugMetricsLayoutView.js
@@ -0,0 +1,86 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'hbs!tmpl/dev_debug/DebugMetricsLayoutView_tmpl',
+    'utils/Utils'
+], function(require, Backbone, DebugMetricsLayoutView_tmpl, Utils) {
+    'use strict';
+
+    var DebugMetricsLayoutView = Backbone.Marionette.LayoutView.extend(
+        /** @lends DebugMetricsLayoutView */
+        {
+            _viewName: 'DebugMetricsLayoutView',
+
+            template: DebugMetricsLayoutView_tmpl,
+
+            /** Layout sub regions */
+            regions: {
+                RDebugMetricsLayoutView: "#r_debugMetricsLayoutView"
+            },
+
+            /** ui selector cache */
+            ui: {
+                tablist: '[data-id="tab-list"] li'
+            },
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                events["click " + this.ui.tablist] = function(e) {
+                    var tabValue = $(e.currentTarget).attr('role');
+                    Utils.setUrl({
+                        url: Utils.getUrlState.getQueryUrl().queyParams[0],
+                        urlParams: { tabActive: tabValue || 'properties' },
+                        mergeBrowserUrl: false,
+                        trigger: false,
+                        updateTabState: true
+                    });
+
+                };
+
+                return events;
+            },
+            /**
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, _.pick(options, 'value'));
+            },
+            onShow: function() {
+                if (this.value && this.value.tabActive) {
+                    this.$('.nav.nav-tabs').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active');
+                    this.$('.tab-content').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active');
+                    $("html, body").animate({ scrollTop: (this.$('.tab-content').offset().top + 1200) }, 1000);
+                }
+            },
+            bindEvents: function() {},
+            onRender: function() {
+                this.metrice2LayoutView();
+                this.bindEvents();
+            },
+            metrice2LayoutView: function(obj) {
+                var that = this;
+                require(['views/site/DebugMetricsTableLayoutView'], function(DebugMetricsTableLayoutView) {
+                    that.RDebugMetricsLayoutView.show(new DebugMetricsTableLayoutView());
+                });
+
+            }
+        });
+    return DebugMetricsLayoutView;
+});
\ No newline at end of file
diff --git a/dashboardv2/public/js/views/site/DebugMetricsTableLayoutView.js b/dashboardv2/public/js/views/site/DebugMetricsTableLayoutView.js
new file mode 100644
index 0000000..c00733a
--- /dev/null
+++ b/dashboardv2/public/js/views/site/DebugMetricsTableLayoutView.js
@@ -0,0 +1,174 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'hbs!tmpl/site/DebugMetricsTableLayoutView_tmpl',
+    'utils/UrlLinks',
+    'collection/VEntityList',
+    'utils/CommonViewFunction',
+    'utils/Utils'
+], function(require, Backbone, DebugMetricsTableLayoutViewTmpl, UrlLinks, VEntityList, CommonViewFunction, Utils) {
+    'use strict';
+
+    var DebugMetricsTableLayoutView = Backbone.Marionette.LayoutView.extend(
+        /** @lends DebugMetricsTableLayoutView */
+        {
+            _viewName: 'DebugMetricsTableLayoutView',
+            template: DebugMetricsTableLayoutViewTmpl,
+            /** Layout sub regions */
+            regions: {
+                RDebugMetricsTableLayoutView: "#r_debugMetricsTableLayoutView"
+            },
+            /** ui selector cache */
+            ui: {
+                refreshMetricsBtn: '[data-id="refreshMetricsBtn"]'
+            },
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                events["click " + this.ui.refreshMetricsBtn] = function(e) {
+                    this.currPage = 1;
+                    this.limit = 26;
+                    this.debugMetricsCollection.state.pageSize = 25;
+                    this.debugMetricsCollection.state.currentPage = 0;
+                    this.fetchMetricData();
+                };
+                return events;
+            },
+            /**
+             * intialize a new DebugMetricsTableLayoutView Layout
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, options);
+                var that = this;
+                this.DATA_MAX_LENGTH = 25;
+                this.debugMetricsCollection = new VEntityList();
+                this.debugMetricsCollection.url = UrlLinks.debugMetricsApiUrl();
+                this.debugMetricsCollection.modelAttrName = "data";
+                this.commonTableOptions = {
+                    collection: this.debugMetricsCollection,
+                    includeFilter: false,
+                    includePagination: true,
+                    includeFooterRecords: true,
+                    includePageSize: true,
+                    includeGotoPage: true,
+                    includeAtlasTableSorting: true,
+                    includeTableLoader: true,
+                    includeColumnManager: false,
+                    gridOpts: {
+                        className: "table table-hover backgrid table-quickMenu",
+                        emptyText: 'No records found!'
+                    },
+                    filterOpts: {},
+                    paginatorOpts: {}
+                };
+                this.currPage = 1;
+                this.limit = 26;
+            },
+            bindEvents: function() {
+                var that = this;
+            },
+            onRender: function() {
+                this.bindEvents();
+                this.$('.debug-metrics-table').show();
+                this.fetchMetricData();
+            },
+            fetchMetricData: function(options) {
+                var that = this;
+                this.debugMetricsCollection.fetch({
+                    success: function(data) {
+                        var data = _.first(data.toJSON()),
+                            metricsDataKeys = data ? Object.keys(data) : null;
+                        that.debugMetricsCollection.fullCollection.reset();
+                        _.each(metricsDataKeys.sort(), function(keyName) {
+                            that.debugMetricsCollection.add(data[keyName]);
+                        });
+                    },
+                    complete: function(data) {
+                        that.renderTableLayoutView();
+                    }
+                });
+            },
+            renderTableLayoutView: function() {
+                var that = this;
+                require(['utils/TableLayout'], function(TableLayout) {
+                    var cols = new Backgrid.Columns(that.getAuditTableColumns());
+                    that.RDebugMetricsTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, {
+                        columns: cols
+                    })));
+                    if (!(that.debugMetricsCollection.models.length < that.limit)) {
+                        that.RDebugMetricsTableLayoutView.$el.find('table tr').last().hide();
+                    }
+                });
+            },
+            getAuditTableColumns: function() {
+                var that = this;
+                return this.debugMetricsCollection.constructor.getTableCols({
+                    name: {
+                        label: "Name",
+                        cell: "html",
+                        sortable: true,
+                        editable: false
+                    },
+                    numops: {
+                        label: "Count",
+                        cell: "html",
+                        sortable: true,
+                        editable: false
+                    },
+                    minTime: {
+                        label: "Min Time (secs)",
+                        cell: "html",
+                        sortable: true,
+                        editable: false,
+                        formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                return parseFloat((rawValue % 1000) / 100).toFixed(3);
+                            }
+                        })
+                    },
+                    maxTime: {
+                        label: "Max Time (secs)",
+                        cell: "html",
+                        sortable: true,
+                        editable: false,
+                        formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                return parseFloat((rawValue % 1000) / 100).toFixed(3);
+                            }
+                        })
+                    },
+                    avgTime: {
+                        label: "Average Time (secs)",
+                        cell: "html",
+                        sortable: true,
+                        editable: false,
+                        formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                return parseFloat((rawValue % 1000) / 100).toFixed(3);
+                            }
+                        })
+                    }
+                }, this.debugMetricsCollection);
+
+            }
+        });
+    return DebugMetricsTableLayoutView;
+});
diff --git a/dashboardv2/public/js/views/site/Header.js b/dashboardv2/public/js/views/site/Header.js
index bc2f07b..ffb582e 100644
--- a/dashboardv2/public/js/views/site/Header.js
+++ b/dashboardv2/public/js/views/site/Header.js
@@ -34,6 +34,7 @@ define(['require',
                 glossaryImportTempUrl: UrlLinks.glossaryImportTempUrl(),
                 businessMetadataImportTempUrl: UrlLinks.businessMetadataImportTempUrl(),
                 apiDocUrl: UrlLinks.apiDocUrl(),
+                isDebugMetricsEnabled: Globals.isDebugMetricsEnabled
             };
         },
         ui: {
@@ -43,6 +44,7 @@ define(['require',
             clearGlobalSearch: "[data-id='clearGlobalSearch']",
             signOut: "[data-id='signOut']",
             administrator: "[data-id='administrator']",
+            showDebug: "[data-id='showDebug']",
             uiSwitch: "[data-id='uiSwitch']",
             glossaryImport: "[data-id='glossaryImport']",
             businessMetadataImport: "[data-id='businessMetadataImport']"
@@ -91,6 +93,14 @@ define(['require',
             events['click ' + this.ui.businessMetadataImport] = function() {
                 this.onClickImport()
             };
+            events['click ' + this.ui.showDebug] = function() {
+                Utils.setUrl({
+                    url: "#!/debugMetrics",
+                    mergeBrowserUrl: false,
+                    trigger: true,
+                    updateTabState: true
+                });
+            };
 
             return events;
         },
@@ -320,4 +330,4 @@ define(['require',
         }
     });
     return Header;
-});
\ No newline at end of file
+});
diff --git a/dashboardv2/public/js/views/site/SideNavLayoutView.js b/dashboardv2/public/js/views/site/SideNavLayoutView.js
index bf82f98..e0f717a 100644
--- a/dashboardv2/public/js/views/site/SideNavLayoutView.js
+++ b/dashboardv2/public/js/views/site/SideNavLayoutView.js
@@ -116,7 +116,7 @@ define(['require',
                 that.$('.tabs').find('li a[aria-controls="tab-' + view + '"]').parents('li').addClass('active').siblings().removeClass('active');
                 that.$('.tab-content').find('div#tab-' + view).addClass('active').siblings().removeClass('active');
             };
-            if (Utils.getUrlState.isSearchTab() || Utils.getUrlState.isInitial() || Utils.getUrlState.isAdministratorTab()) {
+            if (Utils.getUrlState.isSearchTab() || Utils.getUrlState.isInitial() || Utils.getUrlState.isAdministratorTab() || Utils.getUrlState.isDebugMetricsTab()) {
                 activeTab({ "view": "search" });
             } else if (Utils.getUrlState.isTagTab()) {
                 activeTab({ "view": "classification" });
diff --git a/dashboardv3/public/css/scss/override.scss b/dashboardv3/public/css/scss/override.scss
index 8a89b48..b7d65e7 100644
--- a/dashboardv3/public/css/scss/override.scss
+++ b/dashboardv3/public/css/scss/override.scss
@@ -258,6 +258,10 @@
     overflow: initial;
 }
 
+.tab-content>.tab-pane.active.debug-metrics {
+    padding: 5px 20px 15px 20px;
+}
+
 .advancedInfo {
     margin-left: 5px;
     cursor: pointer;
diff --git a/dashboardv3/public/css/scss/table.scss b/dashboardv3/public/css/scss/table.scss
index 1bebe63..121769b 100644
--- a/dashboardv3/public/css/scss/table.scss
+++ b/dashboardv3/public/css/scss/table.scss
@@ -315,4 +315,21 @@ td {
     &>div {
         flex-grow: 1;
     }
+}
+
+.debug-metrics-table table {
+
+    tr th:not(:first-child),
+    tr td:not(:first-child) {
+        text-align: center !important;
+
+        button {
+            margin: 0 auto;
+        }
+    }
+}
+
+.debug-btn-wrapper {
+    margin-bottom: 5px;
+    z-index: 2;
 }
\ No newline at end of file
diff --git a/dashboardv3/public/js/main.js b/dashboardv3/public/js/main.js
index a4165ae..7264a9c 100644
--- a/dashboardv3/public/js/main.js
+++ b/dashboardv3/public/js/main.js
@@ -309,6 +309,9 @@ require(['App',
                 if (response['atlas.ui.date.timezone.format.enabled'] !== undefined) {
                     Globals.isTimezoneFormatEnabled = response['atlas.ui.date.timezone.format.enabled'];
                 }
+                if (response['atlas.debug.metrics.enabled'] !== undefined) {
+                    Globals.isDebugMetricsEnabled = response["atlas.debug.metrics.enabled"];
+                }
             }
             --that.asyncFetchCounter;
             startApp();
@@ -390,4 +393,4 @@ require(['App',
             startApp();
         }
     });
-});
\ No newline at end of file
+});
diff --git a/dashboardv3/public/js/router/Router.js b/dashboardv3/public/js/router/Router.js
index 1a19523..bd50715 100644
--- a/dashboardv3/public/js/router/Router.js
+++ b/dashboardv3/public/js/router/Router.js
@@ -47,6 +47,8 @@ define([
             //Audit table
             '!/administrator': 'administrator',
             '!/administrator/businessMetadata/:id': 'businessMetadataDetailPage',
+            //Debug Metrics
+            '!/debugMetrics': 'debugMetrics',
             // Default
             "*actions": "defaultAction"
         },
@@ -425,9 +427,9 @@ define([
                 App.rContent.show(new AdministratorLayoutView(_.extend({ value: paramObj, guid: null }, options)));
             });
         },
-        devDebugging: function() {
+        debugMetrics: function() {
             var that = this;
-            require(["views/site/Header", "views/site/SideNavLayoutView", 'views/dev_debug/DevDebuggingLayoutView'], function(Header, SideNavLayoutView, DevDebuggingLayoutView) {
+            require(["views/site/Header", "views/site/SideNavLayoutView", 'views/dev_debug/DebugMetricsLayoutView'], function(Header, SideNavLayoutView, DebugMetricsLayoutView) {
                 var paramObj = Utils.getUrlState.getQueryParams(),
                     options = _.extend({}, that.preFetchedCollectionLists, that.sharedObj, that.ventObj);
                 that.renderViewIfNotExists(that.getHeaderOptions(Header));
@@ -440,10 +442,9 @@ define([
                         return new SideNavLayoutView(options);
                     }
                 });
-                App.rContent.show(new DevDebuggingLayoutView(options));
+                App.rContent.show(new DebugMetricsLayoutView(options));
             });
         },
-
         businessMetadataDetailPage: function(guid) {
             var that = this;
             require(["views/site/Header", "views/site/SideNavLayoutView", "views/business_metadata/BusinessMetadataContainerLayoutView", ], function(Header, SideNavLayoutView, BusinessMetadataContainerLayoutView) {
diff --git a/dashboardv3/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html b/dashboardv3/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html
new file mode 100644
index 0000000..78d91bf
--- /dev/null
+++ b/dashboardv3/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html
@@ -0,0 +1,30 @@
+<!--
+ * 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.
+-->
+<div class="row" style=" margin:0px;">
+    <div class="col-sm-12 default-tab">
+        <ul class="nav nav-tabs" data-id="tab-list">
+            <li role="debugMetrics" class="tab active"><a href="#tab-debugMetrics" aria-controls="tab-debugMetrics" role="tab" data-toggle="tab">REST API Metrics</a> </li>
+        </ul>
+    </div>
+</div>
+<div class="tab-content admin-details">
+    <div id="tab-debugMetrics" role="debugMetrics" class="tab-pane active animated fadeIn debug-metrics">
+        <div id="r_debugMetricsLayoutView">
+        </div>
+    </div>
+</div>
+</div>
\ No newline at end of file
diff --git a/dashboardv3/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html b/dashboardv3/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html
new file mode 100644
index 0000000..43a38c2
--- /dev/null
+++ b/dashboardv3/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html
@@ -0,0 +1,28 @@
+<!--
+ * 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.
+-->
+<div class="metrics-details" data-id="metricsTablePage">
+    <div class="col-sm-12 debug-btn-wrapper">
+        <button type="button" class="btn btn-action btn-sm pull-right typeLOV" title="" data-id="refreshMetricsBtn" data-original-title="Refresh"><i class="fa fa-refresh"></i></button>
+    </div>
+    <div class="position-relative">
+        <div class="tableOverlay"></div>
+        <div class='attr-filter-overlay hide'></div>
+        <div class="debug-metrics-table  metrics-details">
+            <div id="r_debugMetricsTableLayoutView"></div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/dashboardv3/public/js/templates/site/Header.html b/dashboardv3/public/js/templates/site/Header.html
index f752f3c..a8ff7f9 100644
--- a/dashboardv3/public/js/templates/site/Header.html
+++ b/dashboardv3/public/js/templates/site/Header.html
@@ -49,6 +49,9 @@
                                             <li><a target="_blank" href="http://atlas.apache.org/">Documentation</a></li>
                                             <li><a target="_blank" href="{{apiDocUrl}}">API Documentation</a></li>
                                             <li class="aboutAtlas"><a href="javascript:void(0)">About</a></li>
+                                            {{#if isDebugMetricsEnabled}}
+                                                <li class="show-debug"><a href="javascript:void(0)" data-id="showDebug">Debug</a></li>
+                                            {{/if}}    
                                         </ul>
                                     </li>
                                     <li class="divider"></li>
@@ -62,4 +65,4 @@
         </tr>
     </table>
 </header>
-<div id="r_filterBrowserLayoutView"></div>
\ No newline at end of file
+<div id="r_filterBrowserLayoutView"></div>
diff --git a/dashboardv3/public/js/utils/Globals.js b/dashboardv3/public/js/utils/Globals.js
index 56c155c..8ae89eb 100644
--- a/dashboardv3/public/js/utils/Globals.js
+++ b/dashboardv3/public/js/utils/Globals.js
@@ -29,7 +29,8 @@ define(["require"], function(require) {
             tagUrl: "#!/tag",
             searchUrl: "#!/search",
             glossaryUrl: "#!/glossary",
-            administratorUrl: "#!/administrator"
+            administratorUrl: "#!/administrator",
+            debugMetricsUrl: "#!/debugMetrics"
         },
         detailPageState: {}
     };
@@ -46,5 +47,7 @@ define(["require"], function(require) {
     Globals.dateFormat = "MM/DD/YYYY";
     Globals.isTimezoneFormatEnabled = true;
 
+    Globals.isDebugMetricsEnabled = false;
+
     return Globals;
-});
\ No newline at end of file
+});
diff --git a/dashboardv3/public/js/utils/UrlLinks.js b/dashboardv3/public/js/utils/UrlLinks.js
index 661dfb6..5047fe3 100644
--- a/dashboardv3/public/js/utils/UrlLinks.js
+++ b/dashboardv3/public/js/utils/UrlLinks.js
@@ -46,6 +46,12 @@ define(['require', 'utils/Enums', 'utils/Utils', 'underscore'], function(require
         metricsApiUrl: function() {
             return this.baseUrl + '/admin/metrics'
         },
+        debugMetricsApiUrl: function() {
+            return this.baseUrl + '/admin/debug/metrics'
+        },
+        regitrydataDefApiUrl: function(name) {
+            return this.baseUrlV2 + '/entity/getRegistryData';
+        },
         rootEntityDefUrl: function(name) {
             return this.baseUrlV2 + '/types/entitydef/name/' + name;
         },
@@ -248,4 +254,4 @@ define(['require', 'utils/Enums', 'utils/Utils', 'underscore'], function(require
     });
 
     return UrlLinks;
-});
\ No newline at end of file
+});
diff --git a/dashboardv3/public/js/utils/Utils.js b/dashboardv3/public/js/utils/Utils.js
index b46be20..1a73b7c 100644
--- a/dashboardv3/public/js/utils/Utils.js
+++ b/dashboardv3/public/js/utils/Utils.js
@@ -348,8 +348,13 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
                     urlUpdate['searchUrl'] = options.url;
                 } else if (Utils.getUrlState.isGlossaryTab(options.url)) {
                     urlUpdate['glossaryUrl'] = options.url;
+                } else if (Utils.getUrlState.isBMDetailPage(options.url)) {
+                    urlUpdate['bmDetailPageUrl'] = options.url;
+                    urlUpdate['administratorUrl'] = options.url;
                 } else if (Utils.getUrlState.isAdministratorTab(options.url)) {
                     urlUpdate['administratorUrl'] = options.url;
+                } else if (Utils.getUrlState.isDebugMetricsTab(options.url)) {
+                    urlUpdate['debugMetricsUrl'] = options.url;
                 }
                 $.extend(Globals.saveApplicationState.tabState, urlUpdate);
             }
@@ -397,6 +402,16 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
                 matchString: "administrator"
             });
         },
+        isBMDetailPage: function(url) {
+            var quey = this.getQueryUrl(url);
+            return (quey.hash.indexOf("businessMetadata") > -1) ? true : false;
+        },
+        isDebugMetricsTab: function(url) {
+            return this.checkTabUrl({
+                url: url,
+                matchString: "debugMetrics"
+            });
+        },
         isGlossaryTab: function(url) {
             return this.checkTabUrl({
                 url: url,
diff --git a/dashboardv3/public/js/views/dev_debug/DebugMetricsLayoutView.js b/dashboardv3/public/js/views/dev_debug/DebugMetricsLayoutView.js
new file mode 100644
index 0000000..375d551
--- /dev/null
+++ b/dashboardv3/public/js/views/dev_debug/DebugMetricsLayoutView.js
@@ -0,0 +1,86 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'hbs!tmpl/dev_debug/DebugMetricsLayoutView_tmpl',
+    'utils/Utils'
+], function(require, Backbone, DebugMetricsLayoutView_tmpl, Utils) {
+    'use strict';
+
+    var DebugMetricsLayoutView = Backbone.Marionette.LayoutView.extend(
+        /** @lends DebugMetricsLayoutView */
+        {
+            _viewName: 'DebugMetricsLayoutView',
+
+            template: DebugMetricsLayoutView_tmpl,
+
+            /** Layout sub regions */
+            regions: {
+                RDebugMetricsLayoutView: "#r_debugMetricsLayoutView"
+            },
+
+            /** ui selector cache */
+            ui: {
+                tablist: '[data-id="tab-list"] li'
+            },
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                events["click " + this.ui.tablist] = function(e) {
+                    var tabValue = $(e.currentTarget).attr('role');
+                    Utils.setUrl({
+                        url: Utils.getUrlState.getQueryUrl().queyParams[0],
+                        urlParams: { tabActive: tabValue || 'properties' },
+                        mergeBrowserUrl: false,
+                        trigger: false,
+                        updateTabState: true
+                    });
+
+                };
+
+                return events;
+            },
+            /**
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, _.pick(options, 'value'));
+            },
+            onShow: function() {
+                if (this.value && this.value.tabActive) {
+                    this.$('.nav.nav-tabs').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active');
+                    this.$('.tab-content').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active');
+                    $("html, body").animate({ scrollTop: (this.$('.tab-content').offset().top + 1200) }, 1000);
+                }
+            },
+            bindEvents: function() {},
+            onRender: function() {
+                this.metrice2LayoutView();
+                this.bindEvents();
+            },
+            metrice2LayoutView: function(obj) {
+                var that = this;
+                require(['views/site/DebugMetricsTableLayoutView'], function(DebugMetricsTableLayoutView) {
+                    that.RDebugMetricsLayoutView.show(new DebugMetricsTableLayoutView());
+                });
+
+            }
+        });
+    return DebugMetricsLayoutView;
+});
\ No newline at end of file
diff --git a/dashboardv3/public/js/views/site/DebugMetricsTableLayoutView.js b/dashboardv3/public/js/views/site/DebugMetricsTableLayoutView.js
new file mode 100644
index 0000000..c00733a
--- /dev/null
+++ b/dashboardv3/public/js/views/site/DebugMetricsTableLayoutView.js
@@ -0,0 +1,174 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'hbs!tmpl/site/DebugMetricsTableLayoutView_tmpl',
+    'utils/UrlLinks',
+    'collection/VEntityList',
+    'utils/CommonViewFunction',
+    'utils/Utils'
+], function(require, Backbone, DebugMetricsTableLayoutViewTmpl, UrlLinks, VEntityList, CommonViewFunction, Utils) {
+    'use strict';
+
+    var DebugMetricsTableLayoutView = Backbone.Marionette.LayoutView.extend(
+        /** @lends DebugMetricsTableLayoutView */
+        {
+            _viewName: 'DebugMetricsTableLayoutView',
+            template: DebugMetricsTableLayoutViewTmpl,
+            /** Layout sub regions */
+            regions: {
+                RDebugMetricsTableLayoutView: "#r_debugMetricsTableLayoutView"
+            },
+            /** ui selector cache */
+            ui: {
+                refreshMetricsBtn: '[data-id="refreshMetricsBtn"]'
+            },
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                events["click " + this.ui.refreshMetricsBtn] = function(e) {
+                    this.currPage = 1;
+                    this.limit = 26;
+                    this.debugMetricsCollection.state.pageSize = 25;
+                    this.debugMetricsCollection.state.currentPage = 0;
+                    this.fetchMetricData();
+                };
+                return events;
+            },
+            /**
+             * intialize a new DebugMetricsTableLayoutView Layout
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, options);
+                var that = this;
+                this.DATA_MAX_LENGTH = 25;
+                this.debugMetricsCollection = new VEntityList();
+                this.debugMetricsCollection.url = UrlLinks.debugMetricsApiUrl();
+                this.debugMetricsCollection.modelAttrName = "data";
+                this.commonTableOptions = {
+                    collection: this.debugMetricsCollection,
+                    includeFilter: false,
+                    includePagination: true,
+                    includeFooterRecords: true,
+                    includePageSize: true,
+                    includeGotoPage: true,
+                    includeAtlasTableSorting: true,
+                    includeTableLoader: true,
+                    includeColumnManager: false,
+                    gridOpts: {
+                        className: "table table-hover backgrid table-quickMenu",
+                        emptyText: 'No records found!'
+                    },
+                    filterOpts: {},
+                    paginatorOpts: {}
+                };
+                this.currPage = 1;
+                this.limit = 26;
+            },
+            bindEvents: function() {
+                var that = this;
+            },
+            onRender: function() {
+                this.bindEvents();
+                this.$('.debug-metrics-table').show();
+                this.fetchMetricData();
+            },
+            fetchMetricData: function(options) {
+                var that = this;
+                this.debugMetricsCollection.fetch({
+                    success: function(data) {
+                        var data = _.first(data.toJSON()),
+                            metricsDataKeys = data ? Object.keys(data) : null;
+                        that.debugMetricsCollection.fullCollection.reset();
+                        _.each(metricsDataKeys.sort(), function(keyName) {
+                            that.debugMetricsCollection.add(data[keyName]);
+                        });
+                    },
+                    complete: function(data) {
+                        that.renderTableLayoutView();
+                    }
+                });
+            },
+            renderTableLayoutView: function() {
+                var that = this;
+                require(['utils/TableLayout'], function(TableLayout) {
+                    var cols = new Backgrid.Columns(that.getAuditTableColumns());
+                    that.RDebugMetricsTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, {
+                        columns: cols
+                    })));
+                    if (!(that.debugMetricsCollection.models.length < that.limit)) {
+                        that.RDebugMetricsTableLayoutView.$el.find('table tr').last().hide();
+                    }
+                });
+            },
+            getAuditTableColumns: function() {
+                var that = this;
+                return this.debugMetricsCollection.constructor.getTableCols({
+                    name: {
+                        label: "Name",
+                        cell: "html",
+                        sortable: true,
+                        editable: false
+                    },
+                    numops: {
+                        label: "Count",
+                        cell: "html",
+                        sortable: true,
+                        editable: false
+                    },
+                    minTime: {
+                        label: "Min Time (secs)",
+                        cell: "html",
+                        sortable: true,
+                        editable: false,
+                        formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                return parseFloat((rawValue % 1000) / 100).toFixed(3);
+                            }
+                        })
+                    },
+                    maxTime: {
+                        label: "Max Time (secs)",
+                        cell: "html",
+                        sortable: true,
+                        editable: false,
+                        formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                return parseFloat((rawValue % 1000) / 100).toFixed(3);
+                            }
+                        })
+                    },
+                    avgTime: {
+                        label: "Average Time (secs)",
+                        cell: "html",
+                        sortable: true,
+                        editable: false,
+                        formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                return parseFloat((rawValue % 1000) / 100).toFixed(3);
+                            }
+                        })
+                    }
+                }, this.debugMetricsCollection);
+
+            }
+        });
+    return DebugMetricsTableLayoutView;
+});
diff --git a/dashboardv3/public/js/views/site/Header.js b/dashboardv3/public/js/views/site/Header.js
index ccb813d..e2ecd7e 100644
--- a/dashboardv3/public/js/views/site/Header.js
+++ b/dashboardv3/public/js/views/site/Header.js
@@ -34,12 +34,14 @@ define(['require',
         templateHelpers: function() {
             return {
                 apiDocUrl: UrlLinks.apiDocUrl(),
+                isDebugMetricsEnabled: Globals.isDebugMetricsEnabled
             };
         },
         ui: {
             backButton: "[data-id='backButton']",
             menuHamburger: "[data-id='menuHamburger']",
             administrator: "[data-id='administrator']",
+            showDebug: "[data-id='showDebug']",
             signOut: "[data-id='signOut']",
             uiSwitch: "[data-id='uiSwitch']"
         },
@@ -67,6 +69,14 @@ define(['require',
                     updateTabState: true
                 });
             };
+            events['click ' + this.ui.showDebug] = function() {
+                Utils.setUrl({
+                    url: "#!/debugMetrics",
+                    mergeBrowserUrl: false,
+                    trigger: true,
+                    updateTabState: true
+                });
+            };
             events["click " + this.ui.uiSwitch] = function() {
                 var path = Utils.getBaseUrl(window.location.pathname) + "/index.html";
                 if (window.location.hash.length > 2) {
@@ -144,4 +154,4 @@ define(['require',
         },
     });
     return Header;
-});
\ No newline at end of file
+});
diff --git a/distro/src/conf/hadoop-metrics2.properties b/distro/src/conf/hadoop-metrics2.properties
new file mode 100755
index 0000000..52c1d4f
--- /dev/null
+++ b/distro/src/conf/hadoop-metrics2.properties
@@ -0,0 +1,25 @@
+#
+#   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.
+#
+# syntax: [prefix].[source|sink].[instance].[options]
+# See javadoc of package-info.java for org.apache.hadoop.metrics2 for details
+
+# default sampling period, in seconds
+*.period=30
+
+atlas-debug-metrics-context.sink.atlas-debug-metrics-context.class=org.apache.hadoop.metrics2.sink.FileSink
+atlas-debug-metrics-context.sink.atlas-debug-metrics-context.context=atlas-debug-metrics-context
+atlas-debug-metrics-context.sink.atlas-debug-metrics-context.filename=${atlas.log.dir}/atlas-metrics.out
\ No newline at end of file
diff --git a/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java b/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java
index 05b0784..e31afa8 100644
--- a/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java
+++ b/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java
@@ -77,6 +77,7 @@ public enum AtlasConfiguration {
     REBUILD_INDEX("atlas.rebuild.index", false),
     STORE_DIFFERENTIAL_AUDITS("atlas.entity.audit.differential", false),
     DSL_EXECUTOR_TRAVERSAL("atlas.dsl.executor.traversal", true),
+    DEBUG_METRICS_ENABLED("atlas.debug.metrics.enabled", false),
     TASKS_USE_ENABLED("atlas.tasks.enabled", true);
 
     private static final Configuration APPLICATION_PROPERTIES;
diff --git a/webapp/src/main/java/org/apache/atlas/web/model/DebugMetrics.java b/webapp/src/main/java/org/apache/atlas/web/model/DebugMetrics.java
new file mode 100644
index 0000000..856a6fb
--- /dev/null
+++ b/webapp/src/main/java/org/apache/atlas/web/model/DebugMetrics.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.atlas.web.model;
+
+public class DebugMetrics {
+    private String name;
+    private int    numops;
+    private float  minTime;
+    private float  maxTime;
+    private float  stdDevTime;
+    private float  avgTime;
+
+    public DebugMetrics() {}
+
+    public DebugMetrics(String name){
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getNumops() {
+        return numops;
+    }
+
+    public void setNumops(int numops) {
+        this.numops = numops;
+    }
+
+    public float getMinTime() {
+        return minTime;
+    }
+
+    public void setMinTime(float minTime) {
+        this.minTime = minTime;
+    }
+
+    public float getMaxTime() {
+        return maxTime;
+    }
+
+    public void setMaxTime(float maxTime) {
+        this.maxTime = maxTime;
+    }
+
+    public float getStdDevTime() {
+        return stdDevTime;
+    }
+
+    public void setStdDevTime(float stdDevTime) {
+        this.stdDevTime = stdDevTime;
+    }
+
+    public float getAvgTime() {
+        return avgTime;
+    }
+
+    public void setAvgTime(float avgTime) {
+        this.avgTime = avgTime;
+    }
+}
\ No newline at end of file
diff --git a/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java b/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java
index a9fa8ba..b812819 100755
--- a/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java
+++ b/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java
@@ -21,6 +21,7 @@ package org.apache.atlas.web.resources;
 import com.sun.jersey.multipart.FormDataParam;
 import org.apache.atlas.ApplicationProperties;
 import org.apache.atlas.AtlasClient;
+import org.apache.atlas.AtlasConfiguration;
 import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.authorize.AtlasAdminAccessRequest;
 import org.apache.atlas.authorize.AtlasAuthorizationUtils;
@@ -66,6 +67,7 @@ import org.apache.atlas.util.SearchTracker;
 import org.apache.atlas.utils.AtlasJson;
 import org.apache.atlas.utils.AtlasPerfTracer;
 import org.apache.atlas.web.filters.AtlasCSRFPreventionFilter;
+import org.apache.atlas.web.service.AtlasDebugMetricsSink;
 import org.apache.atlas.web.service.ServiceState;
 import org.apache.atlas.web.util.Servlets;
 import org.apache.commons.collections.CollectionUtils;
@@ -80,7 +82,6 @@ import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Service;
 
-import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.servlet.http.HttpServletRequest;
@@ -167,6 +168,8 @@ public class AdminResource {
     private final  EntityAuditRepository    auditRepository;
     private final  boolean                  isTimezoneFormatEnabled;
     private final  String                   uiDateFormat;
+    private final  AtlasDebugMetricsSink    debugMetricsRESTSink;
+    private final  boolean                  isDebugMetricsEnabled;
 
     static {
         try {
@@ -183,7 +186,7 @@ public class AdminResource {
                          AtlasServerService serverService,
                          ExportImportAuditService exportImportAuditService, AtlasEntityStore entityStore,
                          AtlasPatchManager patchManager, AtlasAuditService auditService, EntityAuditRepository auditRepository,
-                         TaskManagement taskManagement) {
+                         TaskManagement taskManagement, AtlasDebugMetricsSink debugMetricsRESTSink) {
         this.serviceState              = serviceState;
         this.metricsService            = metricsService;
         this.exportService             = exportService;
@@ -199,15 +202,18 @@ public class AdminResource {
         this.auditService              = auditService;
         this.auditRepository           = auditRepository;
         this.taskManagement            = taskManagement;
+        this.debugMetricsRESTSink      = debugMetricsRESTSink;
 
         if (atlasProperties != null) {
             this.defaultUIVersion = atlasProperties.getString(DEFAULT_UI_VERSION, UI_VERSION_V2);
             this.isTimezoneFormatEnabled = atlasProperties.getBoolean(UI_DATE_TIMEZONE_FORMAT_ENABLED, true);
             this.uiDateFormat = atlasProperties.getString(UI_DATE_FORMAT, UI_DATE_DEFAULT_FORMAT);
+            this.isDebugMetricsEnabled = AtlasConfiguration.DEBUG_METRICS_ENABLED.getBoolean();
         } else {
             this.defaultUIVersion = UI_VERSION_V2;
             this.isTimezoneFormatEnabled = true;
             this.uiDateFormat = UI_DATE_DEFAULT_FORMAT;
+            this.isDebugMetricsEnabled = false;
         }
     }
 
@@ -355,6 +361,7 @@ public class AdminResource {
         responseData.put("timezones", TIMEZONE_LIST);
         responseData.put(UI_DATE_TIMEZONE_FORMAT_ENABLED, isTimezoneFormatEnabled);
         responseData.put(UI_DATE_FORMAT, uiDateFormat);
+        responseData.put(AtlasConfiguration.DEBUG_METRICS_ENABLED.getPropertyName(), isDebugMetricsEnabled);
 
         response = Response.ok(AtlasJson.toV1Json(responseData)).build();
 
@@ -759,6 +766,12 @@ public class AdminResource {
         }
     }
 
+    @GET
+    @Path("/debug/metrics")
+    public Map getDebugMetrics() {
+        return debugMetricsRESTSink.getMetrics();
+    }
+
     private String getEditableEntityTypes(Configuration config) {
         String ret = DEFAULT_EDITABLE_ENTITY_TYPES;
 
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java
index 8aec3a6..4c7b622 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java
@@ -20,6 +20,7 @@ package org.apache.atlas.web.rest;
 import org.apache.atlas.AtlasClient;
 import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.SortOrder;
+import org.apache.atlas.annotation.Timed;
 import org.apache.atlas.authorize.AtlasAuthorizationUtils;
 import org.apache.atlas.discovery.AtlasDiscoveryService;
 import org.apache.atlas.discovery.EntityDiscoveryService;
@@ -100,6 +101,7 @@ public class DiscoveryREST {
      */
     @GET
     @Path("/dsl")
+    @Timed
     public AtlasSearchResult searchUsingDSL(@QueryParam("query")          String query,
                                             @QueryParam("typeName")       String typeName,
                                             @QueryParam("classification") String classification,
@@ -147,6 +149,7 @@ public class DiscoveryREST {
      */
     @GET
     @Path("/fulltext")
+    @Timed
     public AtlasSearchResult searchUsingFullText(@QueryParam("query")                  String  query,
                                                  @QueryParam("excludeDeletedEntities") boolean excludeDeletedEntities,
                                                  @QueryParam("limit")                  int     limit,
@@ -186,6 +189,7 @@ public class DiscoveryREST {
      */
     @GET
     @Path("/basic")
+    @Timed
     public AtlasSearchResult searchUsingBasic(@QueryParam("query")                  String  query,
                                               @QueryParam("typeName")               String  typeName,
                                               @QueryParam("classification")         String  classification,
@@ -241,6 +245,7 @@ public class DiscoveryREST {
      */
     @GET
     @Path("/attribute")
+    @Timed
     public AtlasSearchResult searchUsingAttribute(@QueryParam("attrName")        String attrName,
                                                   @QueryParam("attrValuePrefix") String attrValuePrefix,
                                                   @QueryParam("typeName")        String typeName,
@@ -314,6 +319,7 @@ public class DiscoveryREST {
      */
     @Path("basic")
     @POST
+    @Timed
     public AtlasSearchResult searchWithParameters(SearchParameters parameters) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -364,6 +370,7 @@ public class DiscoveryREST {
      */
     @GET
     @Path("relationship")
+    @Timed
     public AtlasSearchResult searchRelatedEntities(@QueryParam("guid")                            String      guid,
                                                    @QueryParam("relation")                        String      relation,
                                                    @QueryParam("attributes")                      Set<String> attributes,
@@ -409,6 +416,7 @@ public class DiscoveryREST {
      */
     @POST
     @Path("saved")
+    @Timed
     public AtlasUserSavedSearch addSavedSearch(AtlasUserSavedSearch savedSearch) throws AtlasBaseException, IOException {
         validateUserSavedSearch(savedSearch);
 
@@ -433,6 +441,7 @@ public class DiscoveryREST {
      */
     @PUT
     @Path("saved")
+    @Timed
     public AtlasUserSavedSearch updateSavedSearch(AtlasUserSavedSearch savedSearch) throws AtlasBaseException {
         validateUserSavedSearch(savedSearch);
 
@@ -458,6 +467,7 @@ public class DiscoveryREST {
      */
     @GET
     @Path("saved/{name}")
+    @Timed
     public AtlasUserSavedSearch getSavedSearch(@PathParam("name") String searchName,
                                                @QueryParam("user") String userName) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", searchName);
@@ -484,6 +494,7 @@ public class DiscoveryREST {
      */
     @GET
     @Path("saved")
+    @Timed
     public List<AtlasUserSavedSearch> getSavedSearches(@QueryParam("user") String userName) throws AtlasBaseException {
         Servlets.validateQueryParamLength("user", userName);
 
@@ -505,6 +516,7 @@ public class DiscoveryREST {
      */
     @DELETE
     @Path("saved/{guid}")
+    @Timed
     public void deleteSavedSearch(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -532,6 +544,7 @@ public class DiscoveryREST {
      */
     @Path("saved/execute/{name}")
     @GET
+    @Timed
     public AtlasSearchResult executeSavedSearchByName(@PathParam("name") String searchName,
                                                       @QueryParam("user") String userName) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", searchName);
@@ -562,6 +575,7 @@ public class DiscoveryREST {
      */
     @Path("saved/execute/guid/{guid}")
     @GET
+    @Timed
     public AtlasSearchResult executeSavedSearchByGuid(@PathParam("guid") String searchGuid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", searchGuid);
 
@@ -589,6 +603,7 @@ public class DiscoveryREST {
      */
     @Path("/quick")
     @GET
+    @Timed
     public AtlasQuickSearchResult quickSearch(@QueryParam("query")                  String  query,
                                               @QueryParam("typeName")               String  typeName,
                                               @QueryParam("excludeDeletedEntities") boolean excludeDeletedEntities,
@@ -633,6 +648,7 @@ public class DiscoveryREST {
      */
     @Path("/quick")
     @POST
+    @Timed
     public AtlasQuickSearchResult quickSearch(QuickSearchParameters quickSearchParameters) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -665,6 +681,7 @@ public class DiscoveryREST {
 
     @Path("suggestions")
     @GET
+    @Timed
     public AtlasSuggestionsResult getSuggestions(@QueryParam("prefixString") String prefixString, @QueryParam("fieldName") String fieldName) {
         AtlasPerfTracer perf = null;
 
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/EntityREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/EntityREST.java
index b1e0d2f..ec893f2 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/EntityREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/EntityREST.java
@@ -21,6 +21,7 @@ import com.sun.jersey.core.header.FormDataContentDisposition;
 import com.sun.jersey.multipart.FormDataParam;
 import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.EntityAuditEvent;
+import org.apache.atlas.annotation.Timed;
 import org.apache.atlas.authorize.AtlasAuthorizationUtils;
 import org.apache.atlas.authorize.AtlasEntityAccessRequest;
 import org.apache.atlas.authorize.AtlasPrivilege;
@@ -123,6 +124,7 @@ public class EntityREST {
      */
     @GET
     @Path("/guid/{guid}")
+    @Timed
     public AtlasEntityWithExtInfo getById(@PathParam("guid") String guid, @QueryParam("minExtInfo") @DefaultValue("false") boolean minExtInfo, @QueryParam("ignoreRelationships") @DefaultValue("false") boolean ignoreRelationships) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -147,6 +149,7 @@ public class EntityREST {
      */
     @GET
     @Path("/guid/{guid}/header")
+    @Timed
     public AtlasEntityHeader getHeaderById(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -182,6 +185,7 @@ public class EntityREST {
      */
     @GET
     @Path("/uniqueAttribute/type/{typeName}/header")
+    @Timed
     public AtlasEntityHeader getEntityHeaderByUniqueAttributes(@PathParam("typeName") String typeName,
                                                                @Context HttpServletRequest servletRequest) throws AtlasBaseException {
         Servlets.validateQueryParamLength("typeName", typeName);
@@ -225,6 +229,7 @@ public class EntityREST {
      */
     @GET
     @Path("/uniqueAttribute/type/{typeName}")
+    @Timed
     public AtlasEntityWithExtInfo getByUniqueAttributes(@PathParam("typeName") String typeName, @QueryParam("minExtInfo") @DefaultValue("false") boolean minExtInfo,
                                                         @QueryParam("ignoreRelationships") @DefaultValue("false") boolean ignoreRelationships, @Context HttpServletRequest servletRequest) throws AtlasBaseException {
         Servlets.validateQueryParamLength("typeName", typeName);
@@ -267,6 +272,7 @@ public class EntityREST {
      *******/
     @PUT
     @Path("/uniqueAttribute/type/{typeName}")
+    @Timed
     public EntityMutationResponse partialUpdateEntityByUniqueAttrs(@PathParam("typeName") String typeName,
                                                                    @Context HttpServletRequest servletRequest,
                                                                    AtlasEntityWithExtInfo entityInfo) throws Exception {
@@ -310,6 +316,7 @@ public class EntityREST {
      */
     @DELETE
     @Path("/uniqueAttribute/type/{typeName}")
+    @Timed
     public EntityMutationResponse deleteByUniqueAttribute(@PathParam("typeName") String typeName,
                                                           @Context HttpServletRequest servletRequest) throws AtlasBaseException {
         Servlets.validateQueryParamLength("typeName", typeName);
@@ -339,6 +346,7 @@ public class EntityREST {
      * @throws AtlasBaseException
      */
     @POST
+    @Timed
     public EntityMutationResponse createOrUpdate(AtlasEntityWithExtInfo entity) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -361,6 +369,7 @@ public class EntityREST {
      *******/
     @PUT
     @Path("/guid/{guid}")
+    @Timed
     public EntityMutationResponse partialUpdateEntityAttrByGuid(@PathParam("guid") String guid,
                                                                 @QueryParam("name") String attrName,
                                                                 Object attrValue) throws Exception {
@@ -387,6 +396,7 @@ public class EntityREST {
      */
     @DELETE
     @Path("/guid/{guid}")
+    @Timed
     public EntityMutationResponse deleteByGuid(@PathParam("guid") final String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -410,6 +420,7 @@ public class EntityREST {
      */
     @GET
     @Path("/guid/{guid}/classification/{classificationName}")
+    @Timed
     public AtlasClassification getClassification(@PathParam("guid") String guid, @PathParam("classificationName") final String classificationName) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
         Servlets.validateQueryParamLength("classificationName", classificationName);
@@ -439,6 +450,7 @@ public class EntityREST {
      */
     @GET
     @Path("/guid/{guid}/classifications")
+    @Timed
     public AtlasClassification.AtlasClassifications getClassifications(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -465,6 +477,7 @@ public class EntityREST {
      */
     @POST
     @Path("/uniqueAttribute/type/{typeName}/classifications")
+    @Timed
     public void addClassificationsByUniqueAttribute(@PathParam("typeName") String typeName, @Context HttpServletRequest servletRequest, List<AtlasClassification> classifications) throws AtlasBaseException {
         Servlets.validateQueryParamLength("typeName", typeName);
 
@@ -495,6 +508,7 @@ public class EntityREST {
      */
     @POST
     @Path("/guid/{guid}/classifications")
+    @Timed
     public void addClassifications(@PathParam("guid") final String guid, List<AtlasClassification> classifications) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -521,6 +535,7 @@ public class EntityREST {
      */
     @PUT
     @Path("/uniqueAttribute/type/{typeName}/classifications")
+    @Timed
     public void updateClassificationsByUniqueAttribute(@PathParam("typeName") String typeName, @Context HttpServletRequest servletRequest, List<AtlasClassification> classifications) throws AtlasBaseException {
         Servlets.validateQueryParamLength("typeName", typeName);
 
@@ -552,6 +567,7 @@ public class EntityREST {
      */
     @PUT
     @Path("/guid/{guid}/classifications")
+    @Timed
     public void updateClassifications(@PathParam("guid") final String guid, List<AtlasClassification> classifications) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -580,6 +596,7 @@ public class EntityREST {
      */
     @DELETE
     @Path("/uniqueAttribute/type/{typeName}/classification/{classificationName}")
+    @Timed
     public void deleteClassificationByUniqueAttribute(@PathParam("typeName") String typeName, @Context HttpServletRequest servletRequest,@PathParam("classificationName") String classificationName) throws AtlasBaseException {
         Servlets.validateQueryParamLength("typeName", typeName);
         Servlets.validateQueryParamLength("classificationName", classificationName);
@@ -612,6 +629,7 @@ public class EntityREST {
      */
     @DELETE
     @Path("/guid/{guid}/classification/{classificationName}")
+    @Timed
     public void deleteClassification(@PathParam("guid") String guid,
                                      @PathParam("classificationName") final String classificationName,
                                      @QueryParam("associatedEntityGuid") final String associatedEntityGuid) throws AtlasBaseException {
@@ -663,6 +681,7 @@ public class EntityREST {
      */
     @GET
     @Path("/bulk/uniqueAttribute/type/{typeName}")
+    @Timed
     public AtlasEntitiesWithExtInfo getEntitiesByUniqueAttributes(@PathParam("typeName") String typeName,
                                                                   @QueryParam("minExtInfo") @DefaultValue("false") boolean minExtInfo,
                                                                   @QueryParam("ignoreRelationships") @DefaultValue("false") boolean ignoreRelationships,
@@ -695,6 +714,7 @@ public class EntityREST {
      */
     @GET
     @Path("/bulk")
+    @Timed
     public AtlasEntitiesWithExtInfo getByGuids(@QueryParam("guid") List<String> guids, @QueryParam("minExtInfo") @DefaultValue("false") boolean minExtInfo, @QueryParam("ignoreRelationships") @DefaultValue("false") boolean ignoreRelationships) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(guids)) {
             for (String guid : guids) {
@@ -725,6 +745,7 @@ public class EntityREST {
      */
     @POST
     @Path("/bulk")
+    @Timed
     public EntityMutationResponse createOrUpdate(AtlasEntitiesWithExtInfo entities) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -747,6 +768,7 @@ public class EntityREST {
      */
     @DELETE
     @Path("/bulk")
+    @Timed
     public EntityMutationResponse deleteByGuids(@QueryParam("guid") final List<String> guids) throws AtlasBaseException {
         if (CollectionUtils.isNotEmpty(guids)) {
             for (String guid : guids) {
@@ -772,6 +794,7 @@ public class EntityREST {
      */
     @POST
     @Path("/bulk/classification")
+    @Timed
     public void addClassification(ClassificationAssociateRequest request) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -799,6 +822,7 @@ public class EntityREST {
 
     @GET
     @Path("{guid}/audit")
+    @Timed
     public List<EntityAuditEventV2> getAuditEvents(@PathParam("guid") String guid, @QueryParam("startKey") String startKey,
                                                    @QueryParam("auditAction") EntityAuditActionV2 auditAction,
                                                    @QueryParam("count") @DefaultValue("100") short count,
@@ -854,6 +878,7 @@ public class EntityREST {
     @GET
     @Path("bulk/headers")
     @Produces(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public AtlasEntityHeaders getEntityHeaders(@QueryParam("tagUpdateStartTime") long tagUpdateStartTime) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -879,6 +904,7 @@ public class EntityREST {
     @Path("bulk/setClassifications")
     @Produces(Servlets.JSON_MEDIA_TYPE)
     @Consumes(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public String setClassifications(AtlasEntityHeaders entityHeaders) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -898,6 +924,7 @@ public class EntityREST {
     @Path("/guid/{guid}/businessmetadata")
     @Produces(Servlets.JSON_MEDIA_TYPE)
     @Consumes(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public void addOrUpdateBusinessAttributes(@PathParam("guid") final String guid, @QueryParam("isOverwrite") @DefaultValue("false") boolean isOverwrite, Map<String, Map<String, Object>> businessAttributes) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -916,6 +943,7 @@ public class EntityREST {
     @Path("/guid/{guid}/businessmetadata")
     @Produces(Servlets.JSON_MEDIA_TYPE)
     @Consumes(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public void removeBusinessAttributes(@PathParam("guid") final String guid, Map<String, Map<String, Object>> businessAttributes) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -934,6 +962,7 @@ public class EntityREST {
     @Path("/guid/{guid}/businessmetadata/{bmName}")
     @Produces(Servlets.JSON_MEDIA_TYPE)
     @Consumes(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public void addOrUpdateBusinessAttributes(@PathParam("guid") final String guid, @PathParam("bmName") final String bmName, Map<String, Object> businessAttributes) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -952,6 +981,7 @@ public class EntityREST {
     @Path("/guid/{guid}/businessmetadata/{bmName}")
     @Produces(Servlets.JSON_MEDIA_TYPE)
     @Consumes(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public void removeBusinessAttributes(@PathParam("guid") final String guid, @PathParam("bmName") final String bmName, Map<String, Object> businessAttributes) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -976,6 +1006,7 @@ public class EntityREST {
     @Path("/guid/{guid}/labels")
     @Produces(Servlets.JSON_MEDIA_TYPE)
     @Consumes(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public void setLabels(@PathParam("guid") final String guid, Set<String> labels) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -999,6 +1030,7 @@ public class EntityREST {
     @Path("/guid/{guid}/labels")
     @Produces(Servlets.JSON_MEDIA_TYPE)
     @Consumes(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public void removeLabels(@PathParam("guid") final String guid, Set<String> labels) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -1022,6 +1054,7 @@ public class EntityREST {
     @Path("/guid/{guid}/labels")
     @Produces(Servlets.JSON_MEDIA_TYPE)
     @Consumes(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public void addLabels(@PathParam("guid") final String guid, Set<String> labels) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -1038,6 +1071,7 @@ public class EntityREST {
 
     @POST
     @Path("/uniqueAttribute/type/{typeName}/labels")
+    @Timed
     public void setLabels(@PathParam("typeName") String typeName, Set<String> labels,
                           @Context HttpServletRequest servletRequest) throws AtlasBaseException {
 
@@ -1065,6 +1099,7 @@ public class EntityREST {
 
     @PUT
     @Path("/uniqueAttribute/type/{typeName}/labels")
+    @Timed
     public void addLabels(@PathParam("typeName") String typeName, Set<String> labels,
                           @Context HttpServletRequest servletRequest) throws AtlasBaseException {
         Servlets.validateQueryParamLength("typeName", typeName);
@@ -1091,6 +1126,7 @@ public class EntityREST {
 
     @DELETE
     @Path("/uniqueAttribute/type/{typeName}/labels")
+    @Timed
     public void removeLabels(@PathParam("typeName") String typeName, Set<String> labels,
                              @Context HttpServletRequest servletRequest) throws AtlasBaseException {
 
@@ -1245,6 +1281,7 @@ public class EntityREST {
     @POST
     @Path("/businessmetadata/import")
     @Consumes(MediaType.MULTIPART_FORM_DATA)
+    @Timed
     public BulkImportResponse importBMAttributes(@FormDataParam("file") InputStream uploadedInputStream,
                                                  @FormDataParam("file") FormDataContentDisposition fileDetail) throws AtlasBaseException {
 
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java
index c1cf7be..c1de83b 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/GlossaryREST.java
@@ -21,6 +21,7 @@ import com.sun.jersey.core.header.FormDataContentDisposition;
 import com.sun.jersey.multipart.FormDataParam;
 import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.SortOrder;
+import org.apache.atlas.annotation.Timed;
 import org.apache.atlas.bulkimport.BulkImportResponse;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.glossary.GlossaryService;
@@ -85,6 +86,7 @@ public class GlossaryREST {
      * @throws AtlasBaseException
      */
     @GET
+    @Timed
     public List<AtlasGlossary> getGlossaries(@DefaultValue("-1") @QueryParam("limit") final String limit,
                                              @DefaultValue("0") @QueryParam("offset") final String offset,
                                              @DefaultValue("ASC") @QueryParam("sort") final String sort) throws AtlasBaseException {
@@ -112,6 +114,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/{glossaryGuid}")
+    @Timed
     public AtlasGlossary getGlossary(@PathParam("glossaryGuid") String glossaryGuid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("glossaryGuid", glossaryGuid);
 
@@ -143,6 +146,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/{glossaryGuid}/detailed")
+    @Timed
     public AtlasGlossary.AtlasGlossaryExtInfo getDetailedGlossary(@PathParam("glossaryGuid") String glossaryGuid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("glossaryGuid", glossaryGuid);
 
@@ -174,6 +178,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/term/{termGuid}")
+    @Timed
     public AtlasGlossaryTerm getGlossaryTerm(@PathParam("termGuid") String termGuid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("termGuid", termGuid);
 
@@ -204,6 +209,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/category/{categoryGuid}")
+    @Timed
     public AtlasGlossaryCategory getGlossaryCategory(@PathParam("categoryGuid") String categoryGuid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("categoryGuid", categoryGuid);
         AtlasPerfTracer perf = null;
@@ -234,6 +240,7 @@ public class GlossaryREST {
      * @HTTP 409 If Glossary definition already exists (duplicate qualifiedName)
      */
     @POST
+    @Timed
     public AtlasGlossary createGlossary(AtlasGlossary atlasGlossary) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
         try {
@@ -258,6 +265,7 @@ public class GlossaryREST {
      */
     @POST
     @Path("/term")
+    @Timed
     public AtlasGlossaryTerm createGlossaryTerm(AtlasGlossaryTerm glossaryTerm) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
         try {
@@ -283,6 +291,7 @@ public class GlossaryREST {
      */
     @POST
     @Path("/terms")
+    @Timed
     public List<AtlasGlossaryTerm> createGlossaryTerms(List<AtlasGlossaryTerm> glossaryTerm) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
         try {
@@ -312,6 +321,7 @@ public class GlossaryREST {
      */
     @POST
     @Path("/category")
+    @Timed
     public AtlasGlossaryCategory createGlossaryCategory(AtlasGlossaryCategory glossaryCategory) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
         try {
@@ -337,6 +347,7 @@ public class GlossaryREST {
      */
     @POST
     @Path("/categories")
+    @Timed
     public List<AtlasGlossaryCategory> createGlossaryCategories(List<AtlasGlossaryCategory> glossaryCategory) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
         try {
@@ -367,6 +378,7 @@ public class GlossaryREST {
      */
     @PUT
     @Path("/{glossaryGuid}")
+    @Timed
     public AtlasGlossary updateGlossary(@PathParam("glossaryGuid") String glossaryGuid, AtlasGlossary updatedGlossary) throws AtlasBaseException {
         Servlets.validateQueryParamLength("glossaryGuid", glossaryGuid);
         AtlasPerfTracer perf = null;
@@ -393,6 +405,7 @@ public class GlossaryREST {
      */
     @PUT
     @Path("/{glossaryGuid}/partial")
+    @Timed
     public AtlasGlossary partialUpdateGlossary(@PathParam("glossaryGuid") String glossaryGuid, Map<String, String> partialUpdates) throws AtlasBaseException {
         Servlets.validateQueryParamLength("glossaryGuid", glossaryGuid);
 
@@ -432,6 +445,7 @@ public class GlossaryREST {
      */
     @PUT
     @Path("/term/{termGuid}")
+    @Timed
     public AtlasGlossaryTerm updateGlossaryTerm(@PathParam("termGuid") String termGuid, AtlasGlossaryTerm glossaryTerm) throws AtlasBaseException {
         Servlets.validateQueryParamLength("termGuid", termGuid);
         AtlasPerfTracer perf = null;
@@ -458,6 +472,7 @@ public class GlossaryREST {
      */
     @PUT
     @Path("/term/{termGuid}/partial")
+    @Timed
     public AtlasGlossaryTerm partialUpdateGlossaryTerm(@PathParam("termGuid") String termGuid, Map<String, String> partialUpdates) throws AtlasBaseException {
         Servlets.validateQueryParamLength("termGuid", termGuid);
 
@@ -497,6 +512,7 @@ public class GlossaryREST {
      */
     @PUT
     @Path("/category/{categoryGuid}")
+    @Timed
     public AtlasGlossaryCategory updateGlossaryCategory(@PathParam("categoryGuid") String categoryGuid, AtlasGlossaryCategory glossaryCategory) throws AtlasBaseException {
         Servlets.validateQueryParamLength("categoryGuid", categoryGuid);
         AtlasPerfTracer perf = null;
@@ -523,6 +539,7 @@ public class GlossaryREST {
      */
     @PUT
     @Path("/category/{categoryGuid}/partial")
+    @Timed
     public AtlasGlossaryCategory partialUpdateGlossaryCategory(@PathParam("categoryGuid") String categoryGuid, Map<String, String> partialUpdates) throws AtlasBaseException {
         Servlets.validateQueryParamLength("categoryGuid", categoryGuid);
 
@@ -559,6 +576,7 @@ public class GlossaryREST {
      */
     @DELETE
     @Path("/{glossaryGuid}")
+    @Timed
     public void deleteGlossary(@PathParam("glossaryGuid") String glossaryGuid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("glossaryGuid", glossaryGuid);
         AtlasPerfTracer perf = null;
@@ -581,6 +599,7 @@ public class GlossaryREST {
      */
     @DELETE
     @Path("/term/{termGuid}")
+    @Timed
     public void deleteGlossaryTerm(@PathParam("termGuid") String termGuid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("termGuid", termGuid);
         AtlasPerfTracer perf = null;
@@ -603,6 +622,7 @@ public class GlossaryREST {
      */
     @DELETE
     @Path("/category/{categoryGuid}")
+    @Timed
     public void deleteGlossaryCategory(@PathParam("categoryGuid") String categoryGuid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("categoryGuid", categoryGuid);
         AtlasPerfTracer perf = null;
@@ -629,6 +649,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/{glossaryGuid}/terms")
+    @Timed
     public List<AtlasGlossaryTerm> getGlossaryTerms(@PathParam("glossaryGuid") String glossaryGuid,
                                                          @DefaultValue("-1") @QueryParam("limit") String limit,
                                                          @DefaultValue("0") @QueryParam("offset") String offset,
@@ -660,6 +681,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/{glossaryGuid}/terms/headers")
+    @Timed
     public List<AtlasRelatedTermHeader> getGlossaryTermHeaders(@PathParam("glossaryGuid") String glossaryGuid,
                                                          @DefaultValue("-1") @QueryParam("limit") String limit,
                                                          @DefaultValue("0") @QueryParam("offset") String offset,
@@ -691,6 +713,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/{glossaryGuid}/categories")
+    @Timed
     public List<AtlasGlossaryCategory> getGlossaryCategories(@PathParam("glossaryGuid") String glossaryGuid,
                                                                   @DefaultValue("-1") @QueryParam("limit") String limit,
                                                                   @DefaultValue("0") @QueryParam("offset") String offset,
@@ -722,6 +745,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/{glossaryGuid}/categories/headers")
+    @Timed
     public List<AtlasRelatedCategoryHeader> getGlossaryCategoriesHeaders(@PathParam("glossaryGuid") String glossaryGuid,
                                                                   @DefaultValue("-1") @QueryParam("limit") String limit,
                                                                   @DefaultValue("0") @QueryParam("offset") String offset,
@@ -753,6 +777,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/category/{categoryGuid}/terms")
+    @Timed
     public List<AtlasRelatedTermHeader> getCategoryTerms(@PathParam("categoryGuid") String categoryGuid,
                                                          @DefaultValue("-1") @QueryParam("limit") String limit,
                                                          @DefaultValue("0") @QueryParam("offset") String offset,
@@ -785,6 +810,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/terms/{termGuid}/related")
+    @Timed
     public Map<AtlasGlossaryTerm.Relation, Set<AtlasRelatedTermHeader>> getRelatedTerms(@PathParam("termGuid") String termGuid,
                                                                                         @DefaultValue("-1") @QueryParam("limit") String limit,
                                                                                         @DefaultValue("0") @QueryParam("offset") String offset,
@@ -817,6 +843,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/terms/{termGuid}/assignedEntities")
+    @Timed
     public List<AtlasRelatedObjectId> getEntitiesAssignedWithTerm(@PathParam("termGuid") String termGuid,
                                                                   @DefaultValue("-1") @QueryParam("limit") String limit,
                                                                   @DefaultValue("0") @QueryParam("offset") String offset,
@@ -848,6 +875,7 @@ public class GlossaryREST {
      */
     @POST
     @Path("/terms/{termGuid}/assignedEntities")
+    @Timed
     public void assignTermToEntities(@PathParam("termGuid") String termGuid, List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException {
         Servlets.validateQueryParamLength("termGuid", termGuid);
 
@@ -874,6 +902,7 @@ public class GlossaryREST {
      */
     @DELETE
     @Path("/terms/{termGuid}/assignedEntities")
+    @Timed
     public void removeTermAssignmentFromEntities(@PathParam("termGuid") String termGuid, List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException {
         removeTermFromGlossary(termGuid, relatedObjectIds);
     }
@@ -890,6 +919,7 @@ public class GlossaryREST {
      */
     @PUT
     @Path("/terms/{termGuid}/assignedEntities")
+    @Timed
     public void disassociateTermAssignmentFromEntities(@PathParam("termGuid") String termGuid, List<AtlasRelatedObjectId> relatedObjectIds) throws AtlasBaseException {
         removeTermFromGlossary(termGuid, relatedObjectIds);
     }
@@ -924,6 +954,7 @@ public class GlossaryREST {
      */
     @GET
     @Path("/category/{categoryGuid}/related")
+    @Timed
     public Map<String, List<AtlasRelatedCategoryHeader>> getRelatedCategories(@PathParam("categoryGuid") String categoryGuid,
                                                                          @DefaultValue("-1") @QueryParam("limit") String limit,
                                                                          @DefaultValue("0") @QueryParam("offset") String offset,
@@ -984,6 +1015,7 @@ public class GlossaryREST {
     @POST
     @Path("/import")
     @Consumes(MediaType.MULTIPART_FORM_DATA)
+    @Timed
     public BulkImportResponse importGlossaryData(@FormDataParam("file") InputStream inputStream,
                                                  @FormDataParam("file") FormDataContentDisposition fileDetail) throws AtlasBaseException {
         return glossaryService.importGlossaryData(inputStream, fileDetail.getFileName());
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/LineageREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/LineageREST.java
index 08c6555..30b5626 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/LineageREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/LineageREST.java
@@ -20,6 +20,7 @@ package org.apache.atlas.web.rest;
 
 
 import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.annotation.Timed;
 import org.apache.atlas.discovery.AtlasLineageService;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.TypeCategory;
@@ -30,7 +31,6 @@ import org.apache.atlas.type.AtlasEntityType;
 import org.apache.atlas.type.AtlasTypeRegistry;
 import org.apache.atlas.utils.AtlasPerfTracer;
 import org.apache.atlas.web.util.Servlets;
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.slf4j.Logger;
 import org.springframework.stereotype.Service;
@@ -89,6 +89,7 @@ public class LineageREST {
      */
     @GET
     @Path("/{guid}")
+    @Timed
     public AtlasLineageInfo getLineageGraph(@PathParam("guid") String guid,
                                             @QueryParam("direction") @DefaultValue(DEFAULT_DIRECTION)  LineageDirection direction,
                                             @QueryParam("depth") @DefaultValue(DEFAULT_DEPTH) int depth) throws AtlasBaseException {
@@ -130,6 +131,7 @@ public class LineageREST {
     @Path("/uniqueAttribute/type/{typeName}")
     @Consumes(Servlets.JSON_MEDIA_TYPE)
     @Produces(Servlets.JSON_MEDIA_TYPE)
+    @Timed
     public AtlasLineageInfo getLineageByUniqueAttribute(@PathParam("typeName") String typeName, @QueryParam("direction") @DefaultValue(DEFAULT_DIRECTION) LineageDirection direction,
                                                         @QueryParam("depth") @DefaultValue(DEFAULT_DEPTH) int depth, @Context HttpServletRequest servletRequest) throws AtlasBaseException {
         Servlets.validateQueryParamLength("typeName", typeName);
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/RelationshipREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/RelationshipREST.java
index 6d6432f..04114d9 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/RelationshipREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/RelationshipREST.java
@@ -18,6 +18,7 @@
 
 package org.apache.atlas.web.rest;
 
+import org.apache.atlas.annotation.Timed;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.instance.AtlasRelationship;
 import org.apache.atlas.model.instance.AtlasRelationship.AtlasRelationshipWithExtInfo;
@@ -54,6 +55,7 @@ public class RelationshipREST {
      * Create a new relationship between entities.
      */
     @POST
+    @Timed
     public AtlasRelationship create(AtlasRelationship relationship) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -73,6 +75,7 @@ public class RelationshipREST {
      * Update an existing relationship between entities.
      */
     @PUT
+    @Timed
     public AtlasRelationship update(AtlasRelationship relationship) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -93,6 +96,7 @@ public class RelationshipREST {
      */
     @GET
     @Path("/guid/{guid}")
+    @Timed
     public AtlasRelationshipWithExtInfo getById(@PathParam("guid") String guid,
                                                 @QueryParam("extendedInfo") @DefaultValue("false") boolean extendedInfo)
                                                 throws AtlasBaseException {
@@ -124,6 +128,7 @@ public class RelationshipREST {
      */
     @DELETE
     @Path("/guid/{guid}")
+    @Timed
     public void deleteById(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/TypesREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/TypesREST.java
index d879e57..30786dc 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/TypesREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/TypesREST.java
@@ -17,6 +17,7 @@
  */
 package org.apache.atlas.web.rest;
 
+import org.apache.atlas.annotation.Timed;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.SearchFilter;
 import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
@@ -81,6 +82,7 @@ public class TypesREST {
      */
     @GET
     @Path("/typedef/name/{name}")
+    @Timed
     public AtlasBaseTypeDef getTypeDefByName(@PathParam("name") String name) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", name);
 
@@ -98,6 +100,7 @@ public class TypesREST {
      */
     @GET
     @Path("/typedef/guid/{guid}")
+    @Timed
     public AtlasBaseTypeDef getTypeDefByGuid(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -115,6 +118,7 @@ public class TypesREST {
      */
     @GET
     @Path("/typedefs/headers")
+    @Timed
     public List<AtlasTypeDefHeader> getTypeDefHeaders(@Context HttpServletRequest httpServletRequest) throws AtlasBaseException {
         SearchFilter searchFilter = getSearchFilter(httpServletRequest);
 
@@ -131,6 +135,7 @@ public class TypesREST {
      */
     @GET
     @Path("/typedefs")
+    @Timed
     public AtlasTypesDef getAllTypeDefs(@Context HttpServletRequest httpServletRequest) throws AtlasBaseException {
         SearchFilter searchFilter = getSearchFilter(httpServletRequest);
 
@@ -149,6 +154,7 @@ public class TypesREST {
      */
     @GET
     @Path("/enumdef/name/{name}")
+    @Timed
     public AtlasEnumDef getEnumDefByName(@PathParam("name") String name) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", name);
 
@@ -167,6 +173,7 @@ public class TypesREST {
      */
     @GET
     @Path("/enumdef/guid/{guid}")
+    @Timed
     public AtlasEnumDef getEnumDefByGuid(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -186,6 +193,7 @@ public class TypesREST {
      */
     @GET
     @Path("/structdef/name/{name}")
+    @Timed
     public AtlasStructDef getStructDefByName(@PathParam("name") String name) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", name);
 
@@ -204,6 +212,7 @@ public class TypesREST {
      */
     @GET
     @Path("/structdef/guid/{guid}")
+    @Timed
     public AtlasStructDef getStructDefByGuid(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -222,6 +231,7 @@ public class TypesREST {
      */
     @GET
     @Path("/classificationdef/name/{name}")
+    @Timed
     public AtlasClassificationDef getClassificationDefByName(@PathParam("name") String name) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", name);
 
@@ -240,6 +250,7 @@ public class TypesREST {
      */
     @GET
     @Path("/classificationdef/guid/{guid}")
+    @Timed
     public AtlasClassificationDef getClassificationDefByGuid(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -258,6 +269,7 @@ public class TypesREST {
      */
     @GET
     @Path("/entitydef/name/{name}")
+    @Timed
     public AtlasEntityDef getEntityDefByName(@PathParam("name") String name) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", name);
 
@@ -276,6 +288,7 @@ public class TypesREST {
      */
     @GET
     @Path("/entitydef/guid/{guid}")
+    @Timed
     public AtlasEntityDef getEntityDefByGuid(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -293,6 +306,7 @@ public class TypesREST {
      */
     @GET
     @Path("/relationshipdef/name/{name}")
+    @Timed
     public AtlasRelationshipDef getRelationshipDefByName(@PathParam("name") String name) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", name);
 
@@ -311,6 +325,7 @@ public class TypesREST {
      */
     @GET
     @Path("/relationshipdef/guid/{guid}")
+    @Timed
     public AtlasRelationshipDef getRelationshipDefByGuid(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -329,6 +344,7 @@ public class TypesREST {
      */
     @GET
     @Path("/businessmetadatadef/guid/{guid}")
+    @Timed
     public AtlasBusinessMetadataDef getBusinessMetadataDefByGuid(@PathParam("guid") String guid) throws AtlasBaseException {
         Servlets.validateQueryParamLength("guid", guid);
 
@@ -347,6 +363,7 @@ public class TypesREST {
      */
     @GET
     @Path("/businessmetadatadef/name/{name}")
+    @Timed
     public AtlasBusinessMetadataDef getBusinessMetadataDefByName(@PathParam("name") String name) throws AtlasBaseException {
         Servlets.validateQueryParamLength("name", name);
 
@@ -369,6 +386,7 @@ public class TypesREST {
      */
     @POST
     @Path("/typedefs")
+    @Timed
     public AtlasTypesDef createAtlasTypeDefs(final AtlasTypesDef typesDef) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -395,6 +413,7 @@ public class TypesREST {
     @PUT
     @Path("/typedefs")
     @Experimental
+    @Timed
     public AtlasTypesDef updateAtlasTypeDefs(final AtlasTypesDef typesDef) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -420,6 +439,7 @@ public class TypesREST {
     @DELETE
     @Path("/typedefs")
     @Experimental
+    @Timed
     public void deleteAtlasTypeDefs(final AtlasTypesDef typesDef) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
@@ -446,6 +466,7 @@ public class TypesREST {
      */
     @DELETE
     @Path("/typedef/name/{typeName}")
+    @Timed
     public void deleteAtlasTypeByName(@PathParam("typeName") final String typeName) throws AtlasBaseException {
         AtlasPerfTracer perf = null;
 
diff --git a/webapp/src/main/java/org/apache/atlas/web/service/AtlasDebugMetricsSink.java b/webapp/src/main/java/org/apache/atlas/web/service/AtlasDebugMetricsSink.java
new file mode 100644
index 0000000..ef24b86
--- /dev/null
+++ b/webapp/src/main/java/org/apache/atlas/web/service/AtlasDebugMetricsSink.java
@@ -0,0 +1,115 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.atlas.web.service;
+
+import org.apache.atlas.web.model.DebugMetrics;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.metrics2.AbstractMetric;
+import org.apache.hadoop.metrics2.MetricsRecord;
+import org.apache.hadoop.metrics2.MetricsSink;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+
+import static org.apache.atlas.web.service.DebugMetricsWrapper.Constants.AVG_TIME;
+import static org.apache.atlas.web.service.DebugMetricsWrapper.Constants.DEBUG_METRICS_SOURCE;
+import static org.apache.atlas.web.service.DebugMetricsWrapper.Constants.MAX_TIME;
+import static org.apache.atlas.web.service.DebugMetricsWrapper.Constants.MIN_TIME;
+import static org.apache.atlas.web.service.DebugMetricsWrapper.Constants.NUM_OPS;
+import static org.apache.atlas.web.service.DebugMetricsWrapper.Constants.STD_DEV_TIME;
+
+@Component
+public class AtlasDebugMetricsSink implements MetricsSink {
+    private final HashMap<String, DebugMetrics> metricStructuredSnapshot = new HashMap<>();
+
+    @Override
+    public void putMetrics(MetricsRecord metricsRecord) {
+        if (!DEBUG_METRICS_SOURCE.equals(metricsRecord.name())) {
+            return;
+        }
+
+        for (AbstractMetric metric : metricsRecord.metrics()) {
+            float value = metric.value().floatValue();
+
+            if (value == 0 || value == Float.MAX_VALUE || value == Float.MIN_VALUE) {
+                continue;
+            }
+
+            setMetricsData(metric);
+        }
+    }
+
+    public HashMap getMetrics() {
+        return metricStructuredSnapshot;
+    }
+
+    @Override
+    public void init(org.apache.commons.configuration2.SubsetConfiguration subsetConfiguration) {
+    }
+
+    @Override
+    public void flush() {
+    }
+
+    private void setMetricsData(AbstractMetric metric) {
+        String name      = metric.name().toLowerCase();
+        String fieldCaps = AtlasDebugMetricsSource.fieldLowerCaseUpperCaseMap.get(name);
+
+        if (!StringUtils.isEmpty(fieldCaps)) {
+            String       fieldNameLower = fieldCaps.toLowerCase();
+            String       metricType = inferMeasureType(name, fieldNameLower);
+            DebugMetrics debugMetrics = metricStructuredSnapshot.get(fieldCaps);
+
+            if (debugMetrics == null) {
+                debugMetrics = new DebugMetrics(fieldCaps);
+
+                metricStructuredSnapshot.put(fieldCaps, debugMetrics);
+            }
+
+            updateMetricType(debugMetrics, metricType, metric);
+        }
+    }
+
+    private void updateMetricType(DebugMetrics debugMetrics, String metricType, AbstractMetric metric) {
+        switch (metricType) {
+            case NUM_OPS:
+                debugMetrics.setNumops(metric.value().intValue());
+                break;
+
+            case MIN_TIME:
+                debugMetrics.setMinTime(metric.value().floatValue());
+                break;
+
+            case MAX_TIME:
+                debugMetrics.setMaxTime(metric.value().floatValue());
+                break;
+
+            case STD_DEV_TIME:
+                debugMetrics.setStdDevTime(metric.value().floatValue());
+                break;
+
+            case AVG_TIME:
+                debugMetrics.setAvgTime(metric.value().floatValue());
+                break;
+        }
+    }
+
+    private static String inferMeasureType(String fullName, String nameWithoutMetricType) {
+        return fullName.replaceFirst(nameWithoutMetricType, "");
+    }
+}
\ No newline at end of file
diff --git a/webapp/src/main/java/org/apache/atlas/web/service/AtlasDebugMetricsSource.java b/webapp/src/main/java/org/apache/atlas/web/service/AtlasDebugMetricsSource.java
new file mode 100644
index 0000000..ec64b01
--- /dev/null
+++ b/webapp/src/main/java/org/apache/atlas/web/service/AtlasDebugMetricsSource.java
@@ -0,0 +1,647 @@
+/*
+ * 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.atlas.web.service;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.metrics2.annotation.Metric;
+import org.apache.hadoop.metrics2.annotation.Metrics;
+import org.apache.hadoop.metrics2.lib.MutableRate;
+import org.aspectj.lang.Signature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.atlas.web.service.DebugMetricsWrapper.Constants.*;
+
+@Metrics(context = DEBUG_METRICS_CONTEXT)
+public class AtlasDebugMetricsSource {
+    private static final Logger LOG = LoggerFactory.getLogger(AtlasDebugMetricsSource.class);
+
+    protected @Metric(always = true)  MutableRate entityREST_getById;
+    protected @Metric(always = true)  MutableRate entityREST_createOrUpdate;
+    protected @Metric(always = true)  MutableRate entityREST_deleteByGuid;
+    protected @Metric(always = true)  MutableRate entityREST_getClassifications;
+    protected @Metric(always = true)  MutableRate entityREST_addClassificationsByUniqAttr;
+    protected @Metric(always = true)  MutableRate entityREST_addClassifications;
+    protected @Metric(always = true)  MutableRate entityREST_deleteClassificationByUniqAttr;
+    protected @Metric(always = true)  MutableRate entityREST_deleteClassification;
+    protected @Metric(always = true)  MutableRate entityREST_getHeaderById;
+    protected @Metric(always = true)  MutableRate entityREST_getEntityHeaderByUniqAttr;
+    protected @Metric(always = true)  MutableRate entityREST_getByUniqueAttributes;
+    protected @Metric(always = true)  MutableRate entityREST_partialUpdateEntityByUniqAttr;
+    protected @Metric(always = true)  MutableRate entityREST_deleteByUniqAttr;
+    protected @Metric(always = true)  MutableRate entityREST_updateClassificationsByUniqAttr;
+    protected @Metric(always = true)  MutableRate entityREST_updateClassifications;
+    protected @Metric(always = true)  MutableRate entityREST_getEntitiesByUniqAttr;
+    protected @Metric(always = true)  MutableRate entityREST_getByGuids;
+    protected @Metric(always = true)  MutableRate entityREST_createOrUpdateBulk;
+    protected @Metric(always = true)  MutableRate entityREST_deleteByGuids;
+    protected @Metric(always = true)  MutableRate entityREST_addClassification;
+    protected @Metric(always = true)  MutableRate entityREST_getAuditEvents;
+    protected @Metric(always = true)  MutableRate entityREST_getEntityHeaders;
+    protected @Metric(always = true)  MutableRate entityREST_setClassifications;
+    protected @Metric(always = true)  MutableRate entityREST_addOrUpdateBusinessAttributes;
+    protected @Metric(always = true)  MutableRate entityREST_removeBusinessAttributes;
+    protected @Metric(always = true)  MutableRate entityREST_addOrUpdateBusinessAttributesByName;
+    protected @Metric(always = true)  MutableRate entityREST_removeBusinessAttributesByName;
+    protected @Metric(always = true)  MutableRate entityREST_setLabels;
+    protected @Metric(always = true)  MutableRate entityREST_addLabels;
+    protected @Metric(always = true)  MutableRate entityREST_removeLabels;
+    protected @Metric(always = true)  MutableRate entityREST_removeLabelsByTypeName;
+    protected @Metric(always = true)  MutableRate entityREST_setLabelsByTypeName;
+    protected @Metric(always = true)  MutableRate entityREST_addLabelsByTypeName;
+    protected @Metric(always = true)  MutableRate entityREST_importBMAttributes;
+
+    protected @Metric(always = true)  MutableRate typesREST_getEntityDefByName;
+    protected @Metric(always = true)  MutableRate typesREST_getTypeDefByName;
+    protected @Metric(always = true)  MutableRate typesREST_getTypeDefByGuid;
+    protected @Metric(always = true)  MutableRate typesREST_getTypeDefHeaders;
+    protected @Metric(always = true)  MutableRate typesREST_getAllTypeDefs;
+    protected @Metric(always = true)  MutableRate typesREST_getEnumDefByName;
+    protected @Metric(always = true)  MutableRate typesREST_getEnumDefByGuid;
+    protected @Metric(always = true)  MutableRate typesREST_getStructDefByName;
+    protected @Metric(always = true)  MutableRate typesREST_getStructDefByGuid;
+    protected @Metric(always = true)  MutableRate typesREST_getClassificationDefByName;
+    protected @Metric(always = true)  MutableRate typesREST_getClassificationDefByGuid;
+    protected @Metric(always = true)  MutableRate typesREST_getEntityDefByGuid;
+    protected @Metric(always = true)  MutableRate typesREST_getRelationshipDefByName;
+    protected @Metric(always = true)  MutableRate typesREST_getRelationshipDefByGuid;
+    protected @Metric(always = true)  MutableRate typesREST_getBusinessMetadataDefByGuid;
+    protected @Metric(always = true)  MutableRate typesREST_getBusinessMetadataDefByName;
+    protected @Metric(always = true)  MutableRate typesREST_createAtlasTypeDefs;
+    protected @Metric(always = true)  MutableRate typesREST_updateAtlasTypeDefs;
+    protected @Metric(always = true)  MutableRate typesREST_deleteAtlasTypeDefs;
+    protected @Metric(always = true)  MutableRate typesREST_deleteAtlasTypeByName;
+
+
+    protected @Metric(always = true)  MutableRate glossaryREST_getGlossaries;
+    protected @Metric(always = true)  MutableRate glossaryREST_getGlossary;
+    protected @Metric(always = true)  MutableRate glossaryREST_getDetailedGlossary;
+    protected @Metric(always = true)  MutableRate glossaryREST_getGlossaryTerm;
+    protected @Metric(always = true)  MutableRate glossaryREST_getGlossaryCategory;
+    protected @Metric(always = true)  MutableRate glossaryREST_createGlossary;
+    protected @Metric(always = true)  MutableRate glossaryREST_createGlossaryTerm;
+    protected @Metric(always = true)  MutableRate glossaryREST_createGlossaryTerms;
+    protected @Metric(always = true)  MutableRate glossaryREST_createGlossaryCategory;
+    protected @Metric(always = true)  MutableRate glossaryREST_createGlossaryCategories;
+    protected @Metric(always = true)  MutableRate glossaryREST_updateGlossary;
+    protected @Metric(always = true)  MutableRate glossaryREST_partialUpdateGlossary;
+    protected @Metric(always = true)  MutableRate glossaryREST_updateGlossaryTerm;
+    protected @Metric(always = true)  MutableRate glossaryREST_partialUpdateGlossaryTerm;
+    protected @Metric(always = true)  MutableRate glossaryREST_updateGlossaryCategory;
+    protected @Metric(always = true)  MutableRate glossaryREST_partialUpdateGlossaryCategory;
+    protected @Metric(always = true)  MutableRate glossaryREST_deleteGlossary;
+    protected @Metric(always = true)  MutableRate glossaryREST_deleteGlossaryTerm;
+    protected @Metric(always = true)  MutableRate glossaryREST_deleteGlossaryCategory;
+    protected @Metric(always = true)  MutableRate glossaryREST_getGlossaryTerms;
+    protected @Metric(always = true)  MutableRate glossaryREST_getGlossaryTermHeaders;
+    protected @Metric(always = true)  MutableRate glossaryREST_getGlossaryCategories;
+    protected @Metric(always = true)  MutableRate glossaryREST_getGlossaryCategoriesHeaders;
+    protected @Metric(always = true)  MutableRate glossaryREST_getCategoryTerms;
+    protected @Metric(always = true)  MutableRate glossaryREST_getRelatedTerms;
+    protected @Metric(always = true)  MutableRate glossaryREST_getEntitiesAssignedWithTerm;
+    protected @Metric(always = true)  MutableRate glossaryREST_assignTermToEntities;
+    protected @Metric(always = true)  MutableRate glossaryREST_removeTermAssignmentFromEntities;
+    protected @Metric(always = true)  MutableRate glossaryREST_disassociateTermAssignmentFromEntities;
+    protected @Metric(always = true)  MutableRate glossaryREST_getRelatedCategories;
+    protected @Metric(always = true)  MutableRate glossaryREST_importGlossaryData;
+
+    protected @Metric(always = true)  MutableRate discoveryREST_quickSearchQuickSearchParams;
+    protected @Metric(always = true)  MutableRate discoveryREST_searchUsingFullText;
+    protected @Metric(always = true)  MutableRate discoveryREST_searchUsingAttribute;
+    protected @Metric(always = true)  MutableRate discoveryREST_searchWithParameters;
+    protected @Metric(always = true)  MutableRate discoveryREST_searchRelatedEntities;
+    protected @Metric(always = true)  MutableRate discoveryREST_updateSavedSearch;
+    protected @Metric(always = true)  MutableRate discoveryREST_getSavedSearch;
+    protected @Metric(always = true)  MutableRate discoveryREST_getSavedSearches;
+    protected @Metric(always = true)  MutableRate discoveryREST_deleteSavedSearch;
+    protected @Metric(always = true)  MutableRate discoveryREST_executeSavedSearchByName;
+    protected @Metric(always = true)  MutableRate discoveryREST_executeSavedSearchByGuid;
+    protected @Metric(always = true)  MutableRate discoveryREST_getSuggestions;
+    protected @Metric(always = true)  MutableRate discoveryREST_searchUsingDSL;
+    protected @Metric(always = true)  MutableRate discoveryREST_searchUsingBasic;
+    protected @Metric(always = true)  MutableRate discoveryREST_quickSearch;
+    protected @Metric(always = true)  MutableRate discoveryREST_addSavedSearch;
+
+    protected @Metric(always = true)  MutableRate notificationHookConsumer_doWork;
+
+    protected @Metric(always = true)  MutableRate lineageREST_getLineageByUniqAttr;
+    protected @Metric(always = true)  MutableRate lineageREST_getLineageGraph;
+
+    protected @Metric(always = true)  MutableRate relationshipREST_create;
+    protected @Metric(always = true)  MutableRate relationshipREST_update;
+    protected @Metric(always = true)  MutableRate relationshipREST_getById;
+    protected @Metric(always = true)  MutableRate relationshipREST_deleteById;
+
+
+    public static final Map<String, String> fieldLowerCaseUpperCaseMap = new HashMap<>();
+    public static final Set<String>         debugMetricsAttributes     = new HashSet<>();
+
+    public AtlasDebugMetricsSource() {
+        initAttrList();
+
+        populateFieldList();
+    }
+
+    public void update(Signature name, Long timeConsumed) {
+        String signatureName = name.toString();
+
+        switch (signatureName) {
+            case EntityREST_createOrUpdateBulk:
+                entityREST_createOrUpdateBulk.add(timeConsumed);
+                break;
+
+            case EntityREST_addOrUpdateBMByName:
+                entityREST_addOrUpdateBusinessAttributesByName.add(timeConsumed);
+                break;
+
+            case EntityREST_removeBMByName:
+                entityREST_removeBusinessAttributesByName.add(timeConsumed);
+                break;
+
+            case EntityREST_removeLabelsByTypeName:
+                entityREST_removeLabelsByTypeName.add(timeConsumed);
+                break;
+
+            case EntityREST_setLabelsByTypeName:
+                entityREST_setLabelsByTypeName.add(timeConsumed);
+                break;
+
+            case EntityREST_addLabelsByTypeName:
+                entityREST_addLabelsByTypeName.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_quickSearchQuickSearchParams:
+                discoveryREST_quickSearchQuickSearchParams.add(timeConsumed);
+                break;
+
+            default:
+                update(name.toShortString(), timeConsumed);
+                break;
+        }
+    }
+
+    private void populateFieldList() {
+        Field fields[] = AtlasDebugMetricsSource.class.getDeclaredFields();
+
+        for (int i = 0; i < fields.length; i++) {
+            if (fields[i].getAnnotation(Metric.class) == null) {
+                continue;
+            }
+
+            String name = fields[i].getName();
+
+            for(String metricName : debugMetricsAttributes) {
+                fieldLowerCaseUpperCaseMap.put(name.toLowerCase() + metricName, StringUtils.capitalize(name));
+            }
+
+        }
+    }
+
+    private void initAttrList() {
+        debugMetricsAttributes.add(NUM_OPS);
+        debugMetricsAttributes.add(MIN_TIME);
+        debugMetricsAttributes.add(STD_DEV_TIME);
+        debugMetricsAttributes.add(MAX_TIME);
+        debugMetricsAttributes.add(AVG_TIME);
+    }
+
+    private void update(String name, Long timeConsumed) {
+        switch (name) {
+            case RelationshipREST_create:
+                relationshipREST_create.add(timeConsumed);
+                break;
+
+            case RelationshipREST_update:
+                relationshipREST_update.add(timeConsumed);
+                break;
+
+            case RelationshipREST_getById:
+                relationshipREST_getById.add(timeConsumed);
+                break;
+
+            case RelationshipREST_deleteById:
+                relationshipREST_deleteById.add(timeConsumed);
+                break;
+
+                //DiscoveryREST apis
+            case DiscoveryREST_searchUsingFullText:
+                discoveryREST_searchUsingFullText.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_searchUsingAttribute:
+                discoveryREST_searchUsingAttribute.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_searchWithParameters:
+                discoveryREST_searchWithParameters.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_searchRelatedEntities:
+                discoveryREST_searchRelatedEntities.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_updateSavedSearch:
+                discoveryREST_updateSavedSearch.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_getSavedSearch:
+                discoveryREST_getSavedSearch.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_getSavedSearches:
+                discoveryREST_getSavedSearches.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_deleteSavedSearch:
+                discoveryREST_deleteSavedSearch.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_executeSavedSearchByName:
+                discoveryREST_executeSavedSearchByName.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_executeSavedSearchByGuid:
+                discoveryREST_executeSavedSearchByGuid.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_getSuggestions:
+                discoveryREST_getSuggestions.add(timeConsumed);
+                break;
+
+            //GlossaryRest apis
+
+            case GlossaryREST_getGlossaries:
+                glossaryREST_getGlossaries.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getGlossary:
+                glossaryREST_getGlossary.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getDetailedGlossary:
+                glossaryREST_getDetailedGlossary.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getGlossaryTerm:
+                glossaryREST_getGlossaryTerm.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getGlossaryCategory:
+                glossaryREST_getGlossaryCategory.add(timeConsumed);
+                break;
+
+            case GlossaryREST_createGlossary:
+                glossaryREST_createGlossary.add(timeConsumed);
+                break;
+
+            case GlossaryREST_createGlossaryTerm:
+                glossaryREST_createGlossaryTerm.add(timeConsumed);
+                break;
+
+            case GlossaryREST_createGlossaryTerms:
+                glossaryREST_createGlossaryTerms.add(timeConsumed);
+                break;
+
+            case GlossaryREST_createGlossaryCategory:
+                glossaryREST_createGlossaryCategory.add(timeConsumed);
+                break;
+
+            case GlossaryREST_createGlossaryCategories:
+                glossaryREST_createGlossaryCategories.add(timeConsumed);
+                break;
+
+            case GlossaryREST_updateGlossary:
+                glossaryREST_updateGlossary.add(timeConsumed);
+                break;
+
+            case GlossaryREST_partialUpdateGlossary:
+                glossaryREST_partialUpdateGlossary.add(timeConsumed);
+                break;
+
+            case GlossaryREST_updateGlossaryTerm:
+                glossaryREST_updateGlossaryTerm.add(timeConsumed);
+                break;
+
+            case GlossaryREST_partialUpdateGlossaryTerm:
+                glossaryREST_partialUpdateGlossaryTerm.add(timeConsumed);
+                break;
+
+            case GlossaryREST_updateGlossaryCategory:
+                glossaryREST_updateGlossaryCategory.add(timeConsumed);
+                break;
+
+            case GlossaryREST_partialUpdateGlossaryCategory:
+                glossaryREST_partialUpdateGlossaryCategory.add(timeConsumed);
+                break;
+
+            case GlossaryREST_deleteGlossary:
+                glossaryREST_deleteGlossary.add(timeConsumed);
+                break;
+
+            case GlossaryREST_deleteGlossaryTerm:
+                glossaryREST_deleteGlossaryTerm.add(timeConsumed);
+                break;
+
+            case GlossaryREST_deleteGlossaryCategory:
+                glossaryREST_deleteGlossaryCategory.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getGlossaryTerms:
+                glossaryREST_getGlossaryTerms.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getGlossaryTermHeaders:
+                glossaryREST_getGlossaryTermHeaders.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getGlossaryCategories:
+                glossaryREST_getGlossaryCategories.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getGlossaryCategoriesHeaders:
+                glossaryREST_getGlossaryCategoriesHeaders.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getCategoryTerms:
+                glossaryREST_getCategoryTerms.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getRelatedTerms:
+                glossaryREST_getRelatedTerms.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getEntitiesAssignedWithTerm:
+                glossaryREST_getEntitiesAssignedWithTerm.add(timeConsumed);
+                break;
+
+            case GlossaryREST_assignTermToEntities:
+                glossaryREST_assignTermToEntities.add(timeConsumed);
+                break;
+
+            case GlossaryREST_removeTermAssignmentFromEntities:
+                glossaryREST_removeTermAssignmentFromEntities.add(timeConsumed);
+                break;
+
+            case GlossaryREST_disassociateTermAssignmentFromEntities:
+                glossaryREST_disassociateTermAssignmentFromEntities.add(timeConsumed);
+                break;
+
+            case GlossaryREST_getRelatedCategories:
+                glossaryREST_getRelatedCategories.add(timeConsumed);
+                break;
+
+            case GlossaryREST_importGlossaryData:
+                glossaryREST_importGlossaryData.add(timeConsumed);
+                break;
+
+            //TypesREST apis
+
+            case TypesREST_getTypeDefByName:
+                typesREST_getTypeDefByName.add(timeConsumed);
+                break;
+
+            case TypesREST_getTypeDefByGuid:
+                typesREST_getTypeDefByGuid.add(timeConsumed);
+                break;
+
+            case TypesREST_getTypeDefHeaders:
+                typesREST_getTypeDefHeaders.add(timeConsumed);
+                break;
+
+            case TypesREST_getAllTypeDefs:
+                typesREST_getAllTypeDefs.add(timeConsumed);
+                break;
+
+            case TypesREST_getEnumDefByName:
+                typesREST_getEnumDefByName.add(timeConsumed);
+                break;
+
+            case TypesREST_getEnumDefByGuid:
+                typesREST_getEnumDefByGuid.add(timeConsumed);
+                break;
+
+            case TypesREST_getStructDefByName:
+                typesREST_getStructDefByName.add(timeConsumed);
+                break;
+
+            case TypesREST_getStructDefByGuid:
+                typesREST_getStructDefByGuid.add(timeConsumed);
+                break;
+
+            case TypesREST_getClassificationDefByName:
+                typesREST_getClassificationDefByName.add(timeConsumed);
+                break;
+
+            case TypesREST_getClassificationDefByGuid:
+                typesREST_getClassificationDefByGuid.add(timeConsumed);
+                break;
+
+            case TypesREST_getEntityDefByName:
+                typesREST_getEntityDefByName.add(timeConsumed);
+                break;
+
+            case TypesREST_getEntityDefByGuid:
+                typesREST_getEntityDefByGuid.add(timeConsumed);
+                break;
+
+            case TypesREST_getRelationshipDefByName:
+                typesREST_getRelationshipDefByName.add(timeConsumed);
+                break;
+
+            case TypesREST_getRelationshipDefByGuid:
+                typesREST_getRelationshipDefByGuid.add(timeConsumed);
+                break;
+
+            case TypesREST_getBusinessMetadataDefByGuid:
+                typesREST_getBusinessMetadataDefByGuid.add(timeConsumed);
+                break;
+
+            case TypesREST_getBusinessMetadataDefByName:
+                typesREST_getBusinessMetadataDefByName.add(timeConsumed);
+                break;
+
+            case TypesREST_createAtlasTypeDefs:
+                typesREST_createAtlasTypeDefs.add(timeConsumed);
+                break;
+
+            case TypesREST_updateAtlasTypeDefs:
+                typesREST_updateAtlasTypeDefs.add(timeConsumed);
+                break;
+
+            case TypesREST_deleteAtlasTypeDefs:
+                typesREST_deleteAtlasTypeDefs.add(timeConsumed);
+                break;
+
+            case TypesREST_deleteAtlasTypeByName:
+                typesREST_deleteAtlasTypeByName.add(timeConsumed);
+                break;
+
+            case EntityREST_getHeaderById:
+                entityREST_getHeaderById.add(timeConsumed);
+                break;
+
+            case EntityREST_getEntityHeaderByUA:
+                entityREST_getEntityHeaderByUniqAttr.add(timeConsumed);
+                break;
+
+            case EntityREST_getByUniqueAttributes:
+                entityREST_getByUniqueAttributes.add(timeConsumed);
+                break;
+
+            case EntityREST_partialUpdateEntityByUA:
+                entityREST_partialUpdateEntityByUniqAttr.add(timeConsumed);
+                break;
+
+            case EntityREST_deleteByUA:
+                entityREST_deleteByUniqAttr.add(timeConsumed);
+                break;
+
+            case EntityREST_updateClassificationsByUA:
+                entityREST_updateClassificationsByUniqAttr.add(timeConsumed);
+                break;
+
+            case EntityREST_updateClassifications:
+                entityREST_updateClassifications.add(timeConsumed);
+                break;
+
+            case EntityREST_getEntitiesByUA:
+                entityREST_getEntitiesByUniqAttr.add(timeConsumed);
+                break;
+
+            case EntityREST_getByGuids:
+                entityREST_getByGuids.add(timeConsumed);
+                break;
+
+            case EntityREST_deleteByGuids:
+                entityREST_deleteByGuids.add(timeConsumed);
+                break;
+
+            case EntityREST_addClassification:
+                entityREST_addClassification.add(timeConsumed);
+                break;
+
+            case EntityREST_getAuditEvents:
+                entityREST_getAuditEvents.add(timeConsumed);
+                break;
+
+            case EntityREST_getEntityHeaders:
+                entityREST_getEntityHeaders.add(timeConsumed);
+                break;
+
+            case EntityREST_setClassifications:
+                entityREST_setClassifications.add(timeConsumed);
+                break;
+
+            case EntityREST_addOrUpdateBusinessAttributes:
+                entityREST_addOrUpdateBusinessAttributes.add(timeConsumed);
+                break;
+
+            case EntityREST_removeBusinessAttributes:
+                entityREST_removeBusinessAttributes.add(timeConsumed);
+                break;
+
+            case EntityREST_setLabels:
+                entityREST_setLabels.add(timeConsumed);
+                break;
+
+            case EntityREST_addLabels:
+                entityREST_addLabels.add(timeConsumed);
+                break;
+
+            case EntityREST_removeLabels:
+                entityREST_removeLabels.add(timeConsumed);
+                break;
+
+            case EntityREST_getById:
+                entityREST_getById.add(timeConsumed);
+                break;
+
+            case EntityREST_createOrUpdate:
+                entityREST_createOrUpdate.add(timeConsumed);
+                break;
+
+            case EntityREST_deleteByGuid:
+                entityREST_deleteByGuid.add(timeConsumed);
+                break;
+
+            case EntityREST_getClassifications:
+                entityREST_getClassifications.add(timeConsumed);
+                break;
+
+            case EntityREST_addClassificationsByUA:
+                entityREST_addClassificationsByUniqAttr.add(timeConsumed);
+                break;
+
+            case EntityREST_addClassifications:
+                entityREST_addClassifications.add(timeConsumed);
+                break;
+
+            case EntityREST_deleteClassificationByUA:
+                entityREST_deleteClassificationByUniqAttr.add(timeConsumed);
+                break;
+
+            case EntityREST_deleteClassification:
+                entityREST_deleteClassification.add(timeConsumed);
+                break;
+
+            case EntityREST_importBMAttributes:
+                entityREST_importBMAttributes.add(timeConsumed);
+                break;
+
+            case NotificationHookConsumer_doWork:
+                notificationHookConsumer_doWork.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_searchUsingDSL:
+                discoveryREST_searchUsingDSL.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_searchUsingBasic:
+                discoveryREST_searchUsingBasic.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_quickSearch:
+                discoveryREST_quickSearch.add(timeConsumed);
+                break;
+
+            case DiscoveryREST_addSavedSearch:
+                discoveryREST_addSavedSearch.add(timeConsumed);
+                break;
+
+            case LineageREST_getLineageByUA:
+                lineageREST_getLineageByUniqAttr.add(timeConsumed);
+                break;
+
+            case LineageREST_getLineageGraph:
+                lineageREST_getLineageGraph.add(timeConsumed);
+                break;
+
+            default:
+                LOG.error("The signature '{}' is not handled!", name);
+                break;
+        }
+    }
+}
\ No newline at end of file
diff --git a/webapp/src/main/java/org/apache/atlas/web/service/DebugMetricsWrapper.java b/webapp/src/main/java/org/apache/atlas/web/service/DebugMetricsWrapper.java
new file mode 100644
index 0000000..564a946
--- /dev/null
+++ b/webapp/src/main/java/org/apache/atlas/web/service/DebugMetricsWrapper.java
@@ -0,0 +1,190 @@
+/*
+ * 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.atlas.web.service;
+
+import org.apache.hadoop.metrics2.MetricsSystem;
+import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
+import org.aspectj.lang.Signature;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import static org.apache.atlas.web.service.DebugMetricsWrapper.Constants.*;
+
+@Lazy()
+@Service
+public class DebugMetricsWrapper {
+	private AtlasDebugMetricsSource debugMetricsSource = new AtlasDebugMetricsSource();
+
+	@Inject
+	AtlasDebugMetricsSink debugMetricsRESTSink;
+
+	@PostConstruct
+	public void init() {
+		MetricsSystem metricsSystem = DefaultMetricsSystem.initialize(DEBUG_METRICS_CONTEXT);
+		metricsSystem.register(debugMetricsSource);
+        metricsSystem.register(DEBUG_METRICS_REST_SINK, "", debugMetricsRESTSink);
+    }
+
+	public void update(Signature name, long timeConsumed) {
+		debugMetricsSource.update(name, timeConsumed);
+	}
+
+	class Constants {
+		public static final String NUM_OPS                       = "numops";
+		public static final String MIN_TIME                      = "mintime";
+		public static final String MAX_TIME                      = "maxtime";
+		public static final String STD_DEV_TIME                  = "stdevtime";
+		public static final String AVG_TIME                      = "avgtime";
+
+		public static final String DEBUG_METRICS_SOURCE          = "AtlasDebugMetricsSource";
+		public static final String DEBUG_METRICS_CONTEXT         = "atlas-debug-metrics-context";
+		public static final String DEBUG_METRICS_REST_SINK       = "AtlasDebugMetricsRESTSink";
+
+		public static final String EntityRESTPrefix              = "EntityREST.";
+		public static final String TypesRESTPrefix               = "TypesREST.";
+		public static final String GlossaryRESTPrefix            = "GlossaryREST.";
+		public static final String DiscoveryRESTPrefix           = "DiscoveryREST.";
+		public static final String LineageRESTPrefix             = "LineageREST.";
+		public static final String RelationshipRESTPrefix        = "RelationshipREST.";
+
+		public static final String EntityREST_getById                        = EntityRESTPrefix + "getById(..)";
+		public static final String EntityREST_createOrUpdate                 = EntityRESTPrefix + "createOrUpdate(..)";
+		public static final String EntityREST_deleteByGuid                   = EntityRESTPrefix + "deleteByGuid(..)";
+		public static final String EntityREST_getClassifications             = EntityRESTPrefix + "getClassifications(..)";
+		public static final String EntityREST_addClassificationsByUA         = EntityRESTPrefix + "addClassificationsByUniqueAttribute(..)";
+		public static final String EntityREST_addClassifications             = EntityRESTPrefix + "addClassifications(..)";
+		public static final String EntityREST_deleteClassificationByUA       = EntityRESTPrefix + "deleteClassificationByUniqueAttribute(..)";
+		public static final String EntityREST_deleteClassification           = EntityRESTPrefix + "deleteClassification(..)";
+		public static final String EntityREST_getHeaderById                  = EntityRESTPrefix + "getHeaderById(..)";
+		public static final String EntityREST_getEntityHeaderByUA            = EntityRESTPrefix + "getEntityHeaderByUniqueAttributes(..)";
+		public static final String EntityREST_getByUniqueAttributes          = EntityRESTPrefix + "getByUniqueAttributes(..)";
+		public static final String EntityREST_partialUpdateEntityByUA        = EntityRESTPrefix + "partialUpdateEntityByUniqueAttrs(..)";
+		public static final String EntityREST_deleteByUA                     = EntityRESTPrefix + "deleteByUniqueAttribute(..)";
+		public static final String EntityREST_updateClassificationsByUA      = EntityRESTPrefix + "updateClassificationsByUniqueAttribute(..)";
+		public static final String EntityREST_updateClassifications          = EntityRESTPrefix + "updateClassifications(..)";
+		public static final String EntityREST_getEntitiesByUA                = EntityRESTPrefix + "getEntitiesByUniqueAttributes(..)";
+		public static final String EntityREST_getByGuids                     = EntityRESTPrefix + "getByGuids(..)";
+		public static final String EntityREST_deleteByGuids                  = EntityRESTPrefix + "deleteByGuids(..)";
+		public static final String EntityREST_addClassification              = EntityRESTPrefix + "addClassification(..)";
+		public static final String EntityREST_getAuditEvents                 = EntityRESTPrefix + "getAuditEvents(..)";
+		public static final String EntityREST_getEntityHeaders               = EntityRESTPrefix + "getEntityHeaders(..)";
+		public static final String EntityREST_setClassifications             = EntityRESTPrefix + "setClassifications(..)";
+		public static final String EntityREST_addOrUpdateBusinessAttributes  = EntityRESTPrefix + "addOrUpdateBusinessAttributes(..)";
+		public static final String EntityREST_removeBusinessAttributes       = EntityRESTPrefix + "removeBusinessAttributes(..)";
+		public static final String EntityREST_setLabels                      = EntityRESTPrefix + "setLabels(..)";
+		public static final String EntityREST_addLabels                      = EntityRESTPrefix + "addLabels(..)";
+		public static final String EntityREST_removeLabels                   = EntityRESTPrefix + "removeLabels(..)";
+		public static final String EntityREST_importBMAttributes             = EntityRESTPrefix + "importBMAttributes(..)";
+
+		//TypesREST
+		public static final String TypesREST_getTypeDefByName                    = TypesRESTPrefix + "getTypeDefByName(..)";
+		public static final String TypesREST_getTypeDefByGuid                    = TypesRESTPrefix + "getTypeDefByGuid(..)";
+		public static final String TypesREST_getTypeDefHeaders                   = TypesRESTPrefix + "getTypeDefHeaders(..)";
+		public static final String TypesREST_getAllTypeDefs                      = TypesRESTPrefix + "getAllTypeDefs(..)";
+		public static final String TypesREST_getEnumDefByName                    = TypesRESTPrefix + "getEnumDefByName(..)";
+		public static final String TypesREST_getEnumDefByGuid                    = TypesRESTPrefix + "getEnumDefByGuid(..)";
+		public static final String TypesREST_getStructDefByName                  = TypesRESTPrefix + "getStructDefByName(..)";
+		public static final String TypesREST_getStructDefByGuid                  = TypesRESTPrefix + "getStructDefByGuid(..)";
+		public static final String TypesREST_getClassificationDefByName          = TypesRESTPrefix + "getClassificationDefByName(..)";
+		public static final String TypesREST_getClassificationDefByGuid          = TypesRESTPrefix + "getClassificationDefByGuid(..)";
+		public static final String TypesREST_getEntityDefByName                  = TypesRESTPrefix + "getEntityDefByName(..)";
+		public static final String TypesREST_getEntityDefByGuid                  = TypesRESTPrefix + "getEntityDefByGuid(..)";
+		public static final String TypesREST_getRelationshipDefByName            = TypesRESTPrefix + "getRelationshipDefByName(..)";
+		public static final String TypesREST_getRelationshipDefByGuid            = TypesRESTPrefix + "getRelationshipDefByGuid(..)";
+		public static final String TypesREST_getBusinessMetadataDefByGuid        = TypesRESTPrefix + "getBusinessMetadataDefByGuid(..)";
+		public static final String TypesREST_getBusinessMetadataDefByName        = TypesRESTPrefix + "getBusinessMetadataDefByName(..)";
+		public static final String TypesREST_createAtlasTypeDefs                 = TypesRESTPrefix + "createAtlasTypeDefs(..)";
+		public static final String TypesREST_updateAtlasTypeDefs                 = TypesRESTPrefix + "updateAtlasTypeDefs(..)";
+		public static final String TypesREST_deleteAtlasTypeDefs                 = TypesRESTPrefix + "deleteAtlasTypeDefs(..)";
+		public static final String TypesREST_deleteAtlasTypeByName               = TypesRESTPrefix + "deleteAtlasTypeByName(..)";
+
+		//GlossaryREST
+		public static final String GlossaryREST_getGlossaries                          = GlossaryRESTPrefix + "getGlossaries(..)";
+		public static final String GlossaryREST_getGlossary                            = GlossaryRESTPrefix + "getGlossary(..)";
+		public static final String GlossaryREST_getDetailedGlossary                    = GlossaryRESTPrefix + "getDetailedGlossary(..)";
+		public static final String GlossaryREST_getGlossaryTerm                        = GlossaryRESTPrefix + "getGlossaryTerm(..)";
+		public static final String GlossaryREST_getGlossaryCategory                    = GlossaryRESTPrefix + "getGlossaryCategory(..)";
+		public static final String GlossaryREST_createGlossary                         = GlossaryRESTPrefix + "createGlossary(..)";
+		public static final String GlossaryREST_createGlossaryTerm                     = GlossaryRESTPrefix + "createGlossaryTerm(..)";
+		public static final String GlossaryREST_createGlossaryTerms                    = GlossaryRESTPrefix + "createGlossaryTerms(..)";
+		public static final String GlossaryREST_createGlossaryCategory                 = GlossaryRESTPrefix + "createGlossaryCategory(..)";
+		public static final String GlossaryREST_createGlossaryCategories               = GlossaryRESTPrefix + "createGlossaryCategories(..)";
+		public static final String GlossaryREST_updateGlossary                         = GlossaryRESTPrefix + "updateGlossary(..)";
+		public static final String GlossaryREST_partialUpdateGlossary                  = GlossaryRESTPrefix + "partialUpdateGlossary(..)";
+		public static final String GlossaryREST_updateGlossaryTerm                     = GlossaryRESTPrefix + "updateGlossaryTerm(..)";
+		public static final String GlossaryREST_partialUpdateGlossaryTerm              = GlossaryRESTPrefix + "partialUpdateGlossaryTerm(..)";
+		public static final String GlossaryREST_updateGlossaryCategory                 = GlossaryRESTPrefix + "updateGlossaryCategory(..)";
+		public static final String GlossaryREST_partialUpdateGlossaryCategory          = GlossaryRESTPrefix + "partialUpdateGlossaryCategory(..)";
+		public static final String GlossaryREST_deleteGlossary                         = GlossaryRESTPrefix + "deleteGlossary(..)";
+		public static final String GlossaryREST_deleteGlossaryTerm                     = GlossaryRESTPrefix + "deleteGlossaryTerm(..)";
+		public static final String GlossaryREST_deleteGlossaryCategory                 = GlossaryRESTPrefix + "deleteGlossaryCategory(..)";
+		public static final String GlossaryREST_getGlossaryTerms                       = GlossaryRESTPrefix + "getGlossaryTerms(..)";
+		public static final String GlossaryREST_getGlossaryTermHeaders                 = GlossaryRESTPrefix + "getGlossaryTermHeaders(..)";
+		public static final String GlossaryREST_getGlossaryCategories                  = GlossaryRESTPrefix + "getGlossaryCategories(..)";
+		public static final String GlossaryREST_getGlossaryCategoriesHeaders           = GlossaryRESTPrefix + "getGlossaryCategoriesHeaders(..)";
+		public static final String GlossaryREST_getCategoryTerms                       = GlossaryRESTPrefix + "getCategoryTerms(..)";
+		public static final String GlossaryREST_getRelatedTerms                        = GlossaryRESTPrefix + "getRelatedTerms(..)";
+		public static final String GlossaryREST_getEntitiesAssignedWithTerm            = GlossaryRESTPrefix + "getEntitiesAssignedWithTerm(..)";
+		public static final String GlossaryREST_assignTermToEntities                   = GlossaryRESTPrefix + "assignTermToEntities(..)";
+		public static final String GlossaryREST_removeTermAssignmentFromEntities       = GlossaryRESTPrefix + "removeTermAssignmentFromEntities(..)";
+		public static final String GlossaryREST_disassociateTermAssignmentFromEntities = GlossaryRESTPrefix + "disassociateTermAssignmentFromEntities(..)";
+		public static final String GlossaryREST_getRelatedCategories                   = GlossaryRESTPrefix + "getRelatedCategories(..)";
+		public static final String GlossaryREST_importGlossaryData                     = GlossaryRESTPrefix + "importGlossaryData(..)";
+
+		//DiscoveryREST
+		public static final String DiscoveryREST_searchUsingDSL                        = DiscoveryRESTPrefix + "searchUsingDSL(..)";
+		public static final String DiscoveryREST_searchUsingBasic                      = DiscoveryRESTPrefix + "searchUsingBasic(..)";
+		public static final String DiscoveryREST_quickSearch                           = DiscoveryRESTPrefix + "quickSearch(..)";
+		public static final String DiscoveryREST_addSavedSearch                        = DiscoveryRESTPrefix + "addSavedSearch(..)";
+		public static final String DiscoveryREST_searchUsingFullText                   = DiscoveryRESTPrefix + "searchUsingFullText(..)";
+		public static final String DiscoveryREST_searchUsingAttribute                  = DiscoveryRESTPrefix + "searchUsingAttribute(..)";
+		public static final String DiscoveryREST_searchWithParameters                  = DiscoveryRESTPrefix + "searchWithParameters(..)";
+		public static final String DiscoveryREST_searchRelatedEntities                 = DiscoveryRESTPrefix + "searchRelatedEntities(..)";
+		public static final String DiscoveryREST_updateSavedSearch                     = DiscoveryRESTPrefix + "updateSavedSearch(..)";
+		public static final String DiscoveryREST_getSavedSearch                        = DiscoveryRESTPrefix + "getSavedSearch(..)";
+		public static final String DiscoveryREST_getSavedSearches                      = DiscoveryRESTPrefix + "getSavedSearches(..)";
+		public static final String DiscoveryREST_deleteSavedSearch                     = DiscoveryRESTPrefix + "deleteSavedSearch(..)";
+		public static final String DiscoveryREST_executeSavedSearchByName              = DiscoveryRESTPrefix + "executeSavedSearchByName(..)";
+		public static final String DiscoveryREST_executeSavedSearchByGuid              = DiscoveryRESTPrefix + "executeSavedSearchByGuid(..)";
+		public static final String DiscoveryREST_getSuggestions                        = DiscoveryRESTPrefix + "getSuggestions(..)";
+
+		//RelationshipREST
+		public static final String RelationshipREST_create                             = RelationshipRESTPrefix + "create(..)";
+		public static final String RelationshipREST_update                             = RelationshipRESTPrefix + "update(..)";
+		public static final String RelationshipREST_getById                            = RelationshipRESTPrefix + "getById(..)";
+		public static final String RelationshipREST_deleteById                         = RelationshipRESTPrefix + "deleteById(..)";
+
+		public static final String LineageREST_getLineageByUA                          = LineageRESTPrefix + "getLineageByUniqueAttribute(..)";
+		public static final String LineageREST_getLineageGraph                         = LineageRESTPrefix + "getLineageGraph(..)";
+		public static final String NotificationHookConsumer_doWork                     = "NotificationHookConsumer.doWork(..)";
+
+		//duplicate short signature apis
+		public static final String EntityREST_createOrUpdateBulk                     = "EntityMutationResponse org.apache.atlas.web.rest.EntityREST.createOrUpdate(AtlasEntitiesWithExtInfo)";
+		public static final String EntityREST_removeLabelsByTypeName                 = "void org.apache.atlas.web.rest.EntityREST.removeLabels(String,Set,HttpServletRequest)";
+		public static final String EntityREST_setLabelsByTypeName                    = "void org.apache.atlas.web.rest.EntityREST.setLabels(String,Set,HttpServletRequest)";
+		public static final String EntityREST_addLabelsByTypeName                    = "void org.apache.atlas.web.rest.EntityREST.addLabels(String,Set,HttpServletRequest)";
+		public static final String EntityREST_addOrUpdateBMByName                    = "void org.apache.atlas.web.rest.EntityREST.addOrUpdateBusinessAttributes(String,String,Map)";
+		public static final String EntityREST_removeBMByName                         = "void org.apache.atlas.web.rest.EntityREST.removeBusinessAttributes(String,String,Map)";
+		public static final String DiscoveryREST_quickSearchQuickSearchParams        = "AtlasQuickSearchResult org.apache.atlas.web.rest.DiscoveryREST.quickSearch(QuickSearchParameters)";
+	}
+}
\ No newline at end of file
diff --git a/webapp/src/main/java/org/apache/atlas/web/service/TimedAspectInterceptor.java b/webapp/src/main/java/org/apache/atlas/web/service/TimedAspectInterceptor.java
new file mode 100644
index 0000000..64225d0
--- /dev/null
+++ b/webapp/src/main/java/org/apache/atlas/web/service/TimedAspectInterceptor.java
@@ -0,0 +1,61 @@
+/**
+ * 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.atlas.web.service;
+
+import org.apache.atlas.AtlasConfiguration;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+
+import javax.inject.Inject;
+
+@Aspect
+@Component
+public class TimedAspectInterceptor {
+    private static final boolean debugMetricsEnabled = AtlasConfiguration.DEBUG_METRICS_ENABLED.getBoolean();
+
+    private final DebugMetricsWrapper wrapper;
+
+    @Inject
+    public TimedAspectInterceptor(DebugMetricsWrapper wrapper) {
+        this.wrapper = wrapper;
+    }
+
+    @Around("@annotation(org.apache.atlas.annotation.Timed) && execution(public * *(..))")
+    public Object timerAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
+        long start = System.currentTimeMillis();
+
+        try {
+            return proceedingJoinPoint.proceed();
+        } catch (Throwable throwable){
+            throw throwable;
+        } finally {
+            if (debugMetricsEnabled) {
+                reportMetrics(start, proceedingJoinPoint.getSignature());
+            }
+        }
+    }
+
+    private void reportMetrics(long start, Signature signature) {
+        long executionTime = System.currentTimeMillis() - start;
+
+        wrapper.update(signature, executionTime);
+    }
+}
\ No newline at end of file
diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java
index 50f93d9..9d5a9e5 100755
--- a/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java
+++ b/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java
@@ -637,6 +637,16 @@ public abstract class BaseResourceIT {
         return atlasEntity;
     }
 
+    protected  AtlasEntity createEntity(String typeName, String name) {
+        AtlasEntity atlasEntity = new AtlasEntity(typeName);
+
+        atlasEntity.setAttribute("name", name);
+        atlasEntity.setAttribute("qualifiedName", name);
+        atlasEntity.setAttribute("clusterName", randomString());
+
+        return atlasEntity;
+    }
+
     public interface Predicate {
 
         /**
diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/DebugMetricsIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/DebugMetricsIT.java
new file mode 100644
index 0000000..3c614d4
--- /dev/null
+++ b/webapp/src/test/java/org/apache/atlas/web/integration/DebugMetricsIT.java
@@ -0,0 +1,79 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.atlas.web.integration;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import org.apache.atlas.AtlasBaseClient;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.utils.AtlasJson;
+import org.apache.atlas.web.model.DebugMetrics;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.Response;
+import java.util.HashMap;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+public class DebugMetricsIT extends BaseResourceIT {
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Test
+    public void checkMetricCountIncrement() {
+
+        // Get the metrics
+        AtlasBaseClient.API metricsAPI = new AtlasBaseClient.API(AtlasBaseClient.BASE_URI + "admin/debug/metrics", HttpMethod.GET, Response.Status.OK);
+        try {
+            String metricsJson = atlasClientV1.callAPI(metricsAPI, String.class, null);
+            HashMap<String, DebugMetrics> currentMetrics = AtlasJson.fromJson(metricsJson, new TypeReference<HashMap<String, DebugMetrics>>() {});
+            DebugMetrics currentCreateOrUpdateDTO = currentMetrics.get("EntityREST_createOrUpdate");
+            long currentCreateOrUpdateCount = 0;
+            if(currentCreateOrUpdateDTO != null) {
+                currentCreateOrUpdateCount = currentCreateOrUpdateDTO.getNumops();
+            }
+
+            // hit the api
+            AtlasEntity atlasEntity = createEntity(DATABASE_TYPE_BUILTIN, randomString());
+            atlasClientV2.createEntity(new AtlasEntity.AtlasEntityWithExtInfo(atlasEntity));
+
+            atlasEntity = createEntity(DATABASE_TYPE_BUILTIN, randomString());
+            atlasClientV2.createEntity(new AtlasEntity.AtlasEntityWithExtInfo(atlasEntity));
+
+            // get the metrics again
+            Thread.sleep(30000); // The metrics take some time to update
+            metricsJson = atlasClientV1.callAPI(metricsAPI, String.class, null);
+            HashMap<String, DebugMetrics> newMetrics = AtlasJson.fromJson(metricsJson, new TypeReference<HashMap<String, DebugMetrics>>() {});
+            DebugMetrics newCreateOrUpdateDTO = newMetrics.get("EntityREST_createOrUpdate");
+
+            // check if the metric count has increased
+            long newCreateOrUpdateCount = 0;
+            if(newCreateOrUpdateDTO != null) {
+                newCreateOrUpdateCount = newCreateOrUpdateDTO.getNumops();
+            }
+            assertEquals(newCreateOrUpdateCount, (currentCreateOrUpdateCount + 2), "Count didn't increase after making API call");
+        } catch (Exception e) {
+            fail("Caught exception while running the test: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java
index ef5350d..a4d7946 100644
--- a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java
+++ b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java
@@ -51,7 +51,7 @@ public class AdminResourceTest {
 
         when(serviceState.getState()).thenReturn(ServiceState.ServiceStateValue.ACTIVE);
 
-        AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null, null, null, null, null, null, null, null, null);
+        AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
         Response response = adminResource.getStatus();
         assertEquals(response.getStatus(), HttpServletResponse.SC_OK);
         JsonNode entity = AtlasJson.parseToV1JsonNode((String) response.getEntity());
@@ -62,7 +62,7 @@ public class AdminResourceTest {
     public void testResourceGetsValueFromServiceState() throws IOException {
         when(serviceState.getState()).thenReturn(ServiceState.ServiceStateValue.PASSIVE);
 
-        AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null, null, null, null, null, null, null, null, null);
+        AdminResource adminResource = new AdminResource(serviceState, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
         Response response = adminResource.getStatus();
 
         verify(serviceState).getState();