Last active
January 22, 2025 19:05
-
-
Save rwunsch/261c39503efc7ea6ae4f57484a043500 to your computer and use it in GitHub Desktop.
Java Flight Recorder - execution script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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