blob: a382d4b62694b50ddd8bec5c0429d36ca98e9e35 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.monitor.integration;
import static java.lang.Integer.parseInt;
import static java.lang.System.getProperty;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.util.BytesContentProvider;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.monitor.JMXMonitor;
import org.eclipse.jetty.monitor.jmx.EventNotifier;
import org.eclipse.jetty.monitor.jmx.EventState;
import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
import org.eclipse.jetty.monitor.jmx.EventTrigger;
import org.eclipse.jetty.monitor.jmx.MonitorAction;
import org.eclipse.jetty.monitor.triggers.AggregateEventTrigger;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
public class JavaMonitorAction extends MonitorAction
{
private static final Logger LOG = Log.getLogger(JavaMonitorAction.class);
private final HttpClient _client;
private final String _url;
private final String _uuid;
private final String _appid;
private String _srvip;
private String _session;
/* ------------------------------------------------------------ */
public JavaMonitorAction(EventNotifier notifier, String url, String uuid, String appid, long pollInterval)
throws Exception
{
super(new AggregateEventTrigger(),notifier,pollInterval);
_url = url;
_uuid = uuid;
_appid = appid;
QueuedThreadPool executor = new QueuedThreadPool();
executor.setName(executor.getName() + "-monitor");
_client = new HttpClient();
_client.setExecutor(executor);
try
{
_client.start();
_srvip = getServerIP();
}
catch (Exception ex)
{
LOG.debug(ex);
}
sendData(new Properties());
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.monitor.jmx.MonitorAction#execute(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long)
*/
@Override
public void execute(EventTrigger trigger, EventState<?> state, long timestamp)
{
exec(trigger, state, timestamp);
}
/* ------------------------------------------------------------ */
/**
* @param trigger
* @param state
* @param timestamp
*/
private <T> void exec(EventTrigger trigger, EventState<T> state, long timestamp)
{
Collection<TriggerState<T>> trs = state.values();
Properties data = new Properties();
for (TriggerState<T> ts : trs)
{
Object value = ts.getValue();
StringBuffer buffer = new StringBuffer();
buffer.append(value == null ? "" : value.toString());
buffer.append("|");
buffer.append(getClassID(value));
buffer.append("||");
buffer.append(ts.getDescription());
data.setProperty(ts.getID(), buffer.toString());
try
{
sendData(data);
}
catch (Exception ex)
{
LOG.debug(ex);
}
}
}
/* ------------------------------------------------------------ */
/**
* @param data
* @throws Exception
*/
private void sendData(Properties data)
throws Exception
{
data.put("account", _uuid);
data.put("appserver", "Jetty");
data.put("localIp", _srvip);
if (_appid == null)
data.put("lowestPort", getHttpPort());
else
data.put("lowestPort", _appid);
if (_session != null)
data.put("session", _session);
Properties response = sendRequest(data);
parseResponse(response);
}
/* ------------------------------------------------------------ */
/**
* @param request
* @return
* @throws Exception
*/
private Properties sendRequest(Properties request)
throws Exception
{
ByteArrayOutputStream reqStream = null;
ByteArrayInputStream resStream = null;
Properties response = null;
try {
reqStream = new ByteArrayOutputStream();
request.storeToXML(reqStream,null);
ContentResponse r3sponse = _client.POST(_url)
.header("Connection","close")
.content(new BytesContentProvider(reqStream.toByteArray()))
.send();
if (r3sponse.getStatus() == HttpStatus.OK_200)
{
response = new Properties();
resStream = new ByteArrayInputStream(r3sponse.getContent());
response.loadFromXML(resStream);
}
}
finally
{
try
{
if (reqStream != null)
reqStream.close();
}
catch (IOException ex)
{
LOG.ignore(ex);
}
try
{
if (resStream != null)
resStream.close();
}
catch (IOException ex)
{
LOG.ignore(ex);
}
}
return response;
}
/* ------------------------------------------------------------ */
private void parseResponse(Properties response)
{
if (response.get("onhold") != null)
throw new Error("Suspended");
if (response.get("session") != null)
{
_session = (String) response.remove("session");
AggregateEventTrigger trigger = (AggregateEventTrigger)getTrigger();
String queryString;
ObjectName[] queryResults;
for (Map.Entry<Object, Object> entry : response.entrySet())
{
String[] values = ((String) entry.getValue()).split("\\|");
queryString = values[0];
if (queryString.startsWith("com.javamonitor.openfire"))
continue;
if (queryString.startsWith("com.javamonitor"))
{
queryString = "org.eclipse.jetty.monitor.integration:type=javamonitortools,id=0";
}
queryResults = null;
try
{
queryResults = queryNames(queryString);
}
catch (IOException e)
{
LOG.debug(e);
}
catch (MalformedObjectNameException e)
{
LOG.debug(e);
}
if (queryResults != null)
{
int idx = 0;
for(ObjectName objName : queryResults)
{
String id = entry.getKey().toString()+(idx == 0 ? "" : ":"+idx);
String name = queryString.equals(objName.toString()) ? "" : objName.toString();
boolean repeat = Boolean.parseBoolean(values[2]);
trigger.add(new JavaMonitorTrigger(objName, values[1], id, name, repeat));
}
}
}
}
}
/* ------------------------------------------------------------ */
/**
* @param value
* @return
*/
private int getClassID(final Object value)
{
if (value == null)
return 0;
if (value instanceof Byte ||
value instanceof Short ||
value instanceof Integer ||
value instanceof Long)
return 1;
if (value instanceof Float ||
value instanceof Double)
return 2;
if (value instanceof Boolean)
return 3;
return 4; // String
}
/* ------------------------------------------------------------ */
/**
* @return
* @throws Exception
*/
private String getServerIP()
throws Exception
{
Socket s = null;
try {
if (getProperty("http.proxyHost") != null)
{
s = new Socket(getProperty("http.proxyHost"),
parseInt(getProperty("http.proxyPort", "80")));
}
else
{
int port = 80;
URL url = new URL(_url);
if (url.getPort() != -1) {
port = url.getPort();
}
s = new Socket(url.getHost(), port);
}
return s.getLocalAddress().getHostAddress();
}
finally
{
try
{
if (s != null)
s.close();
}
catch (IOException ex)
{
LOG.ignore(ex);
}
}
}
/* ------------------------------------------------------------ */
public Integer getHttpPort()
{
Collection<ObjectName> connectors = null;
MBeanServerConnection service;
try
{
service = JMXMonitor.getServiceConnection();
connectors = service.queryNames(new ObjectName("org.eclipse.jetty.nio:type=selectchannelconnector,*"), null);
if (connectors != null && connectors.size() > 0)
{
Integer lowest = Integer.MAX_VALUE;
for (final ObjectName connector : connectors) {
lowest = (Integer)service.getAttribute(connector, "port");
}
if (lowest < Integer.MAX_VALUE)
return lowest;
}
}
catch (Exception ex)
{
LOG.debug(ex);
}
return 0;
}
/* ------------------------------------------------------------ */
/**
* @param param
* @return
* @throws IOException
* @throws NullPointerException
* @throws MalformedObjectNameException
*/
private ObjectName[] queryNames(ObjectName param)
throws IOException, MalformedObjectNameException
{
ObjectName[] result = null;
MBeanServerConnection connection = JMXMonitor.getServiceConnection();
Set names = connection.queryNames(param, null);
if (names != null && names.size() > 0)
{
result = new ObjectName[names.size()];
int idx = 0;
for(Object name : names)
{
if (name instanceof ObjectName)
result[idx++] = (ObjectName)name;
else
result[idx++] = new ObjectName(name.toString());
}
}
return result;
}
private ObjectName[] queryNames(String param)
throws IOException, MalformedObjectNameException
{
return queryNames(new ObjectName(param));
}
}