Java tutorial
/* * Copyright 2017-present Facebook, Inc. * * 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 com.facebook.buck.distributed; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import com.google.common.collect.Maps; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; import javax.annotation.concurrent.GuardedBy; public class DistBuildClientStatsTracker { @VisibleForTesting protected enum DistBuildClientStat { PERFORM_DISTRIBUTED_BUILD, PERFORM_LOCAL_BUILD, CREATE_DISTRIBUTED_BUILD, UPLOAD_MISSING_FILES, UPLOAD_TARGET_GRAPH, UPLOAD_BUCK_DOT_FILES, SET_BUCK_VERSION, MATERIALIZE_SLAVE_LOGS, } @GuardedBy("this") private final Map<DistBuildClientStat, Stopwatch> stopwatchesByType = Maps.newHashMap(); @GuardedBy("this") private final Map<DistBuildClientStat, Long> durationsMsByType = Maps.newHashMap(); private volatile Optional<String> stampedeId = Optional.empty(); private volatile Optional<Integer> distributedBuildExitCode = Optional.empty(); private volatile Optional<Boolean> isLocalFallbackBuildEnabled = Optional.empty(); private volatile boolean performedLocalBuild = false; private volatile boolean buckClientError = false; private volatile Optional<Integer> localBuildExitCode = Optional.empty(); private volatile Optional<Long> missingFilesUploadedCount = Optional.empty(); private volatile Optional<String> buckClientErrorMessage = Optional.empty(); private void generateStatsPreconditionChecksNoException() { // Unless there was an exception, we expect all the following fields to be present. Preconditions.checkArgument(distributedBuildExitCode.isPresent(), "distributedBuildExitCode not set"); Preconditions.checkArgument(isLocalFallbackBuildEnabled.isPresent(), "isLocalFallbackBuildEnabled not set"); Preconditions.checkArgument(missingFilesUploadedCount.isPresent(), "missingFilesUploadedCount not set"); if (performedLocalBuild) { Preconditions.checkArgument(localBuildExitCode.isPresent()); Preconditions.checkNotNull(durationsMsByType.get(DistBuildClientStat.PERFORM_LOCAL_BUILD), "No time was recorded for stat: " + DistBuildClientStat.PERFORM_LOCAL_BUILD); } Preconditions.checkNotNull(durationsMsByType.get(DistBuildClientStat.PERFORM_DISTRIBUTED_BUILD), "No time was recorded for stat: " + DistBuildClientStat.PERFORM_DISTRIBUTED_BUILD); Preconditions.checkNotNull(durationsMsByType.get(DistBuildClientStat.CREATE_DISTRIBUTED_BUILD), "No time was recorded for stat: " + DistBuildClientStat.CREATE_DISTRIBUTED_BUILD); Preconditions.checkNotNull(durationsMsByType.get(DistBuildClientStat.UPLOAD_MISSING_FILES), "No time was recorded for stat: " + DistBuildClientStat.UPLOAD_MISSING_FILES); Preconditions.checkNotNull(durationsMsByType.get(DistBuildClientStat.UPLOAD_TARGET_GRAPH), "No time was recorded for stat: " + DistBuildClientStat.UPLOAD_TARGET_GRAPH); Preconditions.checkNotNull(durationsMsByType.get(DistBuildClientStat.UPLOAD_BUCK_DOT_FILES), "No time was recorded for stat: " + DistBuildClientStat.UPLOAD_BUCK_DOT_FILES); Preconditions.checkNotNull(durationsMsByType.get(DistBuildClientStat.SET_BUCK_VERSION), "No time was recorded for stat: " + DistBuildClientStat.SET_BUCK_VERSION); // MATERIALIZE_SLAVE_LOGS is optional even if no buck client errors. } private Optional<Long> getDurationOrEmpty(DistBuildClientStat stat) { if (!durationsMsByType.containsKey(stat)) { return Optional.empty(); } return Optional.of(durationsMsByType.get(stat)); } public synchronized DistBuildClientStats generateStats() { // Without a Stampede ID there is nothing useful to record. Preconditions.checkArgument(stampedeId.isPresent()); if (!buckClientError) { generateStatsPreconditionChecksNoException(); } else { // Buck client threw an exception, so we will log on a best effort basis. Preconditions.checkArgument(buckClientErrorMessage.isPresent()); } DistBuildClientStats.Builder builder = DistBuildClientStats.builder().setStampedeId(stampedeId.get()) .setPerformedLocalBuild(performedLocalBuild).setBuckClientError(buckClientError); builder.setDistributedBuildExitCode(distributedBuildExitCode); builder.setLocalFallbackBuildEnabled(isLocalFallbackBuildEnabled); builder.setBuckClientErrorMessage(buckClientErrorMessage); if (performedLocalBuild) { builder.setLocalBuildExitCode(localBuildExitCode); builder.setLocalBuildDurationMs(getDurationOrEmpty(DistBuildClientStat.PERFORM_LOCAL_BUILD)); } builder.setPerformDistributedBuildDurationMs( getDurationOrEmpty(DistBuildClientStat.PERFORM_DISTRIBUTED_BUILD)); builder.setCreateDistributedBuildDurationMs( getDurationOrEmpty(DistBuildClientStat.CREATE_DISTRIBUTED_BUILD)); builder.setUploadMissingFilesDurationMs(getDurationOrEmpty(DistBuildClientStat.UPLOAD_MISSING_FILES)); builder.setUploadTargetGraphDurationMs(getDurationOrEmpty(DistBuildClientStat.UPLOAD_TARGET_GRAPH)); builder.setUploadBuckDotFilesDurationMs(getDurationOrEmpty(DistBuildClientStat.UPLOAD_BUCK_DOT_FILES)); builder.setSetBuckVersionDurationMs(getDurationOrEmpty(DistBuildClientStat.SET_BUCK_VERSION)); builder.setMaterializeSlaveLogsDurationMs(getDurationOrEmpty(DistBuildClientStat.MATERIALIZE_SLAVE_LOGS)); builder.setMissingFilesUploadedCount(missingFilesUploadedCount); return builder.build(); } public void setMissingFilesUploadedCount(long missingFilesUploadedCount) { this.missingFilesUploadedCount = Optional.of(missingFilesUploadedCount); } public void setPerformedLocalBuild(boolean performedLocalBuild) { this.performedLocalBuild = performedLocalBuild; } public void setLocalBuildExitCode(int localBuildExitCode) { this.localBuildExitCode = Optional.of(localBuildExitCode); } public void setStampedeId(String stampedeId) { this.stampedeId = Optional.of(stampedeId); } public void setDistributedBuildExitCode(int distributedBuildExitCode) { this.distributedBuildExitCode = Optional.of(distributedBuildExitCode); } public void setIsLocalFallbackBuildEnabled(boolean isLocalFallbackBuildEnabled) { this.isLocalFallbackBuildEnabled = Optional.of(isLocalFallbackBuildEnabled); } public void startCreateBuildTimer() { startTimer(DistBuildClientStat.CREATE_DISTRIBUTED_BUILD); } public void stopCreateBuildTimer() { stopTimer(DistBuildClientStat.CREATE_DISTRIBUTED_BUILD); } public void startUploadMissingFilesTimer() { startTimer(DistBuildClientStat.UPLOAD_MISSING_FILES); } public void stopUploadMissingFilesTimer() { stopTimer(DistBuildClientStat.UPLOAD_MISSING_FILES); } public void startUploadTargetGraphTimer() { startTimer(DistBuildClientStat.UPLOAD_TARGET_GRAPH); } public void stopUploadTargetGraphTimer() { stopTimer(DistBuildClientStat.UPLOAD_TARGET_GRAPH); } public void startUploadBuckDotFilesTimer() { startTimer(DistBuildClientStat.UPLOAD_BUCK_DOT_FILES); } public void stopUploadBuckDotFilesTimer() { stopTimer(DistBuildClientStat.UPLOAD_BUCK_DOT_FILES); } public void startSetBuckVersionTimer() { startTimer(DistBuildClientStat.SET_BUCK_VERSION); } public void stopSetBuckVersionTimer() { stopTimer(DistBuildClientStat.SET_BUCK_VERSION); } public void startPerformDistributedBuildTimer() { startTimer(DistBuildClientStat.PERFORM_DISTRIBUTED_BUILD); } public void stopPerformDistributedBuildTimer() { stopTimer(DistBuildClientStat.PERFORM_DISTRIBUTED_BUILD); } public void startPerformLocalBuildTimer() { startTimer(DistBuildClientStat.PERFORM_LOCAL_BUILD); } public void stopPerformLocalBuildTimer() { stopTimer(DistBuildClientStat.PERFORM_LOCAL_BUILD); } public void startMaterializeSlaveLogsTimer() { startTimer(DistBuildClientStat.MATERIALIZE_SLAVE_LOGS); } public void stopMaterializeSlaveLogsTimer() { stopTimer(DistBuildClientStat.MATERIALIZE_SLAVE_LOGS); } public boolean hasStampedeId() { return stampedeId.isPresent(); } public void setBuckClientError(boolean buckClientError) { this.buckClientError = buckClientError; } public void setBuckClientErrorMessage(String buckClientErrorMessage) { this.buckClientErrorMessage = Optional.of(buckClientErrorMessage); } @VisibleForTesting protected synchronized void setDurationMs(DistBuildClientStat stat, long duration) { durationsMsByType.put(stat, duration); } private synchronized void startTimer(DistBuildClientStat stat) { Stopwatch stopwatch = Stopwatch.createStarted(); stopwatchesByType.put(stat, stopwatch); } private synchronized void stopTimer(DistBuildClientStat stat) { Preconditions.checkNotNull(stopwatchesByType.get(stat), "Cannot stop timer for stat: [" + stat + "] as it was not started."); Stopwatch stopwatch = stopwatchesByType.get(stat); stopwatch.stop(); long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS); durationsMsByType.put(stat, elapsed); } }