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));
+    }
+
+}

Reply via email to