Mercurial > hg > release > thermostat-0.6
changeset 24:3387781e66ff
Generic storage interface.
- This unfortunately huge commit allows for addition of new Backends and/or
changes to the data stored by a existing Backends, without needing to
add or change any code behind the Storage interface.
- Additional change that crept in incidentally: network-info is moved
to separate collection.
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/agent/storage/Category.java Thu Dec 22 18:45:12 2011 -0500 @@ -0,0 +1,36 @@ +package com.redhat.thermostat.agent.storage; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class Category { + private final String name; + private final List<Key> keys; + private boolean locked = false; + + public Category(String name) { + this.name = name; + keys = new ArrayList<Key>(); + } + + public String getName() { + return name; + } + + public synchronized void lock() { + locked = true; + } + + public synchronized void addKey(Key key) { + if (!locked) { + keys.add(key); + } else { + throw new IllegalStateException("Once locked, a category's keys may not be changed."); + } + } + + public synchronized Iterator<Key> getEntryIterator() { + return keys.iterator(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/agent/storage/Chunk.java Thu Dec 22 18:45:12 2011 -0500 @@ -0,0 +1,44 @@ +package com.redhat.thermostat.agent.storage; + +import java.util.HashMap; +import java.util.Map; + +/** + * A Chunk is a unit containing a set of data that can be added as a whole to the dataset + * that exists behind the storage layer. + */ +public class Chunk { + private final Category category; + private final boolean replace; + + private Map<Key, String> values = new HashMap<Key, String>(); + + /** + * + * @param timestamp The time that should be associated with the data in this nugget. + * @param category The {@link Category} of this data. This should be a Category that the {@link Backend} + * who is producing this Chunk has registered via {@link Storage#registerCategory()} + * @param add whether this chunk should replace the values based on the keys for this category, + * or be added to a set of values in this category + */ + public Chunk(Category category, boolean replace) { + this.category = category; + this.replace = replace; + } + + public Category getCategory() { + return category; + } + + public boolean getReplace() { + return replace; + } + + public void put(Key entry, String value) { + values.put(entry, value); + } + + public String get(Key entry) { + return values.get(entry); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/agent/storage/Key.java Thu Dec 22 18:45:12 2011 -0500 @@ -0,0 +1,48 @@ +package com.redhat.thermostat.agent.storage; + +/** + * A Key is used to refer to data in a {@link Chunk}. It may also be a partial key to the + * set of data represented by a {@link Chunk} in a category. + */ +public class Key { + + // Key used by most Categories. + public static Key TIMESTAMP = new Key("timestamp", false); + + private String name; + private boolean isPartialCategoryKey; + + public Key(String name, boolean isPartialCategoryKey) { + this.name = name; + this.isPartialCategoryKey = isPartialCategoryKey; + } + + public String getName() { + return name; + } + + public boolean isPartialCategoryKey() { + return isPartialCategoryKey; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if ((o == null) || (o.getClass() != this.getClass())) { + return false; + } + Key e = (Key) o; + return (isPartialCategoryKey == e.isPartialCategoryKey()) && + name.equals(e.getName()); + } + + @Override + public int hashCode() { + int hash = 1867; + hash = hash * 37 + (isPartialCategoryKey ? 0 : 1); + hash = hash * 37 + (name == null ? 0 : name.hashCode()); + return hash; + } +}
--- a/src/com/redhat/thermostat/agent/storage/MongoStorage.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/agent/storage/MongoStorage.java Thu Dec 22 18:45:12 2011 -0500 @@ -1,8 +1,9 @@ package com.redhat.thermostat.agent.storage; import java.net.UnknownHostException; -import java.util.List; -import java.util.Map.Entry; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import java.util.UUID; import org.bson.BSONObject; @@ -15,12 +16,15 @@ import com.mongodb.MongoURI; import com.mongodb.WriteConcern; import com.redhat.thermostat.agent.config.StartupConfiguration; -import com.redhat.thermostat.common.Constants; -import com.redhat.thermostat.common.CpuStat; -import com.redhat.thermostat.common.HostInfo; -import com.redhat.thermostat.common.MemoryStat; -public class MongoStorage implements Storage { +/** + * Implementation of the Storage interface that uses MongoDB to store the instrumentation data. + * + * In this implementation, each CATEGORY is given a distinct collection. + */ +public class MongoStorage extends Storage { + + public static final String KEY_AGENT_ID = "agent-id"; private Mongo mongo = null; private DB db = null; @@ -34,7 +38,7 @@ public void connect(MongoURI uri) throws UnknownHostException { mongo = new Mongo(uri); - db = mongo.getDB(StorageConstants.THERMOSTAT_DB); + db = mongo.getDB(StorageConstants.THERMOSTAT_DB_NAME); } @Override @@ -44,7 +48,7 @@ @Override public void addAgentInformation(StartupConfiguration config) { - DBCollection configCollection = db.getCollection(StorageConstants.COLLECTION_AGENT_CONFIG); + DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG); DBObject toInsert = config.toDBObject(); /* cast required to disambiguate between putAll(BSONObject) and putAll(Map) */ toInsert.putAll((BSONObject) getAgentDBObject()); @@ -53,14 +57,14 @@ @Override public void removeAgentInformation() { - DBCollection configCollection = db.getCollection(StorageConstants.COLLECTION_AGENT_CONFIG); + DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG); BasicDBObject toRemove = getAgentDBObject(); configCollection.remove(toRemove, WriteConcern.NORMAL); } @Override public String getBackendConfig(String backendName, String configurationKey) { - DBCollection configCollection = db.getCollection(StorageConstants.COLLECTION_AGENT_CONFIG); + DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG); BasicDBObject query = getAgentDBObject(); query.put(StorageConstants.KEY_AGENT_CONFIG_BACKENDS + "." + backendName, new BasicDBObject("$exists", true)); DBObject config = configCollection.findOne(query); @@ -72,76 +76,59 @@ } private BasicDBObject getAgentDBObject() { - return new BasicDBObject(StorageConstants.KEY_AGENT_ID, agentId.toString()); + return new BasicDBObject(KEY_AGENT_ID, agentId.toString()); } @Override - public void updateHostInfo(HostInfo hostInfo) { - /* - * Host Info is determined (completely) on the agent side. No one else - * should be touching it. So let's overwrite any changes to it. - */ - DBObject queryForOldObject = getAgentDBObject(); - - BasicDBObject toInsert = new BasicDBObject(); - toInsert.put(StorageConstants.KEY_AGENT_ID, agentId.toString()); - toInsert.put(StorageConstants.KEY_HOST_INFO_HOSTNAME, hostInfo.getHostname()); - - BasicDBObject osParts = new BasicDBObject(); - osParts.put(StorageConstants.KEY_HOST_INFO_OS_NAME, hostInfo.getOsName()); - osParts.put(StorageConstants.KEY_HOST_INFO_OS_KERNEL, hostInfo.getOsKernel()); - toInsert.put(StorageConstants.KEY_HOST_INFO_OS, osParts); - - BasicDBObject cpuParts = new BasicDBObject(); - cpuParts.put(StorageConstants.KEY_HOST_INFO_CPU_COUNT, hostInfo.getCpuCount()); - toInsert.put(StorageConstants.KEY_HOST_INFO_CPU, cpuParts); - - BasicDBObject memoryParts = new BasicDBObject(); - memoryParts.put(StorageConstants.KEY_HOST_INFO_MEMORY_TOTAL, hostInfo.getTotalMemory()); - toInsert.put(StorageConstants.KEY_HOST_INFO_MEMORY, memoryParts); - - BasicDBObject networkParts = new BasicDBObject(); - for (Entry<String, List<String>> entry: hostInfo.getNetworkInfo().entrySet()) { - BasicDBObject details = new BasicDBObject(); - details.put(StorageConstants.KEY_HOST_INFO_NETWORK_ADDR_IPV4, - entry.getValue().get(Constants.HOST_INFO_NETWORK_IPV4_INDEX)); - details.put(StorageConstants.KEY_HOST_INFO_NETWORK_ADDR_IPV6, - entry.getValue().get(Constants.HOST_INFO_NETWORK_IPV6_INDEX)); - networkParts.put(entry.getKey(), details); + protected void addChunkImpl(Chunk chunk) { + Category cat = chunk.getCategory(); + DBCollection coll = db.getCollection(cat.getName()); + BasicDBObject toInsert = getAgentDBObject(); + BasicDBObject toDelete = null; + boolean replace = chunk.getReplace(); + Map<String, BasicDBObject> nestedParts = new HashMap<String, BasicDBObject>(); + Map<String, BasicDBObject> deleteNestedParts = null; + if (replace) { + toDelete = getAgentDBObject(); + deleteNestedParts = new HashMap<String, BasicDBObject>(); } - toInsert.put(StorageConstants.KEY_HOST_INFO_NETWORK, networkParts); - - DBCollection hostInfoCollection = db.getCollection(StorageConstants.COLLECTION_HOST_INFO); - hostInfoCollection.update( - queryForOldObject, - toInsert, - true, - false, /* doesnt matter should only have one object */ - WriteConcern.NORMAL - ); - } - - @Override - public void addCpuStat(CpuStat stat) { - DBCollection cpuStatsCollection = db.getCollection(StorageConstants.COLLECTION_CPU_STATS); - BasicDBObject toInsert = getAgentDBObject(); - toInsert.put(StorageConstants.KEY_TIMESTAMP, stat.getTimeStamp()); - toInsert.put(StorageConstants.KEY_CPU_STATS_LOAD, stat.getLoad()); - cpuStatsCollection.insert(toInsert, WriteConcern.NORMAL); - } - - @Override - public void addMemoryStat(MemoryStat stat) { - DBCollection memoryStatsCollection = db.getCollection(StorageConstants.COLLECTION_MEMORY_STATS); - BasicDBObject toInsert = getAgentDBObject(); - toInsert.put(StorageConstants.KEY_TIMESTAMP, stat.getTimeStamp()); - toInsert.put(StorageConstants.KEY_MEMORY_STATS_TOTAL, stat.getTotal()); - toInsert.put(StorageConstants.KEY_MEMORY_STATS_FREE, stat.getFree()); - toInsert.put(StorageConstants.KEY_MEMORY_STATS_BUFFERS, stat.getBuffers()); - toInsert.put(StorageConstants.KEY_MEMORY_STATS_CACHED, stat.getCached()); - toInsert.put(StorageConstants.KEY_MEMORY_STATS_SWAP_TOTAL, stat.getSwapTotal()); - toInsert.put(StorageConstants.KEY_MEMORY_STATS_SWAP_FREE, stat.getSwapFree()); - toInsert.put(StorageConstants.KEY_MEMORY_STATS_COMMIT_LIMIT, stat.getCommitLimit()); - memoryStatsCollection.insert(toInsert, WriteConcern.NORMAL); + for (Iterator<com.redhat.thermostat.agent.storage.Key> iter = cat.getEntryIterator(); iter.hasNext();) { + com.redhat.thermostat.agent.storage.Key key = iter.next(); + boolean isKey = key.isPartialCategoryKey(); + String[] entryParts = key.getName().split("."); + if (entryParts.length == 2) { + BasicDBObject nested = nestedParts.get(entryParts[0]); + if (nested == null) { + nested = new BasicDBObject(); + nestedParts.put(entryParts[0], nested); + } + nested.append(entryParts[1], chunk.get(key)); + if (replace && isKey) { + BasicDBObject deleteNested = deleteNestedParts.get(entryParts[0]); + if (deleteNested == null) { + deleteNested = new BasicDBObject(); + deleteNestedParts.put(entryParts[0], deleteNested); + } + deleteNested.append(entryParts[1], deleteNested); + } + } else { + String mongoKey = key.getName(); + String value = chunk.get(key); + toInsert.append(mongoKey, value); + if (replace && isKey) { + toDelete.append(mongoKey, value); + } + } + } + for (String mongoKey : nestedParts.keySet()) { + toInsert.append(mongoKey, nestedParts.get(mongoKey)); + } + if (replace) { + for (String mongoKey : deleteNestedParts.keySet()) { + toDelete.append(mongoKey, deleteNestedParts.get(mongoKey)); + } + coll.remove(toDelete); + } + coll.insert(toInsert); } }
--- a/src/com/redhat/thermostat/agent/storage/Storage.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/agent/storage/Storage.java Thu Dec 22 18:45:12 2011 -0500 @@ -1,31 +1,47 @@ package com.redhat.thermostat.agent.storage; import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import com.redhat.thermostat.agent.config.StartupConfiguration; -import com.redhat.thermostat.common.CpuStat; -import com.redhat.thermostat.common.HostInfo; -import com.redhat.thermostat.common.MemoryStat; +import com.redhat.thermostat.backend.Backend; -public interface Storage { - public void connect(String uri) throws UnknownHostException; - - public void setAgentId(UUID id); +public abstract class Storage { + private Map<String, Backend> categoryMap; - public void addAgentInformation(StartupConfiguration config); + public Storage() { + categoryMap = new HashMap<String, Backend>(); + } - public void removeAgentInformation(); + public abstract void connect(String uri) throws UnknownHostException; - public void addCpuStat(CpuStat stat); + public abstract void setAgentId(UUID id); - public void addMemoryStat(MemoryStat stat); + public abstract void addAgentInformation(StartupConfiguration config); - public void updateHostInfo(HostInfo hostInfo); + public abstract void removeAgentInformation(); /** * @return {@code null} if the value is invalid or missing */ - public String getBackendConfig(String backendName, String configurationKey); + public abstract String getBackendConfig(String backendName, String configurationKey); + + public final void registerCategory(Category category, Backend backend) { + if (categoryMap.containsKey(category.getName())) { + throw new IllegalStateException("Category may only be associated with one backend."); + } + categoryMap.put(category.getName(), backend); + } + public final void putChunk(Chunk chunk, Backend backend) { + Category category = chunk.getCategory(); + if (backend != categoryMap.get(category.getName())) { // This had better be not just equivalent, but actually the same object. + throw new IllegalArgumentException("Invalid category-backend combination while inserting data. Category: " + category.getName() + " Backend: " + backend.getName()); + } + addChunkImpl(chunk); + } + + protected abstract void addChunkImpl(Chunk chunk); }
--- a/src/com/redhat/thermostat/agent/storage/StorageConstants.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/agent/storage/StorageConstants.java Thu Dec 22 18:45:12 2011 -0500 @@ -1,39 +1,10 @@ package com.redhat.thermostat.agent.storage; public class StorageConstants { - public static final String THERMOSTAT_DB = "thermostat"; + public static final String THERMOSTAT_DB_NAME = "thermostat"; - public static final String COLLECTION_AGENT_CONFIG = "agent-config"; - public static final String COLLECTION_HOST_INFO = "host-info"; - public static final String COLLECTION_CPU_STATS = "cpu-stats"; - public static final String COLLECTION_MEMORY_STATS = "memory-stats"; - - public static final String KEY_AGENT_ID = "agent-id"; - public static final String KEY_TIMESTAMP = "timestamp"; + public static final String CATEGORY_AGENT_CONFIG = "agent-config"; 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_HOST_INFO_HOSTNAME = "hostname"; - public static final String KEY_HOST_INFO_OS = "os"; - public static final String KEY_HOST_INFO_OS_NAME = "name"; - public static final String KEY_HOST_INFO_OS_KERNEL = "kernel"; - public static final String KEY_HOST_INFO_CPU = "cpu"; - public static final String KEY_HOST_INFO_CPU_COUNT = "num"; - public static final String KEY_HOST_INFO_MEMORY = "memory"; - public static final String KEY_HOST_INFO_MEMORY_TOTAL = "total"; - public static final String KEY_HOST_INFO_NETWORK = "network"; - public static final String KEY_HOST_INFO_NETWORK_ADDR_IPV4 = "ipv4addr"; - public static final String KEY_HOST_INFO_NETWORK_ADDR_IPV6 = "ipv6addr"; - - public static final String KEY_CPU_STATS_LOAD = "load"; - - public static final String KEY_MEMORY_STATS_TOTAL = "total"; - public static final String KEY_MEMORY_STATS_FREE = "free"; - public static final String KEY_MEMORY_STATS_BUFFERS = "buffers"; - public static final String KEY_MEMORY_STATS_CACHED = "cached"; - public static final String KEY_MEMORY_STATS_SWAP_TOTAL = "swap-total"; - public static final String KEY_MEMORY_STATS_SWAP_FREE = "swap-free"; - public static final String KEY_MEMORY_STATS_COMMIT_LIMIT = "commit-limit"; - }
--- a/src/com/redhat/thermostat/backend/Backend.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/backend/Backend.java Thu Dec 22 18:45:12 2011 -0500 @@ -1,8 +1,11 @@ package com.redhat.thermostat.backend; +import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import com.redhat.thermostat.agent.storage.Category; +import com.redhat.thermostat.agent.storage.Chunk; import com.redhat.thermostat.agent.storage.Storage; /** @@ -12,7 +15,7 @@ public abstract class Backend { private boolean initialConfigurationComplete = false; - protected Storage storage; + private Storage storage; /** * @@ -36,10 +39,15 @@ initialConfigurationComplete = true; } - protected void setStorage(Storage storage) { + public final void setStorage(Storage storage) { this.storage = storage; + for (Iterator<Category> iter = getCategoryIterator(); iter.hasNext();) { + storage.registerCategory(iter.next(), this); + } } + protected abstract Iterator<Category> getCategoryIterator(); + /** * Set the named configuration to the given value. * @param name @@ -107,4 +115,7 @@ */ public abstract boolean isActive(); + public final void store(Chunk chunk) { + storage.putChunk(chunk, this); + } }
--- a/src/com/redhat/thermostat/backend/sample/SampleBackend.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/backend/sample/SampleBackend.java Thu Dec 22 18:45:12 2011 -0500 @@ -1,10 +1,13 @@ package com.redhat.thermostat.backend.sample; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import com.redhat.thermostat.agent.storage.Category; import com.redhat.thermostat.backend.Backend; import com.redhat.thermostat.common.utils.LoggingUtils; @@ -77,4 +80,9 @@ return currentlyActive; } + @Override + protected Iterator<Category> getCategoryIterator() { + return new HashSet<Category>().iterator(); + } + }
--- a/src/com/redhat/thermostat/backend/system/HostInfoBuilder.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/backend/system/HostInfoBuilder.java Thu Dec 22 18:45:12 2011 -0500 @@ -3,24 +3,14 @@ import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; -import java.net.Inet4Address; -import java.net.Inet6Address; import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import com.redhat.thermostat.common.Constants; import com.redhat.thermostat.common.HostInfo; import com.redhat.thermostat.common.utils.LoggingUtils; -import com.redhat.thermostat.common.utils.StringUtils; public class HostInfoBuilder { @@ -29,7 +19,7 @@ private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilder.class); - public HostInfo build() { + public static HostInfo build() { InetAddress localAddr; String hostname; try { @@ -72,31 +62,11 @@ } logger.log(Level.FINEST, "totalMemory: " + totalMemory + " bytes"); - HashMap<String, List<String>> networkInfo = new HashMap<String, List<String>>(); - try { - Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); - for (NetworkInterface iface : Collections.list(ifaces)) { - List<String> ipAddresses = new ArrayList<String>(2); - ipAddresses.add(Constants.HOST_INFO_NETWORK_IPV4_INDEX, null); - ipAddresses.add(Constants.HOST_INFO_NETWORK_IPV6_INDEX, null); - for (InetAddress addr : Collections.list(iface.getInetAddresses())) { - if (addr instanceof Inet4Address) { - ipAddresses.set(Constants.HOST_INFO_NETWORK_IPV4_INDEX, fixAddr(addr.toString())); - } else if (addr instanceof Inet6Address) { - ipAddresses.set(Constants.HOST_INFO_NETWORK_IPV6_INDEX, fixAddr(addr.toString())); - } - } - networkInfo.put(iface.getName(), ipAddresses); - } - } catch (SocketException e) { - logger.log(Level.WARNING, "error enumerating network interfaces"); - } - - return new HostInfo(hostname, osName, osKernel, cpuCount, totalMemory, networkInfo); + return new HostInfo(hostname, osName, osKernel, cpuCount, totalMemory); } - private int getProcessorCountFromProc() { + private static int getProcessorCountFromProc() { final String KEY_PROCESSOR_ID = "processor"; int totalCpus = 0; BufferedReader reader = null; @@ -121,22 +91,4 @@ } return totalCpus; } - - /** - * Removes the "hostname/" and the "%scope_id" parts from the - * {@link InetAddress#toString()} output. - */ - private String fixAddr(String addr) { - int slashPos = addr.indexOf("/"); - if (slashPos == -1) { - return addr; - } - String fixed = addr.substring(slashPos + 1); - int percentPos = fixed.indexOf("%"); - if (percentPos == -1) { - return fixed; - } - fixed = fixed.substring(0, percentPos); - return fixed; - } }
--- a/src/com/redhat/thermostat/backend/system/JvmStatHostListener.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/backend/system/JvmStatHostListener.java Thu Dec 22 18:45:12 2011 -0500 @@ -2,6 +2,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -17,7 +18,7 @@ import sun.jvmstat.monitor.event.HostListener; import sun.jvmstat.monitor.event.VmStatusChangeEvent; -import com.redhat.thermostat.agent.storage.Storage; +import com.redhat.thermostat.agent.storage.Category; import com.redhat.thermostat.common.VmInfo; import com.redhat.thermostat.common.utils.LoggingUtils; @@ -25,15 +26,18 @@ private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class); - private Storage storage; + private SystemBackend backend; private Map<Integer, JvmStatVmListener> listenerMap = new HashMap<Integer, JvmStatVmListener>(); - public void setStorage(Storage storage) { - if (storage == null) { - throw new NullPointerException(); - } - this.storage = storage; + public static Collection<Category> getCategories() { + ArrayList<Category> categories = new ArrayList<Category>(); + // TODO add appropriate categories + return categories; + } + + public void setBackend(SystemBackend backend) { + this.backend = backend; } @Override @@ -43,10 +47,6 @@ @Override public void vmStatusChanged(VmStatusChangeEvent event) { - if (storage == null) { - throw new NullPointerException("null"); - } - MonitoredHost host = event.getMonitoredHost(); Iterator<Integer> newActive = event.getStarted().iterator(); @@ -100,7 +100,7 @@ logger.log(Level.WARNING, "error getting vm info for " + vmId, me); } - JvmStatVmListener listener = new JvmStatVmListener(storage, vmId); + JvmStatVmListener listener = new JvmStatVmListener(backend, vmId); listenerMap.put(vmId, listener); vm.addVmListener(listener); }
--- a/src/com/redhat/thermostat/backend/system/JvmStatVmListener.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/backend/system/JvmStatVmListener.java Thu Dec 22 18:45:12 2011 -0500 @@ -1,6 +1,7 @@ package com.redhat.thermostat.backend.system; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -11,7 +12,7 @@ import sun.jvmstat.monitor.event.VmEvent; import sun.jvmstat.monitor.event.VmListener; -import com.redhat.thermostat.agent.storage.Storage; +import com.redhat.thermostat.agent.storage.Category; import com.redhat.thermostat.common.VmGcStat; import com.redhat.thermostat.common.VmMemoryStat; import com.redhat.thermostat.common.VmMemoryStat.Generation; @@ -23,13 +24,19 @@ private static final Logger logger = LoggingUtils.getLogger(JvmStatVmListener.class); private final int vmId; - private final Storage storage; + private final SystemBackend backend; - public JvmStatVmListener(Storage storage, int vmId) { - this.storage = storage; + public JvmStatVmListener(SystemBackend backend, int vmId) { + this.backend = backend; this.vmId = vmId; } + public static Collection<Category> getCategories() { + ArrayList<Category> categories = new ArrayList<Category>(); + // TODO add appropriate categories + return categories; + } + @Override public void disconnected(VmEvent event) { /* nothing to do here */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/backend/system/NetworkInfoBuilder.java Thu Dec 22 18:45:12 2011 -0500 @@ -0,0 +1,59 @@ +package com.redhat.thermostat.backend.system; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Collections; +import java.util.Enumeration; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.NetworkInfo; +import com.redhat.thermostat.common.NetworkInterfaceInfo; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class NetworkInfoBuilder { + + private static final Logger logger = LoggingUtils.getLogger(NetworkInfoBuilder.class); + + public static NetworkInfo build() { + NetworkInfo info = new NetworkInfo(); + try { + Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface iface : Collections.list(ifaces)) { + NetworkInterfaceInfo iInfo = new NetworkInterfaceInfo(iface.getName()); + for (InetAddress addr : Collections.list(iface.getInetAddresses())) { + if (addr instanceof Inet4Address) { + iInfo.setIp4Addr(fixAddr(addr.toString())); + } else if (addr instanceof Inet6Address) { + iInfo.setIp6Addr(fixAddr(addr.toString())); + } + } + info.addNetworkInterfaceInfo(iInfo); + } + } catch (SocketException e) { + logger.log(Level.WARNING, "error enumerating network interfaces"); + } + return info; + } + + /** + * Removes the "hostname/" and the "%scope_id" parts from the + * {@link InetAddress#toString()} output. + */ + private static String fixAddr(String addr) { + int slashPos = addr.indexOf("/"); + if (slashPos == -1) { + return addr; + } + String fixed = addr.substring(slashPos + 1); + int percentPos = fixed.indexOf("%"); + if (percentPos == -1) { + return fixed; + } + fixed = fixed.substring(0, percentPos); + return fixed; + } +}
--- a/src/com/redhat/thermostat/backend/system/SystemBackend.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/backend/system/SystemBackend.java Thu Dec 22 18:45:12 2011 -0500 @@ -1,6 +1,9 @@ package com.redhat.thermostat.backend.system; import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; @@ -11,10 +14,14 @@ import sun.jvmstat.monitor.MonitorException; import sun.jvmstat.monitor.MonitoredHost; +import com.redhat.thermostat.agent.storage.Category; +import com.redhat.thermostat.agent.storage.Key; +import com.redhat.thermostat.agent.storage.Chunk; import com.redhat.thermostat.backend.Backend; import com.redhat.thermostat.common.CpuStat; import com.redhat.thermostat.common.HostInfo; import com.redhat.thermostat.common.MemoryStat; +import com.redhat.thermostat.common.NetworkInterfaceInfo; import com.redhat.thermostat.common.NotImplementedException; import com.redhat.thermostat.common.utils.LoggingUtils; @@ -27,7 +34,7 @@ private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class); - private long procCheckInterval = 1000; + private long procCheckInterval = 1000; // TODO make this configurable. private Timer timer = null; @@ -35,6 +42,76 @@ private MonitoredHost host = null; private JvmStatHostListener hostListener = new JvmStatHostListener(); + private List<Category> categories = new ArrayList<Category>(); + + private Category hostInfoCategory = new Category("host-info"); + private Key hostNameKey = new Key("hostname", true); + private Key osNameKey = new Key("os_name", false); + private Key osKernelKey = new Key("os_kernel", false); + private Key cpuCountKey = new Key("cpu_num", false); + private Key hostMemoryTotalKey = new Key("memory_total", false); + + private Category networkInfoCategory = new Category("network-info"); + private Key ifaceKey = new Key("iface", true); + private Key ip4AddrKey = new Key("ipv4addr", false); + private Key ip6AddrKey = new Key("ipv6addr", false); + + private Category cpuStatCategory = new Category("cpu-stats"); + private Key cpu5LoadKey = new Key("5load", false); + private Key cpu10LoadKey = new Key("10load", false); + private Key cpu15LoadKey = new Key("15load", false); + + private Category memoryStatCategory = new Category("memory-stats"); + private Key memoryTotalKey = new Key("total", false); + private Key memoryFreeKey = new Key("free", false); + private Key memoryBuffersKey = new Key("buffers", false); + private Key memoryCachedKey = new Key("cached", false); + private Key memorySwapTotalKey = new Key("swap-total", false); + private Key memorySwapFreeKey = new Key("swap-free", false); + private Key memoryCommitLimitKey = new Key("commit-limit", false); + + { + // Set up categories that will later be registered. + // host-info category. + hostInfoCategory.addKey(hostNameKey); + hostInfoCategory.addKey(osNameKey); + hostInfoCategory.addKey(osKernelKey); + hostInfoCategory.addKey(cpuCountKey); + hostInfoCategory.addKey(hostMemoryTotalKey); + hostInfoCategory.lock(); + categories.add(hostInfoCategory); + + //network-info category + networkInfoCategory.addKey(ifaceKey); + networkInfoCategory.addKey(ip4AddrKey); + networkInfoCategory.addKey(ip6AddrKey); + networkInfoCategory.lock(); + categories.add(networkInfoCategory); + + // cpu-stats category. + cpuStatCategory.addKey(Key.TIMESTAMP); + cpuStatCategory.addKey(cpu5LoadKey); + cpuStatCategory.addKey(cpu10LoadKey); + cpuStatCategory.addKey(cpu15LoadKey); + cpuStatCategory.lock(); + categories.add(cpuStatCategory); + + // memory-stat category. + memoryStatCategory.addKey(Key.TIMESTAMP); + memoryStatCategory.addKey(memoryTotalKey); + memoryStatCategory.addKey(memoryFreeKey); + memoryStatCategory.addKey(memoryBuffersKey); + memoryStatCategory.addKey(memoryCachedKey); + memoryStatCategory.addKey(memorySwapTotalKey); + memoryStatCategory.addKey(memorySwapFreeKey); + memoryStatCategory.addKey(memoryCommitLimitKey); + memoryStatCategory.lock(); + categories.add(memoryStatCategory); + + categories.addAll(JvmStatHostListener.getCategories()); + categories.addAll(JvmStatVmListener.getCategories()); + } + @Override protected void setConfigurationValue(String name, String value) { @@ -72,30 +149,29 @@ return true; } - HostInfo hostInfo = new HostInfoBuilder().build(); - storage.updateHostInfo(hostInfo); + store(makeHostChunk(HostInfoBuilder.build())); timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { - CpuStat cpuStat = new CpuStatBuilder().build(); - storage.addCpuStat(cpuStat); - - MemoryStat memoryStat = new MemoryStatBuilder().build(); - storage.addMemoryStat(memoryStat); + store(makeCpuChunk(new CpuStatBuilder().build())); + for (Iterator<NetworkInterfaceInfo> iter = NetworkInfoBuilder.build().getInterfacesIterator(); iter.hasNext();) { + store(makeNetworkChunk(iter.next())); + } + store(makeMemoryChunk(new MemoryStatBuilder().build())); } }, 0, procCheckInterval); try { hostId = new HostIdentifier((String) null); host = MonitoredHost.getMonitoredHost(hostId); - hostListener.setStorage(storage); + hostListener.setBackend(this); host.addHostListener(hostListener); } catch (MonitorException me) { - logger.log(Level.WARNING , "problems with connecting jvmstat to local machien" , me); + logger.log(Level.WARNING , "problems with connecting jvmstat to local machine" , me); } catch (URISyntaxException use) { - logger.log(Level.WARNING , "problems with connecting jvmstat to local machien" , use); + logger.log(Level.WARNING , "problems with connecting jvmstat to local machine" , use); } return true; @@ -132,4 +208,54 @@ return null; } + @Override + protected Iterator<Category> getCategoryIterator() { + return categories.iterator(); + } + + private Chunk makeCpuChunk(CpuStat cpuStat) { + Chunk chunk = new Chunk(/*cpuStat.getTimeStamp(), */cpuStatCategory, false); + chunk.put(Key.TIMESTAMP, Long.toString(cpuStat.getTimeStamp())); + chunk.put(cpu5LoadKey, Double.toString(cpuStat.getLoad5())); + chunk.put(cpu10LoadKey, Double.toString(cpuStat.getLoad10())); + chunk.put(cpu15LoadKey, Double.toString(cpuStat.getLoad15())); + return chunk; + } + + private Chunk makeHostChunk(HostInfo hostInfo) { + Chunk chunk = new Chunk(hostInfoCategory, false); + chunk.put(hostNameKey, hostInfo.getHostname()); + chunk.put(osNameKey, hostInfo.getOsName()); + chunk.put(osKernelKey, hostInfo.getOsKernel()); + chunk.put(cpuCountKey, Integer.toString(hostInfo.getCpuCount())); + chunk.put(hostMemoryTotalKey, Long.toString(hostInfo.getTotalMemory())); + return chunk; + } + + private Chunk makeNetworkChunk(NetworkInterfaceInfo info) { + Chunk chunk = new Chunk(networkInfoCategory, true); + chunk.put(ifaceKey, info.getInterfaceName()); + String ip4 = info.getIp4Addr(); + if (ip4 != null) { + chunk.put(ip4AddrKey, ip4); + } + String ip6 = info.getIp6Addr(); + if (ip6 != null) { + chunk.put(ip6AddrKey, ip6); + } + return chunk; + } + + private Chunk makeMemoryChunk(MemoryStat mem) { + Chunk chunk = new Chunk(memoryStatCategory, false); + chunk.put(Key.TIMESTAMP, Long.toString(mem.getTimeStamp())); + chunk.put(memoryTotalKey, Long.toString(mem.getTotal())); + chunk.put(memoryFreeKey, Long.toString(mem.getFree())); + chunk.put(memoryBuffersKey, Long.toString(mem.getBuffers())); + chunk.put(memoryCachedKey, Long.toString(mem.getCached())); + chunk.put(memorySwapTotalKey, Long.toString(mem.getSwapTotal())); + chunk.put(memorySwapFreeKey, Long.toString(mem.getSwapFree())); + chunk.put(memoryCommitLimitKey, Long.toString(mem.getCommitLimit())); + return chunk; + } }
--- a/src/com/redhat/thermostat/common/Constants.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/common/Constants.java Thu Dec 22 18:45:12 2011 -0500 @@ -6,8 +6,6 @@ */ public class Constants { - public static final String LOG_LEVEL_CONFIG = "com.redhat.thermostat.level="; - public static final String AGENT_PROPERTIES_FILE = "config/agent.properties"; public static final int EXIT_UNKNOWN_ERROR = 1;
--- a/src/com/redhat/thermostat/common/HostInfo.java Fri Dec 16 17:33:54 2011 -0500 +++ b/src/com/redhat/thermostat/common/HostInfo.java Thu Dec 22 18:45:12 2011 -0500 @@ -1,8 +1,5 @@ package com.redhat.thermostat.common; -import java.util.List; -import java.util.Map; - public class HostInfo { private final String hostname; @@ -10,15 +7,13 @@ private final String osKernel; private final int cpuCount; private final long totalMemory; - private final Map<String, List<String>> networkInfo; - public HostInfo(String hostname, String osName, String osKernel, int cpuCount, long totalMemory, Map<String, List<String>> networkInfo) { + public HostInfo(String hostname, String osName, String osKernel, int cpuCount, long totalMemory) { this.hostname = hostname; this.osName = osName; this.osKernel = osKernel; this.cpuCount = cpuCount; this.totalMemory = totalMemory; - this.networkInfo = networkInfo; } public String getHostname() { @@ -43,13 +38,4 @@ public long getTotalMemory() { return totalMemory; } - - /** - * @returns a map of the following form: {iface-name: [ipv4_addr, - * ipv6_addr]} - */ - public Map<String, List<String>> getNetworkInfo() { - return networkInfo; - } - }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/common/NetworkInfo.java Thu Dec 22 18:45:12 2011 -0500 @@ -0,0 +1,26 @@ +package com.redhat.thermostat.common; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class NetworkInfo { + + private Map<String, NetworkInterfaceInfo> interfaces = new HashMap<String, NetworkInterfaceInfo>(); + + public NetworkInfo() { + + } + + public synchronized void addNetworkInterfaceInfo(NetworkInterfaceInfo info) { + interfaces.put(info.getInterfaceName(), info); + } + + public synchronized void removeNetworkInterfaceInfo(NetworkInterfaceInfo info) { + interfaces.remove(info.getInterfaceName()); + } + + public Iterator<NetworkInterfaceInfo> getInterfacesIterator() { + return interfaces.values().iterator(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/common/NetworkInterfaceInfo.java Thu Dec 22 18:45:12 2011 -0500 @@ -0,0 +1,42 @@ +package com.redhat.thermostat.common; + +public class NetworkInterfaceInfo { + + private String iFace; + private String ip4Addr; + private String ip6Addr; + + public NetworkInterfaceInfo(String iFace) { + this.iFace = iFace; + this.ip4Addr = null; + this.ip6Addr = null; + } + + public String getInterfaceName() { + return iFace; + } + + public String getIp4Addr() { + return ip4Addr; + } + + public void setIp4Addr(String newAddr) { + ip4Addr = newAddr; + } + + public void clearIp4Addr() { + ip4Addr = null; + } + + public String getIp6Addr() { + return ip6Addr; + } + + public void setIp6Addr(String newAddr) { + ip6Addr = newAddr; + } + + public void clearIp6Addr() { + ip6Addr = null; + } +}