summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2021-08-30 09:43:11 +0200
committerGitHub <noreply@github.com>2021-08-30 09:43:11 +0200
commit64486991f53145248a8140e49f3275efc75736b5 (patch)
treeb9b9d4fbe81980a60944924d063d4db50a620797
parentc3131b0641776e410a51f4d42d8b7a2faa3f82bf (diff)
parenta221c1931fbe50164b91d61068458778f27c68a2 (diff)
Merge pull request #18885 from vespa-engine/bjorncs/jvm-heap-dump
Add helper script to generate JVM heap dump
-rw-r--r--container-core/CMakeLists.txt1
-rwxr-xr-xcontainer-core/src/main/sh/vespa-jvm-dumper133
-rw-r--r--dist/vespa.spec1
3 files changed, 135 insertions, 0 deletions
diff --git a/container-core/CMakeLists.txt b/container-core/CMakeLists.txt
index 433e3c799b5..75ec63674c4 100644
--- a/container-core/CMakeLists.txt
+++ b/container-core/CMakeLists.txt
@@ -3,3 +3,4 @@ install_config_definitions()
install_java_artifact_dependencies(container-core)
vespa_install_script(src/main/sh/vespa-load-balancer-status libexec/vespa)
+vespa_install_script(src/main/sh/vespa-jvm-dumper bin)
diff --git a/container-core/src/main/sh/vespa-jvm-dumper b/container-core/src/main/sh/vespa-jvm-dumper
new file mode 100755
index 00000000000..4710c9c9d9f
--- /dev/null
+++ b/container-core/src/main/sh/vespa-jvm-dumper
@@ -0,0 +1,133 @@
+#!/usr/bin/env bash
+# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+# BEGIN environment bootstrap section
+# Do not edit between here and END as this section should stay identical in all scripts
+
+findpath () {
+ myname=${0}
+ mypath=${myname%/*}
+ myname=${myname##*/}
+ empty_if_start_slash=${mypath%%/*}
+ if [ "${empty_if_start_slash}" ]; then
+ mypath=$(pwd)/${mypath}
+ fi
+ if [ "$mypath" ] && [ -d "$mypath" ]; then
+ return
+ fi
+ mypath=$(pwd)
+ if [ -f "${mypath}/${myname}" ]; then
+ return
+ fi
+ echo "FATAL: Could not figure out the path where $myname lives from $0"
+ exit 1
+}
+
+COMMON_ENV=libexec/vespa/common-env.sh
+
+source_common_env () {
+ if [ "$VESPA_HOME" ] && [ -d "$VESPA_HOME" ]; then
+ export VESPA_HOME
+ common_env=$VESPA_HOME/$COMMON_ENV
+ if [ -f "$common_env" ]; then
+ . $common_env
+ return
+ fi
+ fi
+ return 1
+}
+
+findroot () {
+ source_common_env && return
+ if [ "$VESPA_HOME" ]; then
+ echo "FATAL: bad VESPA_HOME value '$VESPA_HOME'"
+ exit 1
+ fi
+ if [ "$ROOT" ] && [ -d "$ROOT" ]; then
+ VESPA_HOME="$ROOT"
+ source_common_env && return
+ fi
+ findpath
+ while [ "$mypath" ]; do
+ VESPA_HOME=${mypath}
+ source_common_env && return
+ mypath=${mypath%/*}
+ done
+ echo "FATAL: missing VESPA_HOME environment variable"
+ echo "Could not locate $COMMON_ENV anywhere"
+ exit 1
+}
+
+findhost () {
+ if [ "${VESPA_HOSTNAME}" = "" ]; then
+ VESPA_HOSTNAME=$(vespa-detect-hostname || hostname -f || hostname || echo "localhost") || exit 1
+ fi
+ validate="${VESPA_HOME}/bin/vespa-validate-hostname"
+ if [ -f "$validate" ]; then
+ "$validate" "${VESPA_HOSTNAME}" || exit 1
+ fi
+ export VESPA_HOSTNAME
+}
+
+findroot
+findhost
+
+# END environment bootstrap section
+
+set -euo pipefail
+
+if [ $# -ne 2 ]; then
+ echo "Usage: $0 <id> <output-directory>"
+ echo ""
+ vespa-sentinel-cmd list 2>/dev/null
+ exit 1
+fi
+
+readonly SERVICE=$1
+readonly OUTPUT_DIRECTORY=$2
+if ! [ -d "${OUTPUT_DIRECTORY}" -a -w "${OUTPUT_DIRECTORY}" ]; then
+ echo "Directory '${OUTPUT_DIRECTORY}' is not writable"
+ exit 1
+fi
+readonly STATUS=$(vespa-sentinel-cmd list | grep "id=\"${SERVICE}\"")
+if [ -z "${STATUS}" ]; then
+ echo "No service named '${SERVICE}'"
+ exit 1
+else
+ echo "Found service: ${STATUS}"
+fi
+readonly JVM_PID=$(echo ${STATUS} | cut -d " " -f 4 | cut -d "=" -f 2)
+if ! [[ "${JVM_PID}" =~ ^[0-9]+$ ]]; then
+ echo "Could not find valid pid for '${SERVICE}' (pid='${JVM_PID}')"
+ exit 1
+else
+ echo "Pid for '${SERVICE}' is '${JVM_PID}'"
+fi
+if ! [ -n $(ps -p ${JVM_PID} -o pid=) ]; then
+ echo "Could not find process for '${JVM_PID}'"
+ exit 1
+fi
+
+echo "Creating heap dump"
+readonly HEAP_DUMP_FILE=${OUTPUT_DIRECTORY}/heapdump.bin
+if test -f "${HEAP_DUMP_FILE}"; then
+ rm "${HEAP_DUMP_FILE}"
+fi
+jmap -dump:live,format=b,file=${HEAP_DUMP_FILE} ${JVM_PID}
+
+echo "Getting jmap information"
+jhsdb jmap --heap --pid ${JVM_PID} > ${OUTPUT_DIRECTORY}/jmap-output
+
+echo "Getting jstat information"
+jstat -gcutil ${JVM_PID} > ${OUTPUT_DIRECTORY}/jstat-output
+
+echo "Getting jstack information"
+jstack ${JVM_PID} > ${OUTPUT_DIRECTORY}/jstack-output
+
+echo "Getting pmap information"
+pmap -x ${JVM_PID} | sort -nk3 | tail -10 > ${OUTPUT_DIRECTORY}/pmap-output
+
+echo "Copying vespa logs"
+cp ${VESPA_HOME}/logs/vespa/vespa.log ${OUTPUT_DIRECTORY}/vespa.log
+
+echo "Done!"
diff --git a/dist/vespa.spec b/dist/vespa.spec
index 6bd5fc5c96e..3df5c3744d3 100644
--- a/dist/vespa.spec
+++ b/dist/vespa.spec
@@ -686,6 +686,7 @@ fi
%endif
%dir %{_prefix}
%dir %{_prefix}/bin
+%{_prefix}/bin/vespa-jvm-dumper
%{_prefix}/bin/vespa-logfmt
%{_prefix}/bin/vespa-security-env
%dir %{_prefix}/conf