You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/08/11 22:42:43 UTC

[05/18] incubator-brooklyn git commit: Adds SoftwareProcess.RETRIEVE_USAGE_METRICS

Adds SoftwareProcess.RETRIEVE_USAGE_METRICS

- RETRIEVE_USAGE_METRICS defaults to true
- Setting RETRIEVE_USAGE_METRICS to false will disable the automatic
  retrieval of performance/usage metrics in some entity types.
- Adds FeedConfig.enabled as an easy way to programmatically
  prevent a feed from being enabled (which can be easier to program
  against than guarding its creation with an if statement).
- Adds TomcatServerDisableRetrieveUsageMetricsIntegrationTest


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/b4166230
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/b4166230
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/b4166230

Branch: refs/heads/master
Commit: b416623040397d9129953bf4b95db07dea0a1546
Parents: ce0c422
Author: Aled Sage <al...@gmail.com>
Authored: Sat Apr 18 14:40:33 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Aug 11 17:51:35 2015 +0100

----------------------------------------------------------------------
 .../java/brooklyn/event/feed/FeedConfig.java    | 14 +++++
 .../event/feed/function/FunctionFeed.java       |  1 +
 .../java/brooklyn/event/feed/http/HttpFeed.java |  1 +
 .../brooklyn/event/feed/shell/ShellFeed.java    |  1 +
 .../windows/WindowsPerformanceCounterFeed.java  |  1 +
 .../internal/AbstractManagementContext.java     |  6 --
 .../internal/CollectionChangeListener.java      |  1 +
 .../entity/monitoring/zabbix/ZabbixFeed.java    |  1 +
 .../brooklyn/entity/basic/SoftwareProcess.java  |  5 ++
 .../brooklyn/entity/chef/ChefAttributeFeed.java |  1 +
 .../java/brooklyn/event/feed/jmx/JmxFeed.java   |  3 +
 .../entity/database/mysql/MySqlNodeImpl.java    |  5 +-
 .../entity/messaging/kafka/KafkaBrokerImpl.java | 27 +++++---
 .../entity/messaging/qpid/QpidBrokerImpl.java   |  3 +-
 .../nosql/cassandra/CassandraNodeImpl.java      | 24 +++++---
 .../entity/nosql/couchdb/CouchDBNodeImpl.java   | 23 ++++---
 .../entity/nosql/redis/RedisStoreImpl.java      | 24 +++++---
 .../entity/webapp/jboss/JBoss6ServerImpl.java   | 27 +++++---
 .../entity/webapp/jboss/JBoss7ServerImpl.java   | 19 ++++--
 .../entity/webapp/tomcat/TomcatServerImpl.java  | 31 ++++++----
 ...ableRetrieveUsageMetricsIntegrationTest.java | 65 ++++++++++++++++++++
 21 files changed, 213 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/core/src/main/java/brooklyn/event/feed/FeedConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/FeedConfig.java b/core/src/main/java/brooklyn/event/feed/FeedConfig.java
