Repository: brooklyn-server
Updated Branches:
  refs/heads/master c7731a4fa -> a58ba05c7


Added a percentage enricher


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

Branch: refs/heads/master
Commit: 1b7c6be62592421ea2144a6bd15a0c635bf544a2
Parents: a941963
Author: graeme.miller <[email protected]>
Authored: Thu Jun 23 14:34:21 2016 +0100
Committer: graeme.miller <[email protected]>
Committed: Fri Jun 24 14:16:45 2016 +0100

----------------------------------------------------------------------
 .../enricher/stock/PercentageEnricher.java      | 127 +++++++++
 .../enricher/stock/PercentageEnricherTest.java  | 275 +++++++++++++++++++
 .../entity/machine/AddMachineMetrics.java       |   8 +
 .../entity/machine/MachineAttributes.java       |   6 +
 4 files changed, 416 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b7c6be6/core/src/main/java/org/apache/brooklyn/enricher/stock/PercentageEnricher.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/enricher/stock/PercentageEnricher.java 
b/core/src/main/java/org/apache/brooklyn/enricher/stock/PercentageEnricher.java
new file mode 100644
index 0000000..9bc7e7e
--- /dev/null
+++ 
b/core/src/main/java/org/apache/brooklyn/enricher/stock/PercentageEnricher.java
@@ -0,0 +1,127 @@
+/*
+ * 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.brooklyn.enricher.stock;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.reflect.TypeToken;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.SensorEvent;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.enricher.AbstractEnricher;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
+
+public class PercentageEnricher extends AbstractEnricher implements 
SensorEventListener<Number> {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(PercentageEnricher.class);
+
+    public static final ConfigKey<AttributeSensor<? extends Number>> 
SOURCE_CURRENT_SENSOR = ConfigKeys.newConfigKey(new TypeToken<AttributeSensor<? 
extends Number>>() {
+    }, "enricher.sourceCurrentSensor");
+
+    public static final ConfigKey<AttributeSensor<? extends Number>> 
SOURCE_TOTAL_SENSOR = ConfigKeys.newConfigKey(new TypeToken<AttributeSensor<? 
extends Number>>() {
+    }, "enricher.sourceTotalSensor");
+
+    public static final ConfigKey<AttributeSensor<Double>> TARGET_SENSOR = 
ConfigKeys.newConfigKey(new TypeToken<AttributeSensor<Double>>() {
+    }, "enricher.targetSensor");
+
+    public static final ConfigKey<Entity> PRODUCER = 
ConfigKeys.newConfigKey(Entity.class, "enricher.producer");
+
+    protected AttributeSensor<? extends Number> sourceCurrentSensor;
+    protected AttributeSensor<? extends Number> sourceTotalSensor;
+    protected AttributeSensor<Double> targetSensor;
+    protected Entity producer;
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    @Override
+    public void setEntity(EntityLocal entity) {
+        super.setEntity(entity);
+
+        this.sourceCurrentSensor = getConfig(SOURCE_CURRENT_SENSOR);
+        this.sourceTotalSensor = getConfig(SOURCE_TOTAL_SENSOR);
+        this.targetSensor = getConfig(TARGET_SENSOR);
+        this.producer = getConfig(PRODUCER) == null ? entity : 
getConfig(PRODUCER);
+
+        if (sourceCurrentSensor == null) {
+            throw new IllegalArgumentException("Enricher " + 
JavaClassNames.simpleClassName(this) + " has no " + 
SOURCE_CURRENT_SENSOR.getName());
+        }
+        if (sourceTotalSensor == null) {
+            throw new IllegalArgumentException("Enricher " + 
JavaClassNames.simpleClassName(this) + " has no " + 
SOURCE_TOTAL_SENSOR.getName());
+        }
+        if (targetSensor == null) {
+            throw new IllegalArgumentException("Enricher " + 
JavaClassNames.simpleClassName(this) + " has no " + TARGET_SENSOR.getName());
+        }
+
+        if (targetSensor.equals(sourceCurrentSensor)) {
+            throw new IllegalArgumentException("Enricher " + 
JavaClassNames.simpleClassName(this) + " detect cycle with " + 
SOURCE_CURRENT_SENSOR.getName());
+        }
+        if (targetSensor.equals(sourceTotalSensor)) {
+            throw new IllegalArgumentException("Enricher " + 
JavaClassNames.simpleClassName(this) + " detect cycle with " + 
SOURCE_TOTAL_SENSOR.getName());
+        }
+
+        subscriptions().subscribe(MutableMap.of("notifyOfInitialValue", true), 
producer, sourceCurrentSensor, this);
+        subscriptions().subscribe(MutableMap.of("notifyOfInitialValue", true), 
producer, sourceTotalSensor, this);
+
+    }
+
+    @Override
+    public void onEvent(SensorEvent<Number> event) {
+        Number current = producer.sensors().get(sourceCurrentSensor);
+        Number total = producer.sensors().get(sourceTotalSensor);
+        Double result = null;
+
+        if (current == null) {
+            LOG.debug("Current is null, returning");
+            return;
+        }
+
+        if (total == null || total.equals(0)) {
+            LOG.debug("total {" + total + "} is null or zero, returning");
+            return;
+        }
+
+        Double currentDouble = current.doubleValue();
+        Double totalDouble = total.doubleValue();
+
+        if (currentDouble > totalDouble) {
+            LOG.debug("Current is greater than total, returning");
+            return;
+        }
+
+        if (currentDouble < 0 || totalDouble < 0) {
+            LOG.debug("Current {"+currentDouble+"}  or total {"+totalDouble+"} 
is negative, returning");
+            return;
+        }
+
+        if (current.equals(0)) {
+            LOG.debug("current is zero, setting percent to zero");
+            result = 0d;
+        } else {
+            result = currentDouble / totalDouble;
+        }
+
+        emit(targetSensor, result);
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b7c6be6/core/src/test/java/org/apache/brooklyn/enricher/stock/PercentageEnricherTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/enricher/stock/PercentageEnricherTest.java
 
b/core/src/test/java/org/apache/brooklyn/enricher/stock/PercentageEnricherTest.java
new file mode 100644
index 0000000..575970f
--- /dev/null
+++ 
b/core/src/test/java/org/apache/brooklyn/enricher/stock/PercentageEnricherTest.java
@@ -0,0 +1,275 @@
+/*
+ * 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.brooklyn.enricher.stock;
+
+import static org.testng.Assert.assertEquals;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.EnricherSpec;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.location.SimulatedLocation;
+import org.apache.brooklyn.core.sensor.BasicAttributeSensor;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+
+public class PercentageEnricherTest extends BrooklynAppUnitTestSupport {
+
+    public static final Logger log = 
LoggerFactory.getLogger(PercentageEnricherTest.class);
+
+    AttributeSensor<Double> currentSensor;
+    AttributeSensor<Double> totalSensor;
+    AttributeSensor<Double> targetSensor;
+
+    @BeforeMethod(alwaysRun = true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        currentSensor = new BasicAttributeSensor<Double>(Double.class, 
"current");
+        totalSensor = new BasicAttributeSensor<Double>(Double.class, "total");
+        targetSensor = new BasicAttributeSensor<Double>(Double.class, 
"target");
+
+        app.start(ImmutableList.of(new SimulatedLocation()));
+    }
+
+    private void addEnricher() {
+        app.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, 
currentSensor)
+                .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor)
+                .configure(PercentageEnricher.TARGET_SENSOR, targetSensor));
+    }
+
+    @Test
+    public void vanillaTest() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, 50d);
+        app.sensors().set(totalSensor, 100d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d);
+    }
+
+    @Test
+    public void currentNullTest() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, null);
+        app.sensors().set(totalSensor, 100d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null);
+    }
+
+    @Test
+    public void totalNullTest() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, 50d);
+        app.sensors().set(totalSensor, null);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null);
+    }
+
+    @Test
+    public void bothInputNullTest() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, null);
+        app.sensors().set(totalSensor, null);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null);
+    }
+
+    @Test
+    public void currentZeroTest() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, 0d);
+        app.sensors().set(totalSensor, 100d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0d);
+    }
+
+    @Test
+    public void totalZeroTest() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, 50d);
+        app.sensors().set(totalSensor, 0d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null);
+    }
+
+    @Test
+    public void totalLessThanCurrentTest() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, 50d);
+        app.sensors().set(totalSensor, 25d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null);
+    }
+
+    @Test
+    public void oneHundredPercentTest() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, 50d);
+        app.sensors().set(totalSensor, 50d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 100d);
+    }
+
+    @Test
+    public void negativeCurrent() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, -50d);
+        app.sensors().set(totalSensor, 100d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null);
+    }
+
+    @Test
+    public void negativeTotal() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, 50d);
+        app.sensors().set(totalSensor, -100d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null);
+    }
+
+    @Test
+    public void bothSourceNegative() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, -50d);
+        app.sensors().set(totalSensor, -100d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null);
+    }
+
+    @Test
+    public void totalDoubleMaxValue() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, Double.MAX_VALUE);
+        app.sensors().set(totalSensor, Double.MAX_VALUE);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 100d);
+    }
+
+    //SETUP TESTS
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void totalNoCurrentSensor() {
+        app.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor)
+                .configure(PercentageEnricher.TARGET_SENSOR, targetSensor));
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void totalNoTotalSensor() {
+        app.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, 
currentSensor)
+                .configure(PercentageEnricher.TARGET_SENSOR, targetSensor));
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void totalNoTargetSensor() {
+        app.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, 
currentSensor)
+                .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, 
totalSensor));
+    }
+
+    @Test
+    public void testDifferentProducer() {
+        EntitySpec<TestApplication> appSpec = 
EntitySpec.create(TestApplication.class)
+                .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, 
shouldSkipOnBoxBaseDirResolution());
+
+        TestApplication producer = 
mgmt.getEntityManager().createEntity(appSpec);
+
+        app.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, 
currentSensor)
+                .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor)
+                .configure(PercentageEnricher.TARGET_SENSOR, targetSensor)
+                .configure(PercentageEnricher.PRODUCER, producer)
+        );
+
+        producer.sensors().set(currentSensor, 25d);
+        producer.sensors().set(totalSensor, 50d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d);
+        EntityAsserts.assertAttributeEqualsEventually(producer, targetSensor, 
null);
+    }
+
+    @Test
+    public void testLong() {
+        AttributeSensor<Long> currentSensor = new 
BasicAttributeSensor<Long>(Long.class, "current");
+        AttributeSensor<Long> totalSensor = new 
BasicAttributeSensor<Long>(Long.class, "total");
+
+        app.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, 
currentSensor)
+                .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor)
+                .configure(PercentageEnricher.TARGET_SENSOR, targetSensor)
+        );
+
+        app.sensors().set(currentSensor, 25l);
+        app.sensors().set(totalSensor, 50l);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d);
+    }
+
+    @Test
+    public void testInteger() {
+        AttributeSensor<Integer> currentSensor = new 
BasicAttributeSensor<Integer>(Integer.class, "current");
+        AttributeSensor<Integer> totalSensor = new 
BasicAttributeSensor<Integer>(Integer.class, "total");
+
+        app.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, 
currentSensor)
+                .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor)
+                .configure(PercentageEnricher.TARGET_SENSOR, targetSensor)
+        );
+
+        app.sensors().set(currentSensor, 25);
+        app.sensors().set(totalSensor, 50);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d);
+    }
+
+    @Test
+    public void testFloat() {
+        AttributeSensor<Float> currentSensor = new 
BasicAttributeSensor<Float>(Float.class, "current");
+        AttributeSensor<Float> totalSensor = new 
BasicAttributeSensor<Float>(Float.class, "total");
+
+        app.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, 
currentSensor)
+                .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor)
+                .configure(PercentageEnricher.TARGET_SENSOR, targetSensor)
+        );
+
+        app.sensors().set(currentSensor, 25f);
+        app.sensors().set(totalSensor, 50f);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d);
+    }
+
+    @Test
+    public void validThenInvalid() {
+        addEnricher();
+
+        app.sensors().set(currentSensor, 50d);
+        app.sensors().set(totalSensor, 100d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d);
+        app.sensors().set(totalSensor, 0d);
+        EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b7c6be6/software/base/src/main/java/org/apache/brooklyn/entity/machine/AddMachineMetrics.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/main/java/org/apache/brooklyn/entity/machine/AddMachineMetrics.java
 
b/software/base/src/main/java/org/apache/brooklyn/entity/machine/AddMachineMetrics.java
index e118b93..a61d4ee 100644
--- 
a/software/base/src/main/java/org/apache/brooklyn/entity/machine/AddMachineMetrics.java
+++ 
b/software/base/src/main/java/org/apache/brooklyn/entity/machine/AddMachineMetrics.java
@@ -35,6 +35,8 @@ import org.apache.brooklyn.api.entity.EntityInitializer;
 import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.enricher.stock.PercentageEnricher;
+import org.apache.brooklyn.enricher.stock.Transformer;
 import org.apache.brooklyn.enricher.stock.YamlRollingTimeWindowMeanEnricher;
 import org.apache.brooklyn.enricher.stock.YamlTimeWeightedDeltaEnricher;
 import org.apache.brooklyn.entity.software.base.SoftwareProcess;
@@ -75,6 +77,12 @@ public class AddMachineMetrics implements EntityInitializer {
         
entity.enrichers().add(EnricherSpec.create(YamlRollingTimeWindowMeanEnricher.class)
                 .configure(YamlRollingTimeWindowMeanEnricher.SOURCE_SENSOR, 
MachineAttributes.USED_MEMORY_DELTA_PER_SECOND_LAST)
                 .configure(YamlRollingTimeWindowMeanEnricher.TARGET_SENSOR, 
MachineAttributes.USED_MEMORY_DELTA_PER_SECOND_IN_WINDOW));
+
+        entity.enrichers().add(EnricherSpec.create(PercentageEnricher.class)
+                .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, 
MachineAttributes.USED_MEMORY)
+                .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, 
MachineAttributes.TOTAL_MEMORY)
+                .configure(PercentageEnricher.TARGET_SENSOR, 
MachineAttributes.USED_MEMORY_PERCENT));
+
     }
 
     public static SshFeed createMachineMetricsFeed(EntityLocal entity) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b7c6be6/software/base/src/main/java/org/apache/brooklyn/entity/machine/MachineAttributes.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/main/java/org/apache/brooklyn/entity/machine/MachineAttributes.java
 
b/software/base/src/main/java/org/apache/brooklyn/entity/machine/MachineAttributes.java
index ff3ef86..fc852b6 100644
--- 
a/software/base/src/main/java/org/apache/brooklyn/entity/machine/MachineAttributes.java
+++ 
b/software/base/src/main/java/org/apache/brooklyn/entity/machine/MachineAttributes.java
@@ -56,6 +56,9 @@ public class MachineAttributes {
     public static final AttributeSensor<Double> 
USED_MEMORY_DELTA_PER_SECOND_LAST = 
Sensors.newDoubleSensor("memory.used.delta", "Change in memory usage per 
second");
     public static final AttributeSensor<Double> 
USED_MEMORY_DELTA_PER_SECOND_IN_WINDOW = 
Sensors.newDoubleSensor("memory.used.windowed", "Average change in memory usage 
over 30s");
 
+    public static final AttributeSensor<Double> USED_MEMORY_PERCENT = 
Sensors.newDoubleSensor("memory.used.percent", "The percentage of memory used");
+    public static final AttributeSensor<Double> AVERAGE_USED_MEMORY_PERCENT = 
Sensors.newDoubleSensor("memory.used.percent.average", "Average percentage of 
memory used across the cluster");
+
     private static AtomicBoolean initialized = new AtomicBoolean(false);
 
     /**
@@ -75,6 +78,9 @@ public class MachineAttributes {
         RendererHints.register(CPU_USAGE, 
RendererHints.displayValue(MathFunctions.percent(2)));
         RendererHints.register(AVERAGE_CPU_USAGE, 
RendererHints.displayValue(MathFunctions.percent(2)));
 
+        RendererHints.register(USED_MEMORY_PERCENT, 
RendererHints.displayValue(MathFunctions.percent(2)));
+        RendererHints.register(AVERAGE_USED_MEMORY_PERCENT, 
RendererHints.displayValue(MathFunctions.percent(2)));
+
         RendererHints.register(FREE_MEMORY, 
RendererHints.displayValue(Functionals.chain(MathFunctions.times(1000L), 
ByteSizeStrings.metric())));
         RendererHints.register(TOTAL_MEMORY, 
RendererHints.displayValue(Functionals.chain(MathFunctions.times(1000L), 
ByteSizeStrings.metric())));
         RendererHints.register(USED_MEMORY, 
RendererHints.displayValue(Functionals.chain(MathFunctions.times(1000L), 
ByteSizeStrings.metric())));

Reply via email to