/** * Licensed 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.aurora.scheduler.preemptor; import java.util.Set; import javax.inject.Inject; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.collect.ImmutableSet; import org.apache.aurora.scheduler.stats.CachedCounters; import org.apache.aurora.scheduler.storage.entities.ITaskConfig; import static java.util.Objects.requireNonNull; /** * Defines methods to manage preemptor metrics. */ @VisibleForTesting public class PreemptorMetrics { @VisibleForTesting static final String MISSING_ATTRIBUTES_NAME = "preemptor_missing_attributes"; @VisibleForTesting static final String TASK_PROCESSOR_RUN_NAME = "preemptor_task_processor_runs"; @VisibleForTesting static final String UNMATCHED_TASKS = "preemptor_unmatched_tasks"; private volatile boolean exported = false; private final CachedCounters counters; @Inject PreemptorMetrics(CachedCounters counters) { this.counters = requireNonNull(counters); assertFullyExported(); } private static String prod(boolean production) { return production ? "prod" : "non_prod"; } private static String result(boolean success) { return success ? "successful" : "failed"; } private void assertFullyExported() { if (exported) { return; } // Dummy-read all stats to ensure they are exported. Set<String> allStats = ImmutableSet.of( attemptsStatName(false), attemptsStatName(true), successStatName(false), successStatName(true), slotSearchStatName(true, false), slotSearchStatName(false, false), slotSearchStatName(true, true), slotSearchStatName(false, true), slotValidationStatName(true), slotValidationStatName(false), MISSING_ATTRIBUTES_NAME, TASK_PROCESSOR_RUN_NAME, UNMATCHED_TASKS); for (String stat : allStats) { counters.get(stat); } exported = true; } private void increment(String stat) { assertFullyExported(); counters.get(stat).incrementAndGet(); } @VisibleForTesting static String attemptsStatName(boolean production) { return "preemptor_slot_search_attempts_for_" + prod(production); } @VisibleForTesting static String successStatName(boolean production) { return "preemptor_tasks_preempted_" + prod(production); } @VisibleForTesting static String slotSearchStatName(boolean success, boolean production) { return "preemptor_slot_search_" + result(success) + "_for_" + prod(production); } @VisibleForTesting static String slotValidationStatName(boolean success) { return "preemptor_slot_validation_" + result(success); } void recordPreemptionAttemptFor(ITaskConfig task) { increment(attemptsStatName(task.isProduction())); } void recordTaskPreemption(PreemptionVictim victim) { increment(successStatName(victim.isProduction())); } void recordSlotSearchResult(Optional<?> result, ITaskConfig task) { increment(slotSearchStatName(result.isPresent(), task.isProduction())); } void recordUnmatchedTask() { increment(UNMATCHED_TASKS); } void recordSlotValidationResult(Optional<?> result) { increment(slotValidationStatName(result.isPresent())); } void recordMissingAttributes() { increment(MISSING_ATTRIBUTES_NAME); } void recordTaskProcessorRun() { increment(TASK_PROCESSOR_RUN_NAME); } }