index 6796730..f51050f 100644
--- a/core/src/main/java/brooklyn/event/feed/FeedConfig.java
+++ b/core/src/main/java/brooklyn/event/feed/FeedConfig.java
@@ -63,6 +63,7 @@ public class FeedConfig<V, T, F extends FeedConfig<V, T, F>> {
     private Function<? super Exception, T> onexception;
     private Predicate<? super V> checkSuccess;
     private boolean suppressDuplicates;
+    private boolean enabled = true;
     
     public FeedConfig(AttributeSensor<T> sensor) {
         this.sensor = checkNotNull(sensor, "sensor");
@@ -75,6 +76,7 @@ public class FeedConfig<V, T, F extends FeedConfig<V, T, F>> {
         this.onexception = other.onexception;
         this.checkSuccess = other.checkSuccess;
         this.suppressDuplicates = other.suppressDuplicates;
+        this.enabled = other.enabled;
     }
 
     @SuppressWarnings("unchecked")
@@ -106,6 +108,10 @@ public class FeedConfig<V, T, F extends FeedConfig<V, T, F>> {
         return suppressDuplicates;
     }
     
+    public boolean isEnabled() {
+        return enabled;
+    }
+    
     /** sets the predicate used to check whether a feed run is successful */
     public F checkSuccess(Predicate<? super V> val) {
         this.checkSuccess = checkNotNull(val, "checkSuccess");
@@ -186,6 +192,14 @@ public class FeedConfig<V, T, F extends FeedConfig<V, T, F>> {
         return self();
     }
     
+    /**
+     * Whether this feed is enabled (defaulting to true).
+     */
+    public F enabled(boolean val) {
+        enabled = val;
+        return self();
+    }
+    
     public boolean hasSuccessHandler() {
         return this.onsuccess != null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/core/src/main/java/brooklyn/event/feed/function/FunctionFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/function/FunctionFeed.java b/core/src/main/java/brooklyn/event/feed/function/FunctionFeed.java
index 6acf408..9f96f24 100644
--- a/core/src/main/java/brooklyn/event/feed/function/FunctionFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/function/FunctionFeed.java
@@ -175,6 +175,7 @@ public class FunctionFeed extends AbstractFeed {
         
         SetMultimap<FunctionPollIdentifier, FunctionPollConfig<?,?>> polls = HashMultimap.<FunctionPollIdentifier,FunctionPollConfig<?,?>>create();
         for (FunctionPollConfig<?,?> config : builder.polls) {
+            if (!config.isEnabled()) continue;
             @SuppressWarnings({ "rawtypes", "unchecked" })
             FunctionPollConfig<?,?> configCopy = new FunctionPollConfig(config);
             if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java b/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
index ab9dcd1..5131a4b 100644
--- a/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
@@ -279,6 +279,7 @@ public class HttpFeed extends AbstractFeed {
         
         SetMultimap<HttpPollIdentifier, HttpPollConfig<?>> polls = HashMultimap.<HttpPollIdentifier,HttpPollConfig<?>>create();
         for (HttpPollConfig<?> config : builder.polls) {
+            if (!config.isEnabled()) continue;
             @SuppressWarnings({ "unchecked", "rawtypes" })
             HttpPollConfig<?> configCopy = new HttpPollConfig(config);
             if (configCopy.getPeriod() < 0) configCopy.period(builder.period);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java b/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java
index f92ec07..f325a2d 100644
--- a/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java
@@ -196,6 +196,7 @@ public class ShellFeed extends AbstractFeed {
 
         SetMultimap<ShellPollIdentifier, ShellPollConfig<?>> polls = HashMultimap.<ShellPollIdentifier,ShellPollConfig<?>>create();
         for (ShellPollConfig<?> config : builder.polls) {
+            if (!config.isEnabled()) continue;
             @SuppressWarnings({ "unchecked", "rawtypes" })
             ShellPollConfig<?> configCopy = new ShellPollConfig(config);
             if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java b/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java
index 5278ff9..99eec78 100644
--- a/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java
@@ -169,6 +169,7 @@ public class WindowsPerformanceCounterFeed extends AbstractFeed {
     protected WindowsPerformanceCounterFeed(Builder builder) {
         List<WindowsPerformanceCounterPollConfig<?>> polls = Lists.newArrayList();
         for (WindowsPerformanceCounterPollConfig<?> config : builder.polls) {
+            if (!config.isEnabled()) continue;
             @SuppressWarnings({ "unchecked", "rawtypes" })
             WindowsPerformanceCounterPollConfig<?> configCopy = new WindowsPerformanceCounterPollConfig(config);
             if (configCopy.getPeriod() < 0) configCopy.period(builder.period);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
index e296ddf..3cd64da 100644
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -340,12 +340,6 @@ public abstract class AbstractManagementContext implements ManagementContextInte
     protected abstract <T> Task<T> runAtEntity(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters);
 
     @Override
-    public abstract void addEntitySetListener(CollectionChangeListener<Entity> listener);
-
-    @Override
-    public abstract void removeEntitySetListener(CollectionChangeListener<Entity> listener);
-    
-    @Override
     public StringConfigMap getConfig() {
         return configMap;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java b/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java
index c4cb8be..654debc 100644
--- a/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java
+++ b/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java
@@ -17,6 +17,7 @@
  * under the License.
  */
 package brooklyn.management.internal;
+
 public interface CollectionChangeListener<Item> {
     void onItemAdded(Item item);
     void onItemRemoved(Item item);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
index 08fba87..4347543 100644
--- a/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
+++ b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
@@ -305,6 +305,7 @@ public class ZabbixFeed extends AbstractFeed {
 
         Set<ZabbixPollConfig<?>> polls = Sets.newLinkedHashSet();
         for (ZabbixPollConfig<?> config : builder.polls) {
+            if (!config.isEnabled()) continue;
             @SuppressWarnings({ "unchecked", "rawtypes" })
             ZabbixPollConfig<?> configCopy = new ZabbixPollConfig(config);
             if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
index 5144a2b..05852d0 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
@@ -239,6 +239,11 @@ public interface SoftwareProcess extends Entity, Startable {
             "softwareProcess.lifecycleTasks", "An object that handles lifecycle of an entity's associated machine.",
             new SoftwareProcessDriverLifecycleEffectorTasks());
 
+    ConfigKey<Boolean> RETRIEVE_USAGE_METRICS = ConfigKeys.newBooleanConfigKey(
+            "metrics.usage.retrieve",
+            "Whether to retrieve the usage (e.g. performance) metrics",
+            true);
+
     /** Controls the behavior when starting (stop, restart) {@link Startable} children as part of the start (stop, restart) effector on this entity
      * <p>
      * (NB: restarts are currently not propagated to children in the default {@link SoftwareProcess}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java b/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java
index d55845e..4cf7a95 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java
@@ -199,6 +199,7 @@ public class ChefAttributeFeed extends AbstractFeed {
 
         Set<ChefAttributePollConfig<?>> polls = Sets.newLinkedHashSet();
         for (ChefAttributePollConfig<?> config : builder.polls) {
+            if (!config.isEnabled()) continue;
             @SuppressWarnings({ "unchecked", "rawtypes" })
             ChefAttributePollConfig<?> configCopy = new ChefAttributePollConfig(config);
             if (configCopy.getPeriod() < 0) configCopy.period(builder.period);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/base/src/main/java/brooklyn/event/feed/jmx/JmxFeed.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/event/feed/jmx/JmxFeed.java b/software/base/src/main/java/brooklyn/event/feed/jmx/JmxFeed.java
index de0a553..00bb017 100644
--- a/software/base/src/main/java/brooklyn/event/feed/jmx/JmxFeed.java
+++ b/software/base/src/main/java/brooklyn/event/feed/jmx/JmxFeed.java
@@ -198,6 +198,7 @@ public class JmxFeed extends AbstractFeed {
         
         SetMultimap<String, JmxAttributePollConfig<?>> attributePolls = HashMultimap.<String,JmxAttributePollConfig<?>>create();
         for (JmxAttributePollConfig<?> config : builder.attributePolls) {
+            if (!config.isEnabled()) continue;
             @SuppressWarnings({ "rawtypes", "unchecked" })
             JmxAttributePollConfig<?> configCopy = new JmxAttributePollConfig(config);
             if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);
@@ -207,6 +208,7 @@ public class JmxFeed extends AbstractFeed {
         
         SetMultimap<List<?>, JmxOperationPollConfig<?>> operationPolls = HashMultimap.<List<?>,JmxOperationPollConfig<?>>create();
         for (JmxOperationPollConfig<?> config : builder.operationPolls) {
+            if (!config.isEnabled()) continue;
             @SuppressWarnings({ "rawtypes", "unchecked" })
             JmxOperationPollConfig<?> configCopy = new JmxOperationPollConfig(config);
             if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);
@@ -216,6 +218,7 @@ public class JmxFeed extends AbstractFeed {
         
         SetMultimap<NotificationFilter, JmxNotificationSubscriptionConfig<?>> notificationSubscriptions = HashMultimap.create();
         for (JmxNotificationSubscriptionConfig<?> config : builder.notificationSubscriptions) {
+            if (!config.isEnabled()) continue;
             notificationSubscriptions.put(config.getNotificationFilter(), config);
         }
         setConfig(NOTIFICATION_SUBSCRIPTIONS, notificationSubscriptions);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
index 8346fbb..892f552 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
@@ -93,6 +93,8 @@ public class MySqlNodeImpl extends SoftwareProcessImpl implements MySqlNode {
          * So can extract lots of sensors from that.
          */
         Maybe<SshMachineLocation> machine = Locations.findUniqueSshMachineLocation(getLocations());
+        boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
+
         if (machine.isPresent()) {
             String cmd = getDriver().getStatusCmd();
             feed = SshFeed.builder()
@@ -108,7 +110,8 @@ public class MySqlNodeImpl extends SoftwareProcessImpl implements MySqlNode {
                                     if (q==null) return null;
                                     return Double.parseDouble(q);
                                 }})
-                            .setOnFailureOrException(null) )
+                            .setOnFailureOrException(null)
+                            .enabled(retrieveUsageMetrics))
                     .poll(new SshPollConfig<Boolean>(SERVICE_PROCESS_IS_RUNNING)
                             .command(cmd)
                             .setOnSuccess(true)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBrokerImpl.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBrokerImpl.java b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBrokerImpl.java
index d6aadd1..1354d6f 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBrokerImpl.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBrokerImpl.java
@@ -91,7 +91,8 @@ public class KafkaBrokerImpl extends SoftwareProcessImpl implements MessageBroke
     @Override
     protected void connectSensors() {
         connectServiceUpIsRunning();
-
+        boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
+        
         if (((KafkaBrokerDriver)getDriver()).isJmxEnabled()) {
             jmxFeed = JmxFeed.builder()
                 .entity(this)
@@ -99,35 +100,43 @@ public class KafkaBrokerImpl extends SoftwareProcessImpl implements MessageBroke
                 .pollAttribute(new JmxAttributePollConfig<Long>(FETCH_REQUEST_COUNT)
                         .objectName(SOCKET_SERVER_STATS_MBEAN)
                         .attributeName("NumFetchRequests")
-                        .onException(Functions.constant(-1l)))
+                        .onException(Functions.constant(-1l))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(TOTAL_FETCH_TIME)
                         .objectName(SOCKET_SERVER_STATS_MBEAN)
                         .attributeName("TotalFetchRequestMs")
-                        .onException(Functions.constant(-1l)))
+                        .onException(Functions.constant(-1l))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Double>(MAX_FETCH_TIME)
                         .objectName(SOCKET_SERVER_STATS_MBEAN)
                         .attributeName("MaxFetchRequestMs")
-                        .onException(Functions.constant(-1.0d)))
+                        .onException(Functions.constant(-1.0d))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(PRODUCE_REQUEST_COUNT)
                         .objectName(SOCKET_SERVER_STATS_MBEAN)
                         .attributeName("NumProduceRequests")
-                        .onException(Functions.constant(-1l)))
+                        .onException(Functions.constant(-1l))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(TOTAL_PRODUCE_TIME)
                         .objectName(SOCKET_SERVER_STATS_MBEAN)
                         .attributeName("TotalProduceRequestMs")
-                        .onException(Functions.constant(-1l)))
+                        .onException(Functions.constant(-1l))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Double>(MAX_PRODUCE_TIME)
                         .objectName(SOCKET_SERVER_STATS_MBEAN)
                         .attributeName("MaxProduceRequestMs")
-                        .onException(Functions.constant(-1.0d)))
+                        .onException(Functions.constant(-1.0d))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(BYTES_RECEIVED)
                         .objectName(SOCKET_SERVER_STATS_MBEAN)
                         .attributeName("TotalBytesRead")
-                        .onException(Functions.constant(-1l)))
+                        .onException(Functions.constant(-1l))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(BYTES_SENT)
                         .objectName(SOCKET_SERVER_STATS_MBEAN)
                         .attributeName("TotalBytesWritten")
-                        .onException(Functions.constant(-1l)))
+                        .onException(Functions.constant(-1l))
+                        .enabled(retrieveUsageMetrics))
                 .build();
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java b/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
index 9ccbec1..d67ce95 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBrokerImpl.java
@@ -129,7 +129,8 @@ public class QpidBrokerImpl extends JMSBrokerImpl<QpidQueue, QpidTopic> implemen
                                     }
                                     return true;
                                 }})
-                        .onException(Functions.constant(false)))
+                        .onException(Functions.constant(false))
+                        .suppressDuplicates(true))
                 .build();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java
index c9923ef..dedf875 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java
@@ -406,6 +406,8 @@ public class CassandraNodeImpl extends SoftwareProcessImpl implements CassandraN
         super.connectSensors();
 
         jmxHelper = new JmxHelper(this);
+        boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
+        
         jmxFeed = JmxFeed.builder()
                 .entity(this)
                 .period(3000, TimeUnit.MILLISECONDS)
@@ -493,27 +495,33 @@ public class CassandraNodeImpl extends SoftwareProcessImpl implements CassandraN
                 .pollAttribute(new JmxAttributePollConfig<Integer>(READ_ACTIVE)
                         .objectName(readStageMBean)
                         .attributeName("ActiveCount")
-                        .onException(Functions.constant((Integer)null)))
+                        .onException(Functions.constant((Integer)null))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(READ_PENDING)
                         .objectName(readStageMBean)
                         .attributeName("PendingTasks")
-                        .onException(Functions.constant((Long)null)))
+                        .onException(Functions.constant((Long)null))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(READ_COMPLETED)
                         .objectName(readStageMBean)
                         .attributeName("CompletedTasks")
-                        .onException(Functions.constant((Long)null)))
+                        .onException(Functions.constant((Long)null))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Integer>(WRITE_ACTIVE)
                         .objectName(mutationStageMBean)
                         .attributeName("ActiveCount")
-                        .onException(Functions.constant((Integer)null)))
+                        .onException(Functions.constant((Integer)null))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(WRITE_PENDING)
                         .objectName(mutationStageMBean)
                         .attributeName("PendingTasks")
