changeset 44:5d3346b09eb8

Agent: publish configuration to storage.
author Jon VanAlten <jon.vanalten@redhat.com>
date Tue, 17 Jan 2012 15:33:44 -0500
parents fb343e1da209
children 23515a4050af
files src/com/redhat/thermostat/agent/Agent.java src/com/redhat/thermostat/agent/config/ConfigurationWatcher.java src/com/redhat/thermostat/agent/config/StartupConfiguration.java src/com/redhat/thermostat/agent/storage/MongoStorage.java src/com/redhat/thermostat/agent/storage/Storage.java src/com/redhat/thermostat/agent/storage/StorageConstants.java src/com/redhat/thermostat/backend/Backend.java src/com/redhat/thermostat/backend/sample/SampleBackend.java src/com/redhat/thermostat/backend/system/JvmStatHostListener.java src/com/redhat/thermostat/backend/system/SystemBackend.java
diffstat 10 files changed, 148 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/src/com/redhat/thermostat/agent/Agent.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/agent/Agent.java	Tue Jan 17 15:33:44 2012 -0500
@@ -61,8 +61,8 @@
     public synchronized void start() throws LaunchException {
         if (configWatcherThread == null) {
             startBackends();
-            storage.addAgentInformation(config);
-            configWatcherThread = new Thread(new ConfigurationWatcher(storage), "Configuration Watcher");
+            storage.addAgentInformation(config, backendRegistry);
+            configWatcherThread = new Thread(new ConfigurationWatcher(storage, backendRegistry), "Configuration Watcher");
             configWatcherThread.start();
         } else {
             logger.warning("Attempt to start agent when already started.");
--- a/src/com/redhat/thermostat/agent/config/ConfigurationWatcher.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/agent/config/ConfigurationWatcher.java	Tue Jan 17 15:33:44 2012 -0500
@@ -3,6 +3,7 @@
 import java.util.logging.Logger;
 
 import com.redhat.thermostat.agent.storage.Storage;
+import com.redhat.thermostat.backend.BackendRegistry;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 
 public class ConfigurationWatcher implements Runnable {
@@ -10,9 +11,11 @@
     private static final Logger logger = LoggingUtils.getLogger(ConfigurationWatcher.class);
 
     private Storage storage;
+    private BackendRegistry backends;
 
-    public ConfigurationWatcher(Storage storage) {
+    public ConfigurationWatcher(Storage storage, BackendRegistry backends) {
         this.storage = storage;
+        this.backends = backends;
     }
 
     @Override
--- a/src/com/redhat/thermostat/agent/config/StartupConfiguration.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/agent/config/StartupConfiguration.java	Tue Jan 17 15:33:44 2012 -0500
@@ -12,11 +12,8 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
 import com.redhat.thermostat.agent.Agent;
 import com.redhat.thermostat.agent.Defaults;
-import com.redhat.thermostat.agent.storage.StorageConstants;
 import com.redhat.thermostat.common.Constants;
 import com.redhat.thermostat.common.LaunchException;
 import com.redhat.thermostat.common.utils.LoggingUtils;
@@ -102,14 +99,6 @@
         return hostname;
     }
 
-    // TODO move this into Storage as well
-    public DBObject toDBObject() {
-        BasicDBObject result = new BasicDBObject();
-        result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_START_TIME, startTimestamp);
-        // TODO create nested backend config parts
-        return result;
-    }
-
     public void setAgent(Agent agent) {
         this.agent = agent;
     }
@@ -141,6 +130,10 @@
         return configMap;
     }
 
+    public long getStartTime() {
+        return startTimestamp;
+    }
+
     /**
      * Exposes the command line arguments in a more object-oriented style.
      * <p>
--- a/src/com/redhat/thermostat/agent/storage/MongoStorage.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/agent/storage/MongoStorage.java	Tue Jan 17 15:33:44 2012 -0500
@@ -5,9 +5,11 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.UUID;
+import java.util.logging.Logger;
 
 import org.bson.BSONObject;
 
+import com.mongodb.BasicDBList;
 import com.mongodb.BasicDBObject;
 import com.mongodb.DB;
 import com.mongodb.DBCollection;
@@ -16,6 +18,9 @@
 import com.mongodb.MongoURI;
 import com.mongodb.WriteConcern;
 import com.redhat.thermostat.agent.config.StartupConfiguration;
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.backend.BackendRegistry;
+import com.redhat.thermostat.common.utils.LoggingUtils;
 
 /**
  * Implementation of the Storage interface that uses MongoDB to store the instrumentation data.
@@ -26,6 +31,8 @@
 
     public static final String KEY_AGENT_ID = "agent-id";
 
+    private static final Logger logger = LoggingUtils.getLogger(MongoStorage.class);
+
     private Mongo mongo = null;
     private DB db = null;
 
@@ -47,9 +54,9 @@
     }
 
     @Override
-    public void addAgentInformation(StartupConfiguration config) {
+    public void addAgentInformation(StartupConfiguration config, BackendRegistry registry) {
         DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
-        DBObject toInsert = config.toDBObject();
+        DBObject toInsert = createConfigDBObject(config, registry);
         /* cast required to disambiguate between putAll(BSONObject) and putAll(Map) */
         toInsert.putAll((BSONObject) getAgentDBObject());
         configCollection.insert(toInsert, WriteConcern.SAFE);
@@ -131,4 +138,35 @@
         }
         coll.insert(toInsert);
     }
