Skip to content

[GR-61664] Add support for querying ProgressReporter's JSON metric values #11304

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

Merged
merged 2 commits into from
Jun 3, 2025
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private static void sourceElement(SourceSizePair p, JsonWriter w) throws IOExcep
w.appendObjectEnd();
}

private static List<ResourceReportEntry> getResourceReportEntryList(ConcurrentHashMap<Resources.ModuleResourceKey, List<SourceAndOrigin>> collection) {
public static List<ResourceReportEntry> getResourceReportEntryList(ConcurrentHashMap<Resources.ModuleResourceKey, List<SourceAndOrigin>> collection) {
if (collection.isEmpty()) {
LogUtils.warning("Attempting to write information about resources without data being collected. " +
"Either the GenerateEmbeddedResourcesFile hosted option is disabled " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,20 @@ private void checkForExcessiveGarbageCollection() {
lastGCStats = currentGCStats;
}

public Object getJsonMetricValue(JsonMetric metric) {
if (jsonHelper == null) {
return null;
}
return metric.getValue(jsonHelper);
}

public boolean containsJsonMetricValue(JsonMetric metric) {
if (jsonHelper == null) {
return false;
}
return metric.containsValue(jsonHelper);
}

public void recordJsonMetric(JsonMetric metric, Object value) {
if (jsonHelper != null) {
metric.record(jsonHelper, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,82 @@ private static List<String> buildKeys(String... keys) {
return Arrays.stream(keys).filter(Objects::nonNull).toList();
}

/**
* Returns the {@link Map} stored in the given object under the given key or null if the map
* does not exist.
*/
@SuppressWarnings("unchecked")
private static Map<String, Object> getMap(Map<String, Object> object, String key) {
Objects.requireNonNull(key, "JSON keys must not be 'null'");
return (Map<String, Object>) object.get(key);
}

/**
* Gets value from {@link #statsHolder} for the given key sequence.
* <p>
* For example for {@code keys = [a, b, c, d]} it will return the value of
* {@code statsHolder[a][b][c][d]}.
*/
private Object getValue(List<String> keys) {
assert !keys.isEmpty();
Map<String, Object> currentLevel = statsHolder;

/*
* Iteratively index into the next level until the second-last key. Return null if there is
* no defined value on some level while traversing.
*/
for (int i = 0; i < keys.size() - 1; i++) {
currentLevel = getMap(currentLevel, keys.get(i));
if (currentLevel == null) {
return null;
}
}

return currentLevel.get(keys.getLast());
}

public Object getAnalysisResults(AnalysisResults key) {
return getValue(buildKeys(ANALYSIS_RESULTS_KEY, key.bucket, key.key));
}

public Object getGeneralInfo(GeneralInfo info) {
return getValue(buildKeys(GENERAL_INFO_KEY, info.bucket, info.key));
}

public Object getImageDetails(ImageDetailKey key) {
return getValue(buildKeys(IMAGE_DETAILS_KEY, key.bucket, key.subBucket, key.jsonKey));
}

public Object getResourceUsage(ResourceUsageKey key) {
return getValue(buildKeys(RESOURCE_USAGE_KEY, key.bucket, key.jsonKey));
}

/**
* Checks if there is a set value from {@link #statsHolder} for the given key sequence.
* <p>
* For example for {@code keys = [a, b, c, d]} it will return true if
* {@code statsHolder[a][b][c][d]} exists.
*/
private boolean containsValue(List<String> keys) {
return getValue(keys) != null;
}

public boolean containsAnalysisResults(AnalysisResults key) {
return containsValue(buildKeys(ANALYSIS_RESULTS_KEY, key.bucket, key.key));
}

public boolean containsGeneralInfo(GeneralInfo info) {
return containsValue(buildKeys(GENERAL_INFO_KEY, info.bucket, info.key));
}

public boolean containsImageDetails(ImageDetailKey key) {
return containsValue(buildKeys(IMAGE_DETAILS_KEY, key.bucket, key.subBucket, key.jsonKey));
}

public boolean containsResourceUsage(ResourceUsageKey key) {
return containsValue(buildKeys(RESOURCE_USAGE_KEY, key.bucket, key.jsonKey));
}

/**
* Returns the {@link Map} stored in the given object under the given key.
* <p>
Expand Down Expand Up @@ -108,11 +184,15 @@ public void print(JsonWriter writer) throws IOException {
writer.print(statsHolder);
}

interface JsonMetric {
public interface JsonMetric {
Object getValue(ProgressReporterJsonHelper helper);

boolean containsValue(ProgressReporterJsonHelper helper);

void record(ProgressReporterJsonHelper helper, Object value);
}

enum ImageDetailKey implements JsonMetric {
public enum ImageDetailKey implements JsonMetric {
TOTAL_SIZE(null, null, "total_bytes"),
CODE_AREA_SIZE("code_area", null, "bytes"),
NUM_COMP_UNITS("code_area", null, "compilation_units"),
Expand All @@ -134,13 +214,23 @@ enum ImageDetailKey implements JsonMetric {
this.subBucket = subBucket;
}

@Override
public Object getValue(ProgressReporterJsonHelper helper) {
return helper.getImageDetails(this);
}

@Override
public boolean containsValue(ProgressReporterJsonHelper helper) {
return helper.containsImageDetails(this);
}

@Override
public void record(ProgressReporterJsonHelper helper, Object value) {
helper.putImageDetails(this, value);
}
}

enum ResourceUsageKey implements JsonMetric {
public enum ResourceUsageKey implements JsonMetric {
CPU_LOAD("cpu", "load"),
CPU_CORES_TOTAL("cpu", "total_cores"),
GC_COUNT("garbage_collection", "count"),
Expand All @@ -159,6 +249,16 @@ enum ResourceUsageKey implements JsonMetric {
this.jsonKey = key;
}

@Override
public Object getValue(ProgressReporterJsonHelper helper) {
return helper.getResourceUsage(this);
}

@Override
public boolean containsValue(ProgressReporterJsonHelper helper) {
return helper.containsResourceUsage(this);
}

@Override
public void record(ProgressReporterJsonHelper helper, Object value) {
helper.putResourceUsage(this, value);
Expand Down Expand Up @@ -199,6 +299,16 @@ public String bucket() {
return bucket;
}

@Override
public Object getValue(ProgressReporterJsonHelper helper) {
return helper.getAnalysisResults(this);
}

@Override
public boolean containsValue(ProgressReporterJsonHelper helper) {
return helper.containsAnalysisResults(this);
}

@Override
public void record(ProgressReporterJsonHelper helper, Object value) {
if (value instanceof Integer v) {
Expand Down Expand Up @@ -234,6 +344,16 @@ public String jsonKey() {
return key;
}

@Override
public Object getValue(ProgressReporterJsonHelper helper) {
return helper.getGeneralInfo(this);
}

@Override
public boolean containsValue(ProgressReporterJsonHelper helper) {
return helper.containsGeneralInfo(this);
}

@Override
public void record(ProgressReporterJsonHelper helper, Object value) {
if (value instanceof String || value instanceof Boolean || value instanceof List || value == null) {
Expand Down
Loading