-                        .onException(Functions.constant((Long)null)))
+                        .onException(Functions.constant((Long)null))
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Long>(WRITE_COMPLETED)
                         .objectName(mutationStageMBean)
                         .attributeName("CompletedTasks")
-                        .onException(Functions.constant((Long)null)))
+                        .onException(Functions.constant((Long)null))
+                        .enabled(retrieveUsageMetrics))
                 .build();
         
         functionFeed = FunctionFeed.builder()
@@ -543,8 +551,8 @@ public class CassandraNodeImpl extends SoftwareProcessImpl implements CassandraN
                                 setAttribute(SERVICE_UP,
                                         getAttribute(THRIFT_PORT_LATENCY)!=null && getAttribute(THRIFT_PORT_LATENCY)>=0 && 
                                         Boolean.TRUE.equals(getAttribute(SERVICE_UP_JMX)));
-                            }
-                        }))
+                            }})
+                        .enabled(retrieveUsageMetrics))
                 .build();
         
         jmxMxBeanFeed = JavaAppUtils.connectMXBeanSensors(this);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java
index 298b6b6..2f5bd36 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java
@@ -31,6 +31,8 @@ import brooklyn.entity.webapp.WebAppServiceMethods;
 import brooklyn.event.feed.http.HttpFeed;
 import brooklyn.event.feed.http.HttpPollConfig;
 import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.guava.Functionals;
 
 import com.google.common.base.Function;
 import com.google.common.base.Functions;
