/* * Copyright 2012 NGDATA nv * * Licensed 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.lilyproject.clientmetrics; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.openmbean.CompositeDataSupport; import java.io.PrintStream; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.joda.time.Period; import org.joda.time.format.PeriodFormat; import org.lilyproject.util.zookeeper.ZooKeeperItf; /** * Various utility methods to pull interesting data from Lily. */ public class LilyMetrics { private ZooKeeperItf zk; private JmxConnections jmxConnections = new JmxConnections(); private static final String LILY_JMX_PORT = "10202"; public LilyMetrics(ZooKeeperItf zk) { this.zk = zk; } public void close() { jmxConnections.close(); } public void outputLilyServerInfo(PrintStream ps) throws Exception { Table table = new Table(ps); table.addColumn(30, "Lily server", "s"); table.addColumn(10, "Version", "s"); table.addColumn(-1, "IndexerMaster", "s"); table.addColumn(-1, "Max heap", "f"); table.addColumn(-1, "Used heap", "f"); table.finishDefinition(); List<String> lilyServers = zk.getChildren("/lily/repositoryNodes", false); table.fullSepLine(); table.crossColumn("Information on the Lily servers"); table.columnSepLine(); table.titles(); table.columnSepLine(); ObjectName lily = new ObjectName("Lily:name=Info"); ObjectName memory = new ObjectName("java.lang:type=Memory"); // This data structure is used to collect for each index, and for each server, the timestamp of the // last WALEdit processed by the SEP Map<String, Map<String, Long>> sepTimestampByIndexAndServer = new HashMap<String, Map<String, Long>>() { @Override public Map<String, Long> get(Object key) { Map<String, Long> value = super.get(key); if (value == null) { value = new HashMap<String, Long>(); put((String)key, value); } return value; } }; for (String server : lilyServers) { int colonPos = server.indexOf(':'); String address = server.substring(0, colonPos); MBeanServerConnection connection = jmxConnections.getConnector(address, LILY_JMX_PORT).getMBeanServerConnection(); String version = (String)connection.getAttribute(lily, "Version"); boolean indexerMaster = (Boolean)connection.getAttribute(lily, "IndexerMaster"); CompositeDataSupport heapMemUsage = (CompositeDataSupport)connection.getAttribute(memory, "HeapMemoryUsage"); double maxHeapMB = ((double)(Long)heapMemUsage.get("max")) / 1024d / 1024d; double usedHeapMB = ((double)(Long)heapMemUsage.get("used")) / 1024d / 1024d; table.columns(address, version, String.valueOf(indexerMaster), maxHeapMB, usedHeapMB); ObjectName indexUpdaterPattern = new ObjectName("Lily:service=SEP,name=IndexUpdater_*"); Set<ObjectName> indexUpdaterNames = connection.queryNames(indexUpdaterPattern, null); for (ObjectName indexUpdater : indexUpdaterNames) { Long lastSepTimestamp = (Long)connection.getAttribute(indexUpdater, "lastSepTimestamp"); String indexName = indexUpdater.getKeyProperty("name").substring("IndexUpdater_".length()); sepTimestampByIndexAndServer.get(indexName).put(server, lastSepTimestamp); } } table.columnSepLine(); if (sepTimestampByIndexAndServer.size() > 0) { long now = System.currentTimeMillis(); ps.println(); ps.println("SEP: how long ago was the timestamp of the last processed event:"); for (Map.Entry<String, Map<String, Long>> indexEntry : sepTimestampByIndexAndServer.entrySet()) { ps.println(" Index " + indexEntry.getKey()); for (Map.Entry<String, Long> serverEntry : indexEntry.getValue().entrySet()) { Period duration = new Period(now - serverEntry.getValue()); ps.println(" Server " + serverEntry.getKey() + ": " + PeriodFormat.getDefault().print(duration)); } } } } }