package org.act.tstream.stats;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import backtype.storm.generated.GlobalStreamId;
import org.act.tstream.cluster.Common;
import org.act.tstream.common.stats.StatBuckets;
import org.act.tstream.common.stats.StaticsType;
import org.act.tstream.stats.rolling.RollingWindowSet;
import org.act.tstream.utils.EventSampler;
import org.act.tstream.utils.Pair;
import org.act.tstream.utils.TimeUtils;
/**
* both spout and bolt will use base statics
*
* @author Longda/yannian
*
*/
public class CommonStatsRolling {
private static final long serialVersionUID = -2145444660360278001L;
protected Map<StaticsType, RollingWindowSet> staticTypeMap = new HashMap<StaticsType, RollingWindowSet>();
// <StremId, EventSampler>
protected Map<String, EventSampler> emittedSamplers;
protected Map<String, EventSampler> sendTpsSamplers;
// <componentId, <streamId, EventSampler>>
protected Map<String, Map<String, EventSampler>> recvTpsSamplers;
protected Map<String, Map<String, EventSampler>> processSamplers;
// in order to improve performance, use two type of samplers
// protected Map<String, Map<String, EventSampler>> ackedSamplers;
// protected Map<String, Map<String, EventSampler>> failedSamplers;
protected Map<String, Map<String, EventSampler>> boltAckedSamplers;
protected Map<String, Map<String, EventSampler>> boltFailedSamplers;
protected Map<String, EventSampler> spoutAckedSamplers;
protected Map<String, EventSampler> spoutFailedSamplers;
protected boolean enable = true;
protected Integer rate;
public CommonStatsRolling(Integer rate) {
RollingWindowSet emitted = StatFunction
.keyed_counter_rolling_window_set(
StatFunction.NUM_STAT_BUCKETS, StatBuckets.STAT_BUCKETS);
staticTypeMap.put(StaticsType.emitted, emitted);
RollingWindowSet sendTps = StatFunction.keyed_avg_rolling_window_set(
StatFunction.NUM_STAT_BUCKETS, StatBuckets.STAT_BUCKETS);
staticTypeMap.put(StaticsType.send_tps, sendTps);
RollingWindowSet recvTps = StatFunction.keyed_avg_rolling_window_set(
StatFunction.NUM_STAT_BUCKETS, StatBuckets.STAT_BUCKETS);
staticTypeMap.put(StaticsType.recv_tps, recvTps);
RollingWindowSet acked = StatFunction.keyed_counter_rolling_window_set(
StatFunction.NUM_STAT_BUCKETS, StatBuckets.STAT_BUCKETS);
staticTypeMap.put(StaticsType.acked, acked);
RollingWindowSet failed = StatFunction
.keyed_counter_rolling_window_set(
StatFunction.NUM_STAT_BUCKETS, StatBuckets.STAT_BUCKETS);
staticTypeMap.put(StaticsType.failed, failed);
RollingWindowSet process_latencies = StatFunction
.keyed_avg_rolling_window_set(StatFunction.NUM_STAT_BUCKETS,
StatBuckets.STAT_BUCKETS);
staticTypeMap.put(StaticsType.process_latencies, process_latencies);
emittedSamplers = new HashMap<String, EventSampler>();
sendTpsSamplers = new HashMap<String, EventSampler>();
recvTpsSamplers = new HashMap<String, Map<String, EventSampler>>();
boltAckedSamplers = new HashMap<String, Map<String, EventSampler>>();
boltFailedSamplers = new HashMap<String, Map<String, EventSampler>>();
spoutAckedSamplers = new HashMap<String, EventSampler>();
spoutFailedSamplers = new HashMap<String, EventSampler>();
processSamplers = new HashMap<String, Map<String, EventSampler>>();
this.rate = rate;
}
/**
* update statics
*
* @param common
* @param path
* @param args
*/
public void update_task_stat(StaticsType type, Object... args) {
RollingWindowSet statics = staticTypeMap.get(type);
if (statics != null) {
statics.update_rolling_window_set(args);
}
}
public void send_tuple(String stream, int num_out_tasks) {
if (enable == false) {
return;
}
if (num_out_tasks <= 0) {
return;
}
EventSampler emittedSampler = emittedSamplers.get(stream);
if (emittedSampler == null) {
emittedSampler = new EventSampler(rate);
emittedSamplers.put(stream, emittedSampler);
}
Integer times = emittedSampler.timesCheck();
if (times != null) {
update_task_stat(StaticsType.emitted, stream, times * num_out_tasks);
}
EventSampler sendTpsSampler = sendTpsSamplers.get(stream);
if (sendTpsSampler == null) {
sendTpsSampler = new EventSampler(rate);
sendTpsSamplers.put(stream, sendTpsSampler);
}
Integer send = sendTpsSampler.tpsCheck();
if (send != null) {
update_task_stat(StaticsType.send_tps, stream, send * num_out_tasks);
}
}
public void recv_tuple(String component, String stream) {
if (enable == false) {
return;
}
Map<String, EventSampler> componentSamplers = recvTpsSamplers
.get(component);
if (componentSamplers == null) {
componentSamplers = new HashMap<String, EventSampler>();
recvTpsSamplers.put(component, componentSamplers);
}
EventSampler sampler = componentSamplers.get(stream);
if (sampler == null) {
sampler = new EventSampler(rate);
componentSamplers.put(stream, sampler);
}
Integer recv = sampler.tpsCheck();
if (recv != null) {
GlobalStreamId key = new GlobalStreamId(component, stream);
update_task_stat(StaticsType.recv_tps, key, recv);
}
}
public void bolt_acked_tuple(String component, String stream,
Long latency_ms) {
if (enable == false) {
return;
}
if (latency_ms == null) {
return;
}
Map<String, EventSampler> componentSamplers = boltAckedSamplers
.get(component);
if (componentSamplers == null) {
componentSamplers = new HashMap<String, EventSampler>();
boltAckedSamplers.put(component, componentSamplers);
}
EventSampler sampler = componentSamplers.get(stream);
if (sampler == null) {
sampler = new EventSampler(rate);
componentSamplers.put(stream, sampler);
}
Pair<Integer, Double> pair = sampler.avgCheck(latency_ms * 1000);
if (pair == null) {
return;
}
long avgLatency = (long)((double)pair.getSecond());
GlobalStreamId key = new GlobalStreamId(component, stream);
update_task_stat(StaticsType.acked, key, pair.getFirst());
update_task_stat(StaticsType.process_latencies, key, avgLatency);
}
public void bolt_failed_tuple(String component, String stream) {
if (enable == false) {
return;
}
Map<String, EventSampler> componentSamplers = boltFailedSamplers
.get(component);
if (componentSamplers == null) {
componentSamplers = new HashMap<String, EventSampler>();
boltFailedSamplers.put(component, componentSamplers);
}
EventSampler sampler = componentSamplers.get(stream);
if (sampler == null) {
sampler = new EventSampler(rate);
componentSamplers.put(stream, sampler);
}
Integer times = sampler.timesCheck();
if (times == null) {
return;
}
GlobalStreamId key = new GlobalStreamId(component, stream);
update_task_stat(StaticsType.failed, key, times);
}
public void spout_acked_tuple(String stream, long st) {
if (enable == false) {
return;
}
if (st == 0) {
return;
}
EventSampler sampler = spoutAckedSamplers.get(stream);
if (sampler == null) {
sampler = new EventSampler(rate);
spoutAckedSamplers.put(stream, sampler);
}
long latency_ms = TimeUtils.time_delta_ms(st);
Pair<Integer, Double> pair = sampler.avgCheck(latency_ms * 1000);
if (pair == null) {
return;
}
long avgLatency = (long)((double)pair.getSecond());
GlobalStreamId key = new GlobalStreamId(Common.ACKER_COMPONENT_ID,
stream);
update_task_stat(StaticsType.acked, key, pair.getFirst());
update_task_stat(StaticsType.process_latencies, key, avgLatency);
}
public void spout_failed_tuple(String stream) {
if (enable == false) {
return;
}
EventSampler sampler = spoutFailedSamplers.get(stream);
if (sampler == null) {
sampler = new EventSampler(rate);
spoutFailedSamplers.put(stream, sampler);
}
Integer times = sampler.timesCheck();
if (times == null) {
return;
}
GlobalStreamId key = new GlobalStreamId(Common.ACKER_COMPONENT_ID,
stream);
update_task_stat(StaticsType.failed, key, times);
}
public CommonStatsData render_stats() {
cleanup_stats(false);
CommonStatsData ret = new CommonStatsData();
for (Entry<StaticsType, RollingWindowSet> entry : staticTypeMap
.entrySet()) {
StaticsType type = entry.getKey();
RollingWindowSet rws = entry.getValue();
Map<Integer, Object> csData = rws.value_rolling_window_set();
ret.put(type, csData);
}
return ret;
}
protected void cleanup_common_stats() {
for (Entry<StaticsType, RollingWindowSet> entry : staticTypeMap
.entrySet()) {
RollingWindowSet rws = entry.getValue();
rws.cleanup_rolling_window_set();
}
}
public void cleanup_stats(boolean skipcommon) {
if (skipcommon == false) {
cleanup_common_stats();
}
}
public RollingWindowSet get(StaticsType type) {
return staticTypeMap.get(type);
}
public void put(StaticsType type, RollingWindowSet statics) {
staticTypeMap.put(type, statics);
}
public Integer getRate() {
return rate;
}
public void setRate(Integer rate) {
this.rate = rate;
}
}