@@ -62,27 +64,28 @@ public class CouchDBNodeImpl extends SoftwareProcessImpl implements CouchDBNode
 
         connectServiceUpIsRunning();
 
+        boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
+        
         httpFeed = HttpFeed.builder()
                 .entity(this)
                 .period(500, TimeUnit.MILLISECONDS)
                 .baseUri(String.format("http://%s:%d/_stats", getAttribute(HOSTNAME), getHttpPort()))
                 .poll(new HttpPollConfig<Integer>(REQUEST_COUNT)
                         .onSuccess(HttpValueFunctions.jsonContents(new String[] { "httpd", "requests", "count" }, Integer.class))
-                        .onFailureOrException(Functions.constant(-1)))
+                        .onFailureOrException(Functions.constant(-1))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new HttpPollConfig<Integer>(ERROR_COUNT)
                         .onSuccess(HttpValueFunctions.jsonContents(new String[] { "httpd_status_codes", "404", "count" }, Integer.class))
-                        .onFailureOrException(Functions.constant(-1)))
+                        .onFailureOrException(Functions.constant(-1))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new HttpPollConfig<Integer>(TOTAL_PROCESSING_TIME)
                         .onSuccess(HttpValueFunctions.jsonContents(new String[] { "couchdb", "request_time", "count" }, Integer.class))
