package com.tts.jtcollector;
import com.tts.util.AvroSchemaSystem;
import org.apache.avro.Schema;
import org.apache.log4j.Logger;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created with IntelliJ IDEA.
* User: wendybartlett
* Date: 10/7/13
* Time: 3:09 PM
* To change this template use File | Settings | File Templates.
*/
public class JTCollector {
static Logger log = Logger.getLogger(JTCollector.class.getName());
private static List<String> listOfCollectors = Collections.synchronizedList(new ArrayList<String>());
private static List<String> listOfRunningCollectors = Collections.synchronizedList(new ArrayList<String>());
private static List<String> listOfMetrics = Collections.synchronizedList(new ArrayList<String>());
private static List<String> listOfMetricsForTSD = null;
private static List<String> listToNotRestart = Collections.synchronizedList(new ArrayList<String>());
public static ArrayList<CollectorWorker> worker_threads = new ArrayList<CollectorWorker>();
public static ArrayList<MetricSender> sender_threads = new ArrayList<MetricSender>();
private static Properties server_props = new Properties();
private static Properties producer_props = null;
private static String jtcollectorPath = null;
public static AvroSchemaSystem avro = null;
private static String properties_file = "";
private static boolean useTSD = false;
private static boolean useAvro = false;
private static boolean useKafka = false;
public static int numCollectorThreads = 1;
public static int numSenderThreads = 1;
public static int loaderWaitTime = 0;
public static AtomicLong numMessagesSent = new AtomicLong(0);
public static AtomicLong avroEncodeFailure = new AtomicLong(0);
private static CollectorLoader loader = null;
private static TSDClient tsd = null;
private static JTCollectorMetricsCollector jtcollector = null;
public static String metrics_topic;
public static String metrics_schema_id;
public static String prefixDelimiter;
public static String schemaRepoPath;
public static Schema writer_schema;
public static void shutdown(String[] args) {
try {
log.info("Received service shutdown request...");
for (CollectorWorker worker : worker_threads ) {
worker.freeResources();
worker.interrupt();
log.info("Shutting down: " + worker.getName());
}
for (MetricSender sender : sender_threads ) {
sender.freeResources();
sender.interrupt();
log.info("Shutting down: " + sender.getName());
}
if (useTSD) {
tsd.interrupt();
tsd.freeResources();
}
loader.interrupt();
loader.freeResources();
log.info("Shutting down: " + loader.getName());
jtcollector.freeResources();
jtcollector.interrupt();
log.info("Shutting down: " + jtcollector.getName());
} catch (Exception e) {
log.error("Error while attempting to shutdown!", e);
}
}
public static void main(String[] args) throws IOException {
// Get properties file from args
for (String arg : args) {
if (arg.contains("properties")) {
properties_file = arg;
}
}
// Load properties file
server_props.load(new FileInputStream(properties_file));
jtcollectorPath = server_props.getProperty("jtcollector.path");
loaderWaitTime = Integer.parseInt(server_props.getProperty("loader.wait.time", "300000")); //Wait 5 minutes before checking for offline loaders
numCollectorThreads = Integer.parseInt(server_props.getProperty("number.collector.threads"));
numSenderThreads = Integer.parseInt(server_props.getProperty("number.sender.threads"));
// Normalize the jtcollectorPath
if (!jtcollectorPath.substring(jtcollectorPath.length() - 1).equals(File.separator))
jtcollectorPath = jtcollectorPath + File.separator;
// Connect to TSD if host set, otherwise, check Avro and Kafka
String tsdHost = server_props.getProperty("tsd.host");
String tsdPort = null;
if (tsdHost.length() > 0 && (!tsdHost.equals("tsd.example.com")))
useTSD = true;
if (useTSD) {
tsdPort = server_props.getProperty("tsd.port", "4242");
listOfMetricsForTSD = Collections.synchronizedList(new ArrayList<String>());
// Start collector loader
log.info("Spawning tsd thread...");
tsd = new TSDClient(tsdHost, tsdPort, 5, listOfMetricsForTSD);
tsd.setName("TSD-Thread");
tsd.start();
} else {
log.info("JTCollector not using TSD...");
}
// Assign kafka properties
String kafkaBrokerList = server_props.getProperty("metadata.broker.list");
if (kafkaBrokerList.length() > 0 && (!kafkaBrokerList.equals("metadata_broker_list")) && (!kafkaBrokerList.equals(""))) {
useKafka = true;
}
if (useKafka) {
producer_props = new Properties();
producer_props.put("metadata.broker.list", server_props.getProperty("metadata.broker.list"));
producer_props.put("request.required.acks", server_props.getProperty("request.required.acks"));
producer_props.put("producer.type", server_props.getProperty("producer.type"));
producer_props.put("compression.codec", server_props.getProperty("compression.codec"));
producer_props.put("compressed.topics", server_props.getProperty("compressed.topics"));
producer_props.put("message.send.max.retries", server_props.getProperty("message.send.max.retries"));
producer_props.put("retry.backoff.ms", server_props.getProperty("retry.backoff.ms"));
producer_props.put("topic.metadata.refresh.interval.ms", server_props.getProperty("topic.metadata.refresh.interval.ms"));
producer_props.put("queue.buffering.max.ms", server_props.getProperty("queue.buffering.max.ms"));
producer_props.put("queue.buffering.max.messages", server_props.getProperty("queue.buffering.max.messages"));
producer_props.put("queue.enqueue.timeout.ms", server_props.getProperty("queue.enqueue.timeout.ms"));
producer_props.put("batch.num.messages", server_props.getProperty("batch.num.messages"));
producer_props.put("send.buffer.bytes", server_props.getProperty("send.buffer.bytes"));
producer_props.put("client.id", server_props.getProperty("client.id"));
producer_props.put("request.timeout.ms", server_props.getProperty("request.timeout.ms"));
}
// Get Avro schema for metrics
String schemaRepoHost = server_props.getProperty("avro.schema.repo.host");
if (schemaRepoHost.length() > 0 && (!schemaRepoHost.equals("avro.example.com")))
useAvro = true;
if (useAvro) {
String schemaRepoPort = server_props.getProperty("avro.schema.repo.port", "2876");
metrics_topic = server_props.getProperty("kafka.metrics.topic.name", "metrics");
metrics_schema_id = server_props.getProperty("avro.schema.id", "0");
prefixDelimiter = server_props.getProperty("prefix.delimiter", "");
schemaRepoPath = server_props.getProperty("avro.schema.repo.path");
// Normalize the schema repo path
if (!schemaRepoPath.substring(schemaRepoPath.length() - 1).equals("/"))
schemaRepoPath = schemaRepoPath + "/";
avro = new AvroSchemaSystem(schemaRepoHost, schemaRepoPort, prefixDelimiter, schemaRepoPath);
writer_schema = JTCollector.avro.getSchema(JTCollector.metrics_topic, JTCollector.metrics_schema_id);
}
// Start collector loader
log.info("Spawning loader thread...");
loader = new CollectorLoader(jtcollectorPath + "collectors", loaderWaitTime, listOfCollectors, listOfRunningCollectors, listToNotRestart);
loader.setName("Loader-Thread");
loader.start();
// Start collector workers
for (int x = 0; x < numCollectorThreads; x++ ) {
CollectorWorker thread = new CollectorWorker(listOfCollectors, listOfMetrics, listOfRunningCollectors, listToNotRestart, jtcollectorPath);
thread.setName("Worker-Thread-" + x);
worker_threads.add(thread);
thread.start();
log.info("Spawning worker threads...");
}
// Start metric senders
for (int x = 0; x < numSenderThreads; x++ ) {
MetricSender thread = null;
if (useAvro) {
log.info("Using Avro...checking Kafka as well...");
try {
// If we are using Avro, we be sending to Kafka, and will not be sending directly to a TSD
thread = new MetricSender(listOfMetrics, producer_props, writer_schema);
} catch (NullPointerException e) {
log.error("Error in config for either Kafka or Avro.", e);
System.exit(12);
}
} else {
try {
// We aren't using avro, so let's decide if we are sending to TSD, Kafka, or Both
thread = new MetricSender(listOfMetrics, producer_props, listOfMetricsForTSD);
} catch (Exception e) {
log.error("Error in config for either Kafka or OpenTSDB.", e);
System.exit(24);
}
}
thread.setName("Metric-Thread-" + x);
sender_threads.add(thread);
thread.start();
log.info("Spawning metric threads...");
}
// Start jtcollector metric collectors
jtcollector = new JTCollectorMetricsCollector(15 * 1000);
jtcollector.setName("JTCollector-Thread");
jtcollector.start();
}
}