/*
* #!
* %
* Copyright (C) 2014 - 2016 Humboldt-Universität zu Berlin
* %
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #_
*/
package de.hub.cs.dbis.aeolus.monitoring.throughput;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichSpout;
import backtype.storm.topology.OutputFieldsDeclarer;
import de.hub.cs.dbis.aeolus.monitoring.MonitoringTopoloyBuilder;
/**
* {@link ThroughputSpout} counts the number of emitted tuples and reports the count in regular intervals. The counts
* are grouped by stream ID and and overall count is reported, too.<br />
* <br />
* Internally, it uses a {@link SpoutThroughputCounter}.
*
* @author mjsax
*/
public class ThroughputSpout implements IRichSpout {
private final static long serialVersionUID = 7077749897674933208L;
private final static Logger logger = LoggerFactory.getLogger(ThroughputSpout.class);
/** The original user spout. */
private IRichSpout userSpout;
/** The reporting interval in milliseconds; */
private long reportingIntervalMs;
/** The name of the report stream. */
private final String reportStream;
/** A asynchrony reporting thread, to report collected output stream statistics periodically. */
private SpoutReportingThread reporter;
/**
* Instantiates a new {@link ThroughputSpout} that report the throughput of the given spout to the default report
* stream {@link MonitoringTopoloyBuilder#DEFAULT_THROUGHPUT_STREAM}.
*
* @param userSpout
* The user spout to be monitored.
* @param reportingIntervalMs
* The reporting interval in milliseconds.
*/
public ThroughputSpout(IRichSpout userSpout, long reportingIntervalMs) {
this(userSpout, reportingIntervalMs, MonitoringTopoloyBuilder.DEFAULT_THROUGHPUT_STREAM);
}
/**
* Instantiates a new {@link ThroughputSpout} that report the throughput of the given spout to the specified stream
*
* @param userSpout
* The user spout to be monitored.
* @param reportingIntervalMs
* The reporting interval in milliseconds.
* @param reportStream
* The name of the report stream.
*/
public ThroughputSpout(IRichSpout userSpout, long reportingIntervalMs, String reportStream) {
this.userSpout = userSpout;
this.reportingIntervalMs = reportingIntervalMs;
this.reportStream = reportStream;
}
@Override
public void open(@SuppressWarnings("rawtypes") Map conf, TopologyContext context, SpoutOutputCollector collector) {
ThroughputSpoutOutputCollector col = new ThroughputSpoutOutputCollector(collector, this.reportStream,
context.getThisTaskId());
this.reporter = new SpoutReportingThread(col, this.reportingIntervalMs);
this.reporter.start();
this.userSpout.open(conf, context, col);
}
@Override
public void close() {
this.reporter.isRunning = false;
try {
this.reporter.join();
} catch(InterruptedException e) {
logger.error(e.getMessage(), e);
}
this.userSpout.close();
}
@Override
public void activate() {
this.userSpout.activate();
}
@Override
public void deactivate() {
this.userSpout.deactivate();
}
@Override
public void nextTuple() {
this.userSpout.nextTuple();
}
@Override
public void ack(Object msgId) {
this.userSpout.ack(msgId);
}
@Override
public void fail(Object msgId) {
this.userSpout.fail(msgId);
}
/**
* {@inheritDoc}
*
* Additionally to the output streams declared by the monitored user spout, a statistical output stream is declared.
*/
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
this.userSpout.declareOutputFields(declarer);
AbstractThroughputCounter.declareStatsStream(this.reportStream, declarer);
}
@Override
public Map<String, Object> getComponentConfiguration() {
return this.userSpout.getComponentConfiguration();
}
}