-                        .onFailureOrException(Functions.constant(-1)))
+                        .onFailureOrException(Functions.constant(-1))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new HttpPollConfig<Integer>(MAX_PROCESSING_TIME)
-                        .onSuccess(HttpValueFunctions.chain(HttpValueFunctions.jsonContents(new String[] { "couchdb", "request_time", "max" }, Double.class), new Function<Double, Integer>() {
-                            @Override
-                            public Integer apply(@Nullable Double input) {
-                                return Integer.valueOf(input.intValue());
-                            }
-                        }))
-                        .onFailureOrException(Functions.constant(-1)))
+                        .onSuccess(Functionals.chain(HttpValueFunctions.jsonContents(new String[] { "couchdb", "request_time", "max" }, Double.class), TypeCoercions.function(Integer.class)))
+                        .onFailureOrException(Functions.constant(-1))
+                        .enabled(retrieveUsageMetrics))
                 .build();
 
         WebAppServiceMethods.connectWebAppServerPolicies(this);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStoreImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStoreImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStoreImpl.java
index f556bcf..c2d559f 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStoreImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStoreImpl.java
@@ -64,7 +64,8 @@ public class RedisStoreImpl extends SoftwareProcessImpl implements RedisStore {
         if (!location.isPresent()) throw new IllegalStateException("Could not find SshMachineLocation in list of locations");
         SshMachineLocation machine = (SshMachineLocation) location.get();
         String statsCommand = getDriver().getRunDir() + "/bin/redis-cli -p " + getRedisPort() + " info stats";
-
+        boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
+        
         sshFeed = SshFeed.builder()
                 .entity(this)
                 .machine(machine)
@@ -72,31 +73,38 @@ public class RedisStoreImpl extends SoftwareProcessImpl implements RedisStore {
                 .poll(new SshPollConfig<Integer>(UPTIME)
                         .command(getDriver().getRunDir() + "/bin/redis-cli -p " + getRedisPort() + " info server")
                         .onFailureOrException(Functions.constant(-1))
-                        .onSuccess(infoFunction("uptime_in_seconds")))
+                        .onSuccess(infoFunction("uptime_in_seconds"))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new SshPollConfig<Integer>(TOTAL_CONNECTIONS_RECEIVED)
                         .command(statsCommand)
                         .onFailureOrException(Functions.constant(-1))
-                        .onSuccess(infoFunction("total_connections_received")))
+                        .onSuccess(infoFunction("total_connections_received"))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new SshPollConfig<Integer>(TOTAL_COMMANDS_PROCESSED)
                         .command(statsCommand)
                         .onFailureOrException(Functions.constant(-1))
-                        .onSuccess(infoFunction("total_commands_processed")))
+                        .onSuccess(infoFunction("total_commands_processed"))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new SshPollConfig<Integer>(EXPIRED_KEYS)
                         .command(statsCommand)
                         .onFailureOrException(Functions.constant(-1))
-                        .onSuccess(infoFunction("expired_keys")))
+                        .onSuccess(infoFunction("expired_keys"))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new SshPollConfig<Integer>(EVICTED_KEYS)
                         .command(statsCommand)
                         .onFailureOrException(Functions.constant(-1))
-                        .onSuccess(infoFunction("evicted_keys")))
+                        .onSuccess(infoFunction("evicted_keys"))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new SshPollConfig<Integer>(KEYSPACE_HITS)
                         .command(statsCommand)
                         .onFailureOrException(Functions.constant(-1))
-                        .onSuccess(infoFunction("keyspace_hits")))
+                        .onSuccess(infoFunction("keyspace_hits"))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new SshPollConfig<Integer>(KEYSPACE_MISSES)
                         .command(statsCommand)
                         .onFailureOrException(Functions.constant(-1))
-                        .onSuccess(infoFunction("keyspace_misses")))
+                        .onSuccess(infoFunction("keyspace_misses"))
+                        .enabled(retrieveUsageMetrics))
                 .build();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss6ServerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss6ServerImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss6ServerImpl.java
index 932fd44..7bfb6e6 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss6ServerImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss6ServerImpl.java
@@ -25,7 +25,9 @@ import java.util.concurrent.TimeUnit;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.enricher.Enrichers;
 import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.webapp.JavaWebAppSoftwareProcessImpl;
 import brooklyn.event.feed.jmx.JmxAttributePollConfig;
 import brooklyn.event.feed.jmx.JmxFeed;
@@ -60,24 +62,31 @@ public class JBoss6ServerImpl extends JavaWebAppSoftwareProcessImpl implements J
 
         String requestProcessorMbeanName = "jboss.web:type=GlobalRequestProcessor,name=http-*";
         String serverMbeanName = "jboss.system:type=Server";
-        
+        boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
+
         jmxFeed = JmxFeed.builder()
                 .entity(this)
                 .period(500, TimeUnit.MILLISECONDS)
+                .pollAttribute(new JmxAttributePollConfig<Boolean>(SERVICE_UP)
+                        // TODO instead of setting SERVICE_UP directly, want to use equivalent of 
+                        // addEnricher(Enrichers.builder().updatingMap(Attributes.SERVICE_NOT_UP_INDICATORS).key("serverMBean")...
+                        // but not supported in feed?
+                        .objectName(serverMbeanName)
+                        .attributeName("Started")
+                        .onException(Functions.constant(false))
+                        .suppressDuplicates(true))
                 .pollAttribute(new JmxAttributePollConfig<Integer>(ERROR_COUNT)
                         .objectName(requestProcessorMbeanName)
-                        .attributeName("errorCount"))
+                        .attributeName("errorCount")
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Integer>(REQUEST_COUNT)
                         .objectName(requestProcessorMbeanName)
