001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2002-2004 French National Institute For Research In Computer
004: * Science And Control (INRIA).
005: * Copyright (C) 2005 Continuent, Inc.
006: * Contact: sequoia@continuent.org
007: *
008: * Licensed under the Apache License, Version 2.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: * Initial developer(s): Emmanuel Cecchet.
021: * Contributor(s): ______________________________________.
022: */package org.continuent.sequoia.controller.monitoring;
023:
024: import java.util.ArrayList;
025: import java.util.Collection;
026: import java.util.Hashtable;
027: import java.util.Iterator;
028:
029: import org.continuent.sequoia.common.log.Trace;
030: import org.continuent.sequoia.common.util.Stats;
031: import org.continuent.sequoia.common.xml.DatabasesXmlTags;
032: import org.continuent.sequoia.controller.requests.AbstractRequest;
033:
034: /**
035: * This class implements a SQL monitoring module.
036: *
037: * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
038: * @version 1.0
039: */
040: public class SQLMonitoring extends Monitoring {
041: private Hashtable statList; // SQL query -> Stat
042: private ArrayList ruleList;
043: private boolean defaultRule;
044:
045: private static Trace logger = null;
046:
047: /**
048: * Create a SQLMonitoring object.
049: *
050: * @param vdbName name of the virtual database to be used by the logger
051: */
052: public SQLMonitoring(String vdbName) {
053: statList = new Hashtable();
054: ruleList = new ArrayList();
055: logger = Trace
056: .getLogger("org.continuent.sequoia.controller.monitoring."
057: + vdbName);
058: setActive(true);
059: }
060:
061: /**
062: * @see org.continuent.sequoia.controller.monitoring.Monitoring#cleanStats()
063: */
064: public void cleanStats() {
065: statList.clear();
066: }
067:
068: /**
069: * Log the time elapsed to execute the given request. The time is computed
070: * from the request start and end time stored in the object.
071: *
072: * @param request the request executed
073: */
074: public final void logRequestTime(AbstractRequest request) {
075: Stats stat = getStatForRequest(request);
076: if (stat == null)
077: return;
078: stat.incrementCount();
079: long time = request.getEndTime() - request.getStartTime();
080: stat.updateTime(time);
081: if (logger.isDebugEnabled())
082: logger.debug(time + "ms for " + stat.getName());
083: }
084:
085: /**
086: * Log an error for the given request.
087: *
088: * @param request the request that failed to execute
089: */
090: public final void logError(AbstractRequest request) {
091: Stats stat = getStatForRequest(request);
092: if (stat == null)
093: return;
094: stat.incrementError();
095: if (logger.isDebugEnabled())
096: logger.debug("ERROR " + stat.getName());
097: }
098:
099: /**
100: * Log a cache hit for the given request.
101: *
102: * @param request the request that failed to execute
103: */
104: public final void logCacheHit(AbstractRequest request) {
105: Stats stat = getStatForRequest(request);
106: if (stat == null)
107: return;
108: stat.incrementCacheHit();
109: if (logger.isDebugEnabled())
110: logger.debug("Cache hit " + stat.getName());
111: }
112:
113: /**
114: * Reset the stats associated to a request.
115: *
116: * @param request the request to reset
117: */
118: public final void resetRequestStat(AbstractRequest request) {
119: Stats stat = getStatForRequest(request);
120: if (stat == null)
121: return;
122: stat.reset();
123: }
124:
125: /**
126: * Retrieve the stat corresponding to a request and create it if it does not
127: * exist.
128: *
129: * @param request the request to look for
130: * @return corresponding stat or null if a rule does not authorize this
131: * request to be monitored
132: */
133: public final Stats getStatForRequest(AbstractRequest request) {
134: String sql = monitorRequestRule(request);
135: if (sql == null)
136: return null;
137:
138: // Note that the Hashtable is synchronized
139: Stats stat = (Stats) statList.get(sql);
140: if (stat == null) { // No entry for this query, create a new Stats entry
141: stat = new Stats(sql);
142: statList.put(sql, stat);
143: }
144: return stat;
145: }
146:
147: /**
148: * Return all stats information in the form of a String
149: *
150: * @return stats information
151: */
152: public String[][] getAllStatsInformation() {
153: Collection values = statList.values();
154: String[][] result = new String[values.size()][];
155: int i = 0;
156: for (Iterator iter = values.iterator(); iter.hasNext(); i++) {
157: Stats stat = (Stats) iter.next();
158: result[i] = stat.toStringTable();
159: }
160: return result;
161: }
162:
163: /**
164: * Dump all stats using the current logger (INFO level).
165: */
166: public void dumpAllStatsInformation() {
167: if (logger.isInfoEnabled()) {
168: for (Iterator iter = statList.values().iterator(); iter
169: .hasNext();) {
170: Stats stat = (Stats) iter.next();
171: logger.info(stat.singleLineDisplay());
172: }
173: }
174: }
175:
176: /*
177: * Rules Management
178: */
179:
180: /**
181: * Get the default monitoring rule
182: *
183: * @return true if default is monitoring enabled
184: */
185: public boolean getDefaultRule() {
186: return defaultRule;
187: }
188:
189: /**
190: * Defines the default rule
191: *
192: * @param monitoring true if on, false is off
193: */
194: public void setDefaultRule(boolean monitoring) {
195: this .defaultRule = monitoring;
196: }
197:
198: /**
199: * Add a rule to the list.
200: *
201: * @param rule the rule to add
202: */
203: public void addRule(SQLMonitoringRule rule) {
204: this .ruleList.add(rule);
205: }
206:
207: /**
208: * Check the rule list to check if this request should be monitored or not.
209: *
210: * @param request the query to look for
211: * @return the SQL query to monitor or null if monitoring is off for this
212: * request
213: */
214: private String monitorRequestRule(AbstractRequest request) {
215: for (int i = 0; i < ruleList.size(); i++) {
216: SQLMonitoringRule rule = (SQLMonitoringRule) ruleList
217: .get(i);
218: String sql = rule.matches(request);
219: if (sql != null) { // This rule matches
220: if (rule.isMonitoring())
221: return sql;
222: else
223: return null;
224: }
225: }
226:
227: // No rule matched, use the default rule
228: if (defaultRule)
229: return request.getSqlOrTemplate();
230: else
231: return null;
232: }
233:
234: /**
235: * @return Returns the ruleList.
236: */
237: public ArrayList getRuleList() {
238: return ruleList;
239: }
240:
241: /**
242: * @see org.continuent.sequoia.common.xml.XmlComponent#getXml()
243: */
244: public String getXmlImpl() {
245: String info = "<" + DatabasesXmlTags.ELT_SQLMonitoring + " "
246: + DatabasesXmlTags.ATT_defaultMonitoring + "=\"";
247: String defaultMonitoring = getDefaultRule() ? "on" : "off";
248: info += defaultMonitoring;
249: info += "\">";
250: for (int i = 0; i < ruleList.size(); i++) {
251: SQLMonitoringRule rule = (SQLMonitoringRule) ruleList
252: .get(i);
253: info += rule.getXml();
254: }
255: info += "</" + DatabasesXmlTags.ELT_SQLMonitoring + ">";
256: return info;
257: }
258:
259: }
|