001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.monitoring.snapshot;
018
019 import java.io.File;
020 import java.lang.reflect.UndeclaredThrowableException;
021 import java.util.ArrayList;
022 import java.util.HashMap;
023 import java.util.Iterator;
024 import java.util.Properties;
025 import java.util.Set;
026
027 import javax.management.ObjectName;
028 import javax.naming.Context;
029 import javax.naming.InitialContext;
030
031 import org.apache.commons.logging.Log;
032 import org.apache.commons.logging.LogFactory;
033 import org.apache.geronimo.monitoring.MBeanHelper;
034 import org.apache.geronimo.monitoring.MasterRemoteControlLocal;
035
036 /**
037 * Thread that is in charge of executing every x milliseconds. Upon each
038 * iteration, a snapshot of the server's information is recorded.
039 */
040 public class SnapshotProcessor {
041
042 private static Log log = LogFactory.getLog(SnapshotProcessor.class);
043
044 /**
045 * Collects JSR-77 statistics for all mbeans that have been chosen to
046 * be monitored and stores it in a DB. Will also, archive snapshots
047 * if they have passed their retention period.
048 * @param username
049 * @param password
050 */
051 public static void takeSnapshot(String username, String password) {
052 // ensure that there is a 'monitoring' directory
053 ensureMonitorDir();
054 // get any saved mbean names from snapshot-config.xml
055 ArrayList<String> mbeanNames = SnapshotConfigXMLBuilder.getMBeanNames();
056 // get a handle on the mrc
057 MasterRemoteControlLocal mrc = getMRC(username, password);
058 // in the case where nothing is present, grab a set of default mbeans
059 if(mbeanNames.size() <= 0) {
060 mbeanNames = getDefaultMBeanList(mrc);
061 }
062 // turn on all stats in the list
063 setStatsOn(mbeanNames, mrc);
064 try {
065 // take a snapshot
066 log.info("======SNAPSHOT======");
067 // instantiate map <mbean name, stats for mbean>
068 HashMap<String, HashMap<String, Long>> aggregateStats = new HashMap<String, HashMap<String, Long>>();
069 // for each mbean name in the list, get its stats
070 for(int i = 0; i < mbeanNames.size(); i++) {
071 String mbeanName = mbeanNames.get(i);
072 HashMap<String, Long> stats = (HashMap<String, Long>)mrc.getStats(mbeanName);
073 aggregateStats.put(mbeanName, stats);
074 }
075
076 // store the data in a DB
077 (new SnapshotDBHelper()).addSnapshotToDB(aggregateStats);
078
079 for(Iterator itt = aggregateStats.keySet().iterator(); itt.hasNext(); ) {
080 String mbean = (String)itt.next();
081 HashMap<String, Long> stats = aggregateStats.get(mbean);
082 log.info(mbean);
083 for(Iterator it = stats.keySet().iterator(); it.hasNext(); ) {
084 String key = (String)it.next();
085 Long value = (Long)stats.get(key);
086 log.info(key + ": " + value);
087 }
088 }
089 } catch(Exception e) {
090 log.error(e.getMessage(), e);
091 }
092 }
093
094 /**
095 * Turns all statistics on for each mbean in the list.
096 *
097 * @param mbeanList
098 */
099 private static void setStatsOn(ArrayList<String> mbeanList, MasterRemoteControlLocal mrc) {
100 // for each mbean name in the list
101 for(int i = 0; i < mbeanList.size(); i++) {
102 // turn the statistics collection on
103 String methodName = "setStatsOn";
104 Object[] params = new Object[] { Boolean.TRUE };
105 String[] signatures = new String[] { "boolean" };
106 try {
107 ObjectName objName = new ObjectName(mbeanList.get(i));
108 mrc.invoke(objName, methodName, params, signatures);
109 log.info("Stats for " + mbeanList.get(i) + " was turned on.");
110 }catch (UndeclaredThrowableException e) {
111 // HACK : this will happen for components that always collect statistics
112 // and do not have StatsOn method.
113 } catch(Exception e) {
114 log.error(e.getMessage(), e);
115 }
116 }
117 }
118
119 /**
120 * @return A list of all default mbeans; namely, all connector or container mbean names
121 * Prereq: in order to be a connector or container mbean the name must contain "Connector"/"Container"
122 * and "Tomcat"/"Jetty" or JVM.
123 */
124 private static ArrayList<String> getDefaultMBeanList(MasterRemoteControlLocal mrc) {
125 Set<String> mbeans = MBeanHelper.getStatsProvidersMBeans( mrc.getAllMBeanNames() );
126 ArrayList<String> retval = new ArrayList<String>();
127 for(Iterator it = mbeans.iterator(); it.hasNext(); ) {
128 String name = (String)it.next();
129 if(((name.contains("Connector") || name.contains("Container")) && (name.contains("Jetty") || name.contains("Tomcat")))
130 || name.contains("JVM")) {
131 // this is a connector or JVM, so add to the list
132 retval.add(name);
133 // update the snapshot-config.xml to include these
134 SnapshotConfigXMLBuilder.addMBeanName(name);
135 }
136 }
137 return retval;
138 }
139
140 /**
141 * Checks to see if the GERONIMO_HOME/var/monitoring/ directory was made.
142 * If not, the method creates it.
143 */
144 public static void ensureMonitorDir() {
145 final String pathToDir =
146 System.getProperty("org.apache.geronimo.home.dir") + "/var/monitoring/";
147 File dir = new File(pathToDir);
148 if(dir.exists() && dir.isDirectory()) {
149 // all good
150 return;
151 } else {
152 // make a directory
153 if(dir.mkdir()) {
154 // directory was successfully created
155 log.info("/var/monitoring directory created.");
156 return;
157 } else {
158 log.error("Could not make the directory " + pathToDir);
159 }
160 }
161 }
162
163 /**
164 * @return An instance of a MRC.
165 */
166 public static MasterRemoteControlLocal getMRC(String username, String password) {
167 Properties props = new Properties();
168 props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
169 props.setProperty(Context.SECURITY_PRINCIPAL, username);
170 props.setProperty(Context.SECURITY_CREDENTIALS, password);
171 props.setProperty("openejb.authentication.realmName", "geronimo-admin");
172 try {
173 Context ic = new InitialContext(props);
174 MasterRemoteControlLocal mrc = (MasterRemoteControlLocal)ic.lookup("ejb/mgmt/MRCLocal");
175 return mrc;
176 } catch(Exception e) {
177 return null;
178 }
179 }
180 }