content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you 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 org.apache.cassandra.metrics;
  
  import java.util.concurrent.ThreadPoolExecutor;
  
  import com.codahale.metrics.Counter;
  import com.codahale.metrics.Gauge;
  import org.apache.cassandra.concurrent.ResizableThreadPool;
  import org.apache.cassandra.metrics.CassandraMetricsRegistry.MetricName;
  
  import static java.lang.String.format;
  
  import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
  
  /**
   * Metrics for {@link ThreadPoolExecutor}.
   */
  public class ThreadPoolMetrics
  {
      public static final String TYPE_NAME = "ThreadPools";
      public static final String ACTIVE_TASKS = "ActiveTasks";
      public static final String PENDING_TASKS = "PendingTasks";
      public static final String COMPLETED_TASKS = "CompletedTasks";
      public static final String CURRENTLY_BLOCKED_TASKS = "CurrentlyBlockedTasks";
      public static final String TOTAL_BLOCKED_TASKS = "TotalBlockedTasks";
      public static final String CORE_POOL_SIZE = "CorePoolSize";
      public static final String MAX_POOL_SIZE = "MaxPoolSize";
      public static final String MAX_TASKS_QUEUED = "MaxTasksQueued";
      public static final String OLDEST_TASK_QUEUE_TIME = "OldestTaskQueueTime";
  
      /** Number of active tasks. */
      public final Gauge<Integer> activeTasks;
  
      /** Number of tasks waiting to be executed. */
      public final Gauge<Integer> pendingTasks;
  
      /** Number of completed tasks. */
      public final Gauge<Long> completedTasks;
  
      /**
       * Number of tasks currently blocked, waiting to be accepted by
       * the executor (because all threads are busy and the backing queue is full).
       */
      public final Counter currentBlocked;
  
      /** Number of tasks that had blocked before being accepted (or rejected). */
      public final Counter totalBlocked;
  
      /** Number of threads always available */
      public final Gauge<Integer> corePoolSize;
  
      /** Maximum number of threads before it will start queuing tasks */
      public final Gauge<Integer> maxPoolSize;
  
      /** For how long the oldest task in the queue was queued */
      public final Gauge<Long> oldestTaskQueueTime;
  
      /** Maximum number of tasks queued before a task get blocked */
      public final Gauge<Integer> maxTasksQueued;
  
      public final String path;
      public final String poolName;
  
      /**
       * Create metrics for given ThreadPoolExecutor.
       *
       * @param executor Thread pool
       * @param path Type of thread pool
       * @param poolName Name of thread pool to identify metrics
       */
      public ThreadPoolMetrics(ResizableThreadPool executor, String path, String poolName)
      {
          this.path = path;
          this.poolName = poolName;
  
          totalBlocked = new Counter();
          currentBlocked = new Counter();
          activeTasks = executor::getActiveTaskCount;
          pendingTasks = executor::getPendingTaskCount;
          completedTasks = executor::getCompletedTaskCount;
          corePoolSize = executor::getCorePoolSize;
          maxPoolSize = executor::getMaximumPoolSize;
          maxTasksQueued = executor::getMaxTasksQueued;
          oldestTaskQueueTime = executor::oldestTaskQueueTime;
      }
  
      public ThreadPoolMetrics register()
      {
          Metrics.register(makeMetricName(path, poolName, ACTIVE_TASKS), activeTasks);
          Metrics.register(makeMetricName(path, poolName, PENDING_TASKS), pendingTasks);
          Metrics.register(makeMetricName(path, poolName, COMPLETED_TASKS), completedTasks);
          Metrics.register(makeMetricName(path, poolName, CURRENTLY_BLOCKED_TASKS), currentBlocked);
          Metrics.register(makeMetricName(path, poolName, TOTAL_BLOCKED_TASKS), totalBlocked);
          Metrics.register(makeMetricName(path, poolName, CORE_POOL_SIZE), corePoolSize);
          Metrics.register(makeMetricName(path, poolName, MAX_POOL_SIZE), maxPoolSize);
          Metrics.register(makeMetricName(path, poolName, MAX_TASKS_QUEUED), maxTasksQueued);
          Metrics.register(makeMetricName(path, poolName, OLDEST_TASK_QUEUE_TIME), oldestTaskQueueTime);
          return Metrics.register(this);
      }
  
      public void release()
      {
          Metrics.remove(makeMetricName(path, poolName, ACTIVE_TASKS));
          Metrics.remove(makeMetricName(path, poolName, PENDING_TASKS));
          Metrics.remove(makeMetricName(path, poolName, COMPLETED_TASKS));
          Metrics.remove(makeMetricName(path, poolName, CURRENTLY_BLOCKED_TASKS));
          Metrics.remove(makeMetricName(path, poolName, TOTAL_BLOCKED_TASKS));
          Metrics.remove(makeMetricName(path, poolName, CORE_POOL_SIZE));
          Metrics.remove(makeMetricName(path, poolName, MAX_POOL_SIZE));
          Metrics.remove(makeMetricName(path, poolName, MAX_TASKS_QUEUED));
          Metrics.remove(makeMetricName(path, poolName, OLDEST_TASK_QUEUE_TIME));
          Metrics.remove(this);
      }
  
      private static MetricName makeMetricName(String path, String poolName, String metricName)
      {
          return new MetricName("org.apache.cassandra.metrics",
                                TYPE_NAME,
                                metricName,
                                path + '.' + poolName,
                                format("org.apache.cassandra.metrics:type=%s,path=%s,scope=%s,name=%s",
                                       TYPE_NAME, path, poolName, metricName));
      }
  }
  