-                        .attributeName("requestCount"))
+                        .attributeName("requestCount")
+                        .enabled(retrieveUsageMetrics))
                 .pollAttribute(new JmxAttributePollConfig<Integer>(TOTAL_PROCESSING_TIME)
                         .objectName(requestProcessorMbeanName)
-                        .attributeName("processingTime"))
-                .pollAttribute(new JmxAttributePollConfig<Boolean>(SERVICE_UP)
-                        .objectName(serverMbeanName)
-                        .attributeName("Started")
-                        .onException(Functions.constant(false))
-                        .suppressDuplicates(true))
+                        .attributeName("processingTime")
+                        .enabled(retrieveUsageMetrics))
                 .build();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
index 258b6be..cf6ba59 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
@@ -82,6 +82,7 @@ public class JBoss7ServerImpl extends JavaWebAppSoftwareProcessImpl implements J
         setAttribute(MANAGEMENT_URL, managementUri);
         log.debug("JBoss sensors for "+this+" reading from "+managementUri);
         Map<String, String> includeRuntimeUriVars = ImmutableMap.of("include-runtime","true");
+        boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
         
         httpFeed = HttpFeed.builder()
                 .entity(this)
@@ -97,23 +98,29 @@ public class JBoss7ServerImpl extends JavaWebAppSoftwareProcessImpl implements J
                         .suppressDuplicates(true))
                 .poll(new HttpPollConfig<Integer>(REQUEST_COUNT)
                         .vars(includeRuntimeUriVars)
-                        .onSuccess(HttpValueFunctions.jsonContents("requestCount", Integer.class)))
+                        .onSuccess(HttpValueFunctions.jsonContents("requestCount", Integer.class))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new HttpPollConfig<Integer>(ERROR_COUNT)
                         .vars(includeRuntimeUriVars)
-                        .onSuccess(HttpValueFunctions.jsonContents("errorCount", Integer.class)))
+                        .onSuccess(HttpValueFunctions.jsonContents("errorCount", Integer.class))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new HttpPollConfig<Integer>(TOTAL_PROCESSING_TIME)
                         .vars(includeRuntimeUriVars)
-                        .onSuccess(HttpValueFunctions.jsonContents("processingTime", Integer.class)))
+                        .onSuccess(HttpValueFunctions.jsonContents("processingTime", Integer.class))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new HttpPollConfig<Integer>(MAX_PROCESSING_TIME)
                         .vars(includeRuntimeUriVars)
-                        .onSuccess(HttpValueFunctions.jsonContents("maxTime", Integer.class)))
+                        .onSuccess(HttpValueFunctions.jsonContents("maxTime", Integer.class))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new HttpPollConfig<Long>(BYTES_RECEIVED)
                         .vars(includeRuntimeUriVars)
                         // jboss seems to report 0 even if it has received lots of requests; dunno why.
-                        .onSuccess(HttpValueFunctions.jsonContents("bytesReceived", Long.class)))
+                        .onSuccess(HttpValueFunctions.jsonContents("bytesReceived", Long.class))
+                        .enabled(retrieveUsageMetrics))
                 .poll(new HttpPollConfig<Long>(BYTES_SENT)
                         .vars(includeRuntimeUriVars)
-                        .onSuccess(HttpValueFunctions.jsonContents("bytesSent", Long.class)))
+                        .onSuccess(HttpValueFunctions.jsonContents("bytesSent", Long.class))
+                        .enabled(retrieveUsageMetrics))
                 .build();
         
         connectServiceUp();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/webapp/src/main/java/brooklyn/entity/webapp/tomcat/TomcatServerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/tomcat/TomcatServerImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/tomcat/TomcatServerImpl.java
index 929d120..e5b5ac0 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/tomcat/TomcatServerImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/tomcat/TomcatServerImpl.java
@@ -56,28 +56,35 @@ public class TomcatServerImpl extends JavaWebAppSoftwareProcessImpl implements T
 
             Integer port = isHttpsEnabled() ? getAttribute(HTTPS_PORT) : getAttribute(HTTP_PORT);
             String connectorMbeanName = format("Catalina:type=Connector,port=%s", port);
+            boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
 
             jmxWebFeed = JmxFeed.builder()
                     .entity(this)
                     .period(3000, TimeUnit.MILLISECONDS)
