/**
* Global Sensor Networks (GSN) Source Code
* Copyright (c) 2006-2016, Ecole Polytechnique Federale de Lausanne (EPFL)
*
* This file is part of GSN.
*
* GSN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GSN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GSN. If not, see <http://www.gnu.org/licenses/>.
*
* File: src/ch/epfl/gsn/monitoring/MonitoringServer.java
*
* @author Julien Eberle
*
*/
package ch.epfl.gsn.monitoring;
import javax.net.ServerSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.epfl.gsn.Main;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Map;
public class MonitoringServer extends Thread {
private final transient Logger logger = LoggerFactory.getLogger( MonitoringServer.class );
private ServerSocket socket = null;
private boolean running = true;
private SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
/**
* Return statistics about the GSN server, faking an HTTP server for retro-compatibility
*
* the protocol is similar to the carbon protocol used by Graphite, except the timestamp
* http://matt.aimonetti.net/posts/2013/06/26/practical-guide-to-graphite-monitoring/
*/
public MonitoringServer(int port) {
super("Monitoring Server");
try {
ServerSocketFactory serverSocketFactory = ServerSocketFactory.getDefault();
socket = serverSocketFactory.createServerSocket(port);
socket.setSoTimeout(1000);
}catch(Exception e){
logger.error("unable to open socket for monitoring",e);
}
}
@Override
public void run(){
while (running){
try {
final Socket server = socket.accept();
server.setSoTimeout(60000);
logger.debug("monitoring accepted from "+server.getInetAddress());
Thread t = new Thread(new Runnable(){
@Override
public void run() {
try {
InputStream input = new BufferedInputStream(server.getInputStream());
OutputStream output = new BufferedOutputStream(server.getOutputStream());
byte[] b = new byte[3];
input.read(b);
if (new String(b).equalsIgnoreCase("get")){
StringBuilder values = new StringBuilder();
for (Monitorable m : Main.getInstance().getToMonitor()){
Hashtable<String,Object> h = m.getStatistics();
for (Map.Entry<String,Object> e : h.entrySet()){
values.append(e.getKey()).append(" ");
values.append(e.getValue()).append("\n");
}
}
byte[] content = values.toString().getBytes("utf-8");
String head = "HTTP/1.1 200 OK\r\nDate: " +
sdf.format(new Date()) +
"\r\nServer: Global Sensor Network(GSN)\r\nContent-Length: " +
content.length +
"\r\nCache-Control: public, max-age=0, no-cache\r\nConnection: close\r\n"+
"Content-Type: text/plain; charset=UTF-8\r\n\r\n";
output.write(head.getBytes("utf-8"));
output.write(content);
output.flush();
}
server.close();
}catch (Exception e){
logger.warn("Error while communicating with "+server.getInetAddress(), e);
}
}
});
t.setName("Monitoring thread");
t.start();
} catch(SocketTimeoutException ste){
// just keep trying until someone connects
} catch(IOException ioe){
logger.error("IO Error on monitoring connection.", ioe);
}
}
}
public void stopServer() {
try {
running = false;
Thread.sleep(1000);
socket.close();
Thread.sleep(100);
}catch(Exception e){}
}
}