package storm.applications.topology;
import backtype.storm.Config;
import backtype.storm.generated.StormTopology;
import backtype.storm.tuple.Fields;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static storm.applications.constants.ClickAnalyticsConstants.*;
import storm.applications.bolt.GeoStatsBolt;
import storm.applications.bolt.GeographyBolt;
import storm.applications.bolt.RepeatVisitBolt;
import storm.applications.bolt.VisitStatsBolt;
import storm.applications.sink.BaseSink;
import storm.applications.spout.AbstractSpout;
public class ClickAnalyticsTopology extends AbstractTopology {
private static final Logger LOG = LoggerFactory.getLogger(ClickAnalyticsTopology.class);
private int repeatsThreads;
private int geographyThreads;
private int totalStatsThreads;
private int geoStatsThreads;
private int spoutThreads;
private int visitSinkThreads;
private int locationSinkThreads;
private AbstractSpout spout;
private BaseSink visitSink;
private BaseSink locationSink;
public ClickAnalyticsTopology(String topologyName, Config config) {
super(topologyName, config);
}
@Override
public void initialize() {
repeatsThreads = config.getInt(Conf.REPEATS_THREADS, 1);
geographyThreads = config.getInt(Conf.GEOGRAPHY_THREADS, 1);
totalStatsThreads = config.getInt(Conf.TOTAL_STATS_THREADS, 1);
geoStatsThreads = config.getInt(Conf.GEO_STATS_THREADS, 1);
spoutThreads = config.getInt(BaseConf.SPOUT_THREADS, 1);
visitSinkThreads = config.getInt(getConfigKey(BaseConf.SINK_THREADS, "visit"), 1);
locationSinkThreads = config.getInt(getConfigKey(BaseConf.SINK_THREADS, "location"), 1);
spout = loadSpout();
visitSink = loadSink("visit");
locationSink = loadSink("location");
}
@Override
public StormTopology buildTopology() {
spout.setFields(new Fields(Field.IP, Field.URL, Field.CLIENT_KEY));
builder.setSpout(Component.SPOUT, spout, spoutThreads);
// First layer of bolts
builder.setBolt(Component.REPEATS, new RepeatVisitBolt(), repeatsThreads)
.fieldsGrouping(Component.SPOUT, new Fields(Field.URL, Field.CLIENT_KEY));
builder.setBolt(Component.GEOGRAPHY, new GeographyBolt(), geographyThreads)
.shuffleGrouping(Component.SPOUT);
// second layer of bolts, commutative in nature
builder.setBolt(Component.TOTAL_STATS, new VisitStatsBolt(), totalStatsThreads)
.globalGrouping(Component.REPEATS);
builder.setBolt(Component.GEO_STATS, new GeoStatsBolt(), geoStatsThreads)
.fieldsGrouping(Component.GEOGRAPHY, new Fields(Field.COUNTRY));
// sinks
builder.setBolt(Component.SINK_VISIT, visitSink, visitSinkThreads)
.shuffleGrouping(Component.TOTAL_STATS);
builder.setBolt(Component.SINK_LOCATION, locationSink, locationSinkThreads)
.fieldsGrouping(Component.GEO_STATS, new Fields(Field.COUNTRY));
return builder.createTopology();
}
@Override
public Logger getLogger() {
return LOG;
}
@Override
public String getConfigPrefix() {
return PREFIX;
}
}