001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.core.qos.metrics;
028:
029: import java.io.ObjectOutputStream;
030: import java.io.OutputStream;
031: import java.util.HashMap;
032: import java.util.StringTokenizer;
033:
034: import javax.servlet.http.HttpServlet;
035: import javax.servlet.http.HttpServletRequest;
036: import javax.servlet.http.HttpServletResponse;
037:
038: import org.cougaar.core.component.ServiceBroker;
039: import org.cougaar.core.service.ServletService;
040:
041: /**
042: * This Servlet allows url-based access into the metrics service.
043: * Requires uri parameter <code>paths</code>, the value of which is a
044: * set of Metrics paths, separated by '|'. Also takes an optional
045: * parameter <code>format</code>. If omitted or provided as 'xml',
046: * the output is an xml representation of the results of the queries.
047: * If supplied as 'java', the output is a serialization of an
048: * ArrayList of the results (useful for remote java invokers, not
049: * useful for web display).
050: *
051: * <p> Example:
052: * <p>http://localhost:8800/$3-69-ARBN/metrics/query?format=xml&paths=Agent($3-69-ARBN):Jips|Agent($3-69-ARBN):CPULoadJips10SecAvg
053: *
054: * <p> See org.cougaar.core.examples.metrics.ExampleMetricQueryClient
055: */
056:
057: public class MetricQueryServlet extends HttpServlet {
058: private MetricsService metricsService;
059:
060: public MetricQueryServlet(ServiceBroker sb) {
061: // Register our servlet with servlet service
062: ServletService servletService = (ServletService) sb.getService(
063: this , ServletService.class, null);
064: if (servletService == null) {
065: throw new RuntimeException(
066: "Unable to obtain ServletService");
067: }
068: try {
069: servletService.register(getPath(), this );
070: } catch (Exception e) {
071: throw new RuntimeException(
072: "Unable to register servlet at path <" + getPath()
073: + ">: " + e.getMessage());
074: }
075:
076: // get metrics service
077: try {
078: metricsService = (MetricsService) sb.getService(this ,
079: MetricsService.class, null);
080: } catch (Exception e) {
081: throw new RuntimeException(
082: "Unable to get MetricsService at path <"
083: + getPath() + ">: " + e.getMessage());
084: }
085: }
086:
087: public String getPath() {
088: return "/metrics/query";
089: }
090:
091: public String getTitle() {
092: return "Remote Metrics Access for Node";
093: }
094:
095: /*
096: * Parses params, and send out either a propertylist of metrics(java version),
097: * or a string of xml-formatted text, through a serialized byte array.
098: */
099: public void printPage(HttpServletRequest request, OutputStream out) {
100:
101: String metrics = null;
102: HashMap propertylist = null;
103:
104: try {
105: // parses params
106: String paths = request.getParameter("paths");
107: String format = "xml";
108: format = request.getParameter("format");
109:
110: // default format is a string of xml
111: if (format != null && format.equals("java")) {
112: // parse paths and send out serialized data
113: propertylist = build_propertylist(paths);
114: } else // it's xml
115: {
116: metrics = build_string(paths);
117: out.write(metrics.getBytes());
118: return;
119: }
120:
121: ObjectOutputStream oos = null;
122:
123: // serialize and send out java propertylist of metric data
124: try {
125: oos = new ObjectOutputStream(out);
126: oos.writeObject(propertylist);
127:
128: // don't close, that will end the stream, we don't want to do that
129: //oos.close();
130:
131: } catch (Exception e) {
132: // log here eventuually
133: System.out.println("Error writing metrics data " + e);
134: }
135: } catch (Exception e) {
136: // also log here
137: System.out.println("Exception: " + e);
138: e.printStackTrace();
139: }
140: }
141:
142: public String build_string(String paths) {
143: if (paths == null)
144: return "<?xml version='1.0'?>\n"
145: + "<!-- Null Metrics Query -->\n"
146: + "<!-- Usage: /metrics/query/?paths=Host(Foo):Jips|Host(Foo):LoadAverage -->\n"
147: + "<paths></paths>\n";
148:
149: StringTokenizer st = new StringTokenizer(paths, "|");
150:
151: /* If xml, then parse into xml string and return
152: Calls ServletUtilities.XMLString(Metric) for easy xml print format
153: It looks like (without the carriage return):
154: <paths>
155: <path>
156: <name>pathname</name>
157: <value>metricvalue</value>
158: <units>unitvalue</units>
159: <credibility>credibilityvalue</credibility>
160: <provenance>no idea what this is</provenance>
161: <timestamp>timestamp</timestamp>
162: <halflife>no idea what this is either</halflife>
163: </path>
164: </paths>
165: */
166:
167: // build string of xml metrics
168: String metrics = new String("<?xml version='1.0'?>");
169: metrics = metrics + "<paths>";
170:
171: // build property list
172: while (st.hasMoreTokens()) {
173: String path = st.nextToken();
174: metrics = metrics + "<path>";
175: metrics = metrics + "<name>";
176: metrics = metrics + path;
177: metrics = metrics + "</name>";
178:
179: try {
180: Metric pathMetric = metricsService.getValue(path);
181: // here we call XMLString(Metric), which is an xml toString() for Metric
182: metrics = metrics
183: + ServletUtilities.XMLString(pathMetric);
184: } catch (Exception e) {
185: metrics = metrics + ServletUtilities.XMLString(null);
186: }
187: metrics = metrics + "</path>";
188: }
189: metrics = metrics + "</paths>";
190: return metrics;
191: }
192:
193: /*
194: * Build a java HashMap, instead of xml
195: * Each element in the list will have the form: 'path|metric'
196: */
197: public HashMap build_propertylist(String paths) {
198: if (paths == null)
199: return null;
200:
201: StringTokenizer st = new StringTokenizer(paths, "|");
202:
203: // build propertylist
204: // element has the form: 'Query|Metric'
205: HashMap propertylist = new HashMap();
206:
207: // build property list
208: while (st.hasMoreTokens()) {
209: String path = st.nextToken();
210: Metric pathMetric = null;
211: try {
212: pathMetric = metricsService.getValue(path);
213: } catch (Exception e) {
214: // Bad path spec Leave pathMetric as null or "Undefined"
215: }
216: propertylist.put(path, pathMetric);
217: }
218: return propertylist;
219: }
220:
221: // servlet requirement - pass to our print method to handle
222: public void doGet(HttpServletRequest request,
223: HttpServletResponse response) throws java.io.IOException {
224: OutputStream out = response.getOutputStream();
225: printPage(request, out);
226: }
227: }
|