8320805: JFR: Create view for deprecated methods

Reviewed-by: mgronlun
This commit is contained in:
Erik Gahlin 2023-12-07 11:54:32 +00:00
parent 29d7a22348
commit b5933b186f
7 changed files with 83 additions and 30 deletions

View File

@ -56,6 +56,10 @@ enum Aggregator {
* Aggregate values into a comma-separated list, including {@code null}.
*/
LIST("LIST"),
/**
* Aggregate unique values into a comma-separated list, including {@code null}.
*/
SET("SET"),
/**
* The highest numeric value.
*/

View File

@ -28,7 +28,6 @@ import java.time.Duration;
import java.time.Instant;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -122,7 +121,10 @@ final class FieldBuilder {
configureNotInitFrameField();
return true;
}
if (fieldName.equals("stackTrace.topFrame.class")) {
configureTopFrameClassField();
return true;
}
if (fieldName.equals("stackTrace.topFrame")) {
configureTopFrameField();
return true;
@ -175,6 +177,20 @@ final class FieldBuilder {
field.lexicalSort = true;
}
private void configureTopFrameClassField() {
field.alignLeft = true;
field.label = "Class";
field.dataType = "java.lang.Class";
field.valueGetter = e -> {
RecordedStackTrace t = e.getStackTrace();
if (t == null) {
return null;
}
return t.getFrames().getFirst().getMethod().getType();
};
field.lexicalSort = true;
}
private void configureCustomFrame(Predicate<RecordedFrame> condition) {
field.alignLeft = true;
field.dataType = "jdk.types.Frame";
@ -379,7 +395,7 @@ final class FieldBuilder {
field.alignLeft = false;
field.lexicalSort = false;
}
if (aggregator == Aggregator.LIST) {
if (aggregator == Aggregator.LIST || aggregator == Aggregator.SET) {
field.alignLeft = true;
field.lexicalSort = true;
}
@ -392,6 +408,7 @@ final class FieldBuilder {
case SUM -> "Total " + field.label;
case UNIQUE -> "Unique Count " + field.label;
case LIST -> field.label + "s";
case SET -> field.label + "s";
case MISSING -> field.label;
case DIFFERENCE -> "Difference " + field.label;
case MEDIAN -> "Median " + field.label;

View File

@ -27,6 +27,8 @@ package jdk.jfr.internal.query;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.StringJoiner;
import jdk.jfr.consumer.RecordedClass;
import jdk.jfr.consumer.RecordedClassLoader;
@ -51,6 +53,13 @@ public class FieldFormatter {
if (object == null) {
return field.missingText;
}
if (object instanceof Collection<?> c) {
StringJoiner sj = new StringJoiner(", ");
for (Object o : c) {
sj.add(format(field, o, compact));
}
return sj.toString();
}
if (object instanceof String s) {
return stripFormatting(s);
}
@ -71,6 +80,10 @@ public class FieldFormatter {
return field.missingText;
}
if (object instanceof RecordedFrame f && f.isJavaFrame()) {
object = f.getMethod();
}
if (object instanceof RecordedThread t) {
if (t.getJavaThreadId() > 0) {
return t.getJavaName();

View File

@ -28,10 +28,10 @@ import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.StringJoiner;
abstract class Function {
@ -46,7 +46,11 @@ abstract class Function {
return new FirstNonNull();
}
if (aggregator == Aggregator.LIST) {
return new List();
return new Container(new ArrayList<>());
}
if (aggregator == Aggregator.SET) {
return new Container(new LinkedHashSet<>());
}
if (aggregator == Aggregator.DIFFERENCE) {
@ -378,7 +382,7 @@ abstract class Function {
// **** UNIQUE ****
private static final class Unique extends Function {
private final Set<Object> unique = new HashSet<>();
private final Set<Object> unique = new LinkedHashSet<>();
@Override
public void add(Object value) {
@ -391,23 +395,22 @@ abstract class Function {
}
}
// **** LIST ****
// **** LIST and SET ****
private static final class List extends Function {
private final ArrayList<Object> list = new ArrayList<>();
private static final class Container extends Function {
private final Collection<Object> collection;
private Container(Collection<Object> collection) {
this.collection = collection;
}
@Override
public void add(Object value) {
list.add(value);
collection.add(value);
}
@Override
public Object result() {
StringJoiner sj = new StringJoiner(", ");
for (Object object : list) {
sj.add(String.valueOf(object));
}
return sj.toString();
return collection;
}
}

View File

@ -25,6 +25,7 @@
package jdk.jfr.internal.query;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import jdk.jfr.internal.query.Configuration.Truncate;
@ -69,7 +70,7 @@ final class TableCell {
}
public void addLine(String text) {
int contentWidth = getContentWidth();
if (text.length() >= contentWidth) {
if (text.length() > contentWidth) {
add(truncate(text, contentWidth));
} else {
addAligned(text);
@ -143,6 +144,10 @@ final class TableCell {
}
}
public void sort() {
Collections.sort(lines);
}
public void clear() {
lines.clear();
}

View File

@ -28,11 +28,10 @@ import static jdk.jfr.internal.query.Configuration.MAX_PREFERRED_WIDTH;
import static jdk.jfr.internal.query.Configuration.MIN_PREFERRED_WIDTH;
import static jdk.jfr.internal.query.Configuration.PREFERRED_WIDTH;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
import jdk.jfr.consumer.RecordedFrame;
import jdk.jfr.consumer.RecordedMethod;
import jdk.jfr.consumer.RecordedStackTrace;
import jdk.jfr.internal.query.Configuration.Truncate;
import jdk.jfr.internal.util.Output;
@ -293,37 +292,39 @@ final class TableRenderer {
if (cell.cellHeight > 1) {
Object o = row.getValue(columnIndex);
if (o instanceof RecordedStackTrace s) {
setStackTrace(cell, s);
o = s.getFrames();
}
if (o instanceof Collection<?> c) {
setMultiline(cell, c);
return;
}
}
if (text.length() > cell.getContentSize()) {
Object o = row.getValue(columnIndex);
cell.setContent(FieldFormatter.formatCompact(cell.field, o));
return;
}
cell.setContent(text);
}
private void setStackTrace(TableCell cell, RecordedStackTrace s) {
private void setMultiline(TableCell cell, Collection<?> objects) {
int row = 0;
cell.clear();
for(RecordedFrame f : s.getFrames()) {
for(Object object : objects) {
if (row == cell.cellHeight) {
return;
}
if (f.isJavaFrame()) {
RecordedMethod method = f.getMethod();
String text = FieldFormatter.format(cell.field, method);
if (text.length() > cell.getContentWidth()) {
text = FieldFormatter.formatCompact(cell.field, method);
}
cell.addLine(text);
String text = FieldFormatter.format(cell.field, object);
if (text.length() > cell.getContentWidth()) {
text = FieldFormatter.formatCompact(cell.field, object);
}
cell.addLine(text);
row++;
}
if (cell.field.lexicalSort) {
cell.sort();
}
}
private void printRow() {

View File

@ -173,6 +173,16 @@ table = "COLUMN 'Monitor Address', 'Class', 'Threads', 'Max Duration'
FROM JavaMonitorEnter
GROUP BY monitorClass ORDER BY M"
[application.deprecated-methods-for-removal]
label = "Deprecated Methods for Removal"
table = "COLUMN 'Deprecated Method', 'Called from Class'
FORMAT truncate-beginning, cell-height:10000;truncate-beginning
SELECT method AS m, SET(stackTrace.topFrame.class)
FROM DeprecatedInvocation
WHERE forRemoval = 'true'
GROUP BY m
ORDER BY m"
[environment.cpu-information]
label ="CPU Information"
form = "SELECT cpu, sockets, cores, hwThreads, description FROM CPUInformation"