PercentageEnricher updates
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/bcad2f0b Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/bcad2f0b Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/bcad2f0b Branch: refs/heads/master Commit: bcad2f0b3944918902fd5b24d6f8968a6782a70b Parents: 1b7c6be Author: graeme.miller <[email protected]> Authored: Wed Jun 29 11:50:53 2016 +0100 Committer: graeme.miller <[email protected]> Committed: Wed Jun 29 11:50:53 2016 +0100 ---------------------------------------------------------------------- .../enricher/stock/PercentageEnricher.java | 86 ++++++++---------- .../enricher/stock/PercentageEnricherTest.java | 96 +++++++++++++++----- .../entity/machine/AddMachineMetrics.java | 3 +- 3 files changed, 114 insertions(+), 71 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bcad2f0b/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 index 9bc7e7e..cd827d9 100644 --- a/core/src/main/java/org/apache/brooklyn/enricher/stock/PercentageEnricher.java +++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/PercentageEnricher.java @@ -21,6 +21,7 @@ package org.apache.brooklyn.enricher.stock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Preconditions; import com.google.common.reflect.TypeToken; import org.apache.brooklyn.api.entity.Entity; @@ -30,22 +31,38 @@ 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.config.render.RendererHints; import org.apache.brooklyn.core.enricher.AbstractEnricher; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.javalang.JavaClassNames; +import org.apache.brooklyn.util.math.MathFunctions; +/** + * Enricher that is configured with two numerical sensors; a current and a total. + * The Enricher subscribes to events from these sensors, and will emit the ratio + * of current to total as a target sensor. + */ 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"); + @SuppressWarnings("serial") + public static final ConfigKey<AttributeSensor<? extends Number>> SOURCE_CURRENT_SENSOR = ConfigKeys.newConfigKey( + new TypeToken<AttributeSensor<? extends Number>>() {}, + "enricher.sourceCurrentSensor", + "The sensor from which to take the current value"); - public static final ConfigKey<AttributeSensor<? extends Number>> SOURCE_TOTAL_SENSOR = ConfigKeys.newConfigKey(new TypeToken<AttributeSensor<? extends Number>>() { - }, "enricher.sourceTotalSensor"); + @SuppressWarnings("serial") + public static final ConfigKey<AttributeSensor<? extends Number>> SOURCE_TOTAL_SENSOR = ConfigKeys.newConfigKey( + new TypeToken<AttributeSensor<? extends Number>>() {}, + "enricher.sourceTotalSensor", + "The sensor from which to take the total value"); - public static final ConfigKey<AttributeSensor<Double>> TARGET_SENSOR = ConfigKeys.newConfigKey(new TypeToken<AttributeSensor<Double>>() { - }, "enricher.targetSensor"); + @SuppressWarnings("serial") + public static final ConfigKey<AttributeSensor<Double>> TARGET_SENSOR = ConfigKeys.newConfigKey( + new TypeToken<AttributeSensor<Double>>() {}, + "enricher.targetSensor", + "The sensor on which to emit the ratio"); public static final ConfigKey<Entity> PRODUCER = ConfigKeys.newConfigKey(Entity.class, "enricher.producer"); @@ -59,68 +76,41 @@ public class PercentageEnricher extends AbstractEnricher implements SensorEventL 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); + sourceCurrentSensor = Preconditions.checkNotNull(getConfig(SOURCE_CURRENT_SENSOR), "Can't add Enricher %s to entity %s as it has no %s", JavaClassNames.simpleClassName(this), entity, SOURCE_CURRENT_SENSOR.getName()); + sourceTotalSensor = Preconditions.checkNotNull(getConfig(SOURCE_TOTAL_SENSOR), "Can't add Enricher %s to entity %s as it has no %s", JavaClassNames.simpleClassName(this), entity, SOURCE_TOTAL_SENSOR.getName()); + targetSensor = Preconditions.checkNotNull(getConfig(TARGET_SENSOR), "Can't add Enricher %s to entity %s as it has no %s", JavaClassNames.simpleClassName(this), entity, TARGET_SENSOR.getName()); + 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.equals(sourceCurrentSensor) && entity.equals(producer)) { + throw new IllegalArgumentException("Can't add Enricher " + JavaClassNames.simpleClassName(this) + " to entity "+entity+" as cycle detected with " + SOURCE_CURRENT_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()); + if (targetSensor.equals(sourceTotalSensor) && entity.equals(producer)) { + throw new IllegalArgumentException("Can't add Enricher " + JavaClassNames.simpleClassName(this) + " to entity "+entity+" as cycle detected with " + SOURCE_TOTAL_SENSOR.getName()); } subscriptions().subscribe(MutableMap.of("notifyOfInitialValue", true), producer, sourceCurrentSensor, this); subscriptions().subscribe(MutableMap.of("notifyOfInitialValue", true), producer, sourceTotalSensor, this); - + RendererHints.register(targetSensor, RendererHints.displayValue(MathFunctions.percent(2))); } @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; - } - + Number current = Preconditions.checkNotNull(producer.sensors().get(sourceCurrentSensor), "Can't calculate Enricher %s value for entity %s as current from producer %s is null", JavaClassNames.simpleClassName(this), entity, producer); + Number total = Preconditions.checkNotNull(producer.sensors().get(sourceTotalSensor), "Can't calculate Enricher %s value for entity %s as total from producer %s is null", JavaClassNames.simpleClassName(this), entity, producer); Double currentDouble = current.doubleValue(); Double totalDouble = total.doubleValue(); - if (currentDouble > totalDouble) { - LOG.debug("Current is greater than total, returning"); + if (totalDouble.compareTo(0d) == 0) { + LOG.debug("Can't calculate Enricher ({}) value for entity ({}) as total from producer ({}) is zero", new Object[]{JavaClassNames.simpleClassName(this), entity, producer}); return; } if (currentDouble < 0 || totalDouble < 0) { - LOG.debug("Current {"+currentDouble+"} or total {"+totalDouble+"} is negative, returning"); + LOG.debug("Can't calculate Enricher ({}) value for entity ({}) as Current ({}) or total ({}) value from producer ({}) is negative, returning", new Object[]{JavaClassNames.simpleClassName(this), entity, currentDouble, totalDouble, producer}); return; } - if (current.equals(0)) { - LOG.debug("current is zero, setting percent to zero"); - result = 0d; - } else { - result = currentDouble / totalDouble; - } + Double result = currentDouble / totalDouble; emit(targetSensor, result); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bcad2f0b/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 index 575970f..a3b6d17 100644 --- a/core/src/test/java/org/apache/brooklyn/enricher/stock/PercentageEnricherTest.java +++ b/core/src/test/java/org/apache/brooklyn/enricher/stock/PercentageEnricherTest.java @@ -18,8 +18,6 @@ */ 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; @@ -27,15 +25,15 @@ import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; +import org.apache.brooklyn.api.entity.Entity; 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; +import org.apache.brooklyn.core.test.entity.TestEntity; public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { @@ -69,7 +67,7 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { app.sensors().set(currentSensor, 50d); app.sensors().set(totalSensor, 100d); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); } @Test @@ -123,7 +121,7 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { app.sensors().set(currentSensor, 50d); app.sensors().set(totalSensor, 25d); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, null); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 2.0d); } @Test @@ -132,7 +130,7 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { app.sensors().set(currentSensor, 50d); app.sensors().set(totalSensor, 50d); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 100d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 1.0d); } @Test @@ -168,37 +166,80 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { app.sensors().set(currentSensor, Double.MAX_VALUE); app.sensors().set(totalSensor, Double.MAX_VALUE); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 100d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 1.0d); } - //SETUP TESTS - @Test(expectedExceptions = IllegalArgumentException.class) + + @Test(expectedExceptions = NullPointerException.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) + @Test(expectedExceptions = NullPointerException.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) + @Test(expectedExceptions = NullPointerException.class) public void totalNoTargetSensor() { app.enrichers().add(EnricherSpec.create(PercentageEnricher.class) .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, currentSensor) .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor)); } + @Test(expectedExceptions = IllegalArgumentException.class) + public void testTotalCycleNoProducer() { + app.enrichers().add(EnricherSpec.create(PercentageEnricher.class) + .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, currentSensor) + .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor) + .configure(PercentageEnricher.TARGET_SENSOR, totalSensor)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testCurrentCycleNoProducer() { + app.enrichers().add(EnricherSpec.create(PercentageEnricher.class) + .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, currentSensor) + .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor) + .configure(PercentageEnricher.TARGET_SENSOR, currentSensor)); + } + @Test - public void testDifferentProducer() { - EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class) - .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution()); + public void testNoCycleDifferentProducerTotal() { + Entity producer = app.addChild(EntitySpec.create(TestEntity.class)); - 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, totalSensor) + .configure(PercentageEnricher.PRODUCER, producer)); + + producer.sensors().set(currentSensor, 25d); + producer.sensors().set(totalSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, totalSensor, 0.5d); + } + + @Test + public void testNoCycleDifferentProducerCurrent() { + Entity producer = app.addChild(EntitySpec.create(TestEntity.class)); + + app.enrichers().add(EnricherSpec.create(PercentageEnricher.class) + .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, currentSensor) + .configure(PercentageEnricher.SOURCE_TOTAL_SENSOR, totalSensor) + .configure(PercentageEnricher.TARGET_SENSOR, currentSensor) + .configure(PercentageEnricher.PRODUCER, producer)); + + producer.sensors().set(currentSensor, 25d); + producer.sensors().set(totalSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, currentSensor, 0.5d); + } + + @Test + public void testDifferentProducer() { + Entity producer = app.addChild(EntitySpec.create(TestEntity.class)); app.enrichers().add(EnricherSpec.create(PercentageEnricher.class) .configure(PercentageEnricher.SOURCE_CURRENT_SENSOR, currentSensor) @@ -209,7 +250,7 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { producer.sensors().set(currentSensor, 25d); producer.sensors().set(totalSensor, 50d); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); EntityAsserts.assertAttributeEqualsEventually(producer, targetSensor, null); } @@ -226,7 +267,7 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { app.sensors().set(currentSensor, 25l); app.sensors().set(totalSensor, 50l); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); } @Test @@ -242,7 +283,7 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { app.sensors().set(currentSensor, 25); app.sensors().set(totalSensor, 50); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); } @Test @@ -258,7 +299,7 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { app.sensors().set(currentSensor, 25f); app.sensors().set(totalSensor, 50f); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); } @Test @@ -267,9 +308,20 @@ public class PercentageEnricherTest extends BrooklynAppUnitTestSupport { app.sensors().set(currentSensor, 50d); app.sensors().set(totalSensor, 100d); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); app.sensors().set(totalSensor, 0d); - EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 50d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); + } + + @Test + public void validThenNull() { + addEnricher(); + + app.sensors().set(currentSensor, 50d); + app.sensors().set(totalSensor, 100d); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); + app.sensors().set(totalSensor, null); + EntityAsserts.assertAttributeEqualsEventually(app, targetSensor, 0.5d); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bcad2f0b/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 a61d4ee..a310e8a 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 @@ -81,7 +81,8 @@ public class AddMachineMetrics implements EntityInitializer { 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)); + .configure(PercentageEnricher.TARGET_SENSOR, MachineAttributes.USED_MEMORY_PERCENT) + .configure(PercentageEnricher.SUPPRESS_DUPLICATES, true)); }
