| /* |
| * Copyright (c) 2012, 2018, 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.dcmd; |
| |
| import java.time.Duration; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.StringJoiner; |
| |
| import jdk.jfr.EventType; |
| import jdk.jfr.Recording; |
| import jdk.jfr.SettingDescriptor; |
| import jdk.jfr.internal.LogLevel; |
| import jdk.jfr.internal.LogTag; |
| import jdk.jfr.internal.Logger; |
| import jdk.jfr.internal.Utils; |
| |
| /** |
| * JFR.check - invoked from native |
| * |
| */ |
| final class DCmdCheck extends AbstractDCmd { |
| /** |
| * Execute JFR.check |
| * |
| * @param recordingText name or id of the recording to check, or |
| * <code>null</code> to show a list of all recordings. |
| * |
| * @param verbose if event settings should be included. |
| * |
| * @return result output |
| * |
| * @throws DCmdException if the check could not be completed. |
| */ |
| public String execute(String recordingText, Boolean verbose) throws DCmdException { |
| executeInternal(recordingText, verbose); |
| return getResult(); |
| } |
| |
| private void executeInternal(String name, Boolean verbose) throws DCmdException { |
| if (Logger.shouldLog(LogTag.JFR_DCMD, LogLevel.DEBUG)) { |
| Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG, "Executing DCmdCheck: name=" + name + ", verbose=" + verbose); |
| } |
| |
| if (verbose == null) { |
| verbose = Boolean.FALSE; |
| } |
| |
| if (name != null) { |
| printRecording(findRecording(name), verbose); |
| return; |
| } |
| |
| List<Recording> recordings = getRecordings(); |
| if (!verbose && recordings.isEmpty()) { |
| println("No available recordings."); |
| println(); |
| println("Use jcmd " + getPid() + " JFR.start to start a recording."); |
| return; |
| } |
| boolean first = true; |
| for (Recording recording : recordings) { |
| // Print separation between recordings, |
| if (!first) { |
| println(); |
| if (Boolean.TRUE.equals(verbose)) { |
| println(); |
| } |
| } |
| first = false; |
| printRecording(recording, verbose); |
| } |
| } |
| |
| private void printRecording(Recording recording, boolean verbose) { |
| printGeneral(recording); |
| if (verbose) { |
| println(); |
| printSetttings(recording); |
| } |
| } |
| |
| private void printGeneral(Recording recording) { |
| print("Recording " + recording.getId() + ": name=" + recording.getName()); |
| |
| Duration duration = recording.getDuration(); |
| if (duration != null) { |
| print(" duration="); |
| printTimespan(duration, ""); |
| } |
| |
| long maxSize = recording.getMaxSize(); |
| if (maxSize != 0) { |
| print(" maxsize="); |
| print(Utils.formatBytesCompact(maxSize)); |
| } |
| Duration maxAge = recording.getMaxAge(); |
| if (maxAge != null) { |
| print(" maxage="); |
| printTimespan(maxAge, ""); |
| } |
| |
| print(" (" + recording.getState().toString().toLowerCase() + ")"); |
| println(); |
| } |
| |
| private void printSetttings(Recording recording) { |
| Map<String, String> settings = recording.getSettings(); |
| for (EventType eventType : sortByEventPath(getFlightRecorder().getEventTypes())) { |
| StringJoiner sj = new StringJoiner(",", "[", "]"); |
| sj.setEmptyValue(""); |
| for (SettingDescriptor s : eventType.getSettingDescriptors()) { |
| String settingsPath = eventType.getName() + "#" + s.getName(); |
| if (settings.containsKey(settingsPath)) { |
| sj.add(s.getName() + "=" + settings.get(settingsPath)); |
| } |
| } |
| String settingsText = sj.toString(); |
| if (!settingsText.isEmpty()) { |
| print(" %s (%s)", eventType.getLabel(), eventType.getName()); |
| println(); |
| println(" " + settingsText); |
| } |
| } |
| } |
| |
| private static List<EventType> sortByEventPath(Collection<EventType> events) { |
| List<EventType> sorted = new ArrayList<>(); |
| sorted.addAll(events); |
| Collections.sort(sorted, new Comparator<EventType>() { |
| @Override |
| public int compare(EventType e1, EventType e2) { |
| return e1.getName().compareTo(e2.getName()); |
| } |
| }); |
| return sorted; |
| } |
| } |