Search in sources :

Example 16 with QueueName

use of co.cask.cdap.common.queue.QueueName in project cdap by caskdata.

the class DistributedFlowProgramRunner method getFlowletQueues.

/**
   * Gets the queue configuration of the Flow based on the connections in the given {@link FlowSpecification}.
   */
private Multimap<String, QueueName> getFlowletQueues(ApplicationId appId, FlowSpecification flowSpec) {
    // Generate all queues specifications
    Table<QueueSpecificationGenerator.Node, String, Set<QueueSpecification>> queueSpecs = new SimpleQueueSpecificationGenerator(appId).create(flowSpec);
    // For storing result from flowletId to queue.
    ImmutableSetMultimap.Builder<String, QueueName> resultBuilder = ImmutableSetMultimap.builder();
    // Loop through each flowlet
    for (Map.Entry<String, FlowletDefinition> entry : flowSpec.getFlowlets().entrySet()) {
        String flowletId = entry.getKey();
        // For each queue that the flowlet is a consumer, store the number of instances for this flowlet
        for (QueueSpecification queueSpec : Iterables.concat(queueSpecs.column(flowletId).values())) {
            resultBuilder.put(flowletId, queueSpec.getQueueName());
        }
    }
    return resultBuilder.build();
}
Also used : FlowletDefinition(co.cask.cdap.api.flow.FlowletDefinition) Set(java.util.Set) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) QueueSpecification(co.cask.cdap.app.queue.QueueSpecification) QueueName(co.cask.cdap.common.queue.QueueName) Map(java.util.Map) SimpleQueueSpecificationGenerator(co.cask.cdap.internal.app.queue.SimpleQueueSpecificationGenerator)

Example 17 with QueueName

use of co.cask.cdap.common.queue.QueueName in project cdap by caskdata.

the class HBaseQueueDebugger method main.

public static void main(String[] args) throws Exception {
    if (args.length >= 1 && args[0].equals("help")) {
        System.out.println("Arguments: [<queue-uri> [consumer-flowlet]]");
        System.out.println("queue-uri: queue:///<namespace>/<app>/<flow>/<flowlet>/<queue>");
        System.out.println("consumer-flowlet: <flowlet>");
        System.out.println("If queue-uri is not provided, scan all queues");
        System.out.println("Example: queue:///default/PurchaseHistory/PurchaseFlow/reader/queue collector");
        System.out.println();
        System.out.println("System properties:");
        System.out.println("-D" + PROP_SHOW_PROGRESS + "=true         Show progress while scanning the queue table");
        System.out.println("-D" + PROP_ROWS_CACHE + "=[num_of_rows]   " + "Number of rows to pass to HBase Scan.setCaching() method");
        System.exit(1);
    }
    // e.g. "queue:///default/PurchaseHistory/PurchaseFlow/reader/queue"
    final QueueName queueName = args.length >= 1 ? QueueName.from(URI.create(args[0])) : null;
    Long consumerGroupId = null;
    if (args.length >= 2) {
        Preconditions.checkNotNull(queueName);
        String consumerFlowlet = args[1];
        FlowId flowId = new FlowId(queueName.getFirstComponent(), queueName.getSecondComponent(), queueName.getThirdComponent());
        consumerGroupId = FlowUtils.generateConsumerGroupId(flowId, consumerFlowlet);
    }
    final HBaseQueueDebugger debugger = createDebugger();
    debugger.startAndWait();
    // CDAP-9005 We need to create the NamespaceQueryAdmin without authorization enabled, but create the
    // HBaseQueueDebugger with authorization enabled.
    Injector injector = createInjector(true);
    NoAuthService noAuthService = injector.getInstance(NoAuthService.class);
    noAuthService.startAndWait();
    NamespaceQueryAdmin namespaceQueryAdmin = noAuthService.getNamespaceQueryAdmin();
    Impersonator impersonator = noAuthService.getImpersonator();
    if (queueName != null) {
        final Long finalConsumerGroupId = consumerGroupId;
        impersonator.doAs(new NamespaceId(queueName.getFirstComponent()), new Callable<Void>() {

            @Override
            public Void call() throws Exception {
                debugger.scanQueue(queueName, finalConsumerGroupId);
                return null;
            }
        });
    } else {
        debugger.scanQueues(namespaceQueryAdmin.list());
    }
    noAuthService.stopAndWait();
    debugger.stopAndWait();
}
Also used : Impersonator(co.cask.cdap.security.impersonation.Impersonator) TransactionNotInProgressException(org.apache.tephra.TransactionNotInProgressException) TransactionFailureException(org.apache.tephra.TransactionFailureException) NotFoundException(co.cask.cdap.common.NotFoundException) FlowId(co.cask.cdap.proto.id.FlowId) Injector(com.google.inject.Injector) NamespaceQueryAdmin(co.cask.cdap.common.namespace.NamespaceQueryAdmin) NamespaceId(co.cask.cdap.proto.id.NamespaceId) QueueName(co.cask.cdap.common.queue.QueueName)

