blob: d13c5b108368e1f706a2603dd901c8d6beaace41 [file] [log] [blame]
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.metrics;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.google.devtools.build.lib.actions.ActionCompletionEvent;
import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.ActionSummary;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.MemoryMetrics;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.PackageMetrics;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.TargetMetrics;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.TimingMetrics;
import com.google.devtools.build.lib.buildtool.BuildPrecompleteEvent;
import com.google.devtools.build.lib.metrics.MetricsModule.Options;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
class MetricsCollector {
private final CommandEnvironment env;
private final boolean bepPublishUsedHeapSizePostBuild;
private final AtomicLong executedActionCount = new AtomicLong();
private int actionsConstructed;
private int targetsLoaded;
private int targetsConfigured;
private int packagesLoaded;
MetricsCollector(CommandEnvironment env) {
this.env = env;
Options options = env.getOptions().getOptions(Options.class);
this.bepPublishUsedHeapSizePostBuild =
options != null && options.bepPublishUsedHeapSizePostBuild;
env.getEventBus().register(this);
}
static void installInEnv(CommandEnvironment env) {
new MetricsCollector(env);
}
@Subscribe
public void onAnalysisPhaseComplete(AnalysisPhaseCompleteEvent event) {
actionsConstructed = event.getActionsConstructed();
targetsLoaded = event.getTargetsLoaded();
targetsConfigured = event.getTargetsConfigured();
packagesLoaded = event.getPkgManagerStats().getPackagesLoaded();
}
@Subscribe
@AllowConcurrentEvents
public void onActionComplete(ActionCompletionEvent event) {
executedActionCount.incrementAndGet();
}
@Subscribe
public void onBuildComplete(BuildPrecompleteEvent event) {
env.getEventBus().post(new BuildMetricsEvent(createBuildMetrics()));
}
private BuildMetrics createBuildMetrics() {
BuildMetrics.Builder metrics = BuildMetrics.newBuilder();
metrics.setActionSummary(createActionSummary());
metrics.setMemoryMetrics(createMemoryMetrics());
metrics.setTargetMetrics(createTargetMetrics());
metrics.setPackageMetrics(createPackageMetrics());
metrics.setTimingMetrics(createTimingMetrics());
return metrics.build();
}
private ActionSummary createActionSummary() {
return ActionSummary.newBuilder()
.setActionsCreated(actionsConstructed)
.setActionsExecuted(executedActionCount.get())
.build();
}
private MemoryMetrics createMemoryMetrics() {
MemoryMetrics.Builder memoryMetrics = MemoryMetrics.newBuilder();
if (bepPublishUsedHeapSizePostBuild) {
System.gc();
MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
memoryMetrics.setUsedHeapSizePostBuild(memBean.getHeapMemoryUsage().getUsed());
Optional<Long> peakPostGcHeapSize =
PostGCMemoryUseRecorder.get().getPeakPostGCHeapMemoryUsed();
if (peakPostGcHeapSize.isPresent()) {
memoryMetrics.setPeakPostGcHeapSize(peakPostGcHeapSize.get());
}
}
return memoryMetrics.build();
}
private TargetMetrics createTargetMetrics() {
return TargetMetrics.newBuilder()
.setTargetsLoaded(targetsLoaded)
.setTargetsConfigured(targetsConfigured)
.build();
}
private PackageMetrics createPackageMetrics() {
return PackageMetrics.newBuilder().setPackagesLoaded(packagesLoaded).build();
}
private static TimingMetrics createTimingMetrics() {
TimingMetrics.Builder timingMetricsBuilder = TimingMetrics.newBuilder();
Duration elapsedWallTime = Profiler.elapsedTimeMaybe();
if (elapsedWallTime != null) {
timingMetricsBuilder.setWallTimeInMs(elapsedWallTime.toMillis());
}
Duration cpuTime = Profiler.getProcessCpuTimeMaybe();
if (cpuTime != null) {
timingMetricsBuilder.setCpuTimeInMs(cpuTime.toMillis());
}
return timingMetricsBuilder.build();
}
}