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();