Example 18 with QueueName

use of co.cask.cdap.common.queue.QueueName 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();
}
Also used : HBaseQueueDebugger(co.cask.cdap.data.tools.HBaseQueueDebugger) Set(java.util.Set) MetricsContext(co.cask.cdap.api.metrics.MetricsContext) NotFoundException(co.cask.cdap.common.NotFoundException) MetricTimeSeries(co.cask.cdap.api.metrics.MetricTimeSeries) SimpleQueueSpecificationGenerator(co.cask.cdap.internal.app.queue.SimpleQueueSpecificationGenerator) QueueSpecification(co.cask.cdap.app.queue.QueueSpecification) RunId(org.apache.twill.api.RunId) MetricDataQuery(co.cask.cdap.api.metrics.MetricDataQuery) QueueName(co.cask.cdap.common.queue.QueueName) TimeValue(co.cask.cdap.api.dataset.lib.cube.TimeValue)

Example 19 with QueueName

use of co.cask.cdap.common.queue.QueueName in project cdap by caskdata.

the class MetricStoreRequestExecutor method computeFlowletPending.

private Object computeFlowletPending(MetricDataQuery query) throws Exception {
    // Pending is processed by flowlet minus emitted into the queues it was processing from.
    // trick: get all queues and streams it was processing from using group by
    MetricDataQuery groupByQueueName = new MetricDataQuery(new MetricDataQuery(query, "system.process.events.processed", AggregationFunction.SUM), ImmutableList.of(Constants.Metrics.Tag.FLOWLET_QUEUE));
    Map<String, Long> processedPerQueue = getTotalsWithSingleGroupByTag(groupByQueueName);
    long processedTotal = 0;
    long writtenTotal = 0;
    for (Map.Entry<String, Long> entry : processedPerQueue.entrySet()) {
        String name = entry.getKey();
        // note: each has "input." prefix
        QueueName queueName = QueueName.from(URI.create(name.substring("input.".length(), name.length())));
        long written;
        if (queueName.isQueue()) {
            Map<String, String> sliceByTags = Maps.newHashMap(query.getSliceByTags());
            // we want to aggregate written to the queue by all flowlets
            sliceByTags.remove(Constants.Metrics.Tag.FLOWLET);
            // we want to narrow down to specific queue we know our flowlet was consuming from
            sliceByTags.put(Constants.Metrics.Tag.FLOWLET_QUEUE, queueName.getSimpleName());
            written = getTotals(new MetricDataQuery(new MetricDataQuery(query, sliceByTags), "system.process.events.out", AggregationFunction.SUM));
        } else if (queueName.isStream()) {
            Map<String, String> sliceByTags = Maps.newHashMap();
            // we want to narrow down to specific stream we know our flowlet was consuming from
            sliceByTags.put(Constants.Metrics.Tag.STREAM, queueName.getSimpleName());
            // note: namespace + stream uniquely define the stream
            // we know that flow can consume from stream of the same namespace only at this point
            sliceByTags.put(Constants.Metrics.Tag.NAMESPACE, query.getSliceByTags().get(Constants.Metrics.Tag.NAMESPACE));
            written = getTotals(new MetricDataQuery(new MetricDataQuery(query, sliceByTags), "system.collect.events", AggregationFunction.SUM));
        } else {
            LOG.warn("Unknown queue type: " + name);
            continue;
        }
        processedTotal += entry.getValue();
        writtenTotal += written;
    }
    long pending = writtenTotal - processedTotal;
    return new AggregateResponse(pending > 0 ? pending : 0);
}
Also used : MetricDataQuery(co.cask.cdap.api.metrics.MetricDataQuery) Map(java.util.Map) QueueName(co.cask.cdap.common.queue.QueueName)

Example 20 with QueueName

use of co.cask.cdap.common.queue.QueueName in project cdap by caskdata.

the class FlowletProcessDriver method processMethodCallback.

