package org.aim.mainagent.csharp;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import org.aim.api.measurement.collector.AbstractDataSource;
import org.aim.api.measurement.collector.CollectorFactory;
import org.aim.artifacts.instrumentation.InstrumentationClient;
import org.aim.artifacts.measurement.collector.MemoryDataSource;
import org.aim.logging.AIMLogger;
import org.aim.logging.AIMLoggerFactory;
import org.aim.logging.AIMLoggingConfig;
import org.aim.logging.LoggingLevel;
import org.aim.mainagent.CEventAgentAdapter;
import org.aim.mainagent.csharp.services.CsInstrumentServlet;
import org.aim.mainagent.csharp.services.CsServiceHandler;
import org.aim.mainagent.csharp.services.CsUninstrumentServlet;
import org.aim.mainagent.service.CurrentTimeServlet;
import org.aim.mainagent.service.DisableMeasurementServlet;
import org.aim.mainagent.service.EnableMeasurementServlet;
import org.aim.mainagent.service.GetDataServlet;
import org.aim.mainagent.service.GetStateServlet;
import org.aim.mainagent.service.GetSupportedExtensionsServlet;
import org.aim.mainagent.service.MeasureOverheadServlet;
import org.aim.mainagent.service.MeasurementStateServlet;
import org.aim.mainagent.service.Service;
import org.aim.mainagent.service.TestConnectionServlet;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.http.server.Response;
import org.lpe.common.config.GlobalConfiguration;
import org.lpe.common.extension.ExtensionRegistry;
import org.lpe.common.util.system.LpeSystemUtils;
public final class DotNetAgent {
private static AIMLogger logger;
private static Boolean isInitialized = false;
private static AIMLogger getLogger() {
if (logger == null) {
logger = AIMLoggerFactory.getLogger(DotNetAgent.class);
}
return logger;
}
// //////////////////////
private static final AIMLoggingConfig aimLoggingConfig = new AIMLoggingConfig();
private static final String PORT_KEY = "port";
private static final String DATA_COLLECTOR_KEY = "collector";
private static final String PLUGINS_ROOT_KEY = "pluginsRootDir";
private static final String LOGGING_TYPE_KEY = "logType";
private static final String LOGGING_FILE_KEY = "logFile";
private static final String LOGGING_LEVEL_KEY = "logLevel";
private static final String DEFAULT_PLUGINS_FOLDER = "plugins";
public static final String URL_PATH_INSTRUMENTATION = InstrumentationClient.URL_PATH_INSTRUMENTATION;
public static final String URL_PATH_MEASUREMENT = InstrumentationClient.URL_PATH_MEASUREMENT;
public static final String PATH_PREFIX = InstrumentationClient.PATH_PREFIX;
private static String pluginsRoot;
private static String collectorType = MemoryDataSource.class.getName();
private static final Properties properties = new Properties();
private static String port = "8888";
private static CsServiceHandler serviceHandler;
/**
* @param instrumentListener
* the instrumentListener to set
*/
public static void setServiceHandler(CsServiceHandler instrumentListener) {
DotNetAgent.serviceHandler = instrumentListener;
}
/**
* @return the instrumentListener
*/
public static CsServiceHandler getServiceHandler() {
return serviceHandler;
}
public static void start(String agentConfig) {
synchronized (isInitialized) {
if (isInitialized) {
getLogger().debug("C# agent already started");
return;
} else {
getLogger().debug("Starting C# agent.");
isInitialized = true;
}
}
try {
parseArgs(agentConfig);
AIMLoggerFactory.initialize(aimLoggingConfig);
boolean cAgentInitializedSuccessfully = CEventAgentAdapter.initialize();
if (!cAgentInitializedSuccessfully) {
getLogger().warn("The C event agent could not be initialized and will not be used therefore.");
// TODO: handle this case
}
initializeGlobalConfig();
LpeSystemUtils.loadNativeLibraries();
initDataCollector();
startServer();
} catch (Exception e) {
e.printStackTrace();
getLogger().error("Agent ERROR: {}", e);
}
}
private static void initializeGlobalConfig() {
if (pluginsRoot == null) {
pluginsRoot = System.getProperty("user.dir");
}
Properties coreProperties = new Properties();
coreProperties.setProperty(ExtensionRegistry.APP_ROOT_DIR_PROPERTY_KEY, pluginsRoot);
coreProperties.setProperty(ExtensionRegistry.PLUGINS_FOLDER_PROPERTY_KEY, DEFAULT_PLUGINS_FOLDER);
GlobalConfiguration.initialize(coreProperties);
}
/**
* Initializes the data collector.
*/
private static void initDataCollector() {
AbstractDataSource dataSource = CollectorFactory.createDataSource(collectorType, properties);
AbstractDataSource.setDefaultDataSource(dataSource);
}
private static void startServer() {
HttpServer server = HttpServer.createSimpleServer("", Integer.parseInt(port));
try {
addServlet(server, new TestConnectionServlet(), "testConnection");
addServlet(server, new CsInstrumentServlet(), URL_PATH_INSTRUMENTATION + "/instrument");
addServlet(server, new CsUninstrumentServlet(), URL_PATH_INSTRUMENTATION + "/uninstrument");
addServlet(server, new GetStateServlet(), URL_PATH_INSTRUMENTATION + "/getState");
addServlet(server, new GetSupportedExtensionsServlet(), URL_PATH_INSTRUMENTATION
+ "/getSupportedExtensions");
addServlet(server, new EnableMeasurementServlet(), URL_PATH_MEASUREMENT + "/enable");
addServlet(server, new DisableMeasurementServlet(), URL_PATH_MEASUREMENT + "/disable");
addServlet(server, new GetDataServlet(), URL_PATH_MEASUREMENT + "/getdata");
addServlet(server, new CurrentTimeServlet(), URL_PATH_MEASUREMENT + "/currentTime");
addServlet(server, new MeasureOverheadServlet(), URL_PATH_MEASUREMENT + "/measureOverhead");
addServlet(server, new MeasurementStateServlet(), URL_PATH_MEASUREMENT + "/monitoringState");
server.start();
getLogger().info("Started Instrumentation Agent Server: {}.", getAddress());
} catch (IllegalArgumentException iae) {
getLogger().error("Illegal Argument Exception happend in main method of ServerLauncher: {}",
iae.getMessage());
} catch (IOException ioe) {
getLogger().error("IO Exception happend in main method of ServerLauncher: {}", ioe.getMessage());
}
}
private static void addServlet(final HttpServer server, final Service service, final String path) {
server.getServerConfiguration().addHttpHandler(new HttpHandler() {
@Override
public void service(Request req, Response resp) throws Exception {
service.doService(req, resp);
}
}, "/" + PATH_PREFIX + "/" + path);
}
/**
*
* @return Returns the server address for the REST service.
*/
private static String getAddress() {
return "http://0.0.0.0:" + port + "/" + PATH_PREFIX;
}
/**
* Parses the agent arguments.
*
* @param agentArgs
* arguments as string
*/
private static void parseArgs(String agentArgs) {
if (agentArgs == null) {
return;
}
File agentConfigFile = new File(agentArgs);
if (!agentConfigFile.isFile() || !agentConfigFile.exists()) {
return;
}
Properties agentProperties = new Properties();
try (FileReader reader = new FileReader(agentConfigFile)) {
agentProperties.load(reader);
} catch (IOException e) {
throw new RuntimeException(e);
}
for (Object key : agentProperties.keySet()) {
if (key.toString().equals(PORT_KEY)) {
port = agentProperties.getProperty(PORT_KEY);
} else if (key.toString().equals(DATA_COLLECTOR_KEY)) {
collectorType = agentProperties.getProperty(DATA_COLLECTOR_KEY);
} else if (key.toString().equals(PLUGINS_ROOT_KEY)) {
pluginsRoot = agentProperties.getProperty(PLUGINS_ROOT_KEY);
} else if (key.toString().equals(LOGGING_LEVEL_KEY)) {
aimLoggingConfig.setLoggingLevel(LoggingLevel.logLevelFromName(agentProperties
.getProperty(LOGGING_LEVEL_KEY)));
} else if (key.toString().equals(LOGGING_TYPE_KEY)) {
if (agentProperties.getProperty(LOGGING_TYPE_KEY).compareToIgnoreCase(
AIMLoggingConfig.LoggingType.STDOUT.toString()) == 0) {
aimLoggingConfig.setLoggingType(AIMLoggingConfig.LoggingType.STDOUT);
} else if (agentProperties.getProperty(LOGGING_TYPE_KEY).compareToIgnoreCase(
AIMLoggingConfig.LoggingType.FILE.toString()) == 0) {
aimLoggingConfig.setLoggingType(AIMLoggingConfig.LoggingType.FILE);
}
} else if (key.toString().equals(LOGGING_FILE_KEY)) {
String fileName = agentProperties.getProperty(LOGGING_FILE_KEY);
File file = new File(fileName);
aimLoggingConfig.setFileName(file.getAbsolutePath());
} else {
properties.put(key.toString(), agentProperties.getProperty(key.toString()));
}
}
}
}