mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-10 18:38:27 +00:00
8260862: JFR: New configure command for the jfr tool
Reviewed-by: mgronlun
This commit is contained in:
parent
259319669c
commit
4e708e58dc
@ -6,29 +6,19 @@
|
||||
|
||||
<xsd:complexType name="configurationType">
|
||||
<xsd:sequence>
|
||||
<xsd:element minOccurs="0" maxOccurs="unbounded" name="producer" type="producerType" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute use="required" name="version" type="xsd:decimal" />
|
||||
<xsd:attribute use="required" name="name" type="xsd:string" />
|
||||
<xsd:attribute use="optional" name="description" type="xsd:string" default="" />
|
||||
<xsd:attribute use="optional" name="provider" type="xsd:string" default="" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="producerType">
|
||||
<xsd:sequence>
|
||||
<xsd:element minOccurs="0" maxOccurs="1" name="control" type="controlType" />
|
||||
<xsd:element minOccurs="0" maxOccurs="unbounded" name="event" type="eventType" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute use="required" name="uri" type="xsd:anyURI" />
|
||||
<xsd:attribute use="optional" name="label" type="xsd:string" default="" />
|
||||
<xsd:attribute use="required" name="version" type="xsd:decimal" />
|
||||
<xsd:attribute use="required" name="label" type="xsd:string" />
|
||||
<xsd:attribute use="optional" name="description" type="xsd:string" default="" />
|
||||
<xsd:attribute use="optional" name="provider" type="xsd:string" default="" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="eventType">
|
||||
<xsd:sequence>
|
||||
<xsd:element minOccurs="0" maxOccurs="unbounded" name="setting" type="settingType" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute use="required" name="path" type="xsd:string" />
|
||||
<xsd:attribute use="required" name="name" type="xsd:string" />
|
||||
<xsd:attribute use="optional" name="label" type="xsd:string" />
|
||||
<xsd:attribute use="optional" name="description" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
public final class AbortException extends Exception {
|
||||
private static final long serialVersionUID = -2501519883611363246L;
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
record Constraint(Class<? extends XmlElement> type, int min, int max) {
|
||||
|
||||
public static Constraint any(Class<? extends XmlElement> type) {
|
||||
return new Constraint(type, 0, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static Constraint atLeast(Class<? extends XmlElement> type, int min) {
|
||||
return new Constraint(type, min, Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
// Interface for elements that can control a setting,
|
||||
// <condition>, <selection>, <text> and <flag>
|
||||
interface ControlElement {
|
||||
String getName();
|
||||
}
|
||||
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.jfr.internal.SecuritySupport.SafePath;
|
||||
|
||||
// Holds the structure of a .jfc file similar to an XML DOM.
|
||||
public final class JFCModel {
|
||||
private final Map<String, List<ControlElement>> controls = new LinkedHashMap<>();
|
||||
private final XmlConfiguration configuration;
|
||||
|
||||
public JFCModel(SafePath file) throws ParseException, IOException {
|
||||
this.configuration = createConfiguration(file);
|
||||
this.configuration.validate();
|
||||
addControls();
|
||||
wireConditions();
|
||||
wireSettings();
|
||||
}
|
||||
|
||||
public JFCModel(List<SafePath> files) throws IOException, ParseException {
|
||||
this.configuration = new XmlConfiguration();
|
||||
this.configuration.setAttribute("version", "2.0");
|
||||
for (SafePath file : files) {
|
||||
JFCModel model = new JFCModel(file);
|
||||
for (var entry : model.controls.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
// Fail-fast checks that prevents an ambiguous file to be written later
|
||||
if (controls.containsKey(name)) {
|
||||
throw new ParseException("Control with '" + name + "' is declared in multiple files", 0);
|
||||
}
|
||||
controls.put(name, entry.getValue());
|
||||
}
|
||||
for (XmlElement child : model.configuration.getChildren()) {
|
||||
this.configuration.addChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
configuration.setAttribute("label", label);
|
||||
}
|
||||
|
||||
public void configure(String name, String value) {
|
||||
for (XmlInput i : getInputs()) {
|
||||
if (i.getName().equals(name)) {
|
||||
i.configure(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
boolean add = name.startsWith("+");
|
||||
if (add) {
|
||||
name = name.substring(1);
|
||||
}
|
||||
int index = name.indexOf("#");
|
||||
if (index < 1 || index == name.length() - 1) {
|
||||
throw new IllegalArgumentException("Option '" + name + "' doesn't exist in configuration");
|
||||
}
|
||||
XmlEvent event = configuration.getEvent(name.substring(0, index), add);
|
||||
String settingName = name.substring(index + 1);
|
||||
XmlSetting setting = event.getSetting(settingName, add);
|
||||
|
||||
if (settingName.equals("period") || settingName.equals("threshold")) {
|
||||
try {
|
||||
value = Utilities.parseTimespan(value);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// OK, no validation to allow forward compatibility.
|
||||
}
|
||||
}
|
||||
|
||||
setting.setContent(value);
|
||||
}
|
||||
|
||||
public void configure(UserInterface ui) throws AbortException {
|
||||
for (XmlInput input : getInputs()) {
|
||||
input.configure(ui);
|
||||
}
|
||||
}
|
||||
|
||||
public List<XmlInput> getInputs() {
|
||||
List<XmlInput> inputs = new ArrayList<>();
|
||||
for (XmlControl control : configuration.getControls()) {
|
||||
inputs.addAll(control.getInputs());
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
public XmlConfiguration getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
public void saveToFile(SafePath path) throws IOException {
|
||||
try (PrintWriter p = new PrintWriter(path.toFile(), Charset.forName("UTF-8"))) {
|
||||
PrettyPrinter pp = new PrettyPrinter(p);
|
||||
pp.print(configuration);
|
||||
if (p.checkError()) {
|
||||
throw new IOException("Error writing " + path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<ControlElement> getControlElements(String name) {
|
||||
return controls.getOrDefault(name, Collections.emptyList());
|
||||
}
|
||||
|
||||
private void addControls() {
|
||||
for (var controls : configuration.getControls()) {
|
||||
for (var control : controls.getControlElements()) {
|
||||
add(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void wireConditions() {
|
||||
for (XmlControl control : configuration.getControls()) {
|
||||
for (XmlCondition condition : control.getConditions()) {
|
||||
for (XmlElement element : condition.getChildren()) {
|
||||
wireExpression(condition, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void wireExpression(XmlElement parent, XmlElement element) {
|
||||
element.addListener(parent);
|
||||
if (element instanceof XmlTest test) {
|
||||
wireTest(test);
|
||||
}
|
||||
if (element instanceof XmlExpression expression) {
|
||||
for (XmlExpression child : expression.getExpressions()) {
|
||||
wireExpression(expression, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void wireTest(XmlTest test) {
|
||||
String name = test.getName();
|
||||
for (ControlElement ce : getControlElements(name)) {
|
||||
XmlElement control = (XmlElement) ce;
|
||||
control.addListener(test);
|
||||
}
|
||||
}
|
||||
|
||||
private void wireSettings() {
|
||||
for (XmlEvent event : configuration.getEvents()) {
|
||||
for (XmlSetting setting : event.getSettings()) {
|
||||
var controlName = setting.getControl();
|
||||
if (controlName.isPresent()) {
|
||||
List<ControlElement> controls = getControlElements(controlName.get());
|
||||
if (controls.isEmpty()) {
|
||||
System.out.println("Warning! Setting '" + setting.getFullName() + "' refers to missing control '" + controlName.get() + "'");
|
||||
}
|
||||
for (ControlElement ce : controls) {
|
||||
XmlElement control = (XmlElement) ce;
|
||||
control.addListener(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void add(ControlElement control) {
|
||||
controls.computeIfAbsent(control.getName(), x -> new ArrayList<>()).add(control);
|
||||
}
|
||||
|
||||
private XmlConfiguration createConfiguration(SafePath file) throws ParseException, IOException {
|
||||
if (file.toString().equals("none")) {
|
||||
XmlConfiguration configuration = new XmlConfiguration();
|
||||
configuration.setAttribute("version", "2.0");
|
||||
configuration.setAttribute("label", "None");
|
||||
return configuration;
|
||||
}
|
||||
return Parser.parse(file.toPath());
|
||||
}
|
||||
}
|
||||
106
src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/Parser.java
Normal file
106
src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/Parser.java
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import jdk.internal.org.xml.sax.Attributes;
|
||||
import jdk.internal.org.xml.sax.InputSource;
|
||||
import jdk.internal.org.xml.sax.SAXException;
|
||||
import jdk.internal.org.xml.sax.helpers.DefaultHandler;
|
||||
import jdk.internal.util.xml.SAXParser;
|
||||
import jdk.internal.util.xml.impl.SAXParserImpl;
|
||||
|
||||
final class Parser {
|
||||
|
||||
static XmlConfiguration parse(Path path) throws ParseException, IOException {
|
||||
try (FileReader r = new FileReader(path.toFile(), Charset.forName("UTF-8"))) {
|
||||
SAXParser saxParser = new SAXParserImpl();
|
||||
ConfigurationHandler handler = new ConfigurationHandler();
|
||||
saxParser.parse(new InputSource(r), handler);
|
||||
return handler.configuration;
|
||||
} catch (SAXException sp) {
|
||||
ParseException pe = new ParseException(sp.getMessage(), -1);
|
||||
pe.initCause(sp);
|
||||
throw pe;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ConfigurationHandler extends DefaultHandler {
|
||||
private final Deque<XmlElement> stack = new ArrayDeque<>();
|
||||
private final StringBuilder buffer = new StringBuilder();
|
||||
private XmlConfiguration configuration;
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
if (configuration == null) {
|
||||
if (!qName.equalsIgnoreCase("configuration")) {
|
||||
throw new SAXException("Expected root element to be named 'configuration'");
|
||||
}
|
||||
configuration = new XmlConfiguration();
|
||||
addAttributes(configuration, attributes);
|
||||
stack.push(configuration);
|
||||
return;
|
||||
}
|
||||
XmlElement current = stack.peek();
|
||||
XmlElement child = current.createChild(qName);
|
||||
addAttributes(child, attributes);
|
||||
stack.push(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) throws SAXException {
|
||||
buffer.append(ch, start, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) {
|
||||
String content = buffer.toString().strip();
|
||||
if (!content.isEmpty()) {
|
||||
stack.peek().setContent(content);
|
||||
buffer.setLength(0);
|
||||
}
|
||||
|
||||
XmlElement current = stack.peek();
|
||||
if (current.getElementName().equalsIgnoreCase(qName)) {
|
||||
stack.pop();
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected <" + qName + "/>");
|
||||
}
|
||||
}
|
||||
|
||||
private void addAttributes(XmlElement element, Attributes attributes) {
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
element.setAttribute(attributes.getQName(i), attributes.getValue(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Map;
|
||||
|
||||
final class PrettyPrinter {
|
||||
private final PrintWriter out;
|
||||
|
||||
PrettyPrinter(PrintWriter out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
void print(XmlConfiguration configuration) {
|
||||
printHeader();
|
||||
prettyPrint("", configuration);
|
||||
}
|
||||
|
||||
private void printHeader() {
|
||||
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
}
|
||||
|
||||
private void prettyPrint(String indent, XmlElement element) {
|
||||
printComment(indent, element);
|
||||
String elementName = element.getElementName();
|
||||
out.print(indent + '<' + elementName);
|
||||
printAttributes(element.getAttributes());
|
||||
if (element.getChildren().isEmpty() && !element.hasContent()) {
|
||||
out.println("/>");
|
||||
return;
|
||||
}
|
||||
out.print('>');
|
||||
out.print(Utilities.escapeAll(element.getContent().trim()));
|
||||
if (element.getChildren().isEmpty()) {
|
||||
out.println("</" + elementName + '>');
|
||||
return;
|
||||
}
|
||||
out.println();
|
||||
boolean first = true;
|
||||
for (XmlElement child : element.getChildren()) {
|
||||
if (first && child.isEntity()) {
|
||||
out.println();
|
||||
}
|
||||
prettyPrint(indent + " ", child);
|
||||
if (child.isEntity()) {
|
||||
out.println();
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
out.println(indent + "</" + elementName + '>');
|
||||
}
|
||||
|
||||
private void printComment(String indent, XmlElement element) {
|
||||
String comment = element.comment();
|
||||
if (!comment.isEmpty()) {
|
||||
String text = comment.indent(indent.length());
|
||||
out.println(indent + "<!--");
|
||||
out.println(text.replace("\n", System.lineSeparator()));
|
||||
out.println(indent + "-->");
|
||||
}
|
||||
}
|
||||
|
||||
private void printAttributes(Map<String, String> attributes) {
|
||||
for (var entry : attributes.entrySet()) {
|
||||
out.print(' ');
|
||||
out.print(entry.getKey());
|
||||
out.print("=\"");
|
||||
out.print(Utilities.escapeAll(entry.getValue()));
|
||||
out.print('\"');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
record Result(String value) {
|
||||
public static final Result FALSE = new Result("false");
|
||||
public static final Result TRUE = new Result("true");
|
||||
public static final Result NULL = new Result(null);
|
||||
|
||||
public boolean isTrue() {
|
||||
return "true".equalsIgnoreCase(value);
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return value == null;
|
||||
}
|
||||
|
||||
public boolean isFalse() {
|
||||
return "false".equalsIgnoreCase(value);
|
||||
}
|
||||
|
||||
public static Result of(String value) {
|
||||
if ("true".equalsIgnoreCase(value)) {
|
||||
return TRUE;
|
||||
}
|
||||
if ("false".equalsIgnoreCase(value)) {
|
||||
return FALSE;
|
||||
}
|
||||
return new Result(value);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public final class SettingsLog {
|
||||
private static final Map<String, String> settings = new TreeMap<>();
|
||||
private static boolean enabled;
|
||||
|
||||
public static void enable() {
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
public static void flush() {
|
||||
if (!settings.isEmpty()) {
|
||||
System.out.println();
|
||||
System.out.println("Setting:");
|
||||
for (var s : settings.entrySet()) {
|
||||
System.out.println("\"" + s.getKey() + "=" + s.getValue() + "\"");
|
||||
}
|
||||
settings.clear();
|
||||
}
|
||||
}
|
||||
|
||||
static void log(XmlSetting setting, String value) {
|
||||
if (enabled) {
|
||||
settings.put(setting.getFullName(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public final class UserInterface {
|
||||
|
||||
public void println() {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
public void println(String text) {
|
||||
System.out.println(text);
|
||||
}
|
||||
|
||||
public String readLine() throws AbortException {
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
||||
String line = br.readLine();
|
||||
if (line == null || line.equalsIgnoreCase("Q")) {
|
||||
println();
|
||||
throw new AbortException();
|
||||
}
|
||||
return line;
|
||||
} catch (IOException e) {
|
||||
throw new Error("Unable to read input", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public final class Utilities {
|
||||
private static final String[] UNITS = new String[] {
|
||||
"ns", "us", "ns", "ms", "s", "m", "h", "d" // order matters
|
||||
};
|
||||
|
||||
static XmlElement instantiate(Class<? extends XmlElement> type) {
|
||||
try {
|
||||
return type.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new InternalError("Unable to instantiate " + type, e);
|
||||
}
|
||||
}
|
||||
|
||||
static String elementName(Class<? extends XmlElement> type) {
|
||||
String name = type.getSimpleName();
|
||||
if (name.startsWith("Xml") && name.length() > 3) {
|
||||
return name.substring(3).toLowerCase();
|
||||
}
|
||||
throw new InternalError("Unexpected class " + type);
|
||||
}
|
||||
|
||||
static String escapeAll(String text) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
addCharacter(s, text.charAt(i));
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
private static void addCharacter(StringBuilder s, char c) {
|
||||
if (c == 34) {
|
||||
s.append(""");
|
||||
return;
|
||||
}
|
||||
if (c == 38) {
|
||||
s.append("&");
|
||||
return;
|
||||
}
|
||||
if (c == 39) {
|
||||
s.append("'");
|
||||
return;
|
||||
}
|
||||
if (c == 60) {
|
||||
s.append("<");
|
||||
return;
|
||||
}
|
||||
if (c == 62) {
|
||||
s.append(">");
|
||||
return;
|
||||
}
|
||||
if (c > 0x7F) {
|
||||
s.append("&#");
|
||||
s.append((int) c);
|
||||
s.append(';');
|
||||
return;
|
||||
}
|
||||
s.append(c);
|
||||
}
|
||||
|
||||
static void checkValid(String value, Object... valid) {
|
||||
StringJoiner sj = new StringJoiner(", ");
|
||||
for (Object v : valid) {
|
||||
if (v.equals(value)) {
|
||||
return;
|
||||
}
|
||||
sj.add("'" + v + "'");
|
||||
}
|
||||
String msg = "Incorrect value '" + value + "'. Valid values are " + sj.toString() + ".";
|
||||
int index = msg.lastIndexOf(",");
|
||||
if (index != -1) {
|
||||
msg = msg.substring(0, index) + " and" + msg.substring(index + 1);
|
||||
}
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
static String parseTimespan(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try {
|
||||
for (String unit : UNITS) {
|
||||
if (s.endsWith(unit)) {
|
||||
return parseForUnit(s, unit);
|
||||
}
|
||||
}
|
||||
Long.parseLong(s);
|
||||
sb.append("Timespan '" + s + "' is missing unit.");
|
||||
} catch (NumberFormatException nfe) {
|
||||
sb.append("'" + s + "' is not a valid timespan." + System.lineSeparator());
|
||||
sb.append("Should be numeric value followed by a unit, i.e. 20 ms.");
|
||||
}
|
||||
sb.append(" Valid units are ns, us, ms, s, m, h and d.");
|
||||
throw new IllegalArgumentException(sb.toString());
|
||||
}
|
||||
|
||||
private static String parseForUnit(String s, String unit) {
|
||||
String number = s.trim().substring(0, s.length() - unit.length());
|
||||
return Long.parseLong(number.trim()) + " " + unit;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
// Corresponds to <and>
|
||||
final class XmlAnd extends XmlExpression {
|
||||
|
||||
@Override
|
||||
boolean isEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
Result result = Result.NULL;
|
||||
for (XmlElement e : getProducers()) {
|
||||
Result r = e.evaluate();
|
||||
if (r.isFalse()) {
|
||||
return Result.FALSE;
|
||||
}
|
||||
if (r.isTrue()) {
|
||||
result = Result.TRUE;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
// Corresponds <condition>
|
||||
final class XmlCondition extends XmlExpression implements ControlElement {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return attribute("name");
|
||||
}
|
||||
|
||||
public Result getTrueValue() {
|
||||
return Result.of(attribute("true"));
|
||||
}
|
||||
|
||||
public Result getFalseValue() {
|
||||
return Result.of(attribute("false"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
if (getExpressions().size() > 1) {
|
||||
throw new ParseException("Expected <condition> to not have more than one child", -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> attributes() {
|
||||
return List.of("name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
Optional<String> trueValue = optional("true");
|
||||
Optional<String> falseValue = optional("false");
|
||||
for (XmlElement producer : getProducers()) {
|
||||
Result r = producer.evaluate();
|
||||
if (trueValue.isPresent() && r.isTrue()) {
|
||||
return getTrueValue();
|
||||
}
|
||||
if (falseValue.isPresent() && r.isFalse()) {
|
||||
return getFalseValue();
|
||||
}
|
||||
}
|
||||
return Result.NULL;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
// Corresponds to <configuration>
|
||||
final class XmlConfiguration extends XmlElement {
|
||||
|
||||
public List<XmlEvent> getEvents() {
|
||||
return elements(XmlEvent.class);
|
||||
}
|
||||
|
||||
public Optional<String> getDescription() {
|
||||
return optional("description");
|
||||
}
|
||||
|
||||
public Optional<String> getLabel() {
|
||||
return optional("label");
|
||||
}
|
||||
|
||||
public Optional<String> getProvider() {
|
||||
return optional("provider");
|
||||
}
|
||||
|
||||
public Optional<String> getVersion() {
|
||||
return optional("version");
|
||||
}
|
||||
|
||||
public List<XmlControl> getControls() {
|
||||
return elements(XmlControl.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
String comment() {
|
||||
return """
|
||||
Recommended way to edit .jfc files is to use the configure command of
|
||||
the 'jfr' tool, i.e. jfr configure, or JDK Mission Control
|
||||
see Window -> Flight Recorder Template Manager
|
||||
""";
|
||||
}
|
||||
|
||||
XmlEvent getEvent(String eventName, boolean add) {
|
||||
for (XmlEvent event : getEvents()) {
|
||||
if (eventName.equals(event.getName())) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
if (!add) {
|
||||
throw new IllegalArgumentException("Could not find event '" + eventName + "'");
|
||||
}
|
||||
XmlEvent event = new XmlEvent();
|
||||
event.setAttribute("name", eventName);
|
||||
addChild(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> attributes() {
|
||||
return List.of("version", "label");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateAttributes() throws ParseException {
|
||||
super.validateAttributes();
|
||||
if (!attribute("version").equals("2.0")) {
|
||||
throw new ParseException("Only .jfc files of version 2.0 is supported", -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Constraint> constraints() {
|
||||
return List.of(
|
||||
Constraint.any(XmlEvent.class),
|
||||
Constraint.any(XmlControl.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// Corresponds to <control>
|
||||
final class XmlControl extends XmlElement {
|
||||
|
||||
public List<XmlInput> getInputs() {
|
||||
return elements(XmlInput.class);
|
||||
}
|
||||
|
||||
public List<XmlCondition> getConditions() {
|
||||
return elements(XmlCondition.class);
|
||||
}
|
||||
|
||||
// Returns list of all <selection>, <condition>, <flag> and <text>
|
||||
public List<ControlElement> getControlElements() {
|
||||
return elements(ControlElement.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
String comment() {
|
||||
return """
|
||||
Contents of the control element is not read by the JVM, it's used
|
||||
by JDK Mission Control and the 'jfr'-tool to change settings that
|
||||
carry the control attribute.
|
||||
""";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Constraint> constraints() {
|
||||
return List.of(
|
||||
Constraint.any(XmlCondition.class),
|
||||
Constraint.any(XmlText.class),
|
||||
Constraint.any(XmlSelection.class),
|
||||
Constraint.any(XmlFlag.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
// Base class for XML-elements
|
||||
class XmlElement {
|
||||
private final Map<String, String> attributes = new HashMap<>();
|
||||
private final List<XmlElement> elements = new ArrayList<>();
|
||||
private final List<XmlElement> listeners = new ArrayList<>(2);
|
||||
private final List<XmlElement> producers = new ArrayList<>(2);
|
||||
private final String elementName;
|
||||
|
||||
private XmlElement parent;
|
||||
private String content = "";
|
||||
|
||||
XmlElement() {
|
||||
this.elementName = Utilities.elementName(this.getClass());
|
||||
}
|
||||
|
||||
private XmlElement(String elementName) {
|
||||
this.elementName = elementName;
|
||||
}
|
||||
|
||||
final String getElementName() {
|
||||
return elementName;
|
||||
}
|
||||
|
||||
final boolean hasContent() {
|
||||
return content != null && !content.isEmpty();
|
||||
}
|
||||
|
||||
final Map<String, String> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
final void validate() throws ParseException {
|
||||
validateAttributes();
|
||||
validateChildConstraints();
|
||||
validateChildren();
|
||||
}
|
||||
|
||||
final void setAttribute(String key, String value) {
|
||||
Objects.requireNonNull(key);
|
||||
Objects.requireNonNull(key);
|
||||
attributes.put(key, value);
|
||||
}
|
||||
|
||||
final XmlElement createChild(String name) {
|
||||
XmlElement child = instantiate(name);
|
||||
child.parent = this;
|
||||
addChild(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
private XmlElement instantiate(String name) {
|
||||
for (var e : constraints()) {
|
||||
String elementName = Utilities.elementName(e.type());
|
||||
if (elementName.equalsIgnoreCase(name)) {
|
||||
return Utilities.instantiate(e.type());
|
||||
}
|
||||
}
|
||||
return new XmlElement(name);
|
||||
}
|
||||
|
||||
final void addChild(XmlElement element) {
|
||||
elements.add(element);
|
||||
}
|
||||
|
||||
final List<XmlElement> getChildren() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
final String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
final void addListener(XmlElement listener) {
|
||||
listeners.add(listener);
|
||||
listener.addProducer(this);
|
||||
}
|
||||
|
||||
// If the element should be surrounded with an empty
|
||||
// line when printed to file, for example, <event> but not <setting>
|
||||
boolean isEntity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
String comment() {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected final void notifyListeners() {
|
||||
onChange();
|
||||
SettingsLog.flush();
|
||||
}
|
||||
|
||||
protected void onChange() {
|
||||
for (XmlElement listener : listeners) {
|
||||
listener.onChange();
|
||||
}
|
||||
}
|
||||
|
||||
protected final XmlElement getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
protected List<Constraint> constraints() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
protected List<String> attributes() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
protected final List<XmlElement> getProducers() {
|
||||
return producers;
|
||||
}
|
||||
|
||||
protected final Optional<String> optional(String name) {
|
||||
return Optional.ofNullable(attributes.get(name));
|
||||
}
|
||||
|
||||
protected final String attribute(String name) {
|
||||
return attributes.get(name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected final <T> List<T> elements(Class<T> type) {
|
||||
List<T> result = new ArrayList<>();
|
||||
for (XmlElement e : elements) {
|
||||
if (type.isAssignableFrom(e.getClass())) {
|
||||
result.add((T) e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Result evaluate() {
|
||||
if (producers.isEmpty()) {
|
||||
throw new Error("No producer evaluate for " + getClass());
|
||||
}
|
||||
if (producers.size() != 1) {
|
||||
throw new Error("Unsure how to evaluate multiple producers " + getClass());
|
||||
}
|
||||
return producers.get(0).evaluate();
|
||||
}
|
||||
|
||||
protected void validateAttributes() throws ParseException {
|
||||
for (String key : attributes()) {
|
||||
if (!attributes.containsKey(key)) {
|
||||
throw new ParseException("Missing mandatory attribute '" + key + "'", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateChildren() throws ParseException {
|
||||
for (XmlElement child : elements) {
|
||||
child.validate();
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
for (Constraint c : constraints()) {
|
||||
validateConstraint(c);
|
||||
}
|
||||
}
|
||||
|
||||
private final void validateConstraint(Constraint c) throws ParseException {
|
||||
int count = count(c.type());
|
||||
if (count < c.min()) {
|
||||
String elementName = Utilities.elementName(c.type());
|
||||
throw new ParseException("Missing mandatory element <" + elementName + ">", 0);
|
||||
}
|
||||
if (count > c.max()) {
|
||||
String elementName = Utilities.elementName(c.type());
|
||||
throw new ParseException("Too many elements of type <" + elementName + ">", 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void addProducer(XmlElement producer) {
|
||||
producers.add(producer);
|
||||
}
|
||||
|
||||
private int count(Class<? extends XmlElement> type) {
|
||||
int count = 0;
|
||||
for (XmlElement element : getChildren()) {
|
||||
if (type.isAssignableFrom(element.getClass())) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// Corresponds to <event>
|
||||
final class XmlEvent extends XmlElement {
|
||||
|
||||
public String getName() {
|
||||
return attribute("name");
|
||||
}
|
||||
|
||||
public List<XmlSetting> getSettings() {
|
||||
return elements(XmlSetting.class);
|
||||
}
|
||||
|
||||
XmlSetting getSetting(String settingName, boolean add) {
|
||||
for (XmlSetting setting : getSettings()) {
|
||||
if (settingName.equals(setting.getName())) {
|
||||
return setting;
|
||||
}
|
||||
}
|
||||
if (!add) {
|
||||
String msg = "Could not find setting '" + settingName;
|
||||
msg += "' for event '" + getName() + "'";
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
XmlSetting setting = new XmlSetting();
|
||||
setting.setAttribute("name", settingName);
|
||||
addChild(setting);
|
||||
return setting;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> attributes() {
|
||||
return List.of("name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Constraint> constraints() {
|
||||
return List.of(Constraint.any(XmlSetting.class));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
// Base class for <condition>, <or>, <not>, <and> and <test>
|
||||
abstract class XmlExpression extends XmlElement {
|
||||
|
||||
public final List<XmlExpression> getExpressions() {
|
||||
return elements(XmlExpression.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Constraint> constraints() {
|
||||
return List.of(
|
||||
Constraint.any(XmlOr.class),
|
||||
Constraint.any(XmlAnd.class),
|
||||
Constraint.any(XmlTest.class),
|
||||
Constraint.any(XmlNot.class)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
if (getExpressions().size() < 2) {
|
||||
throw new ParseException("Expected + <" + getElementName() + "> to have at least two children", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
// Corresponds to <flag>
|
||||
final class XmlFlag extends XmlInput {
|
||||
|
||||
@Override
|
||||
public String getOptionSyntax() {
|
||||
return getName() + "=<true|false>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(String value) {
|
||||
Utilities.checkValid(value, "true", "false");
|
||||
setContent(value);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(UserInterface ui) throws AbortException {
|
||||
Result defaultValue = Result.of(getContent());
|
||||
ui.println();
|
||||
ui.println(getLabel() + " [Y/N]: " + (defaultValue.isTrue() ? "Yes" : "No") + " (default)");
|
||||
|
||||
while (!read(ui, defaultValue)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
return Result.of(getContent());
|
||||
}
|
||||
|
||||
private boolean read(UserInterface ui, Result defaultValue) throws AbortException {
|
||||
String line = ui.readLine();
|
||||
if (line.isBlank()) {
|
||||
ui.println("Using default: " + (defaultValue.isTrue() ? "Yes" : "No"));
|
||||
return true;
|
||||
}
|
||||
if (line.equalsIgnoreCase("Y") || line.equalsIgnoreCase("N")) {
|
||||
boolean value = line.equalsIgnoreCase("Y");
|
||||
ui.println("Using: " + (value ? "Yes" : "No"));
|
||||
configure(String.valueOf(value));
|
||||
return true;
|
||||
}
|
||||
ui.println("Not a valid choice.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
// Base class for elements that the user can interact with,
|
||||
// <selection>, <text> and <flag>
|
||||
public abstract class XmlInput extends XmlElement implements ControlElement {
|
||||
|
||||
public abstract String getOptionSyntax();
|
||||
|
||||
abstract void configure(UserInterface ui) throws AbortException;
|
||||
|
||||
abstract void configure(String value);
|
||||
|
||||
public final Optional<String> getContentType() {
|
||||
return optional("contentType");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getName() {
|
||||
return attribute("name");
|
||||
}
|
||||
|
||||
public final String getLabel() {
|
||||
return attribute("label");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> attributes() {
|
||||
return List.of("name", "label");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
// Corresponds to <not>
|
||||
final class XmlNot extends XmlExpression {
|
||||
|
||||
@Override
|
||||
boolean isEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
if (getExpressions().size() != 1) {
|
||||
throw new ParseException("Expected <not> to have a single child", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
List<XmlElement> producers = getProducers();
|
||||
if (!producers.isEmpty()) {
|
||||
Result r = producers.get(0).evaluate();
|
||||
if (!r.isNull()) {
|
||||
return r.isTrue() ? Result.FALSE : Result.TRUE;
|
||||
}
|
||||
}
|
||||
return Result.NULL;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// Corresponds to <option>
|
||||
final class XmlOption extends XmlElement {
|
||||
|
||||
public String getLabel() {
|
||||
return attribute("label");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return attribute("name");
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> attributes() {
|
||||
return List.of("label", "name");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
// Corresponds to <or>
|
||||
final class XmlOr extends XmlExpression {
|
||||
|
||||
@Override
|
||||
boolean isEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
Result result = Result.NULL;
|
||||
for (XmlElement e : getProducers()) {
|
||||
Result r = e.evaluate();
|
||||
if (r.isFalse()) {
|
||||
result = Result.FALSE;
|
||||
}
|
||||
if (r.isTrue()) {
|
||||
return Result.TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
// Corresponds to <selection>
|
||||
final class XmlSelection extends XmlInput {
|
||||
|
||||
@Override
|
||||
public String getOptionSyntax() {
|
||||
StringJoiner sj = new StringJoiner("|", "<", ">");
|
||||
for (XmlOption option : getOptions()) {
|
||||
sj.add(option.getName());
|
||||
}
|
||||
return getName() + "=" + sj.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(String value) {
|
||||
var valid = getOptions().stream().map(XmlOption::getName);
|
||||
Utilities.checkValid(value, valid.toArray());
|
||||
setAttribute("default", value);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(UserInterface ui) throws AbortException {
|
||||
XmlOption selected = getSelected();
|
||||
if (selected == null) {
|
||||
return;
|
||||
}
|
||||
String label = getLabel();
|
||||
ui.println();
|
||||
ui.println(label + ": " + selected.getLabel() + " (default)");
|
||||
int index = 1;
|
||||
List<XmlOption> options = getOptions();
|
||||
for (XmlOption s : options) {
|
||||
ui.println(index + ". " + s.getLabel());
|
||||
index++;
|
||||
}
|
||||
while (true) {
|
||||
String line = ui.readLine();
|
||||
if (line.isBlank()) {
|
||||
ui.println("Using default: " + selected.getLabel());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int s = Integer.parseInt(line) - 1;
|
||||
if (s >= 0 && s < options.size()) {
|
||||
XmlOption o = options.get(s);
|
||||
ui.println("Using: " + o.getLabel());
|
||||
configure(o.getName());
|
||||
return;
|
||||
}
|
||||
ui.println("Not in range.");
|
||||
} catch (NumberFormatException nfe) {
|
||||
ui.println("Must enter a number, or ENTER to select default.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> attributes() {
|
||||
return List.of("name", "label", "default");
|
||||
}
|
||||
|
||||
public String getDefault() {
|
||||
return attribute("default");
|
||||
}
|
||||
|
||||
public List<XmlOption> getOptions() {
|
||||
return elements(XmlOption.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Constraint> constraints() {
|
||||
return List.of(Constraint.atLeast(XmlOption.class, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
return Result.of(getSelected().getContent());
|
||||
}
|
||||
|
||||
private XmlOption getSelected() {
|
||||
List<XmlOption> options = getOptions();
|
||||
for (XmlOption optionElement : options) {
|
||||
if (getDefault().equals(optionElement.getName())) {
|
||||
return optionElement;
|
||||
}
|
||||
}
|
||||
return options.isEmpty() ? null : options.get(0);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
// Corresponds to <setting>
|
||||
final class XmlSetting extends XmlElement {
|
||||
|
||||
@Override
|
||||
public boolean isEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> attributes() {
|
||||
return List.of("name");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return attribute("name");
|
||||
}
|
||||
|
||||
public Optional<String> getControl() {
|
||||
return optional("control");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange() {
|
||||
String value = evaluate().value();
|
||||
if (value != null) {
|
||||
setContent(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
final void setContent(String value) {
|
||||
super.setContent(value);
|
||||
if (getParent() instanceof XmlEvent event) {
|
||||
SettingsLog.log(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
for (XmlElement producer : getProducers()) {
|
||||
Result result = producer.evaluate();
|
||||
if (!result.isNull()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return Result.NULL;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
if (getParent() instanceof XmlEvent event) {
|
||||
return event.getName() + "#" + getName();
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
// Corresponds to <test>
|
||||
final class XmlTest extends XmlExpression {
|
||||
|
||||
public String getName() {
|
||||
return attribute("name");
|
||||
}
|
||||
|
||||
public String getOperator() {
|
||||
return attribute("operator");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return attribute("value");
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> attributes() {
|
||||
return List.of("name", "operator", "value");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateChildConstraints() throws ParseException {
|
||||
if (!getExpressions().isEmpty()) {
|
||||
throw new ParseException("Expected <test> to not have child elements", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateAttributes() throws ParseException {
|
||||
super.validateAttributes();
|
||||
if (!getOperator().equalsIgnoreCase("equal")) {
|
||||
throw new ParseException("Unknown operator '" + getOperator() + "', only supported is 'equal'", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
Result ret = Result.NULL;
|
||||
List<XmlElement> producers = getProducers();
|
||||
if (!producers.isEmpty()) {
|
||||
XmlElement producer = producers.get(0);
|
||||
Result r = producer.evaluate();
|
||||
if (!r.isNull()) {
|
||||
ret = getValue().equals(r.value()) ? Result.TRUE : Result.FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.jfc.model;
|
||||
|
||||
// Corresponds to <text>
|
||||
final class XmlText extends XmlInput {
|
||||
|
||||
@Override
|
||||
public String getOptionSyntax() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getName());
|
||||
sb.append("=<");
|
||||
sb.append(getContentType().orElse("text"));
|
||||
sb.append(">");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(String value) {
|
||||
if (isTimespan()) {
|
||||
value = Utilities.parseTimespan(value);
|
||||
}
|
||||
setContent(value);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(UserInterface ui) throws AbortException {
|
||||
ui.println();
|
||||
ui.println(getLabel() + ": " + getContent() + " (default)");
|
||||
while (!readInput(ui)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result evaluate() {
|
||||
return Result.of(getContent());
|
||||
}
|
||||
|
||||
private boolean readInput(UserInterface ui) throws AbortException {
|
||||
String line = ui.readLine();
|
||||
if (line.isBlank()) {
|
||||
ui.println("Using default: " + getContent());
|
||||
return true;
|
||||
}
|
||||
if (isTimespan()) {
|
||||
try {
|
||||
line = Utilities.parseTimespan(line);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
ui.println(iae.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ui.println("Using: " + line);
|
||||
configure(line);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isTimespan() {
|
||||
return getContentType().orElse("text").equals("timespan");
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,7 @@ final class Assemble extends Command {
|
||||
|
||||
Path file = Paths.get(options.pop());
|
||||
ensureFileDoesNotExist(file);
|
||||
ensureJFRFile(file);
|
||||
ensureFileExtension(file, ".jfr");
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(file.toFile())) {
|
||||
List<Path> files = listJFRFiles(repository);
|
||||
|
||||
@ -47,13 +47,14 @@ import java.util.function.Predicate;
|
||||
import jdk.jfr.EventType;
|
||||
|
||||
abstract class Command {
|
||||
public final static String title = "Tool for working with Flight Recorder files (.jfr)";
|
||||
public final static String title = "Tool for working with Flight Recorder files";
|
||||
private final static Command HELP = new Help();
|
||||
private final static List<Command> COMMANDS = createCommands();
|
||||
|
||||
private static List<Command> createCommands() {
|
||||
List<Command> commands = new ArrayList<>();
|
||||
commands.add(new Print());
|
||||
commands.add(new Configure());
|
||||
commands.add(new Metadata());
|
||||
commands.add(new Summary());
|
||||
commands.add(new Assemble());
|
||||
@ -155,6 +156,14 @@ abstract class Command {
|
||||
public void displayOptionUsage(PrintStream stream) {
|
||||
}
|
||||
|
||||
protected boolean acceptSwitch(Deque<String> options, String expected) throws UserSyntaxException {
|
||||
if (!options.isEmpty() && options.peek().equals(expected)) {
|
||||
options.remove();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean acceptOption(Deque<String> options, String expected) throws UserSyntaxException {
|
||||
if (expected.equals(options.peek())) {
|
||||
if (options.size() < 2) {
|
||||
@ -233,7 +242,7 @@ abstract class Command {
|
||||
try {
|
||||
Path path = Paths.get(file).toAbsolutePath();
|
||||
ensureAccess(path);
|
||||
ensureJFRFile(path);
|
||||
ensureFileExtension(path, ".jfr");
|
||||
return path;
|
||||
} catch (IOError ioe) {
|
||||
throw new UserDataException("i/o error reading file '" + file + "', " + ioe.getMessage());
|
||||
@ -266,9 +275,9 @@ abstract class Command {
|
||||
return file;
|
||||
}
|
||||
|
||||
final protected void ensureJFRFile(Path path) throws UserDataException {
|
||||
if (!path.toString().endsWith(".jfr")) {
|
||||
throw new UserDataException("filename must end with '.jfr'");
|
||||
final protected void ensureFileExtension(Path path, String extension) throws UserDataException {
|
||||
if (!path.toString().endsWith(extension)) {
|
||||
throw new UserDataException("filename must end with '" + extension + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,4 +422,4 @@ abstract class Command {
|
||||
Map<X, Boolean> cache = new HashMap<>();
|
||||
return t -> cache.computeIfAbsent(cacheFunction.apply(t), x -> filter.test(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
301
src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java
Normal file
301
src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.internal.tool;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOError;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.jfr.internal.SecuritySupport;
|
||||
import jdk.jfr.internal.SecuritySupport.SafePath;
|
||||
import jdk.jfr.internal.jfc.JFC;
|
||||
import jdk.jfr.internal.jfc.model.AbortException;
|
||||
import jdk.jfr.internal.jfc.model.JFCModel;
|
||||
import jdk.jfr.internal.jfc.model.SettingsLog;
|
||||
import jdk.jfr.internal.jfc.model.UserInterface;
|
||||
import jdk.jfr.internal.jfc.model.XmlInput;
|
||||
|
||||
final class Configure extends Command {
|
||||
private final List<SafePath> inputFiles = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public List<String> getOptionSyntax() {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("[--interactive] [--verbose]");
|
||||
list.add("[--input <files>] [--output <file>]");
|
||||
list.add("[option=value]* [event-setting=value]*");
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "Configures a .jfc file";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "configure";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Creates a custom .jfc-file for event configuration";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayOptionUsage(PrintStream stream) {
|
||||
stream.println(" --interactive Interactive mode where the configuration is");
|
||||
stream.println(" determined by a set of questions.");
|
||||
stream.println();
|
||||
stream.println(" --verbose Displays the modified settings.");
|
||||
stream.println();
|
||||
stream.println(" --input <files> A comma-separated list of .jfc files from which");
|
||||
stream.println(" the new configuration is based. If no file is");
|
||||
stream.println(" specified, the default file in the JDK is used");
|
||||
stream.println(" (default.jfc). If 'none' is specified, the new");
|
||||
stream.println(" configuration starts empty.");
|
||||
stream.println();
|
||||
stream.println(" --ouput <file> The filename of the generated output file. If not");
|
||||
stream.println(" specified, the filename custom.jfc will be used.");
|
||||
stream.println();
|
||||
stream.println(" option=value The option value to modify. For available options,");
|
||||
stream.println(" see listed input files below.");
|
||||
stream.println();
|
||||
stream.println(" event-setting=value The event setting value to modify. Use the form:");
|
||||
stream.println(" <event-name>#<setting-name>=<value>");
|
||||
stream.println(" To add a new event setting, prefix the event name");
|
||||
stream.println(" with '+'.");
|
||||
stream.println();
|
||||
stream.println("The whitespace delimiter can be omitted for timespan values, i.e. 20ms. For");
|
||||
stream.println("more information about the settings syntax, see Javadoc of the jdk.jfr package.");
|
||||
ensureInputFiles();
|
||||
for (SafePath path : inputFiles) {
|
||||
try {
|
||||
String name = path.toPath().getFileName().toString();
|
||||
displayParameters(stream, path, name);
|
||||
} catch (InvalidPathException | ParseException | IOException e) {
|
||||
stream.println("Unable read options for " + path + " " + e.getMessage());
|
||||
}
|
||||
}
|
||||
stream.println();
|
||||
stream.println("To run interactive configuration wizard:");
|
||||
stream.println();
|
||||
stream.println(" jfr configure --interactive");
|
||||
stream.println();
|
||||
stream.println("Example usage:");
|
||||
stream.println();
|
||||
stream.println(" jfr configure gc=high method-profiling=high --output high.jfc");
|
||||
stream.println();
|
||||
stream.println(" jfr configure jdk.JavaMonitorEnter#threshold=1ms --output locks.jfc");
|
||||
stream.println();
|
||||
stream.println(" jfr configure +HelloWorld#enabled=true +HelloWorld#stackTrace=true");
|
||||
stream.println();
|
||||
stream.println(" jfr configure --input default.jfc,third-party.jfc --output unified.jfc");
|
||||
stream.println();
|
||||
stream.println(" jfr configure --input none +Hello#enabled=true --output minimal.jfc");
|
||||
}
|
||||
|
||||
private void displayParameters(PrintStream stream, SafePath path, String name) throws ParseException, IOException {
|
||||
JFCModel parameters = new JFCModel(path);
|
||||
stream.println();
|
||||
stream.println("Options for " + name + ":");
|
||||
stream.println();
|
||||
for (XmlInput input : parameters.getInputs()) {
|
||||
stream.println(" " + input.getOptionSyntax());
|
||||
stream.println();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Deque<String> options) throws UserSyntaxException, UserDataException {
|
||||
boolean interactive = false;
|
||||
boolean log = false;
|
||||
SafePath output = null;
|
||||
Map<String, String> keyValues = new LinkedHashMap<>();
|
||||
int optionCount = options.size();
|
||||
while (optionCount > 0) {
|
||||
if (acceptSwitch(options, "--interactive")) {
|
||||
interactive = true;
|
||||
}
|
||||
if (acceptSwitch(options, "--verbose")) {
|
||||
log = true;
|
||||
}
|
||||
if (acceptOption(options, "--input")) {
|
||||
String value = options.pop();
|
||||
inputFiles.addAll(makeSafePathList(value));
|
||||
}
|
||||
if (acceptOption(options, "--output")) {
|
||||
if (output != null) {
|
||||
throw new UserDataException("only one output file can be specified");
|
||||
}
|
||||
String value = options.pop();
|
||||
output = makeJFCPath(value);
|
||||
}
|
||||
if (acceptKeyValue(options)) {
|
||||
String value = options.pop();
|
||||
var keyValue = value.split("=");
|
||||
keyValues.put(keyValue[0], keyValue[1]);
|
||||
}
|
||||
if (optionCount == options.size()) {
|
||||
// No progress
|
||||
throw new UserSyntaxException("unknown option " + options.peek());
|
||||
}
|
||||
optionCount = options.size();
|
||||
}
|
||||
if (!interactive && output == null && keyValues.isEmpty()) {
|
||||
throw new UserSyntaxException("missing argument");
|
||||
}
|
||||
ensureInputFiles();
|
||||
configure(interactive, log, output, keyValues);
|
||||
}
|
||||
|
||||
private boolean acceptKeyValue(Deque<String> options) {
|
||||
if (!options.isEmpty()) {
|
||||
String keyValue = options.peek();
|
||||
int index = keyValue.indexOf("=");
|
||||
return index > 0 && index < keyValue.length() - 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void configure(boolean interactive, boolean log, SafePath output, Map<String, String> options) throws UserDataException {
|
||||
try {
|
||||
if (output == null) {
|
||||
output = new SafePath(Path.of("custom.jfc"));
|
||||
}
|
||||
UserInterface ui = new UserInterface();
|
||||
JFCModel model = new JFCModel(inputFiles);
|
||||
model.setLabel("Custom");
|
||||
if (log) {
|
||||
SettingsLog.enable();
|
||||
}
|
||||
for (var option : options.entrySet()) {
|
||||
model.configure(option.getKey(), option.getValue());
|
||||
}
|
||||
SettingsLog.flush();
|
||||
try {
|
||||
if (interactive) {
|
||||
int q = model.getInputs().size() + 1;
|
||||
ui.println("============== .jfc Configuration Wizard ============");
|
||||
ui.println("This wizard will generate a JFR configuration file by");
|
||||
ui.println("asking " + q + " questions. Press ENTER to use the default");
|
||||
ui.println("value, or type Q to abort the wizard.");
|
||||
model.configure(ui);
|
||||
output = filename(ui, output);
|
||||
}
|
||||
} catch (AbortException e) {
|
||||
ui.println("Abort.");
|
||||
return;
|
||||
}
|
||||
model.saveToFile(output);
|
||||
ui.println("Configuration written successfully to:");
|
||||
ui.println(output.toPath().toAbsolutePath().toString());
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new UserDataException(iae.getMessage());
|
||||
} catch (FileNotFoundException ffe) {
|
||||
throw new UserDataException("could not find file: " + ffe.getMessage());
|
||||
} catch (IOException ioe) {
|
||||
throw new UserDataException("i/o error: " + ioe.getMessage());
|
||||
} catch (ParseException pe) {
|
||||
pe.printStackTrace();
|
||||
throw new UserDataException("parsing error: " + pe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<SafePath> makeSafePathList(String value) {
|
||||
List<SafePath> paths = new ArrayList<>();
|
||||
for (String name : value.split(",")) {
|
||||
paths.add(makeSafePath(name));
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
private SafePath makeSafePath(String path) {
|
||||
for (SafePath predefined : SecuritySupport.getPredefinedJFCFiles()) {
|
||||
try {
|
||||
String name = JFC.nameFromPath(predefined.toPath());
|
||||
if (name.equals(path) || (name + ".jfc").equals(path)) {
|
||||
return predefined;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new InternalError("Error in predefined .jfc file", e);
|
||||
}
|
||||
}
|
||||
return new SafePath(path);
|
||||
}
|
||||
|
||||
private void ensureInputFiles() throws InternalError {
|
||||
if (inputFiles.isEmpty()) {
|
||||
for (SafePath predefined : SecuritySupport.getPredefinedJFCFiles()) {
|
||||
if (predefined.toString().endsWith("default.jfc")) {
|
||||
inputFiles.add(predefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static SafePath filename(UserInterface ui, SafePath file) throws AbortException {
|
||||
ui.println();
|
||||
ui.println("Filename: " + file + " (default)");
|
||||
while (true) {
|
||||
String line = ui.readLine();
|
||||
try {
|
||||
if (line.isBlank()) {
|
||||
return file;
|
||||
}
|
||||
if (line.endsWith(".jfc")) {
|
||||
return new SafePath(line);
|
||||
}
|
||||
ui.println("Filename must end with .jfc.");
|
||||
} catch (InvalidPathException ipe) {
|
||||
ui.println("Not a valid filename. " + ipe.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SafePath makeJFCPath(String file) throws UserDataException, UserSyntaxException {
|
||||
if (file.startsWith("--")) {
|
||||
throw new UserSyntaxException("missing file");
|
||||
}
|
||||
try {
|
||||
Path path = Path.of(file).toAbsolutePath();
|
||||
ensureFileExtension(path, ".jfc");
|
||||
return new SafePath(path);
|
||||
} catch (IOError ioe) {
|
||||
throw new UserDataException("i/o error reading file '" + file + "', " + ioe.getMessage());
|
||||
} catch (InvalidPathException ipe) {
|
||||
throw new UserDataException("invalid path '" + file + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
Recommended way to edit .jfc files is to use Java Mission Control,
|
||||
see Window -> Flight Recorder Template Manager.
|
||||
Recommended way to edit .jfc files is to use the configure command of
|
||||
the 'jfr' tool, i.e. jfr configure, or JDK Mission Control
|
||||
see Window -> Flight Recorder Template Manager
|
||||
-->
|
||||
|
||||
<configuration version="2.0" label="Continuous" description="Low overhead configuration safe for continuous use in production environments, typically less than 1 % overhead." provider="Oracle">
|
||||
@ -64,31 +64,31 @@
|
||||
<event name="jdk.ThreadSleep">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ThreadPark">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.JavaMonitorEnter">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.JavaMonitorWait">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.JavaMonitorInflate">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.SyncOnValueBasedClass">
|
||||
@ -120,13 +120,13 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.ClassLoad">
|
||||
<setting name="enabled" control="class-loading-enabled">false</setting>
|
||||
<setting name="enabled" control="class-loading">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ClassDefine">
|
||||
<setting name="enabled" control="class-loading-enabled">false</setting>
|
||||
<setting name="enabled" control="class-loading">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
@ -143,11 +143,11 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.ClassRedefinition">
|
||||
<setting name="enabled" control="class-loading-enabled">true</setting>
|
||||
<setting name="enabled" control="class-loading">true</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ClassUnload">
|
||||
<setting name="enabled" control="class-loading-enabled">false</setting>
|
||||
<setting name="enabled" control="class-loading">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.JVMInformation">
|
||||
@ -207,7 +207,7 @@
|
||||
|
||||
<event name="jdk.ThreadDump">
|
||||
<setting name="enabled" control="thread-dump-enabled">true</setting>
|
||||
<setting name="period" control="thread-dump-interval">everyChunk</setting>
|
||||
<setting name="period" control="thread-dump">everyChunk</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.IntFlag">
|
||||
@ -274,7 +274,7 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.ObjectCount">
|
||||
<setting name="enabled" control="heap-statistics-enabled">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="period">everyChunk</setting>
|
||||
</event>
|
||||
|
||||
@ -382,22 +382,22 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.GCPhasePauseLevel3">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.GCPhasePauseLevel4">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.GCPhaseConcurrent">
|
||||
<setting name="enabled" control="gc-enabled-all">true</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">true</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.GCPhaseConcurrentLevel1">
|
||||
<setting name="enabled" control="gc-enabled-all">true</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">true</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
@ -443,11 +443,11 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.PromoteObjectInNewPLAB">
|
||||
<setting name="enabled" control="promotion-enabled">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.PromoteObjectOutsidePLAB">
|
||||
<setting name="enabled" control="promotion-enabled">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ConcurrentModeFailure">
|
||||
@ -455,7 +455,7 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.AllocationRequiringGC">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
@ -464,27 +464,27 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.G1HeapRegionInformation">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="period">everyChunk</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.G1HeapRegionTypeChange">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ShenandoahHeapRegionInformation">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="period">everyChunk</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ShenandoahHeapRegionStateChange">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.OldObjectSample">
|
||||
<setting name="enabled" control="memory-leak-detection-enabled">true</setting>
|
||||
<setting name="stackTrace" control="memory-leak-detection-stack-trace">false</setting>
|
||||
<setting name="cutoff" control="memory-leak-detection-cutoff">0 ns</setting>
|
||||
<setting name="enabled" control="old-objects-enabled">true</setting>
|
||||
<setting name="stackTrace" control="old-objects-stack-trace">false</setting>
|
||||
<setting name="cutoff" control="old-objects-cutoff">0 ns</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.CompilerConfiguration">
|
||||
@ -605,18 +605,18 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.ObjectAllocationInNewTLAB">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ObjectAllocationOutsideTLAB">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ObjectAllocationSample">
|
||||
<setting name="enabled" control="enable-object-allocation">true</setting>
|
||||
<setting name="throttle" control="object-allocation-rate">150/s</setting>
|
||||
<setting name="enabled" control="object-allocation-enabled">true</setting>
|
||||
<setting name="throttle" control="allocation-profiling">150/s</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
@ -638,31 +638,31 @@
|
||||
<event name="jdk.FileForce">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="file-io-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="file-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.FileRead">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="file-io-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="file-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.FileWrite">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="file-io-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="file-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.SocketRead">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="socket-io-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="socket-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.SocketWrite">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="socket-io-threshold">20 ms</setting>
|
||||
<setting name="threshold" control="socket-threshold">20 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.Deserialization">
|
||||
@ -819,67 +819,63 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
Contents of the control element is not read by the JVM, it's used
|
||||
by Java Mission Control to change settings that carry the control attribute.
|
||||
-->
|
||||
<!--
|
||||
Contents of the control element is not read by the JVM, it's used
|
||||
by JDK Mission Control and the 'jfr' tool to change settings that
|
||||
carry the control attribute.
|
||||
-->
|
||||
<control>
|
||||
<selection name="gc-level" default="detailed" label="Garbage Collector">
|
||||
<selection name="gc" default="normal" label="Garbage Collector">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Normal" name="detailed">normal</option>
|
||||
<option label="All" name="all">all</option>
|
||||
<option label="Normal" name="normal">normal</option>
|
||||
<option label="Detailed" name="detailed">detailed</option>
|
||||
<option label="High, incl. TLABs/PLABs (may cause many events)" name="high">high</option>
|
||||
<option label="All, incl. Heap Statistics (may cause long GCs)" name="all">all</option>
|
||||
</selection>
|
||||
|
||||
<condition name="gc-enabled-normal" true="true" false="false">
|
||||
<or>
|
||||
<test name="gc-level" operator="equal" value="normal"/>
|
||||
<test name="gc-level" operator="equal" value="all"/>
|
||||
<test name="gc" operator="equal" value="normal"/>
|
||||
<test name="gc" operator="equal" value="detailed"/>
|
||||
<test name="gc" operator="equal" value="high"/>
|
||||
<test name="gc" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="gc-enabled-detailed" true="true" false="false">
|
||||
<or>
|
||||
<test name="gc" operator="equal" value="detailed"/>
|
||||
<test name="gc" operator="equal" value="high"/>
|
||||
<test name="gc" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="gc-enabled-high" true="true" false="false">
|
||||
<or>
|
||||
<test name="gc" operator="equal" value="high"/>
|
||||
<test name="gc" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="gc-enabled-all" true="true" false="false">
|
||||
<test name="gc-level" operator="equal" value="all"/>
|
||||
<test name="gc" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<selection name="memory-profiling" default="low" label="Memory Profiling">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Object Allocation" name="low">low</option>
|
||||
<option label="Object Allocation and Promotion" name="medium">medium</option>
|
||||
<option label="All, including Heap Statistics (May cause long full GCs)" name="all">all</option>
|
||||
<selection name="allocation-profiling" default="low" label="Allocation Profiling">
|
||||
<option label="Off" name="off">0/s</option>
|
||||
<option label="Low" name="low">150/s</option>
|
||||
<option label="Medium" name="medium">300/s</option>
|
||||
<option label="High" name="high">1000/s</option>
|
||||
<option label="Maximum" name="maximum">1000000000/s</option>
|
||||
</selection>
|
||||
|
||||
<condition name="memory-profiling-enabled-low" true="true" false="false">
|
||||
<test name="memory-profiling" operator="equal" value="low"/>
|
||||
</condition>
|
||||
|
||||
<condition name="object-allocation-enabled" true="true" false="false">
|
||||
<or>
|
||||
<test name="memory-profiling" operator="equal" value="low"/>
|
||||
<test name="memory-profiling" operator="equal" value="medium"/>
|
||||
<test name="memory-profiling" operator="equal" value="all"/>
|
||||
</or>
|
||||
<not>
|
||||
<test name="allocation-profiling" operator="equal" value="off"/>
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<condition name="object-allocation-rate" true="300/s" false="150/s">
|
||||
<or>
|
||||
<test name="memory-profiling" operator="equal" value="medium"/>
|
||||
<test name="memory-profiling" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="promotion-enabled" true="true" false="false">
|
||||
<or>
|
||||
<test name="memory-profiling" operator="equal" value="medium"/>
|
||||
<test name="memory-profiling" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="heap-statistics-enabled" true="true" false="false">
|
||||
<test name="memory-profiling" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<selection name="compiler-level" default="normal" label="Compiler">
|
||||
<selection name="compiler" default="normal" label="Compiler">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Normal" name="normal">normal</option>
|
||||
<option label="Detailed" name="detailed">detailed</option>
|
||||
@ -887,96 +883,96 @@
|
||||
</selection>
|
||||
|
||||
<condition name="compiler-enabled" true="false" false="true">
|
||||
<test name="compiler-level" operator="equal" value="off"/>
|
||||
<test name="compiler" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-enabled-failure" true="true" false="false">
|
||||
<or>
|
||||
<test name="compiler-level" operator="equal" value="detailed"/>
|
||||
<test name="compiler-level" operator="equal" value="all"/>
|
||||
<test name="compiler" operator="equal" value="detailed"/>
|
||||
<test name="compiler" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-sweeper-threshold" true="0 ms" false="100 ms">
|
||||
<test name="compiler-level" operator="equal" value="all"/>
|
||||
<test name="compiler" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-compilation-threshold" true="1000 ms">
|
||||
<test name="compiler-level" operator="equal" value="normal"/>
|
||||
<test name="compiler" operator="equal" value="normal"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-compilation-threshold" true="100 ms">
|
||||
<test name="compiler-level" operator="equal" value="detailed"/>
|
||||
<test name="compiler" operator="equal" value="detailed"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-compilation-threshold" true="0 ms">
|
||||
<test name="compiler-level" operator="equal" value="all"/>
|
||||
<test name="compiler" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-phase-threshold" true="60 s">
|
||||
<test name="compiler-level" operator="equal" value="normal"/>
|
||||
<test name="compiler" operator="equal" value="normal"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-phase-threshold" true="10 s">
|
||||
<test name="compiler-level" operator="equal" value="detailed"/>
|
||||
<test name="compiler" operator="equal" value="detailed"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-phase-threshold" true="0 s">
|
||||
<test name="compiler-level" operator="equal" value="all"/>
|
||||
<test name="compiler" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<selection name="method-sampling-interval" default="normal" label="Method Sampling">
|
||||
<selection name="method-profiling" default="normal" label="Method Profiling">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Normal" name="normal">normal</option>
|
||||
<option label="High" name="high">high</option>
|
||||
<option label="Ludicrous (High Overhead)" name="ludicrous">ludicrous</option>
|
||||
<option label="Maximum (High Overhead)" name="max">max</option>
|
||||
</selection>
|
||||
|
||||
<condition name="method-sampling-java-interval" true="999 d">
|
||||
<test name="method-sampling-interval" operator="equal" value="off"/>
|
||||
<test name="method-profiling" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-java-interval" true="20 ms">
|
||||
<test name="method-sampling-interval" operator="equal" value="normal"/>
|
||||
<test name="method-profiling" operator="equal" value="normal"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-java-interval" true="10 ms">
|
||||
<test name="method-sampling-interval" operator="equal" value="high"/>
|
||||
<test name="method-profiling" operator="equal" value="high"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-java-interval" true="1 ms">
|
||||
<test name="method-sampling-interval" operator="equal" value="ludicrous"/>
|
||||
<test name="method-profiling" operator="equal" value="max"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-native-interval" true="999 d">
|
||||
<test name="method-sampling-interval" operator="equal" value="off"/>
|
||||
<test name="method-profiling" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-native-interval" true="20 ms">
|
||||
<or>
|
||||
<test name="method-sampling-interval" operator="equal" value="normal"/>
|
||||
<test name="method-sampling-interval" operator="equal" value="high"/>
|
||||
<test name="method-sampling-interval" operator="equal" value="ludicrous"/>
|
||||
<test name="method-profiling" operator="equal" value="normal"/>
|
||||
<test name="method-profiling" operator="equal" value="high"/>
|
||||
<test name="method-profiling" operator="equal" value="max"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-enabled" true="false" false="true">
|
||||
<test name="method-sampling-interval" operator="equal" value="off"/>
|
||||
<test name="method-profiling" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<selection name="thread-dump-interval" default="normal" label="Thread Dump">
|
||||
<selection name="thread-dump" default="once" label="Thread Dump">
|
||||
<option label="Off" name="off">999 d</option>
|
||||
<option label="At least Once" name="normal">everyChunk</option>
|
||||
<option label="Every 60 s" name="everyMinute">60 s</option>
|
||||
<option label="Every 10 s" name="everyTenSecond">10 s</option>
|
||||
<option label="Every 1 s" name="everySecond">1 s</option>
|
||||
<option label="At least Once" name="once">everyChunk</option>
|
||||
<option label="Every 60 s" name="60s">60 s</option>
|
||||
<option label="Every 10 s" name="10s">10 s</option>
|
||||
<option label="Every 1 s" name="1s">1 s</option>
|
||||
</selection>
|
||||
|
||||
<condition name="thread-dump-enabled" true="false" false="true">
|
||||
<test name="thread-dump-interval" operator="equal" value="999 d"/>
|
||||
<test name="thread-dump" operator="equal" value="999 d"/>
|
||||
</condition>
|
||||
|
||||
<selection name="exception-level" default="errors" label="Exceptions">
|
||||
<selection name="exceptions" default="errors" label="Exceptions">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Errors Only" name="errors">errors</option>
|
||||
<option label="All Exceptions, including Errors" name="all">all</option>
|
||||
@ -984,44 +980,44 @@
|
||||
|
||||
<condition name="enable-errors" true="true" false="false">
|
||||
<or>
|
||||
<test name="exception-level" operator="equal" value="errors"/>
|
||||
<test name="exception-level" operator="equal" value="all"/>
|
||||
<test name="exceptions" operator="equal" value="errors"/>
|
||||
<test name="exceptions" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="enable-exceptions" true="true" false="false">
|
||||
<test name="exception-level" operator="equal" value="all"/>
|
||||
<test name="exceptions" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<selection name="memory-leak-detection" default="minimal" label="Memory Leak Detection">
|
||||
<selection name="memory-leaks" default="types" label="Memory Leak Detection">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Object Types" name="minimal">minimal</option>
|
||||
<option label="Object Types + Allocation Stack Traces" name="medium">medium</option>
|
||||
<option label="Object Types + Allocation Stack Traces + Path to GC Root" name="full">full</option>
|
||||
<option label="Object Types" name="types">types</option>
|
||||
<option label="Object Types + Allocation Stack Traces" name="stack-traces">stack-traces</option>
|
||||
<option label="Object Types + Allocation Stack Traces + Path to GC Root" name="gc-roots">gc-roots</option>
|
||||
</selection>
|
||||
|
||||
<condition name="memory-leak-detection-enabled" true="false" false="true">
|
||||
<test name="memory-leak-detection" operator="equal" value="off"/>
|
||||
<condition name="old-objects-enabled" true="false" false="true">
|
||||
<test name="memory-leaks" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<condition name="memory-leak-detection-stack-trace" true="true" false="false">
|
||||
<condition name="old-objects-stack-trace" true="true" false="false">
|
||||
<or>
|
||||
<test name="memory-leak-detection" operator="equal" value="medium"/>
|
||||
<test name="memory-leak-detection" operator="equal" value="full"/>
|
||||
<test name="memory-leaks" operator="equal" value="stack-traces"/>
|
||||
<test name="memory-leaks" operator="equal" value="gc-roots"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="memory-leak-detection-cutoff" true="1 h" false="0 ns">
|
||||
<test name="memory-leak-detection" operator="equal" value="full"/>
|
||||
<condition name="old-objects-cutoff" true="1 h" false="0 ns">
|
||||
<test name="memory-leaks" operator="equal" value="gc-roots"/>
|
||||
</condition>
|
||||
|
||||
<text name="synchronization-threshold" label="Synchronization Threshold" contentType="timespan" minimum="0 s">20 ms</text>
|
||||
<text name="locking-threshold" label="Locking Threshold" contentType="timespan" minimum="0 s">20 ms</text>
|
||||
|
||||
<text name="file-io-threshold" label="File I/O Threshold" contentType="timespan" minimum="0 s">20 ms</text>
|
||||
<text name="file-threshold" label="File I/O Threshold" contentType="timespan" minimum="0 s">20 ms</text>
|
||||
|
||||
<text name="socket-io-threshold" label="Socket I/O Threshold" contentType="timespan" minimum="0 s">20 ms</text>
|
||||
<text name="socket-threshold" label="Socket I/O Threshold" contentType="timespan" minimum="0 s">20 ms</text>
|
||||
|
||||
<flag name="class-loading-enabled" label="Class Loading">false</flag>
|
||||
<flag name="class-loading" label="Class Loading">false</flag>
|
||||
|
||||
</control>
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
Recommended way to edit .jfc files is to use Java Mission Control,
|
||||
see Window -> Flight Recorder Template Manager.
|
||||
Recommended way to edit .jfc files is to use the configure command of
|
||||
the 'jfr' tool, i.e. jfr configure, or JDK Mission Control
|
||||
see Window -> Flight Recorder Template Manager
|
||||
-->
|
||||
|
||||
<configuration version="2.0" label="Profiling" description="Low overhead configuration for profiling, typically around 2 % overhead." provider="Oracle">
|
||||
@ -64,31 +64,31 @@
|
||||
<event name="jdk.ThreadSleep">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ThreadPark">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.JavaMonitorEnter">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.JavaMonitorWait">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.JavaMonitorInflate">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="synchronization-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="locking-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.SyncOnValueBasedClass">
|
||||
@ -120,13 +120,13 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.ClassLoad">
|
||||
<setting name="enabled" control="class-loading-enabled">false</setting>
|
||||
<setting name="enabled" control="class-loading">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ClassDefine">
|
||||
<setting name="enabled" control="class-loading-enabled">false</setting>
|
||||
<setting name="enabled" control="class-loading">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
@ -143,11 +143,11 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.ClassRedefinition">
|
||||
<setting name="enabled" control="class-loading-enabled">true</setting>
|
||||
<setting name="enabled" control="class-loading">true</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ClassUnload">
|
||||
<setting name="enabled" control="class-loading-enabled">false</setting>
|
||||
<setting name="enabled" control="class-loading">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.JVMInformation">
|
||||
@ -207,7 +207,7 @@
|
||||
|
||||
<event name="jdk.ThreadDump">
|
||||
<setting name="enabled" control="thread-dump-enabled">true</setting>
|
||||
<setting name="period" control="thread-dump-interval">60 s</setting>
|
||||
<setting name="period" control="thread-dump">60 s</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.IntFlag">
|
||||
@ -274,7 +274,7 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.ObjectCount">
|
||||
<setting name="enabled" control="heap-statistics-enabled">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="period">everyChunk</setting>
|
||||
</event>
|
||||
|
||||
@ -382,22 +382,22 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.GCPhasePauseLevel3">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.GCPhasePauseLevel4">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.GCPhaseConcurrent">
|
||||
<setting name="enabled" control="gc-enabled-all">true</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">true</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.GCPhaseConcurrentLevel1">
|
||||
<setting name="enabled" control="gc-enabled-all">true</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">true</setting>
|
||||
<setting name="threshold">0 ms</setting>
|
||||
</event>
|
||||
|
||||
@ -443,11 +443,11 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.PromoteObjectInNewPLAB">
|
||||
<setting name="enabled" control="promotion-enabled">true</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">true</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.PromoteObjectOutsidePLAB">
|
||||
<setting name="enabled" control="promotion-enabled">true</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">true</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ConcurrentModeFailure">
|
||||
@ -455,7 +455,7 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.AllocationRequiringGC">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
@ -464,27 +464,27 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.G1HeapRegionInformation">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="period">everyChunk</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.G1HeapRegionTypeChange">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ShenandoahHeapRegionInformation">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="period">everyChunk</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ShenandoahHeapRegionStateChange">
|
||||
<setting name="enabled" control="gc-enabled-all">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.OldObjectSample">
|
||||
<setting name="enabled" control="memory-leak-detection-enabled">true</setting>
|
||||
<setting name="stackTrace" control="memory-leak-detection-stack-trace">true</setting>
|
||||
<setting name="cutoff" control="memory-leak-detection-cutoff">0 ns</setting>
|
||||
<setting name="enabled" control="old-objects-enabled">true</setting>
|
||||
<setting name="stackTrace" control="old-objects-stack-trace">true</setting>
|
||||
<setting name="cutoff" control="old-objects-cutoff">0 ns</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.CompilerConfiguration">
|
||||
@ -605,18 +605,18 @@
|
||||
</event>
|
||||
|
||||
<event name="jdk.ObjectAllocationInNewTLAB">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ObjectAllocationOutsideTLAB">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="enabled" control="gc-enabled-high">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.ObjectAllocationSample">
|
||||
<setting name="enabled" control="enable-object-allocation">true</setting>
|
||||
<setting name="throttle" control="object-allocation-rate">300/s</setting>
|
||||
<setting name="enabled" control="object-allocation-enabled">true</setting>
|
||||
<setting name="throttle" control="allocation-profiling">300/s</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
@ -638,31 +638,31 @@
|
||||
<event name="jdk.FileForce">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="file-io-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="file-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.FileRead">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="file-io-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="file-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.FileWrite">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="file-io-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="file-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.SocketRead">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="socket-io-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="socket-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.SocketWrite">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
<setting name="threshold" control="socket-io-threshold">10 ms</setting>
|
||||
<setting name="threshold" control="socket-threshold">10 ms</setting>
|
||||
</event>
|
||||
|
||||
<event name="jdk.Deserialization">
|
||||
@ -819,66 +819,63 @@
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
Contents of the control element is not read by the JVM, it's used
|
||||
by Java Mission Control to change settings that carry the control attribute.
|
||||
-->
|
||||
<!--
|
||||
Contents of the control element is not read by the JVM, it's used
|
||||
by JDK Mission Control and the 'jfr' tool to change settings that
|
||||
carry the control attribute.
|
||||
-->
|
||||
<control>
|
||||
|
||||
<selection name="gc-level" default="detailed" label="Garbage Collector">
|
||||
<selection name="gc" default="detailed" label="Garbage Collector">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Normal" name="detailed">normal</option>
|
||||
<option label="All" name="all">all</option>
|
||||
<option label="Normal" name="normal">normal</option>
|
||||
<option label="Detailed" name="detailed">detailed</option>
|
||||
<option label="High, incl. TLABs/PLABs (may cause many events)" name="high">high</option>
|
||||
<option label="All, incl. Heap Statistics (may cause long GCs)" name="all">all</option>
|
||||
</selection>
|
||||
|
||||
<condition name="gc-enabled-normal" true="true" false="false">
|
||||
<or>
|
||||
<test name="gc-level" operator="equal" value="normal"/>
|
||||
<test name="gc-level" operator="equal" value="all"/>
|
||||
<test name="gc" operator="equal" value="normal"/>
|
||||
<test name="gc" operator="equal" value="detailed"/>
|
||||
<test name="gc" operator="equal" value="high"/>
|
||||
<test name="gc" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="gc-enabled-detailed" true="true" false="false">
|
||||
<or>
|
||||
<test name="gc" operator="equal" value="detailed"/>
|
||||
<test name="gc" operator="equal" value="high"/>
|
||||
<test name="gc" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="gc-enabled-high" true="true" false="false">
|
||||
<or>
|
||||
<test name="gc" operator="equal" value="high"/>
|
||||
<test name="gc" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="gc-enabled-all" true="true" false="false">
|
||||
<test name="gc-level" operator="equal" value="all"/>
|
||||
<test name="gc" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<selection name="memory-profiling" default="low" label="Memory Profiling">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Object Allocation" name="low">low</option>
|
||||
<option label="Object Allocation and Promotion" name="medium">medium</option>
|
||||
<option label="All, including Heap Statistics (May cause long full GCs)" name="all">all</option>
|
||||
<selection name="allocation-profiling" default="medium" label="Allocation Profiling">
|
||||
<option label="Off" name="off">0/s</option>
|
||||
<option label="Low" name="low">150/s</option>
|
||||
<option label="Medium" name="medium">300/s</option>
|
||||
<option label="High" name="high">1000/s</option>
|
||||
<option label="Maximum" name="maximum">1000000000/s</option>
|
||||
</selection>
|
||||
|
||||
<condition name="memory-profiling-enabled-low" true="true" false="false">
|
||||
<test name="memory-profiling" operator="equal" value="low"/>
|
||||
</condition>
|
||||
|
||||
<condition name="object-allocation-enabled" true="true" false="false">
|
||||
<or>
|
||||
<test name="memory-profiling" operator="equal" value="low"/>
|
||||
<test name="memory-profiling" operator="equal" value="medium"/>
|
||||
<test name="memory-profiling" operator="equal" value="all"/>
|
||||
</or>
|
||||
<not>
|
||||
<test name="allocation-profiling" operator="equal" value="off"/>
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<condition name="object-allocation-rate" true="300/s" false="150/s">
|
||||
<or>
|
||||
<test name="memory-profiling" operator="equal" value="medium"/>
|
||||
<test name="memory-profiling" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="promotion-enabled" true="true" false="false">
|
||||
<or>
|
||||
<test name="memory-profiling" operator="equal" value="medium"/>
|
||||
<test name="memory-profiling" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="heap-statistics-enabled" true="true" false="false">
|
||||
<test name="memory-profiling" operator="equal" value="all"/>
|
||||
</condition>
|
||||
<selection name="compiler-level" default="detailed" label="Compiler">
|
||||
<selection name="compiler" default="detailed" label="Compiler">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Normal" name="normal">normal</option>
|
||||
<option label="Detailed" name="detailed">detailed</option>
|
||||
@ -886,96 +883,96 @@
|
||||
</selection>
|
||||
|
||||
<condition name="compiler-enabled" true="false" false="true">
|
||||
<test name="compiler-level" operator="equal" value="off"/>
|
||||
<test name="compiler" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-enabled-failure" true="true" false="false">
|
||||
<or>
|
||||
<test name="compiler-level" operator="equal" value="detailed"/>
|
||||
<test name="compiler-level" operator="equal" value="all"/>
|
||||
<test name="compiler" operator="equal" value="detailed"/>
|
||||
<test name="compiler" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-sweeper-threshold" true="0 ms" false="100 ms">
|
||||
<test name="compiler-level" operator="equal" value="all"/>
|
||||
<test name="compiler" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-compilation-threshold" true="1000 ms">
|
||||
<test name="compiler-level" operator="equal" value="normal"/>
|
||||
<test name="compiler" operator="equal" value="normal"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-compilation-threshold" true="100 ms">
|
||||
<test name="compiler-level" operator="equal" value="detailed"/>
|
||||
<test name="compiler" operator="equal" value="detailed"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-compilation-threshold" true="0 ms">
|
||||
<test name="compiler-level" operator="equal" value="all"/>
|
||||
<test name="compiler" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-phase-threshold" true="60 s">
|
||||
<test name="compiler-level" operator="equal" value="normal"/>
|
||||
<test name="compiler" operator="equal" value="normal"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-phase-threshold" true="10 s">
|
||||
<test name="compiler-level" operator="equal" value="detailed"/>
|
||||
<test name="compiler" operator="equal" value="detailed"/>
|
||||
</condition>
|
||||
|
||||
<condition name="compiler-phase-threshold" true="0 s">
|
||||
<test name="compiler-level" operator="equal" value="all"/>
|
||||
<test name="compiler" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<selection name="method-sampling-interval" default="normal" label="Method Sampling">
|
||||
<selection name="method-profiling" default="high" label="Method Profiling">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Normal" name="normal">normal</option>
|
||||
<option label="High" name="high">high</option>
|
||||
<option label="Ludicrous (High Overhead)" name="ludicrous">ludicrous</option>
|
||||
<option label="Maximum (High Overhead)" name="max">max</option>
|
||||
</selection>
|
||||
|
||||
<condition name="method-sampling-java-interval" true="999 d">
|
||||
<test name="method-sampling-interval" operator="equal" value="off"/>
|
||||
<test name="method-profiling" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-java-interval" true="20 ms">
|
||||
<test name="method-sampling-interval" operator="equal" value="normal"/>
|
||||
<test name="method-profiling" operator="equal" value="normal"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-java-interval" true="10 ms">
|
||||
<test name="method-sampling-interval" operator="equal" value="high"/>
|
||||
<test name="method-profiling" operator="equal" value="high"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-java-interval" true="1 ms">
|
||||
<test name="method-sampling-interval" operator="equal" value="ludicrous"/>
|
||||
<test name="method-profiling" operator="equal" value="max"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-native-interval" true="999 d">
|
||||
<test name="method-sampling-interval" operator="equal" value="off"/>
|
||||
<test name="method-profiling" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-native-interval" true="20 ms">
|
||||
<or>
|
||||
<test name="method-sampling-interval" operator="equal" value="normal"/>
|
||||
<test name="method-sampling-interval" operator="equal" value="high"/>
|
||||
<test name="method-sampling-interval" operator="equal" value="ludicrous"/>
|
||||
<test name="method-profiling" operator="equal" value="normal"/>
|
||||
<test name="method-profiling" operator="equal" value="high"/>
|
||||
<test name="method-profiling" operator="equal" value="max"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="method-sampling-enabled" true="false" false="true">
|
||||
<test name="method-sampling-interval" operator="equal" value="off"/>
|
||||
<test name="method-profiling" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<selection name="thread-dump-interval" default="everyMinute" label="Thread Dump">
|
||||
<selection name="thread-dump" default="once" label="Thread Dump">
|
||||
<option label="Off" name="off">999 d</option>
|
||||
<option label="At least Once" name="normal">everyChunk</option>
|
||||
<option label="Every 60 s" name="everyMinute">60 s</option>
|
||||
<option label="Every 10 s" name="everyTenSecond">10 s</option>
|
||||
<option label="Every 1 s" name="everySecond">1 s</option>
|
||||
<option label="At least Once" name="once">everyChunk</option>
|
||||
<option label="Every 60 s" name="60s">60 s</option>
|
||||
<option label="Every 10 s" name="10s">10 s</option>
|
||||
<option label="Every 1 s" name="1s">1 s</option>
|
||||
</selection>
|
||||
|
||||
<condition name="thread-dump-enabled" true="false" false="true">
|
||||
<test name="thread-dump-interval" operator="equal" value="999 d"/>
|
||||
<test name="thread-dump" operator="equal" value="999 d"/>
|
||||
</condition>
|
||||
|
||||
<selection name="exception-level" default="errors" label="Exceptions">
|
||||
<selection name="exceptions" default="errors" label="Exceptions">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Errors Only" name="errors">errors</option>
|
||||
<option label="All Exceptions, including Errors" name="all">all</option>
|
||||
@ -983,44 +980,44 @@
|
||||
|
||||
<condition name="enable-errors" true="true" false="false">
|
||||
<or>
|
||||
<test name="exception-level" operator="equal" value="errors"/>
|
||||
<test name="exception-level" operator="equal" value="all"/>
|
||||
<test name="exceptions" operator="equal" value="errors"/>
|
||||
<test name="exceptions" operator="equal" value="all"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="enable-exceptions" true="true" false="false">
|
||||
<test name="exception-level" operator="equal" value="all"/>
|
||||
<test name="exceptions" operator="equal" value="all"/>
|
||||
</condition>
|
||||
|
||||
<selection name="memory-leak-detection" default="medium" label="Memory Leak Detection">
|
||||
<selection name="memory-leaks" default="stack-traces" label="Memory Leak Detection">
|
||||
<option label="Off" name="off">off</option>
|
||||
<option label="Object Types" name="minimal">minimal</option>
|
||||
<option label="Object Types + Allocation Stack Traces" name="medium">medium</option>
|
||||
<option label="Object Types + Allocation Stack Traces + Path to GC Root" name="full">full</option>
|
||||
<option label="Object Types" name="types">types</option>
|
||||
<option label="Object Types + Allocation Stack Traces" name="stack-traces">stack-traces</option>
|
||||
<option label="Object Types + Allocation Stack Traces + Path to GC Root" name="gc-roots">gc-roots</option>
|
||||
</selection>
|
||||
|
||||
<condition name="memory-leak-detection-enabled" true="false" false="true">
|
||||
<test name="memory-leak-detection" operator="equal" value="off"/>
|
||||
<condition name="old-objects-enabled" true="false" false="true">
|
||||
<test name="memory-leaks" operator="equal" value="off"/>
|
||||
</condition>
|
||||
|
||||
<condition name="memory-leak-detection-stack-trace" true="true" false="false">
|
||||
<condition name="old-objects-stack-trace" true="true" false="false">
|
||||
<or>
|
||||
<test name="memory-leak-detection" operator="equal" value="medium"/>
|
||||
<test name="memory-leak-detection" operator="equal" value="full"/>
|
||||
<test name="memory-leaks" operator="equal" value="stack-traces"/>
|
||||
<test name="memory-leaks" operator="equal" value="gc-roots"/>
|
||||
</or>
|
||||
</condition>
|
||||
|
||||
<condition name="memory-leak-detection-cutoff" true="1 h" false="0 ns">
|
||||
<test name="memory-leak-detection" operator="equal" value="full"/>
|
||||
<condition name="old-objects-cutoff" true="1 h" false="0 ns">
|
||||
<test name="memory-leaks" operator="equal" value="gc-roots"/>
|
||||
</condition>
|
||||
|
||||
<text name="synchronization-threshold" label="Synchronization Threshold" contentType="timespan" minimum="0 s">10 ms</text>
|
||||
<text name="locking-threshold" label="Locking Threshold" contentType="timespan" minimum="0 s">10 ms</text>
|
||||
|
||||
<text name="file-io-threshold" label="File I/O Threshold" contentType="timespan" minimum="0 s">10 ms</text>
|
||||
<text name="file-threshold" label="File I/O Threshold" contentType="timespan" minimum="0 s">10 ms</text>
|
||||
|
||||
<text name="socket-io-threshold" label="Socket I/O Threshold" contentType="timespan" minimum="0 s">10 ms</text>
|
||||
<text name="socket-threshold" label="Socket I/O Threshold" contentType="timespan" minimum="0 s">10 ms</text>
|
||||
|
||||
<flag name="class-loading-enabled" label="Class Loading">false</flag>
|
||||
<flag name="class-loading" label="Class Loading">false</flag>
|
||||
|
||||
</control>
|
||||
|
||||
|
||||
362
test/jdk/jdk/jfr/tool/TestConfigure.java
Normal file
362
test/jdk/jdk/jfr/tool/TestConfigure.java
Normal file
@ -0,0 +1,362 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.jfr.tool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jdk.jfr.Configuration;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
/**
|
||||
* @test
|
||||
* @summary Test jfr configure
|
||||
* @key jfr
|
||||
* @requires vm.hasJFR
|
||||
* @library /test/lib /test/jdk
|
||||
* @run main/othervm jdk.jfr.tool.TestConfigure
|
||||
*/
|
||||
public class TestConfigure {
|
||||
|
||||
private static final String DIR = System.getProperty("test.src", ".");
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
testSelection();
|
||||
testText();
|
||||
testFlag();
|
||||
testCondition();
|
||||
testAnd();
|
||||
testOr();
|
||||
testNone();
|
||||
testMissingControl();
|
||||
testDefault();
|
||||
testCopyPredefined();
|
||||
testSuperflouos();
|
||||
testModify();
|
||||
testAdding();
|
||||
testUnification();
|
||||
testTimespan();
|
||||
testVerbose();
|
||||
}
|
||||
|
||||
private static void testVerbose() throws Throwable {
|
||||
var input = newInputFile("flag.jfc");
|
||||
|
||||
var output = newOutputFile("verbose-1.jfc");
|
||||
var result = jfrConfigure("--input", input, "--verbose", "mammal=true", "--output", output);
|
||||
result.shouldContain("com.example.Lion#enabled=true");
|
||||
result.shouldContain("com.example.Tiger#enabled=true");
|
||||
|
||||
output = newOutputFile("verbose-2.jfc");
|
||||
result = jfrConfigure("--input", input, "--verbose", "+com.example.Albatross#enabled=true", "--output", output);
|
||||
result.shouldContain("com.example.Albatross#enabled=true");
|
||||
}
|
||||
|
||||
private static void testTimespan() throws Throwable {
|
||||
var input = newInputFile("timespan.jfc");
|
||||
|
||||
var output = newOutputFile("quoted-timespan.jfc");
|
||||
jfrConfigure("--input", input, "value=20 s","--output", output);
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#threshold", "20 s");
|
||||
expected.put("com.example.Lion#period", "20 s");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
|
||||
output = newOutputFile("compact-timespan.jfc");
|
||||
jfrConfigure("--input", input, "value=13s","--output", output);
|
||||
outputSetting = readSettings(output);
|
||||
expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#threshold", "13 s");
|
||||
expected.put("com.example.Lion#period", "13 s");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
|
||||
output = newOutputFile("threshold-period-timespan.jfc");
|
||||
jfrConfigure("--input", input,
|
||||
"com.example.Tiger#threshold=2s",
|
||||
"com.example.Lion#period=3s",
|
||||
"--output", output);
|
||||
|
||||
outputSetting = readSettings(output);
|
||||
expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#threshold", "2 s");
|
||||
expected.put("com.example.Lion#period", "3 s");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
private static void testUnification() throws Throwable {
|
||||
var input1 = newInputFile("or.jfc");
|
||||
var input2 = newInputFile("and.jfc");
|
||||
var output = newOutputFile("combined.jfc");
|
||||
|
||||
jfrConfigure("--input", input1 + "," + input2, "--output", output);
|
||||
|
||||
var input1Setting = readSettings(input1);
|
||||
var input2Setting = readSettings(input2);
|
||||
var outputSetting = readSettings(output);
|
||||
|
||||
Map<String, String> expected = new HashMap<>();
|
||||
expected.putAll(input1Setting);
|
||||
expected.putAll(input2Setting);
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
private static void testAdding() throws Throwable {
|
||||
var input = newInputFile("plain.jfc");
|
||||
|
||||
var output = newOutputFile("test-adding-succeed-1.jfc");
|
||||
var result = jfrConfigure("--input", input, "+com.example.Tiger#legs=4", "--output", output);
|
||||
result.shouldNotContain("Could not find");
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#legs", "4");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
|
||||
output = newOutputFile("test-adding-succeed-2.jfc");
|
||||
result = jfrConfigure("--input", input, "+com.example.Foo#bar=baz", "--output", output);
|
||||
result.shouldNotContain("Could not find");
|
||||
|
||||
outputSetting = readSettings(output);
|
||||
expected = readSettings(input);
|
||||
expected.put("com.example.Foo#bar", "baz");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
private static void testModify() throws Throwable {
|
||||
var input = newInputFile("plain.jfc");
|
||||
|
||||
var output = newOutputFile("test-modify-fail-1.jfc");
|
||||
var result = jfrConfigure("--input", input, "com.example.Zebra#stackTrace=true", "--output", output);
|
||||
result.shouldContain("Could not find event 'com.example.Zebra'");
|
||||
|
||||
output = newOutputFile("test-modify-fail-2.jfc");
|
||||
result = jfrConfigure("--input", input, "com.example.Tiger#foo=true", "--output", output);
|
||||
result.shouldContain("Could not find setting 'foo' for event 'com.example.Tiger'");
|
||||
|
||||
output = newOutputFile("test-modify-succeed.jfc");
|
||||
result = jfrConfigure("--input", input, "com.example.Tiger#enabled=true", "--output", output);
|
||||
result.shouldNotContain("Could not find");
|
||||
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#enabled", "true");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
// JMC may add attributes or elements, make sure some random elements/attributes survive
|
||||
private static void testSuperflouos() throws Throwable {
|
||||
var output = newOutputFile("test-superfluous.jfc");
|
||||
var input = newInputFile("superfluous.jfc");
|
||||
jfrConfigure("--input", input, "--output", output);
|
||||
String content = Files.readString(Path.of(output));
|
||||
for (String t : List.of("legs=\"4\"", "radio", "red", "</radio>", "option")) {
|
||||
if (!content.contains(t)) {
|
||||
throw new Exception("Expected superfluous element '" + t + "' or attribute to survive");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testMissingControl() throws Throwable {
|
||||
var output = newOutputFile("missed.jfc");
|
||||
var input = newInputFile("missing.jfc");
|
||||
var result = jfrConfigure("--input", input, "--output", output);
|
||||
result.shouldContain("Warning! Setting 'com.example.Tiger#enabled' refers to missing control 'tigre'");
|
||||
}
|
||||
|
||||
private static void testDefault() throws Throwable {
|
||||
var output = newOutputFile("fresh.jfc");
|
||||
var result = jfrConfigure("--output", output);
|
||||
result.shouldNotContain("Warning"); // checks dangling control reference in default.jfc
|
||||
var outputSetting = readSettings(output);
|
||||
aseertEqual(outputSetting, Configuration.getConfiguration("default").getSettings());
|
||||
}
|
||||
|
||||
private static void testCopyPredefined() throws Throwable {
|
||||
var output = newOutputFile("new.jfc");
|
||||
var result = jfrConfigure("--input", "profile", "--output", output);
|
||||
result.shouldNotContain("Warning"); // checks missing control reference in profile.jfc
|
||||
|
||||
var outputSetting = readSettings(output);
|
||||
aseertEqual(outputSetting, Configuration.getConfiguration("profile").getSettings());
|
||||
}
|
||||
|
||||
private static void testNone() throws Throwable {
|
||||
var output = newOutputFile("new.jfc");
|
||||
jfrConfigure("--input", "none", "--output", output);
|
||||
var outputSetting = readSettings(output);
|
||||
aseertEqual(outputSetting, Map.of());
|
||||
}
|
||||
|
||||
private static void testOr() throws Throwable {
|
||||
var output = newOutputFile("test-or-true.jfc");
|
||||
var input = newInputFile("or.jfc");
|
||||
jfrConfigure("--input", input, "month=May", "--output", output);
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("season.Spring#enabled", "true");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
|
||||
output = newOutputFile("test-or-false.jfc");
|
||||
jfrConfigure("--input", input, "month=September", "--output", output);
|
||||
outputSetting = readSettings(output);
|
||||
expected = readSettings(input);
|
||||
expected.put("season.Spring#enabled", "false");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
private static void testAnd() throws Throwable {
|
||||
var output = newOutputFile("test-and-true.jfc");
|
||||
var input = newInputFile("and.jfc");
|
||||
jfrConfigure("--input", input,
|
||||
"closure=true",
|
||||
"identity=true",
|
||||
"associativity=true",
|
||||
"inverse=true",
|
||||
"--output", output);
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("algebra.Group#enabled", "true");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
|
||||
output = newOutputFile("test-and-false.jfc");
|
||||
jfrConfigure("--input", input,
|
||||
"closure=true",
|
||||
"identity=true",
|
||||
"associativity=true",
|
||||
"inverse=false",
|
||||
"--output", output);
|
||||
outputSetting = readSettings(output);
|
||||
expected = readSettings(input);
|
||||
expected.put("algebra.Group#enabled", "false");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
|
||||
private static void testCondition() throws Throwable {
|
||||
var output = newOutputFile("test-condition-1.jfc");
|
||||
var input = newInputFile("condition.jfc");
|
||||
jfrConfigure("--input", input, "variable=activate", "--output", output);
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#period", "1 s");
|
||||
expected.put("com.example.Lion#period", "3 s");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
|
||||
output = newOutputFile("test-condition-2.jfc");
|
||||
jfrConfigure("--input", input, "variable=whatever", "--output", output);
|
||||
outputSetting = readSettings(output);
|
||||
expected = readSettings(input);
|
||||
expected.put("com.example.Lion#period", "5 s");
|
||||
expected.put("com.example.Zebra#period", "7 s");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
private static void testFlag() throws Throwable {
|
||||
var output = newOutputFile("test-flag.jfc");
|
||||
var input = newInputFile("flag.jfc");
|
||||
jfrConfigure("--input", input, "mammal=true", "--output", output);
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#enabled", "true");
|
||||
expected.put("com.example.Lion#enabled", "true");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
private static void testText() throws Throwable {
|
||||
var output = newOutputFile("test-text.jfc");
|
||||
var input = newInputFile("text.jfc");
|
||||
jfrConfigure("--input", input, "animal-threshold=3s", "--output", output);
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#threshold", "3 s");
|
||||
expected.put("com.example.Lion#threshold", "3 s");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
private static void testSelection() throws Throwable {
|
||||
var output = newOutputFile("test-selection.jfc");
|
||||
var input = newInputFile("selection.jfc");
|
||||
jfrConfigure("--input", input, "animal=medium", "--output", output);
|
||||
var outputSetting = readSettings(output);
|
||||
var expected = readSettings(input);
|
||||
expected.put("com.example.Tiger#threshold", "10 s");
|
||||
expected.put("com.example.Lion#threshold", "10 s");
|
||||
|
||||
aseertEqual(outputSetting, expected);
|
||||
}
|
||||
|
||||
private static String newInputFile(String filename) {
|
||||
return Path.of(DIR, "configure", filename).toAbsolutePath().toString();
|
||||
}
|
||||
|
||||
private static Map<String, String> readSettings(String text) throws IOException, ParseException {
|
||||
return Configuration.create(Path.of(text)).getSettings();
|
||||
}
|
||||
|
||||
private static OutputAnalyzer jfrConfigure(String... args) throws Throwable {
|
||||
String[] all = new String[args.length + 1];
|
||||
all[0] = "configure";
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
all[i + 1] = args[i];
|
||||
}
|
||||
OutputAnalyzer o = ExecuteHelper.jfr(all);
|
||||
System.out.println(o.getOutput());
|
||||
return o;
|
||||
}
|
||||
|
||||
private static String newOutputFile(String filename) {
|
||||
return Path.of(DIR, System.currentTimeMillis() + filename).toAbsolutePath().toString();
|
||||
}
|
||||
|
||||
private static void aseertEqual(Map<String, String> output, Map<String, String> expected) throws Exception {
|
||||
if (!output.equals(expected)) {
|
||||
System.out.println("Output:");
|
||||
for (var e : output.entrySet()) {
|
||||
System.out.println("\"" + e.getKey() + "=" + e.getValue() + "\"");
|
||||
}
|
||||
System.out.println("Expected:");
|
||||
for (var e : expected.entrySet()) {
|
||||
System.out.println("\"" + e.getKey() + "=" + e.getValue() + "\"");
|
||||
}
|
||||
throw new Exception("Mismatch between output and expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
24
test/jdk/jdk/jfr/tool/configure/and.jfc
Normal file
24
test/jdk/jdk/jfr/tool/configure/and.jfc
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test and">
|
||||
|
||||
<event name="algebra.Group">
|
||||
<setting name="enabled" control="group">unknown</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<flag name="closure" label="Close">false</flag>
|
||||
<flag name="identity" label="Identity">false</flag>
|
||||
<flag name="associativity" label="Associativity">false</flag>
|
||||
<flag name="inverse" label="Inverse">false</flag>
|
||||
|
||||
<condition name="group" true="true" false="false">
|
||||
<and>
|
||||
<test name="closure" operator="equal" value="true"/>
|
||||
<test name="identity" operator="equal" value="true"/>
|
||||
<test name="associativity" operator="equal" value="true"/>
|
||||
<test name="inverse" operator="equal" value="true"/>
|
||||
</and>
|
||||
</condition>
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
33
test/jdk/jdk/jfr/tool/configure/condition.jfc
Normal file
33
test/jdk/jdk/jfr/tool/configure/condition.jfc
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test condition">
|
||||
|
||||
<event name="com.example.Tiger">
|
||||
<setting name="period" control="tiger">0 s</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Lion">
|
||||
<setting name="period" control="lion">0 s</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Zebra">
|
||||
<setting name="period" control="zebra">0 s</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<text name="variable" label="Variable">disabled</text>
|
||||
|
||||
<condition name="tiger" true="1 s">
|
||||
<test name="variable" operator="equal" value="activate"/>
|
||||
</condition>
|
||||
|
||||
<condition name="lion" true="3 s" false="5 s">
|
||||
<test name="variable" operator="equal" value="activate"/>
|
||||
</condition>
|
||||
|
||||
<condition name="zebra" false="7 s">
|
||||
<test name="variable" operator="equal" value="activate"/>
|
||||
</condition>
|
||||
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
21
test/jdk/jdk/jfr/tool/configure/flag.jfc
Normal file
21
test/jdk/jdk/jfr/tool/configure/flag.jfc
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test flag">
|
||||
|
||||
<event name="com.example.Tiger">
|
||||
<setting name="enabled" control="mammal">false</setting>
|
||||
<setting name="stackTrace">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Lion">
|
||||
<setting name="enabled" control="mammal">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Albatross">
|
||||
<setting name="enabled">false</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<flag name="mammal" label="Mammal">false</flag>
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
19
test/jdk/jdk/jfr/tool/configure/missing.jfc
Normal file
19
test/jdk/jdk/jfr/tool/configure/missing.jfc
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test missing reference">
|
||||
|
||||
<event name="com.example.Tiger">
|
||||
<setting name="enabled" control="tigre">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Cactus">
|
||||
<setting name="threshold">0 s</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<selection name="tiger" label="Tiger" default="true">
|
||||
<option name="true" label="True">true</option>
|
||||
<option name="false" label="False">false</option>
|
||||
</selection>
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
20
test/jdk/jdk/jfr/tool/configure/or.jfc
Normal file
20
test/jdk/jdk/jfr/tool/configure/or.jfc
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test or">
|
||||
|
||||
<event name="season.Spring">
|
||||
<setting name="enabled" control="spring">unknown</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<text name="month" label="Month">January</text>
|
||||
|
||||
<condition name="spring" true="true" false="false">
|
||||
<or>
|
||||
<test name="month" operator="equal" value="March"/>
|
||||
<test name="month" operator="equal" value="April"/>
|
||||
<test name="month" operator="equal" value="May"/>
|
||||
</or>
|
||||
</condition>
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
15
test/jdk/jdk/jfr/tool/configure/plain.jfc
Normal file
15
test/jdk/jdk/jfr/tool/configure/plain.jfc
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test plain">
|
||||
|
||||
<event name="com.example.Tiger">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="stackTrace">false</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Lion">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="stackTrace">true</setting>
|
||||
</event>
|
||||
|
||||
|
||||
</configuration>
|
||||
27
test/jdk/jdk/jfr/tool/configure/selection.jfc
Normal file
27
test/jdk/jdk/jfr/tool/configure/selection.jfc
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test selection">
|
||||
|
||||
<event name="com.example.Tiger">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="threshold" control="animal">0 s</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Lion">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="threshold" control="animal">0 s</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Cactus">
|
||||
<setting name="threshold">0 s</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<selection name="animal" label="Animal" default="off">
|
||||
<option name="off" label="Off">0 s</option>
|
||||
<option name="low" label="Low">1 s</option>
|
||||
<option name="medium" label="Medium">10 s</option>
|
||||
<option name="high" label="High">100 s</option>
|
||||
</selection>
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
18
test/jdk/jdk/jfr/tool/configure/superfluous.jfc
Normal file
18
test/jdk/jdk/jfr/tool/configure/superfluous.jfc
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test superfluous elements and attributes">
|
||||
|
||||
<event legs="4" name="com.example.Tiger">
|
||||
<setting name="enabled" control="animal">false</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<flag name="animal" label="Animal">true</flag>
|
||||
|
||||
<radio name="color" label="Color" default="green">
|
||||
<option name="red" label="Red">red</option>
|
||||
<option name="green" label="Green">green</option>
|
||||
<option name="blue" label="Blue">blue</option>
|
||||
</radio>
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
22
test/jdk/jdk/jfr/tool/configure/text.jfc
Normal file
22
test/jdk/jdk/jfr/tool/configure/text.jfc
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test text">
|
||||
|
||||
<event name="com.example.Tiger">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="threshold" control="animal-threshold">0 s</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Lion">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="threshold" control="animal-threshold">0 s</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Cactus">
|
||||
<setting name="legs">0 s</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<text name="animal-threshold" contentType="timespan" label="Threshold">0 s</text>
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
18
test/jdk/jdk/jfr/tool/configure/timespan.jfc
Normal file
18
test/jdk/jdk/jfr/tool/configure/timespan.jfc
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration version="2.0" label="Test timespan">
|
||||
|
||||
<event name="com.example.Tiger">
|
||||
<setting name="enabled">false</setting>
|
||||
<setting name="threshold" control="value">0 s</setting>
|
||||
</event>
|
||||
|
||||
<event name="com.example.Lion">
|
||||
<setting name="enabled">true</setting>
|
||||
<setting name="period" control="value">0 s</setting>
|
||||
</event>
|
||||
|
||||
<control>
|
||||
<text name="value" label="Value" contentType="timespan">0 s</text>
|
||||
</control>
|
||||
|
||||
</configuration>
|
||||
Loading…
x
Reference in New Issue
Block a user