/* * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. */ package org.opensearch.tasks; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.Collections; import java.util.EnumMap; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; /** * Thread resource usage information for particular resource stats type. *

* It captures the resource usage information like memory, CPU about a particular execution of thread * for a specific stats type. * * @opensearch.internal */ public class ResourceUsageInfo { private static final Logger logger = LogManager.getLogger(ResourceUsageInfo.class); private final EnumMap statsInfo = new EnumMap<>(ResourceStats.class); public ResourceUsageInfo(ResourceUsageMetric... resourceUsageMetrics) { for (ResourceUsageMetric resourceUsageMetric : resourceUsageMetrics) { this.statsInfo.put(resourceUsageMetric.getStats(), new ResourceStatsInfo(resourceUsageMetric.getValue())); } } public void recordResourceUsageMetrics(ResourceUsageMetric... resourceUsageMetrics) { for (ResourceUsageMetric resourceUsageMetric : resourceUsageMetrics) { final ResourceStatsInfo resourceStatsInfo = statsInfo.get(resourceUsageMetric.getStats()); if (resourceStatsInfo != null) { updateResourceUsageInfo(resourceStatsInfo, resourceUsageMetric); } else { throw new IllegalStateException( "cannot update [" + resourceUsageMetric.getStats().toString() + "] entry as its not present current_stats_info:" + statsInfo ); } } } private void updateResourceUsageInfo(ResourceStatsInfo resourceStatsInfo, ResourceUsageMetric resourceUsageMetric) { long currentEndValue; long newEndValue; do { currentEndValue = resourceStatsInfo.endValue.get(); newEndValue = resourceUsageMetric.getValue(); if (currentEndValue > newEndValue) { logger.debug( "dropping resource usage update as the new value is lower than current value [" + "resource_stats=[{}], " + "current_end_value={}, " + "new_end_value={}]", resourceUsageMetric.getStats(), currentEndValue, newEndValue ); return; } } while (!resourceStatsInfo.endValue.compareAndSet(currentEndValue, newEndValue)); logger.debug( "updated resource usage info [resource_stats=[{}], " + "old_end_value={}, new_end_value={}]", resourceUsageMetric.getStats(), currentEndValue, newEndValue ); } public Map getStatsInfo() { return Collections.unmodifiableMap(statsInfo); } @Override public String toString() { return statsInfo.toString(); } /** * Defines resource stats information. */ static class ResourceStatsInfo { private final long startValue; private final AtomicLong endValue; private ResourceStatsInfo(long startValue) { this.startValue = startValue; this.endValue = new AtomicLong(startValue); } public long getTotalValue() { return endValue.get() - startValue; } @Override public String toString() { return String.valueOf(getTotalValue()); } } }