blob: 73ba2f28bc38943e60ef863ed71bea1bc4444feb [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.runtime;
15
16import com.google.common.base.Joiner;
17import com.google.common.eventbus.EventBus;
18import com.google.common.eventbus.Subscribe;
19import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent;
20import com.google.devtools.build.lib.buildtool.buildevent.ExecutionStartingEvent;
21import com.google.devtools.build.lib.events.Event;
22import com.google.devtools.build.lib.events.Reporter;
23import com.google.devtools.build.lib.profiler.Profiler;
24import com.google.devtools.build.lib.profiler.ProfilerTask;
25import com.google.devtools.build.lib.util.BlazeClock;
26
27import java.util.ArrayList;
28import java.util.List;
29import java.util.concurrent.TimeUnit;
30import java.util.logging.Logger;
31
32/**
33 * Blaze module for the build summary message that reports various stats to the user.
34 */
35public class BuildSummaryStatsModule extends BlazeModule {
36
37 private static final Logger LOG = Logger.getLogger(BuildSummaryStatsModule.class.getName());
38
39 private SimpleCriticalPathComputer criticalPathComputer;
40 private EventBus eventBus;
41 private Reporter reporter;
42
43 @Override
Ulf Adams633f5392015-09-15 11:13:08 +000044 public void beforeCommand(Command command, CommandEnvironment env) {
45 this.reporter = env.getReporter();
46 this.eventBus = env.getEventBus();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010047 eventBus.register(this);
48 }
49
Ulf Adams10efbf22016-04-18 11:35:25 +000050 @Override
51 public void afterCommand() {
52 this.criticalPathComputer = null;
53 this.eventBus = null;
54 this.reporter = null;
55 }
56
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010057 @Subscribe
58 public void executionPhaseStarting(ExecutionStartingEvent event) {
59 criticalPathComputer = new SimpleCriticalPathComputer(BlazeClock.instance());
60 eventBus.register(criticalPathComputer);
61 }
62
63 @Subscribe
64 public void buildComplete(BuildCompleteEvent event) {
65 try {
66 // We might want to make this conditional on a flag; it can sometimes be a bit of a nuisance.
67 List<String> items = new ArrayList<>();
68 items.add(String.format("Elapsed time: %.3fs", event.getResult().getElapsedSeconds()));
69
70 if (criticalPathComputer != null) {
71 Profiler.instance().startTask(ProfilerTask.CRITICAL_PATH, "Critical path");
72 AggregatedCriticalPath<SimpleCriticalPathComponent> criticalPath =
73 criticalPathComputer.aggregate();
74 items.add(criticalPath.toStringSummary());
75 LOG.info(criticalPath.toString());
76 LOG.info("Slowest actions:\n " + Joiner.on("\n ")
77 .join(criticalPathComputer.getSlowestComponents()));
78 // We reverse the critical path because the profiler expect events ordered by the time
79 // when the actions were executed while critical path computation is stored in the reverse
80 // way.
81 for (SimpleCriticalPathComponent stat : criticalPath.components().reverse()) {
82 Profiler.instance().logSimpleTaskDuration(
Miguel Alcon Pintoc5102fc2015-02-25 00:10:14 +000083 TimeUnit.MILLISECONDS.toNanos(stat.getStartWallTimeMillis(BlazeClock.instance())),
84 stat.getElapsedTimeNanos(),
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010085 ProfilerTask.CRITICAL_PATH_COMPONENT, stat.getAction());
86 }
87 Profiler.instance().completeTask(ProfilerTask.CRITICAL_PATH);
88 }
89
90 reporter.handle(Event.info(Joiner.on(", ").join(items)));
91 } finally {
92 criticalPathComputer = null;
93 }
94 }
95}