Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build metrics - collect information about produced build items #30274

Merged
merged 1 commit into from Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -254,6 +254,7 @@ private void doProduce(ItemId id, BuildItem value) {
throw Messages.msg.cannotMulti(id);
}
}
execution.getMetrics().buildItemProduced(value);
}

void depFinished() {
Expand Down
41 changes: 38 additions & 3 deletions core/builder/src/main/java/io/quarkus/builder/BuildMetrics.java
Expand Up @@ -13,6 +13,7 @@
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -21,6 +22,7 @@

import io.quarkus.builder.Json.JsonArrayBuilder;
import io.quarkus.builder.Json.JsonObjectBuilder;
import io.quarkus.builder.item.BuildItem;

public class BuildMetrics {

Expand All @@ -30,6 +32,7 @@ public class BuildMetrics {
private volatile long duration;
private final String buildTargetName;
private final ConcurrentMap<String, BuildStepRecord> records = new ConcurrentHashMap<>();
private final ConcurrentMap<String, Integer> buildItems = new ConcurrentHashMap<>();
private final AtomicInteger idGenerator;

public BuildMetrics(String buildTargetName) {
Expand All @@ -54,11 +57,22 @@ public void buildStepFinished(StepInfo stepInfo, String thread, LocalTime starte
new BuildStepRecord(idGenerator.incrementAndGet(), stepInfo, thread, started, duration));
}

public void buildItemProduced(BuildItem buildItem) {
buildItems.compute(buildItem.getClass().getName(), this::itemProduced);
}

private Integer itemProduced(String key, Integer val) {
if (val == null) {
return 1;
}
return val + 1;
}

public void dumpTo(Path file) throws IOException {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");

List<BuildStepRecord> sorted = new ArrayList<>(records.values());
sorted.sort(new Comparator<BuildStepRecord>() {
List<BuildStepRecord> sortedSteps = new ArrayList<>(records.values());
sortedSteps.sort(new Comparator<BuildStepRecord>() {
@Override
public int compare(BuildStepRecord o1, BuildStepRecord o2) {
return Long.compare(o2.duration, o1.duration);
Expand All @@ -72,7 +86,7 @@ public int compare(BuildStepRecord o1, BuildStepRecord o2) {

JsonArrayBuilder steps = Json.array();
json.put("records", steps);
for (BuildStepRecord rec : sorted) {
for (BuildStepRecord rec : sortedSteps) {
JsonObjectBuilder recObject = Json.object();
recObject.put("id", rec.id);
recObject.put("stepId", rec.stepInfo.getBuildStep().getId());
Expand All @@ -91,6 +105,27 @@ public int compare(BuildStepRecord o1, BuildStepRecord o2) {
recObject.put("dependents", dependentsArray);
steps.add(recObject);
}

List<Entry<String, Integer>> sortedItems = new ArrayList<>(buildItems.size());
buildItems.entrySet().forEach(sortedItems::add);
sortedItems.sort(new Comparator<Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
return Integer.compare(o2.getValue(), o1.getValue());
}
});
JsonArrayBuilder items = Json.array();
json.put("items", items);
Integer itemsCount = 0;
for (Entry<String, Integer> e : sortedItems) {
JsonObjectBuilder itemObject = Json.object();
itemObject.put("class", e.getKey());
itemObject.put("count", e.getValue());
items.add(itemObject);
itemsCount += e.getValue();
}
json.put("itemsCount", itemsCount);

try (BufferedWriter writer = new BufferedWriter(new FileWriter(file.toFile(), StandardCharsets.UTF_8))) {
json.appendTo(writer);
}
Expand Down
Expand Up @@ -57,8 +57,8 @@ public Map<String, Object> get() {
buildDuration = data.getLong("duration");
buildStarted = LocalDateTime
.parse(data.getString("started"), DateTimeFormatter.ISO_LOCAL_DATE_TIME).toLocalTime();
JsonArray records = data.getJsonArray("records");

JsonArray records = data.getJsonArray("records");
for (Object record : records) {
JsonObject recordObj = (JsonObject) record;
recordObj.put("encodedStepId", URLEncoder.encode(recordObj.getString("stepId"),
Expand All @@ -73,7 +73,10 @@ public Map<String, Object> get() {
}
steps.add(recordObj);
}

metrics.put("records", records);
metrics.put("items", data.getJsonArray("items"));
metrics.put("itemsCount", data.getInteger("itemsCount"));
metrics.put("duration", buildDuration);
} catch (IOException e) {
LOG.error(e);
Expand Down
Expand Up @@ -15,6 +15,12 @@
Build Steps
</a>
</p>
<p class="card-text">
<a href="io.quarkus.quarkus-vertx-http/build-items" class="badge badge-light">
<i class="fas fa-hard-hat"></i>
Build Items
</a>
</p>
</div>
</div>
</div>
Expand Down
@@ -0,0 +1,34 @@
{#let metrics=info:buildMetrics.get}

{#include main fluid=true}
{#title}Build Items{/title}
{#body}
<p class="lead mt-4 mb-4">
Produced <strong>{metrics.itemsCount}</strong> build items.
</p>

<table class="table table-striped mb-4">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Build Item</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
{#for item in metrics.items}
<tr>
<td>{item_count}</td>
<td>
{item.class}
</td>
<td>
{item.count}
</td>
{/for}
</tbody>
</table>

{/include}

{/let}