-                    .pollAttribute(new JmxAttributePollConfig<Integer>(ERROR_COUNT)
-                            .objectName(requestProcessorMbeanName)
-                            .attributeName("errorCount"))
-                    .pollAttribute(new JmxAttributePollConfig<Integer>(REQUEST_COUNT)
-                            .objectName(requestProcessorMbeanName)
-                            .attributeName("requestCount"))
-                    .pollAttribute(new JmxAttributePollConfig<Integer>(TOTAL_PROCESSING_TIME)
-                            .objectName(requestProcessorMbeanName)
-                            .attributeName("processingTime"))
-                    .pollAttribute(new JmxAttributePollConfig<String>(CONNECTOR_STATUS)
-                            .objectName(connectorMbeanName)
-                            .attributeName("stateName"))
                     .pollAttribute(new JmxAttributePollConfig<Boolean>(SERVICE_PROCESS_IS_RUNNING)
+                            // TODO Want to use something different from SERVICE_PROCESS_IS_RUNNING,
+                            // to indicate this is jmx MBean's reported state (or failure to connect)
                             .objectName(connectorMbeanName)
                             .attributeName("stateName")
                             .onSuccess(Functions.forPredicate(Predicates.<Object>equalTo("STARTED")))
                             .setOnFailureOrException(false)
                             .suppressDuplicates(true))
+                    .pollAttribute(new JmxAttributePollConfig<String>(CONNECTOR_STATUS)
+                            .objectName(connectorMbeanName)
+                            .attributeName("stateName")
+                            .suppressDuplicates(true))
+                    .pollAttribute(new JmxAttributePollConfig<Integer>(ERROR_COUNT)
+                            .objectName(requestProcessorMbeanName)
+                            .attributeName("errorCount")
+                            .enabled(retrieveUsageMetrics))
+                    .pollAttribute(new JmxAttributePollConfig<Integer>(REQUEST_COUNT)
+                            .objectName(requestProcessorMbeanName)
+                            .attributeName("requestCount")
+                            .enabled(retrieveUsageMetrics))
+                    .pollAttribute(new JmxAttributePollConfig<Integer>(TOTAL_PROCESSING_TIME)
+                            .objectName(requestProcessorMbeanName)
+                            .attributeName("processingTime")
+                            .enabled(retrieveUsageMetrics))
                     .build();
 
             jmxAppFeed = JavaAppUtils.connectMXBeanSensors(this);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b4166230/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerDisableRetrieveUsageMetricsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerDisableRetrieveUsageMetricsIntegrationTest.java b/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerDisableRetrieveUsageMetricsIntegrationTest.java
new file mode 100644
index 0000000..0761af6
--- /dev/null
+++ b/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerDisableRetrieveUsageMetricsIntegrationTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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 brooklyn.entity.webapp.tomcat;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppLiveTestSupport;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.test.Asserts;
+import brooklyn.test.EntityTestUtils;
+
+import com.google.common.collect.ImmutableList;
+
+public class TomcatServerDisableRetrieveUsageMetricsIntegrationTest extends BrooklynAppLiveTestSupport {
+    
+    // Note we test the default and the disabled with two entities, in the same method.
+    // This piggie-backs off the necessary length of time required for the default entity
+    // to have its metrics set; we then assert that the other entity does not have its set.
+    @Test(groups="Integration")
+    public void testDisableRetrievalOfUsageMetrics() throws Exception {
+        LocalhostMachineProvisioningLocation loc = app.newLocalhostProvisioningLocation();
+        final TomcatServer tc1 = app.createAndManageChild(EntitySpec.create(TomcatServer.class)
+                .configure(SoftwareProcess.RETRIEVE_USAGE_METRICS, false));
+        final TomcatServer tc2 = app.createAndManageChild(EntitySpec.create(TomcatServer.class));
+        
+        tc1.start(ImmutableList.of(loc));
+        tc2.start(ImmutableList.of(loc));
+
+        // tc2 uses defaults, so will include usage metrics
+        Asserts.succeedsEventually(new Runnable() {
+            public void run() {
+                assertNotNull(tc2.getAttribute(TomcatServer.CONNECTOR_STATUS));
+                assertNotNull(tc2.getAttribute(TomcatServer.ERROR_COUNT));
+                assertNotNull(tc2.getAttribute(TomcatServer.REQUEST_COUNT));
+                assertNotNull(tc2.getAttribute(TomcatServer.TOTAL_PROCESSING_TIME));
+            }});
+
+        // tc1 should have status info, but not usage metrics
+        EntityTestUtils.assertAttributeEventuallyNonNull(tc1, TomcatServer.CONNECTOR_STATUS);
+        EntityTestUtils.assertAttributeEqualsContinually(tc1, TomcatServer.ERROR_COUNT, null);
+        assertNull(tc1.getAttribute(TomcatServer.REQUEST_COUNT));
+        assertNull(tc1.getAttribute(TomcatServer.TOTAL_PROCESSING_TIME));
+    }
+}