private <T> ProcessMethodCallback processMethodCallback(final PriorityQueue<FlowletProcessEntry<?>> processQueue, final FlowletProcessEntry<T> processEntry, final InputDatum<T> input) {
    // If it is generator flowlet, processCount is 1.
    final int processedCount = processEntry.getProcessSpec().getProcessMethod().needsInput() ? input.size() : 1;
    return new ProcessMethodCallback() {

        private final LoadingCache<String, MetricsContext> queueMetricsCollectors = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.HOURS).build(new CacheLoader<String, MetricsContext>() {

            @Override
            public MetricsContext load(String key) throws Exception {
                return flowletContext.getProgramMetrics().childContext(Constants.Metrics.Tag.FLOWLET_QUEUE, key);
            }
        });

        @Override
        public void onSuccess(Object object, InputContext inputContext) {
            try {
                gaugeEventProcessed(input.getQueueName());
                txCallback.onSuccess(object, inputContext);
            } catch (Throwable t) {
                LOG.error("Exception on onSuccess call: {}", flowletContext, t);
            } finally {
                enqueueEntry();
            }
        }

        @Override
        public void onFailure(Object inputObject, InputContext inputContext, FailureReason reason, InputAcknowledger inputAcknowledger) {
            LOG.warn("Process failure: {}, {}, input: {}", flowletContext, reason.getMessage(), input, reason.getCause());
            FailurePolicy failurePolicy;
            try {
                flowletContext.getProgramMetrics().increment("process.errors", 1);
                failurePolicy = txCallback.onFailure(inputObject, inputContext, reason);
                if (failurePolicy == null) {
                    failurePolicy = FailurePolicy.RETRY;
                    LOG.info("Callback returns null for failure policy. Default to {}.", failurePolicy);
                }
            } catch (Throwable t) {
                LOG.error("Exception on onFailure call: {}", flowletContext, t);
                failurePolicy = FailurePolicy.RETRY;
            }
            if (input.getRetry() >= processEntry.getProcessSpec().getProcessMethod().getMaxRetries()) {
                LOG.info("Too many retries, ignores the input: {}", input);
                failurePolicy = FailurePolicy.IGNORE;
            }
            if (failurePolicy == FailurePolicy.RETRY) {
                FlowletProcessEntry retryEntry = processEntry.isRetry() ? processEntry : FlowletProcessEntry.create(processEntry.getProcessSpec(), new ProcessSpecification<>(new SingleItemQueueReader<>(input), processEntry.getProcessSpec().getProcessMethod(), null));
                processQueue.offer(retryEntry);
            } else if (failurePolicy == FailurePolicy.IGNORE) {
                try {
                    gaugeEventProcessed(input.getQueueName());
                    inputAcknowledger.ack();
                } catch (Throwable t) {
                    LOG.error("Fatal problem, fail to ack an input: {}", flowletContext, t);
                } finally {
                    enqueueEntry();
                }
            }
        }

        private void enqueueEntry() {
            processQueue.offer(processEntry.resetRetry());
        }

        private void gaugeEventProcessed(QueueName inputQueueName) {
            if (processEntry.isTick()) {
                flowletContext.getProgramMetrics().increment("process.ticks.processed", processedCount);
            } else if (inputQueueName == null) {
                flowletContext.getProgramMetrics().increment("process.events.processed", processedCount);
            } else {
                queueMetricsCollectors.getUnchecked(inputQueueName.getSimpleName()).increment("process.events.processed", processedCount);
            }
        }
    };
}
Also used : InputContext(co.cask.cdap.api.flow.flowlet.InputContext) FailureReason(co.cask.cdap.api.flow.flowlet.FailureReason) LoadingCache(com.google.common.cache.LoadingCache) CacheLoader(com.google.common.cache.CacheLoader) FailurePolicy(co.cask.cdap.api.flow.flowlet.FailurePolicy) QueueName(co.cask.cdap.common.queue.QueueName)

Aggregations

QueueName (co.cask.cdap.common.queue.QueueName)35 Test (org.junit.Test)20 QueueConsumer (co.cask.cdap.data2.queue.QueueConsumer)12 ConsumerConfig (co.cask.cdap.data2.queue.ConsumerConfig)11 ConsumerGroupConfig (co.cask.cdap.data2.queue.ConsumerGroupConfig)11 QueueEntry (co.cask.cdap.data2.queue.QueueEntry)11 QueueProducer (co.cask.cdap.data2.queue.QueueProducer)9 TransactionContext (org.apache.tephra.TransactionContext)7 IOException (java.io.IOException)6 TransactionAware (org.apache.tephra.TransactionAware)6 TransactionExecutor (org.apache.tephra.TransactionExecutor)6 QueueSpecification (co.cask.cdap.app.queue.QueueSpecification)5 QueueTest (co.cask.cdap.data2.transaction.queue.QueueTest)5 Map (java.util.Map)4 Set (java.util.Set)4 TableNotFoundException (org.apache.hadoop.hbase.TableNotFoundException)4 StreamEvent (co.cask.cdap.api.flow.flowlet.StreamEvent)3 ProgramController (co.cask.cdap.app.runtime.ProgramController)3 SimpleQueueSpecificationGenerator (co.cask.cdap.internal.app.queue.SimpleQueueSpecificationGenerator)3 TypeToken (com.google.common.reflect.TypeToken)3