All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wavefront.agent.queueing.QueueingFactoryImpl Maven / Gradle / Ivy

There is a newer version: 9999.0
Show newest version
package com.wavefront.agent.queueing;

import com.google.common.annotations.VisibleForTesting;
import com.wavefront.agent.api.APIContainer;
import com.wavefront.agent.data.EntityPropertiesFactory;
import com.wavefront.agent.data.DataSubmissionTask;
import com.wavefront.agent.data.EventDataSubmissionTask;
import com.wavefront.agent.data.LineDelimitedDataSubmissionTask;
import com.wavefront.agent.data.SourceTagSubmissionTask;
import com.wavefront.agent.data.TaskInjector;
import com.wavefront.agent.handlers.HandlerKey;
import com.wavefront.common.NamedThreadFactory;
import com.wavefront.data.ReportableEntityType;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * A caching implementation of {@link QueueingFactory}.
 *
 * @author [email protected]
 */
public class QueueingFactoryImpl implements QueueingFactory {

  private final Map executors = new ConcurrentHashMap<>();
  private final Map>> queueProcessors =
      new ConcurrentHashMap<>();
  private final Map> queueControllers = new ConcurrentHashMap<>();
  private final TaskQueueFactory taskQueueFactory;
  private final APIContainer apiContainer;
  private final UUID proxyId;
  private final EntityPropertiesFactory entityPropsFactory;

  /**
   * @param apiContainer       handles interaction with Wavefront servers as well as queueing.
   * @param proxyId            proxy ID.
   * @param taskQueueFactory   factory for backing queues.
   * @param entityPropsFactory factory for entity-specific wrappers for mutable proxy settings.
   */
  public QueueingFactoryImpl(APIContainer apiContainer,
                             UUID proxyId,
                             final TaskQueueFactory taskQueueFactory,
                             final EntityPropertiesFactory entityPropsFactory) {
    this.apiContainer = apiContainer;
    this.proxyId = proxyId;
    this.taskQueueFactory = taskQueueFactory;
    this.entityPropsFactory = entityPropsFactory;
  }

  /**
   * Create a new {@code QueueProcessor} instance for the specified handler key.
   *
   * @param handlerKey      {@link HandlerKey} for the queue processor.
   * @param executorService executor service
   * @param threadNum       thread number
   * @param              data submission task type
   * @return {@code QueueProcessor} object
   */
  > QueueProcessor getQueueProcessor(
      @Nonnull HandlerKey handlerKey, ScheduledExecutorService executorService, int threadNum) {
    TaskQueue taskQueue = taskQueueFactory.getTaskQueue(handlerKey, threadNum);
    //noinspection unchecked
    return (QueueProcessor) queueProcessors.computeIfAbsent(handlerKey, x -> new TreeMap<>()).
        computeIfAbsent(threadNum, x -> new QueueProcessor<>(handlerKey, taskQueue,
            getTaskInjector(handlerKey, taskQueue), executorService,
            entityPropsFactory.get(handlerKey.getEntityType()),
            entityPropsFactory.getGlobalProperties()));
  }

  @SuppressWarnings("unchecked")
  @Override
  public > QueueController getQueueController(
      @Nonnull HandlerKey handlerKey, int numThreads) {
    ScheduledExecutorService executor = executors.computeIfAbsent(handlerKey, x ->
        Executors.newScheduledThreadPool(numThreads, new NamedThreadFactory("queueProcessor-" +
            handlerKey.getEntityType() + "-" + handlerKey.getHandle())));
    List> queueProcessors = IntStream.range(0, numThreads).
        mapToObj(i -> (QueueProcessor) getQueueProcessor(handlerKey, executor, i)).
        collect(Collectors.toList());
    return (QueueController) queueControllers.computeIfAbsent(handlerKey, x ->
      new QueueController<>(handlerKey, queueProcessors,
          backlogSize -> entityPropsFactory.get(handlerKey.getEntityType()).
              reportBacklogSize(handlerKey.getHandle(), backlogSize)));
  }

  @SuppressWarnings("unchecked")
  private > TaskInjector getTaskInjector(HandlerKey handlerKey,
                                                                            TaskQueue queue) {
    ReportableEntityType entityType = handlerKey.getEntityType();
    switch (entityType) {
      case POINT:
      case DELTA_COUNTER:
      case HISTOGRAM:
      case TRACE:
      case TRACE_SPAN_LOGS:
        return task -> ((LineDelimitedDataSubmissionTask) task).injectMembers(
            apiContainer.getProxyV2API(), proxyId, entityPropsFactory.get(entityType),
            (TaskQueue) queue);
      case SOURCE_TAG:
        return task -> ((SourceTagSubmissionTask) task).injectMembers(
            apiContainer.getSourceTagAPI(), entityPropsFactory.get(entityType),
            (TaskQueue) queue);
      case EVENT:
        return task -> ((EventDataSubmissionTask) task).injectMembers(
            apiContainer.getEventAPI(), proxyId, entityPropsFactory.get(entityType),
            (TaskQueue) queue);
      default:
        throw new IllegalArgumentException("Unexpected entity type: " + entityType);
    }
  }

  @VisibleForTesting
  public void flushNow(@Nonnull HandlerKey handlerKey) {
    queueProcessors.get(handlerKey).values().forEach(QueueProcessor::run);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy