use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.
the class FlowQueuePendingCorrector method run.
/**
* Corrects queue.pending metric for a flowlet.
*/
public void run(FlowId flowId, String producerFlowlet, String consumerFlowlet, String flowletQueue, FlowSpecification flow) throws Exception {
System.out.println("Running queue.pending correction on flow '" + flowId + "' producerFlowlet '" + producerFlowlet + "' consumerFlowlet '" + consumerFlowlet + "' flowletQueue '" + flowletQueue + "'");
Map<RunId, ProgramRuntimeService.RuntimeInfo> runtimeInfos = programRuntimeService.list(flowId);
Preconditions.checkState(runtimeInfos.isEmpty(), "Cannot run tool when flow " + flowId + " is still running");
SimpleQueueSpecificationGenerator queueSpecGenerator = new SimpleQueueSpecificationGenerator(flowId.getParent());
Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> table = queueSpecGenerator.create(flow);
Preconditions.checkArgument(table.contains(QueueSpecificationGenerator.Node.flowlet(producerFlowlet), consumerFlowlet), "Flowlet " + producerFlowlet + " is not emitting to " + consumerFlowlet);
Set<QueueSpecification> queueSpecs = table.get(QueueSpecificationGenerator.Node.flowlet(producerFlowlet), consumerFlowlet);
boolean validQueue = false;
for (QueueSpecification queueSpec : queueSpecs) {
if (queueSpec.getQueueName().getSimpleName().equals(flowletQueue)) {
validQueue = true;
break;
}
}
Preconditions.checkArgument(validQueue, "Queue " + flowletQueue + " does not exist for the given flowlets");
QueueName queueName = QueueName.fromFlowlet(flowId, producerFlowlet, flowletQueue);
long consumerGroupId = FlowUtils.generateConsumerGroupId(flowId, consumerFlowlet);
long correctQueuePendingValue;
try {
HBaseQueueDebugger.QueueStatistics stats = queueDebugger.scanQueue(queueName, consumerGroupId);
correctQueuePendingValue = stats.getUnprocessed() + stats.getProcessedAndNotVisible();
} catch (NotFoundException e) {
// OK since flowlet queue exists, but actual queue doesn't exist
// (e.g. when running upgrade tool from 2.8 to 3.0)
correctQueuePendingValue = 0;
}
Map<String, String> tags = ImmutableMap.<String, String>builder().put(Constants.Metrics.Tag.NAMESPACE, flowId.getNamespace()).put(Constants.Metrics.Tag.APP, flowId.getApplication()).put(Constants.Metrics.Tag.FLOW, flowId.getProgram()).put(Constants.Metrics.Tag.CONSUMER, consumerFlowlet).put(Constants.Metrics.Tag.PRODUCER, producerFlowlet).put(Constants.Metrics.Tag.FLOWLET_QUEUE, flowletQueue).build();
MetricDataQuery query = new MetricDataQuery(0, 0, Integer.MAX_VALUE, 1, ImmutableMap.of("system.queue.pending", AggregationFunction.SUM), tags, ImmutableList.<String>of(), null);
Collection<MetricTimeSeries> results = metricStore.query(query);
long queuePending;
if (results.isEmpty()) {
queuePending = 0;
} else {
System.out.println("Got results: " + GSON.toJson(results));
Preconditions.checkState(results.size() == 1);
List<TimeValue> timeValues = results.iterator().next().getTimeValues();
Preconditions.checkState(timeValues.size() == 1);
TimeValue timeValue = timeValues.get(0);
queuePending = timeValue.getValue();
}
metricsCollectionService.startAndWait();
MetricsContext collector = metricsCollectionService.getContext(tags);
collector.gauge("queue.pending", correctQueuePendingValue);
System.out.printf("Adjusted system.queue.pending metric from %d to %d (tags %s)\n", queuePending, correctQueuePendingValue, GSON.toJson(tags));
// stop will flush the metrics
metricsCollectionService.stopAndWait();
}
use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.
the class FlowUtils method getAllConsumerGroups.
/**
* Gets all consumer group configurations for the given queue.
*/
private static Set<ConsumerGroupConfig> getAllConsumerGroups(Program program, FlowSpecification flowSpec, QueueName queueName, Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> queueSpecs) {
Set<ConsumerGroupConfig> groupConfigs = Sets.newHashSet();
SchemaGenerator schemaGenerator = new ReflectionSchemaGenerator();
// Get all the consumers of this queue.
for (Map.Entry<String, FlowletDefinition> entry : flowSpec.getFlowlets().entrySet()) {
String flowletId = entry.getKey();
for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.column(flowletId).values())) {
if (!queueSpec.getQueueName().equals(queueName)) {
continue;
}
try {
// Inspect the flowlet consumer
FlowletDefinition flowletDefinition = entry.getValue();
Class<?> flowletClass = program.getClassLoader().loadClass(flowletDefinition.getFlowletSpec().getClassName());
long groupId = generateConsumerGroupId(program.getId(), flowletId);
addConsumerGroup(queueSpec, flowletClass, groupId, flowletDefinition.getInstances(), schemaGenerator, groupConfigs);
} catch (ClassNotFoundException e) {
// There is no way for not able to load a Flowlet class as it should be verified during deployment.
throw Throwables.propagate(e);
}
}
}
return groupConfigs;
}
use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.
the class FlowUtils method configureQueue.
/**
* Configures all queues being used in a flow.
*
* @return A Multimap from flowletId to QueueName where the flowlet is a consumer of.
*/
public static Multimap<String, QueueName> configureQueue(Program program, FlowSpecification flowSpec, final StreamAdmin streamAdmin, QueueAdmin queueAdmin, TransactionExecutorFactory txExecutorFactory) {
// Generate all queues specifications
ApplicationId appId = new ApplicationId(program.getNamespaceId(), program.getApplicationId());
Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> queueSpecs = new SimpleQueueSpecificationGenerator(appId).create(flowSpec);
// For each queue in the flow, gather all consumer groups information
Multimap<QueueName, ConsumerGroupConfig> queueConfigs = HashMultimap.create();
// Loop through each flowlet and generate the map from consumer flowlet id to queue
ImmutableSetMultimap.Builder<String, QueueName> resultBuilder = ImmutableSetMultimap.builder();
for (Map.Entry<String, FlowletDefinition> entry : flowSpec.getFlowlets().entrySet()) {
String flowletId = entry.getKey();
for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.column(flowletId).values())) {
resultBuilder.put(flowletId, queueSpec.getQueueName());
}
}
// For each queue, gather all consumer groups.
for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.values())) {
QueueName queueName = queueSpec.getQueueName();
queueConfigs.putAll(queueName, getAllConsumerGroups(program, flowSpec, queueName, queueSpecs));
}
try {
// Configure each stream consumer in the Flow. Also collects all queue configurers.
final List<ConsumerGroupConfigurer> groupConfigurers = Lists.newArrayList();
final Map<StreamId, Map<Long, Integer>> streamConfigurers = Maps.newHashMap();
for (Map.Entry<QueueName, Collection<ConsumerGroupConfig>> entry : queueConfigs.asMap().entrySet()) {
LOG.info("Queue config for {} : {}", entry.getKey(), entry.getValue());
if (entry.getKey().isStream()) {
Map<Long, Integer> configs = Maps.newHashMap();
for (ConsumerGroupConfig config : entry.getValue()) {
configs.put(config.getGroupId(), config.getGroupSize());
}
streamConfigurers.put(entry.getKey().toStreamId(), configs);
} else {
groupConfigurers.add(new ConsumerGroupConfigurer(queueAdmin.getQueueConfigurer(entry.getKey()), entry.getValue()));
}
}
// Configure queue transactionally
try {
Transactions.createTransactionExecutor(txExecutorFactory, groupConfigurers).execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
for (ConsumerGroupConfigurer configurer : groupConfigurers) {
configurer.configure();
}
for (Map.Entry<StreamId, Map<Long, Integer>> entry : streamConfigurers.entrySet()) {
streamAdmin.configureGroups(entry.getKey(), entry.getValue());
}
}
});
} finally {
for (ConsumerGroupConfigurer configurer : groupConfigurers) {
Closeables.closeQuietly(configurer);
}
}
return resultBuilder.build();
} catch (Exception e) {
LOG.error("Failed to configure queues", e);
throw Throwables.propagate(e);
}
}
use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.
the class SimpleQueueSpecificationGenerator method create.
/**
* Given a {@link FlowSpecification}.
*
* @param input {@link FlowSpecification}
* @return A {@link Table}
*/
@Override
public Table<Node, String, Set<QueueSpecification>> create(FlowSpecification input) {
Table<Node, String, Set<QueueSpecification>> table = HashBasedTable.create();
String flow = input.getName();
Map<String, FlowletDefinition> flowlets = input.getFlowlets();
// Iterate through connections of a flow.
for (FlowletConnection connection : input.getConnections()) {
final String source = connection.getSourceName();
final String target = connection.getTargetName();
String sourceNamespace = connection.getSourceNamespace() == null ? appId.getNamespace() : connection.getSourceNamespace();
Node sourceNode;
Set<QueueSpecification> queueSpec;
if (connection.getSourceType() == FlowletConnection.Type.FLOWLET) {
sourceNode = new Node(connection.getSourceType(), source);
queueSpec = generateQueueSpecification(appId, flow, connection, flowlets.get(target).getInputs(), flowlets.get(source).getOutputs());
} else {
sourceNode = new Node(connection.getSourceType(), sourceNamespace, source);
queueSpec = generateQueueSpecification(appId, flow, connection, flowlets.get(target).getInputs(), ImmutableMap.<String, Set<Schema>>of(connection.getSourceName(), ImmutableSet.of(STREAM_EVENT_SCHEMA)));
}
Set<QueueSpecification> queueSpecifications = table.get(sourceNode, target);
if (queueSpecifications == null) {
queueSpecifications = Sets.newHashSet();
table.put(sourceNode, target, queueSpecifications);
}
queueSpecifications.addAll(queueSpec);
}
return table;
}
use of co.cask.cdap.app.queue.QueueSpecification in project cdap by caskdata.
the class FlowQueuePendingCorrector method run.
public void run(final FlowId flowId, FlowSpecification flow) throws Exception {
/* Temporary check. Can be removed when FlowId class is ready */
Preconditions.checkArgument(ProgramType.FLOW == flowId.getType(), "Unexpected program type %s, FlowPendingQueueCorrector only runs on flows", flowId.getType());
System.out.println("Running queue.pending correction on flow " + flowId);
SimpleQueueSpecificationGenerator queueSpecGenerator = new SimpleQueueSpecificationGenerator(flowId.getParent());
Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> table = queueSpecGenerator.create(flow);
for (Table.Cell<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> cell : table.cellSet()) {
if (cell.getRowKey().getType() == FlowletConnection.Type.FLOWLET) {
String producerFlowlet = cell.getRowKey().getName();
String consumerFlowlet = cell.getColumnKey();
for (QueueSpecification queue : cell.getValue()) {
run(flowId, producerFlowlet, consumerFlowlet, queue.getQueueName().getSimpleName());
}
}
}
}
Aggregations