Repository: brooklyn-server Updated Branches: refs/heads/master 495b1d335 -> 3f02cccac
Add DurationSinceSensor Records the duration since an event. Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/d2cdb41c Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/d2cdb41c Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/d2cdb41c Branch: refs/heads/master Commit: d2cdb41c7a3e01a26002799d59fe68836d1fd7d5 Parents: 0a5f3e1 Author: Sam Corbett <sam.corb...@cloudsoftcorp.com> Authored: Wed Feb 10 17:12:24 2016 +0000 Committer: Sam Corbett <sam.corb...@cloudsoftcorp.com> Committed: Fri Feb 12 13:36:38 2016 +0000 ---------------------------------------------------------------------- .../core/sensor/DurationSinceSensor.java | 108 +++++++++++++++++++ .../core/sensor/http/HttpRequestSensor.java | 5 +- .../core/sensor/DurationSinceSensorTest.java | 73 +++++++++++++ 3 files changed, 184 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d2cdb41c/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java new file mode 100644 index 0000000..9dc89a5 --- /dev/null +++ b/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java @@ -0,0 +1,108 @@ +/* + * 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.core.sensor; + +import java.util.concurrent.Callable; + +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.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.effector.AddSensor; +import org.apache.brooklyn.feed.function.FunctionFeed; +import org.apache.brooklyn.feed.function.FunctionPollConfig; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.time.Duration; + +import com.google.common.base.Supplier; +import com.google.common.reflect.TypeToken; + +public class DurationSinceSensor extends AddSensor<Duration> { + + private static final Supplier<Long> CURRENT_TIME_SUPPLIER = new CurrentTimeSupplier(); + + public static final ConfigKey<Supplier<Long>> EPOCH_SUPPLIER = ConfigKeys.builder(new TypeToken<Supplier<Long>>() {}) + .name("duration.since.epochsupplier") + .description("The source of time from which durations are measured. Defaults to System.currentTimeMillis.") + .defaultValue(CURRENT_TIME_SUPPLIER) + .build(); + + public static final ConfigKey<Supplier<Long>> TIME_SUPPLIER = ConfigKeys.builder(new TypeToken<Supplier<Long>>() {}) + .name("duration.since.timesupplier") + .description("The source of the current time. Defaults to System.currentTimeMillis.") + .defaultValue(CURRENT_TIME_SUPPLIER) + .build(); + + private final Supplier<Long> epochSupplier; + private final Supplier<Long> timeSupplier; + private final AttributeSensor<Long> epochSensor; + + public DurationSinceSensor(ConfigBag params) { + super(params); + epochSupplier = params.get(EPOCH_SUPPLIER); + timeSupplier = params.get(TIME_SUPPLIER); + epochSensor = Sensors.newLongSensor(sensor.getName() + ".epoch"); + } + + @Override + public void apply(final EntityLocal entity) { + super.apply(entity); + + if (entity.sensors().get(epochSensor) == null) { + entity.sensors().set(epochSensor, epochSupplier.get()); + } + + FunctionFeed feed = FunctionFeed.builder() + .entity(entity) + .poll(new FunctionPollConfig<>(sensor).callable(new UpdateTimeSince(entity))) + .period(period) + .build(); + + entity.addFeed(feed); + } + + private static class CurrentTimeSupplier implements Supplier<Long> { + @Override + public Long get() { + return System.currentTimeMillis(); + } + } + + private class UpdateTimeSince implements Callable<Duration> { + private final Entity entity; + + private UpdateTimeSince(Entity entity) { + this.entity = entity; + } + + @Override + public Duration call() { + Long referencePoint = entity.sensors().get(epochSensor); + // Defensive check. Someone has done something silly if this is false. + if (referencePoint != null) { + return Duration.millis(timeSupplier.get() - referencePoint); + } else { + throw new IllegalStateException("Cannot calculate duration since sensor: " + + entity + " missing required value for " + epochSensor); + } + } + } +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d2cdb41c/core/src/main/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensor.java index 8541fd1..dea44d3 100644 --- a/core/src/main/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensor.java +++ b/core/src/main/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensor.java @@ -43,7 +43,6 @@ import com.google.common.base.Supplier; * {@link JSONObject} from a JSON response in order to populate the sensor with the data at the {@code jsonPath}. * * @see SshCommandSensor - * @see JmxAttributeSensor */ @Beta public final class HttpRequestSensor<T> extends AddSensor<T> { @@ -88,10 +87,12 @@ public final class HttpRequestSensor<T> extends AddSensor<T> { .onSuccess(HttpValueFunctions.<T>jsonContentsFromPath(jsonPath)) .period(period); - HttpFeed.builder().entity(entity) + HttpFeed feed = HttpFeed.builder().entity(entity) .baseUri(uri) .credentialsIfNotNull(username, password) .poll(pollConfig) .build(); + + entity.addFeed(feed); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d2cdb41c/core/src/test/java/org/apache/brooklyn/core/sensor/DurationSinceSensorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/sensor/DurationSinceSensorTest.java b/core/src/test/java/org/apache/brooklyn/core/sensor/DurationSinceSensorTest.java new file mode 100644 index 0000000..f58fffd --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/core/sensor/DurationSinceSensorTest.java @@ -0,0 +1,73 @@ +/* + * 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.core.sensor; + +import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEqualsContinually; +import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEqualsEventually; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +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.core.effector.AddSensor; +import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.time.Duration; +import org.testng.annotations.Test; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableMap; + +public class DurationSinceSensorTest extends BrooklynAppUnitTestSupport { + + @Test + public void testSensorAddedAndUpdated() { + final AtomicLong ticker = new AtomicLong(0); + Supplier<Long> timeSupplier = new Supplier<Long>() { + @Override + public Long get() { + return ticker.get(); + } + }; + Entity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) + .addInitializer(new DurationSinceSensor(ConfigBag.newInstance(ImmutableMap.of( + AddSensor.SENSOR_NAME, "sensor", + AddSensor.SENSOR_TYPE, Duration.class.getName(), + AddSensor.SENSOR_PERIOD, Duration.ONE_MILLISECOND, + DurationSinceSensor.EPOCH_SUPPLIER, Suppliers.ofInstance(0L), + DurationSinceSensor.TIME_SUPPLIER, timeSupplier))))); + + final Map<?, ?> timeout = ImmutableMap.of("timeout", Duration.millis(10)); + final AttributeSensor<Duration> duration = Sensors.newSensor(Duration.class, "sensor"); + assertAttributeEqualsEventually(entity, duration, Duration.millis(0)); + assertAttributeEqualsContinually(timeout, entity, duration, Duration.millis(0)); + ticker.incrementAndGet(); + assertAttributeEqualsEventually(entity, duration, Duration.millis(1)); + assertAttributeEqualsContinually(timeout, entity, duration, Duration.millis(1)); + ticker.incrementAndGet(); + assertAttributeEqualsEventually(entity, duration, Duration.millis(2)); + assertAttributeEqualsContinually(timeout, entity, duration, Duration.millis(2)); + } + +}