+
+    private DBObject createConfigDBObject(StartupConfiguration config, BackendRegistry registry) {
+        BasicDBObject result = getAgentDBObject();
+        result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_START_TIME, config.getStartTime());
+        BasicDBObject backends = new BasicDBObject();
+        for (Backend backend : registry.getAll()) {
+            backends.put(backend.getName(), createBackendConfigDBObject(backend));
+        }
+        result.put(StorageConstants.KEY_AGENT_CONFIG_BACKENDS, backends);
+        return result;
+    }
+
+    private DBObject createBackendConfigDBObject(Backend backend) {
+        BasicDBObject result = new BasicDBObject();
+        Map<String, String> configMap = backend.getConfigurationMap();
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_NAME, backend.getName());
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_DESC, backend.getDescription());
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_ACTIVE, createBackendActiveDBObject(backend));
+        for (String configName : configMap.keySet()) {
+            result.append(configName, configMap.get(configName));
+        }
+        return result;
+    }
+
+    private DBObject createBackendActiveDBObject(Backend backend) {
+        BasicDBObject result = new BasicDBObject();
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_NEW, backend.getObserveNewJvm());
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_PIDS, new BasicDBList());
+        // TODO check which processes are already being listened to.
+        return result;
+    }
 }
--- a/src/com/redhat/thermostat/agent/storage/Storage.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/agent/storage/Storage.java	Tue Jan 17 15:33:44 2012 -0500
@@ -7,6 +7,7 @@
 
 import com.redhat.thermostat.agent.config.StartupConfiguration;
 import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.backend.BackendRegistry;
 
 public abstract class Storage {
     private Map<String, Backend> categoryMap;
@@ -19,7 +20,7 @@
 
     public abstract void setAgentId(UUID id);
 
-    public abstract void addAgentInformation(StartupConfiguration config);
+    public abstract void addAgentInformation(StartupConfiguration config, BackendRegistry registry);
 
     public abstract void removeAgentInformation();
 
--- a/src/com/redhat/thermostat/agent/storage/StorageConstants.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/agent/storage/StorageConstants.java	Tue Jan 17 15:33:44 2012 -0500
@@ -7,4 +7,9 @@
 
     public static final String KEY_AGENT_CONFIG_BACKENDS = "backends";
     public static final String KEY_AGENT_CONFIG_AGENT_START_TIME = "start-time";
+    public static final String KEY_AGENT_CONFIG_BACKEND_NAME = "name";
+    public static final String KEY_AGENT_CONFIG_BACKEND_DESC = "description";
+    public static final String KEY_AGENT_CONFIG_BACKEND_ACTIVE = "active";
+    public static final String KEY_AGENT_CONFIG_BACKEND_NEW = "new";
+    public static final String KEY_AGENT_CONFIG_BACKEND_PIDS = "pids";
 }
