package nl.us2.cloudpelican.stormprocessor;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Random;
/**
* Created by robin on 20/07/15.
*/
public class ParseBolt extends BaseRichBolt {
OutputCollector _collector;
private Settings settings;
private LogTypeSniffer lts;
private SimpleDateFormat iso8601sdf;
private static final int MAX_MSG_LENGTH = 4096;
private static final Logger LOG = LoggerFactory.getLogger(ParseBolt.class);
public ParseBolt(Settings settings) {
super();
this.settings = settings;
}
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
_collector = collector;
lts = new LogTypeSniffer();
iso8601sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
}
public void execute(Tuple tuple) {
executeTuple(tuple);
_collector.ack(tuple);
}
public void executeTuple(Tuple tuple) {
try {
// Validate message
String msg = tuple.getString(0);
if (msg == null) {
return;
}
msg = msg.trim();
if (msg.isEmpty()) {
return;
}
// Msg length?
int len = msg.length();
if (len > MAX_MSG_LENGTH) {
LOG.warn("Truncating msg which has length of " + len);
msg = msg.substring(0, MAX_MSG_LENGTH) + "..";
}
// Sniff type
LogSniffResult res = lts.sniff(msg);
// Parse date
Date ts = null;
if (res.getTypes().contains(LogTypes.RSYSLOG)) {
try {
ts = iso8601sdf.parse(res.getDateStr());
} catch (ParseException pe) {
LOG.error("Failed to parse date '" + res.getDateStr() + "' original message: " + msg); // Do not log stack trace, too noisy
}
}
// Fallback time stamp
if (ts == null) {
ts = new Date(); // Fallback to now()
}
// Emit
_collector.emit("messages", new Values(msg, ts.getTime()));
} catch (Exception e) {
LOG.error("Unexpected error in executeTuple", e);
}
// No ack, is handled in outer
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declareStream("messages", new Fields("_raw", "ts"));
}
}