Skip to content

Instantly share code, notes, and snippets.

@rwunsch
Last active January 22, 2025 19:05
Show Gist options
  • Select an option

  • Save rwunsch/261c39503efc7ea6ae4f57484a043500 to your computer and use it in GitHub Desktop.

Select an option

Save rwunsch/261c39503efc7ea6ae4f57484a043500 to your computer and use it in GitHub Desktop.
Java Flight Recorder - execution script
#!/bin/bash
LOG_FILE="/var/log/jfr_recorder.log"
choose_profile() {
echo "Select a JFR profile or custom settings file:"
echo "1) profile - Captures detailed performance metrics, useful for profiling applications."
echo "2) default - Standard JFR configuration, collects essential runtime data."
# Detect custom .jfc files in the script directory
JFC_FILES=()
COUNTER=3
for FILE in *.jfc; do
if [ -f "$FILE" ]; then
JFC_FILES+=("$FILE")
echo "$COUNTER) $FILE - Custom JFR configuration file"
((COUNTER++))
fi
done
read -r PROFILE_CHOICE
case "$PROFILE_CHOICE" in
1) JFR_PROFILE="profile";;
2) JFR_PROFILE="default";;
[3-9]*)
INDEX=$((PROFILE_CHOICE - 3))
if [ ${INDEX} -ge 0 ] && [ ${INDEX} -lt ${#JFC_FILES[@]} ]; then
JFR_PROFILE="${JFC_FILES[$INDEX]}"
else
echo "Invalid choice. Using 'profile' as default."
JFR_PROFILE="profile"
fi
;;
*)
echo "Invalid choice. Using 'profile' as default."
JFR_PROFILE="profile"
;;
esac
}
# Prompt user for duration
read -p "Enter recording duration (e.g., 60s, 120s, 5m, 10m, 1h): " RECORDING_DURATION
RECORDING_DURATION=${RECORDING_DURATION:-5m}
# Convert duration to seconds (supports s, m, h)
if [[ $RECORDING_DURATION =~ ^([0-9]+)s$ ]]; then
DURATION_SECONDS="${BASH_REMATCH[1]}"
elif [[ $RECORDING_DURATION =~ ^([0-9]+)m$ ]]; then
DURATION_SECONDS=$(( ${BASH_REMATCH[1]} * 60 ))
elif [[ $RECORDING_DURATION =~ ^([0-9]+)h$ ]]; then
DURATION_SECONDS=$(( ${BASH_REMATCH[1]} * 3600 ))
else
echo "Invalid duration format. Please use 60s, 5m, or 1h."
exit 1
fi
# Prompt user for profile choice (now includes custom .jfc files)
choose_profile
# Prompt user for destination directory
read -p "Enter the directory to move the recording after completion (default: /home/robert_ssh): " TARGET_DIR
TARGET_DIR=${TARGET_DIR:-/home/robert_ssh}
# Prompt user for identifier
read -p "Enter an identifier for this recording (e.g., gc-analysis, high-load-test, default=run): " RECORDING_IDENTIFIER
RECORDING_IDENTIFIER=${RECORDING_IDENTIFIER:-run}
# Sanitize identifier (remove spaces/special characters)
SAFE_IDENTIFIER=$(echo "$RECORDING_IDENTIFIER" | tr -cd '[:alnum:]-_')
# Get the Java process ID
AEM_JAVA_PID=$(pgrep -f 'java' | head -n 1)
if [ -z "$AEM_JAVA_PID" ]; then
echo "$(date) - ERROR: No Java process found!" | tee -a "$LOG_FILE"
exit 1
fi
# Generate timestamp
TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
# Define the recording filename (including identifier)
RECORDING_FILE="/tmp/recording-${AEM_JAVA_PID}-${TIMESTAMP}-${SAFE_IDENTIFIER}.jfr"
# Check if JFR is already running
EXISTING_RECORDINGS=$(jcmd $AEM_JAVA_PID JFR.check | grep "recording=")
if [ -n "$EXISTING_RECORDINGS" ]; then
echo "$(date) - ERROR: A JFR recording is already running on PID $AEM_JAVA_PID!" | tee -a "$LOG_FILE"
exit 1
fi
echo "$(date) - INFO: Starting JFR recording for PID $AEM_JAVA_PID, Duration: $RECORDING_DURATION, Profile: $JFR_PROFILE, Identifier: $SAFE_IDENTIFIER" | tee -a "$LOG_FILE"
jcmd $AEM_JAVA_PID JFR.start duration=$RECORDING_DURATION settings=$JFR_PROFILE filename=$RECORDING_FILE
# Sleep for the correct duration
sleep $DURATION_SECONDS
if [ -f "$RECORDING_FILE" ]; then
sudo mv "$RECORDING_FILE" "$TARGET_DIR/"
sudo gzip "$TARGET_DIR/$(basename "$RECORDING_FILE")"
echo "$(date) - INFO: Recording moved to $TARGET_DIR/ and compressed" | tee -a "$LOG_FILE"
else
echo "$(date) - ERROR: Recording file not found!" | tee -a "$LOG_FILE"
exit 1
fi
<?xml version="1.0" encoding="UTF-8"?>
<configuration version="2.0">
<!-- Enable default events -->
<include>default</include>
<!-- CPU Profiling -->
<event name="jdk.ExecutionSample">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="stackDepth">1024</setting> <!-- Increase stack depth -->
</event>
<event name="jdk.NativeMethodSample">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
<setting name="stackDepth">1024</setting> <!-- Increase stack depth -->
</event>
<event name="jdk.CPULoad">
<setting name="enabled">true</setting>
</event>
<!-- Memory Profiling -->
<event name="jdk.ObjectAllocationInNewTLAB">
<setting name="enabled">true</setting>
</event>
<event name="jdk.ObjectAllocationOutsideTLAB">
<setting name="enabled">true</setting>
</event>
<event name="jdk.GCHeapSummary">
<setting name="enabled">true</setting>
</event>
<event name="jdk.GCPhasePause">
<setting name="enabled">true</setting>
</event>
<event name="jdk.GarbageCollection">
<setting name="enabled">true</setting>
</event>
<!-- Thread Profiling -->
<event name="jdk.JavaThreadStatistics">
<setting name="enabled">true</setting>
</event>
<event name="jdk.ThreadStart">
<setting name="enabled">true</setting>
</event>
<event name="jdk.ThreadEnd">
<setting name="enabled">true</setting>
</event>
<event name="jdk.ThreadPark">
<setting name="enabled">true</setting>
</event>
<event name="jdk.ThreadSleep">
<setting name="enabled">true</setting>
</event>
<!-- I/O Profiling -->
<event name="jdk.FileRead">
<setting name="enabled">true</setting>
</event>
<event name="jdk.FileWrite">
<setting name="enabled">true</setting>
</event>
<event name="jdk.SocketRead">
<setting name="enabled">true</setting>
</event>
<event name="jdk.SocketWrite">
<setting name="enabled">true</setting>
</event>
<!-- Blocking and Synchronization -->
<event name="jdk.JavaMonitorEnter">
<setting name="enabled">true</setting>
</event>
<event name="jdk.JavaMonitorWait">
<setting name="enabled">true</setting>
</event>
<event name="jdk.JavaMonitorWaited">
<setting name="enabled">true</setting>
</event>
<event name="jdk.SafepointBegin">
<setting name="enabled">true</setting>
</event>
<event name="jdk.SafepointEnd">
<setting name="enabled">true</setting>
</event>
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment