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 2014/11/10 16:59:49 UTC
[3/4] incubator-brooklyn git commit: Read UsageListeners from config
in brooklyn.properties
Read UsageListeners from config in brooklyn.properties
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/7ee06ba3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/7ee06ba3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/7ee06ba3
Branch: refs/heads/master
Commit: 7ee06ba3c67a6d5ea1cb494b75aabb20b00c13f0
Parents: e315409
Author: Aled Sage <al...@gmail.com>
Authored: Fri Nov 7 19:44:34 2014 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Nov 10 11:39:53 2014 +0000
----------------------------------------------------------------------
.../management/internal/LocalUsageManager.java | 29 +++++
.../management/internal/UsageManager.java | 11 ++
.../management/usage/UsageListenerTest.java | 108 +++++++++++++++++++
3 files changed, 148 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7ee06ba3/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java b/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java
index 1bb4a8e..476ea3e 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java
@@ -20,6 +20,7 @@ package brooklyn.management.internal;
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -41,8 +42,12 @@ import brooklyn.location.basic.LocationInternal;
import brooklyn.management.usage.ApplicationUsage;
import brooklyn.management.usage.LocationUsage;
import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.javalang.Reflections;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -59,6 +64,23 @@ public class LocalUsageManager implements UsageManager {
private static final Logger log = LoggerFactory.getLogger(LocalUsageManager.class);
+ // Register a coercion from String->UsageListener, so that USAGE_LISTENERS defined in brooklyn.properties
+ // will be instantiated, given their class names.
+ static {
+ TypeCoercions.registerAdapter(String.class, UsageListener.class, new Function<String, UsageListener>() {
+ @Override public UsageListener apply(String input) {
+ // TODO Want to use classLoader = mgmt.getCatalog().getRootClassLoader();
+ ClassLoader classLoader = LocalUsageManager.class.getClassLoader();
+ Optional<Object> result = Reflections.invokeConstructorWithArgs(classLoader, input);
+ if (result.isPresent()) {
+ return (UsageListener) result.get();
+ } else {
+ throw new IllegalStateException("Failed to create UsageListener from class name '"+input+"' using no-arg constructor");
+ }
+ }
+ });
+ }
+
@VisibleForTesting
public static final String APPLICATION_USAGE_KEY = "usage-application";
@@ -77,6 +99,13 @@ public class LocalUsageManager implements UsageManager {
public LocalUsageManager(LocalManagementContext managementContext) {
this.managementContext = checkNotNull(managementContext, "managementContext");
+
+ Collection<UsageListener> listeners = managementContext.getBrooklynProperties().getConfig(UsageManager.USAGE_LISTENERS);
+ if (listeners != null) {
+ for (UsageListener listener : listeners) {
+ addUsageListener(listener);
+ }
+ }
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7ee06ba3/core/src/main/java/brooklyn/management/internal/UsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/UsageManager.java b/core/src/main/java/brooklyn/management/internal/UsageManager.java
index 35e602f..56a5ace 100644
--- a/core/src/main/java/brooklyn/management/internal/UsageManager.java
+++ b/core/src/main/java/brooklyn/management/internal/UsageManager.java
@@ -18,10 +18,13 @@
*/
package brooklyn.management.internal;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import brooklyn.config.ConfigKey;
import brooklyn.entity.Application;
+import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.location.Location;
import brooklyn.management.usage.ApplicationUsage;
@@ -31,10 +34,18 @@ import brooklyn.management.usage.LocationUsage.LocationEvent;
import com.google.common.annotations.Beta;
import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.TypeToken;
@Beta
public interface UsageManager {
+ @SuppressWarnings("serial")
+ public static final ConfigKey<List<UsageListener>> USAGE_LISTENERS = ConfigKeys.newConfigKey(
+ new TypeToken<List<UsageListener>>() {},
+ "brooklyn.usageManager.listeners", "Optional usage listeners (i.e. for metering)",
+ ImmutableList.<UsageListener>of());
+
public interface UsageListener {
public static final UsageListener NOOP = new UsageListener() {
@Override public void onApplicationEvent(String applicationId, String applicationName, String entityType,
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7ee06ba3/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.java b/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.java
new file mode 100644
index 0000000..0cc27c7
--- /dev/null
+++ b/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.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 brooklyn.management.usage;
+
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.Entities;
+import brooklyn.location.Location;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.management.internal.UsageManager;
+import brooklyn.management.internal.UsageManager.UsageListener;
+import brooklyn.test.Asserts;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class UsageListenerTest {
+
+ // Also see {Application|Location}UsageTrackingTest for listener functionality
+
+ private static final Logger LOG = LoggerFactory.getLogger(ApplicationUsageTrackingTest.class);
+
+ protected TestApplication app;
+ protected ManagementContextInternal mgmt;
+
+ protected boolean shouldSkipOnBoxBaseDirResolution() {
+ return true;
+ }
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ RecordingStaticUsageListener.clearInstances();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ try {
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ } catch (Throwable t) {
+ LOG.error("Caught exception in tearDown method", t);
+ } finally {
+ mgmt = null;
+ RecordingStaticUsageListener.clearInstances();
+ }
+ }
+
+ @Test
+ public void testAddUsageListenerViaProperties() throws Exception {
+ BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
+ brooklynProperties.put(UsageManager.USAGE_LISTENERS, RecordingStaticUsageListener.class.getName());
+ mgmt = LocalManagementContextForTests.newInstance(brooklynProperties);
+
+ app = TestApplication.Factory.newManagedInstanceForTests(mgmt);
+ app.start(ImmutableList.<Location>of());
+
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ List<List<?>> events = RecordingStaticUsageListener.getInstance().getApplicationEvents();
+ assertTrue(events.size() > 0, "events="+events); // expect some events
+ }});
+ }
+
+ public static class RecordingStaticUsageListener extends RecordingUsageListener implements UsageListener {
+ private static final List<RecordingStaticUsageListener> STATIC_INSTANCES = Lists.newCopyOnWriteArrayList();
+
+ public static RecordingStaticUsageListener getInstance() {
+ return Iterables.getOnlyElement(STATIC_INSTANCES);
+ }
+
+ public static void clearInstances() {
+ STATIC_INSTANCES.clear();
+ }
+
+ public RecordingStaticUsageListener() {
+ // Bad to leak a ref to this before constructor finished, but we'll live with it because
+ // it's just test code!
+ STATIC_INSTANCES.add(this);
+ }
+ }
+}