--- a/src/com/redhat/thermostat/backend/Backend.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/backend/Backend.java	Tue Jan 17 15:33:44 2012 -0500
@@ -1,5 +1,6 @@
 package com.redhat.thermostat.backend;
 
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -15,7 +16,8 @@
 public abstract class Backend {
 
     private boolean initialConfigurationComplete = false;
-    private Storage storage;
+    private Storage storage = null;
+    private boolean observeNewJvm = attachToNewProcessByDefault();
 
     /**
      * 
@@ -55,7 +57,9 @@
      * @throws IllegalArgumentException if either the key does not refer to a valid configuration option
      *                                  for this backend or the value is not valid for the key
      */
-    protected abstract void setConfigurationValue(String name, String value);
+    protected void setConfigurationValue(String name, String value) {
+        throw new IllegalArgumentException("Backend " + getName() + " does not support any specific configuration values.");
+    }
 
     /**
      * @return the name of the {@link Backend}
@@ -77,10 +81,16 @@
      */
     public abstract String getVersion();
 
-    /**
+    /** Get a map containing the current settings of this backend.
+     * Implementors of this abstract class which have some settings that
+     * are be configurable by the client must override this method
+     * to provide an appropriate map.
+     * 
      * @return a map containing the settings of this backend
      */
-    public abstract Map<String, String> getConfigurationMap();
+    public Map<String, String> getConfigurationMap() {
+        return new HashMap<String, String>();
+    }
 
     /**
      * 
@@ -115,6 +125,33 @@
      */
     public abstract boolean isActive();
 
+    /**
+     * A {@link Backend} may be configured to automatically begin collecting from new Java
+     * processes.  This method determines whether this will be the case when the backend
+     * is initially started.
+     * 
+     * @return true if the initial backend behaviour is to attach to new java processes, false otherwise.
+     */
+    public abstract boolean attachToNewProcessByDefault();
+
+    /**
+     * Indicate whether this backend will attach to new java processes.
+     * 
+     * @return true if this backend will attach to new java processes, false otherwise.
+     */
+    public boolean getObserveNewJvm() {
+        return observeNewJvm;
+    }
+
+    /**
+     * Set whether this backend will attach to new java processes.
+     * 
+     * @param newValue
+     */
+    public void setObserveNewJvm(boolean newValue) {
+        observeNewJvm = newValue;
+    }
+
     public final void store(Chunk chunk) {
         storage.putChunk(chunk, this);
     }
--- a/src/com/redhat/thermostat/backend/sample/SampleBackend.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/backend/sample/SampleBackend.java	Tue Jan 17 15:33:44 2012 -0500
@@ -85,4 +85,9 @@
         return new HashSet<Category>().iterator();
     }
 
+    @Override
+    public boolean attachToNewProcessByDefault() {
+        return false;
+    }
+
 }
--- a/src/com/redhat/thermostat/backend/system/JvmStatHostListener.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/backend/system/JvmStatHostListener.java	Tue Jan 17 15:33:44 2012 -0500
@@ -7,6 +7,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -18,13 +20,15 @@
 import sun.jvmstat.monitor.event.HostListener;
 import sun.jvmstat.monitor.event.VmStatusChangeEvent;
 
+import com.redhat.thermostat.agent.JvmStatusListener;
+import com.redhat.thermostat.agent.JvmStatusNotifier;
 import com.redhat.thermostat.agent.storage.Category;
 import com.redhat.thermostat.agent.storage.Chunk;
 import com.redhat.thermostat.agent.storage.Key;
 import com.redhat.thermostat.common.VmInfo;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 
-public class JvmStatHostListener implements HostListener {
+public class JvmStatHostListener implements HostListener, JvmStatusNotifier {
 
     private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class);
 
@@ -65,6 +69,8 @@
 
     private Map<Integer, JvmStatVmListener> listenerMap = new HashMap<Integer, JvmStatVmListener>();
 
+    private Set<JvmStatusListener> statusListeners = new CopyOnWriteArraySet<JvmStatusListener>();
+
     public static Collection<Category> getCategories() {
         ArrayList<Category> categories = new ArrayList<Category>();
         categories.add(vmInfoCategory);
@@ -135,7 +141,7 @@
                 logger.log(Level.WARNING, "error getting vm info for " + vmId, me);
             }
 
-            if (backend.monitorNewVms()) {
+            if (backend.getObserveNewJvm()) {
                 backend.addPid(vmId);
                 JvmStatVmListener listener = new JvmStatVmListener(backend, vmId);
                 listenerMap.put(vmId, listener);
@@ -143,6 +149,9 @@
             } else {
                 logger.log(Level.FINE, "skipping new vm " + vmId);
             }
+            for (JvmStatusListener statusListener : statusListeners) {
+                statusListener.jvmStarted(vmId);
+            }
         }
     }
 
@@ -156,6 +165,9 @@
             if (vm != null) {
                 JvmStatVmListener listener = listenerMap.remove(vmId);
                 vm.removeVmListener(listener);
+                for (JvmStatusListener statusListener : statusListeners) {
+                    statusListener.jvmStopped(vmId);
+                }
             }
             // TODO record vm as stopped
         }
@@ -181,4 +193,14 @@
         chunk.put(vmInfoStopTimeKey, String.valueOf(info.getStopTimeStamp()));
         return chunk;
     }
+
+    @Override
+    public void addJvmStatusListener(JvmStatusListener listener) {
+        statusListeners.add(listener);
+    }
+
+    @Override
+    public void removeJvmStatusListener(JvmStatusListener listener) {
+        statusListeners.remove(listener);
+    }
 }
--- a/src/com/redhat/thermostat/backend/system/SystemBackend.java	Tue Jan 17 14:52:54 2012 -0500
+++ b/src/com/redhat/thermostat/backend/system/SystemBackend.java	Tue Jan 17 15:33:44 2012 -0500
@@ -16,6 +16,8 @@
 import sun.jvmstat.monitor.MonitorException;
 import sun.jvmstat.monitor.MonitoredHost;
 
+import com.redhat.thermostat.agent.JvmStatusListener;
+import com.redhat.thermostat.agent.JvmStatusNotifier;
 import com.redhat.thermostat.agent.storage.Category;
 import com.redhat.thermostat.agent.storage.Chunk;
 import com.redhat.thermostat.agent.storage.Key;
@@ -28,7 +30,7 @@
 import com.redhat.thermostat.common.VmCpuStat;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 
-public class SystemBackend extends Backend {
+public class SystemBackend extends Backend implements JvmStatusNotifier {
 
     private static final String NAME = "system";
     private static final String DESCRIPTION = "gathers basic information from the system";
@@ -45,7 +47,6 @@
     private MonitoredHost host = null;
     private JvmStatHostListener hostListener = new JvmStatHostListener();
 
-    private boolean monitorNewVms = true;
     private Set<Integer> pidsToMonitor = new HashSet<Integer>();
 
     private List<Category> categories = new ArrayList<Category>();
@@ -130,13 +131,6 @@
     }
 
     @Override
-    protected void setConfigurationValue(String name, String value) {
-        if (name.equals("new")) {
-            monitorNewVms = Boolean.valueOf(value);
-        }
-    }
-
-    @Override
     public String getName() {
         return NAME;
     }
@@ -157,18 +151,13 @@
     }
 
     @Override
-    public Map<String, String> getConfigurationMap() {
-        throw new NotImplementedException("get configuration");
-    }
-
-    @Override
     public synchronized boolean activate() {
         if (timer != null) {
             return true;
         }
 
-        if (!monitorNewVms) {
-            logger.log(Level.WARNING, "not monitoring new vms");
+        if (!getObserveNewJvm()) {
+            logger.fine("not monitoring new vms");
         }
         store(makeHostChunk(HostInfoBuilder.build()));
 
@@ -215,7 +204,7 @@
         try {
             host.removeHostListener(hostListener);
         } catch (MonitorException me) {
-            logger.log(Level.INFO, "something went wront in jvmstat's listeningto this host");
+            logger.log(Level.INFO, "something went wrong in jvmstat's listening to this host");
         }
         host = null;
         hostId = null;
@@ -239,10 +228,6 @@
         return categories.iterator();
     }
 
-    public boolean monitorNewVms() {
-        return monitorNewVms;
-    }
-
     public void addPid(int pid) {
         pidsToMonitor.add(pid);
     }
@@ -305,4 +290,19 @@
         chunk.put(vmCpuLoadKey, Double.toString(stat.getCpuLoad()));
         return chunk;
     }
+
+    @Override
+    public boolean attachToNewProcessByDefault() {
+        return true;
+    }
+
+    @Override
+    public void addJvmStatusListener(JvmStatusListener listener) {
+        hostListener.addJvmStatusListener(listener);
+    }
+
+    @Override
+    public void removeJvmStatusListener(JvmStatusListener listener) {
+        hostListener.removeJvmStatusListener(listener);
+    }
 }