Application Debugging
Connect to the JVM of a Self Managed Commerce Application
This section outlines how to connect to a Self Managed Commerce application JVM in a Kubernetes deployment. It is intended for developers who are familiar with Java and the Elastic Path application stack. By default the JMX, and JVM (Java Virtual Machine) debug ports are not made accessible via endpoints for security reasons.
Using JMX Console
Procedure
To connect to a JMX port for a deployed Self Managed Commerce application with JConsole or JVisualVM:
Set the parameter
enableJmx
in the Jenkins jobdeploy-or-delete-commerce-stack
.(Optional) Enable JMX user and password authentication by setting the parameter
enableJmxAuth
.Deploy a Self Managed Commerce stack using the job
deploy-or-delete-commerce-stack
.(Optional) Find the JMX username and password, if JMX user and password authentication is enabled.
The username and password are auto-generated and uploaded to a Kubernetes ConfigMap under the keys
JMX_USER
andJMX_PASSWORD
.To access the ConfigMap, access the Kubernetes dashboard of the same Kubernetes cluster as the Self Managed Commerce deployment. Switch to the same namespace as the deployment and open the ConfigMap named
ep-configmap
.Forward the JMX port of the applications in the cluster to your local computer.
See the following command as an example. Replace
${NAMESPACE}
andapp=ep-cm
with the values for your application.cmPodName=$(kubectl get pods -n ${NAMESPACE} -l 'app=ep-cm' -o jsonpath='{.items[*].metadata.name}') kubectl port-forward pod/${cmPodName} -n ${NAMESPACE} 8888:8888
If authentication is disabled, you can open the JMX connection directly from the terminal.
Run the following command to run JConsole:
jconsole localhost:8888
Run the following command to run JVisualVM, if required:
jvisualvm --openjmx 127.0.0.1:8888
If authentication is enabled, run the Java profiler of choice and connect manually using the UI providing the correct username and password from step 4.
note
Disable JMX connections on production environments to avoid performance issues.
Using remote debugger
To connect to the JVM of a Self Managed Commerce application in debug mode from your IDE:
Enable the parameter
enableDebug
in the Jenkins jobdeploy-or-delete-commerce-stack
Deploy a Self Managed Commerce stack using the job
deploy-or-delete-commerce-stack
Forward the debug port of the application in the cluster to your local computer.
See the following command as an example. Replace
${NAMESPACE}
andapp=ep-cm
with the values for your application.cmPodName=$(kubectl get pods -n ${NAMESPACE} -l 'app=ep-cm' -o jsonpath='{.items[*].metadata.name}') kubectl port-forward pod/$cmPodName -n ${NAMESPACE} 1081:1081
Configure the remote debugger in your IDE to connect to
localhost:1081
.note
You can expose both the JMX and debug ports in one step by port forwarding with both ports appended to the command. See the following command as an example:
cmPodName=$(kubectl get pods -n ${NAMESPACE} -l 'app=ep-cm' -o jsonpath='{.items[*].metadata.name}') kubectl port-forward pod/$cmPodName -n ${NAMESPACE} 8888:8888 1081:1081
Getting the Heap Dump of a Self Managed Commerce Application
The heap dump files are stored on a persistent volume in the Kubernetes cluster, and the volume is mounted on all of the Self Managed Commerce containers. When a heap dump is triggered by the Java virtual machine (JVM), the heap dump is saved in the pod under a path like /hdump/<commerce_service_container_name>/java_pid<pid>.hprof
.
Overview of copying heap dump files
Use kubectl
to connect to a container and copy the file to your local computer. If you know the correct file to copy, use the kubectl cp
command to copy it from a running container. We recommend to compress the large files.
All Self Managed Commerce containers now share a single Elastic File System (EFS) volume mount. With this enhancement, all heap dumps are available on any Self Managed Commerce container that you can connect to through kubectl
. For example, you can get the heap dump files generated by the Elastic Path batch service container from the Elastic Path integration container.
The volume structure is as follows:
/hdump/
CORTEX
java_pid12.hprof
BATCH
java_pid23.hprof
SEARCH
java_pid34.hprof
Setting up the environment variables
Set the environment variable for the Kubernetes namespace that Self Managed Commerce is deployed into from the kubernetesNickName parameter used in the Jenkins job.
The
kubernetesNickNameValue
is the Kubernetes namespace in which the Self Managed Commerce stack is deployed. This will be the value of the Jenkins parameterkubernetesNickname
, from the Jenkins jobdeploy-or-delete-commerce-stack
, that is used when deploying the Self Managed Commerce stack.See the following as an example:
commerce_namespace="kubernetesNickNameValue"
Confirm the service and container names for the Self Managed Commerce service that you would like to get a heap dump from.
Use these to find the right heap dump file in the next steps. If you know the service and container names already, you can skip to the next step. If you are not certain, see the following command as an example:
```bash
epApps=$(kubectl get deploy -n ${commerce_namespace} -o json | jq -r '.items[].metadata | select(.labels.app | startswith("ep-")) | select (.labels.app != "ep-activemq") | .name')
echo "${epApps[@]}" | cut -c4- | rev | cut -c12- | rev
```
Take note of the exact names of the service.
Set the environment variable for the service and container names. The
commerce_service_container_name
variable is the uppercase version of thecommerce_service
that you have set.See the following as an example:
commerce_service="cortex" commerce_service_container_name="CORTEX"
Set the environment variable for the Self Managed Commerce service that you would like to get a heap dump from.
See the following as an example:
service_pod_name=$(kubectl get pods -n ${commerce_namespace} -l "app=ep-${commerce_service}" -o jsonpath="{.items[0].metadata.name}")
Obtaining the heap dump file
Run exec into the container.
See the following as an example:
kubectl exec -it ${service_pod_name} -n ${commerce_namespace} /bin/bash
Zip the contents of the existing heap dump file and exit the container.
See the following as an example:
cd /hdump/${commerce_service_container_name} gzip java_pid<pid>.hprof ls /hdump/${commerce_service_container_name} exit
Copy the zip file.
See the following as an example:
kubectl cp -n ${commerce_namespace} ${service_pod_name}:/hdump/${commerce_service_container_name}/java_pid<pid>.hprof.gz java_pid<pid>.hprof.gz
Identifying the heap dump file (Optional)
Check the status of the Commerce kubernetes service pod.
See the following as an example:
kubectl describe pod ${service_pod_name} -n ${commerce_namespace}
Check whether the container is restarted due to a memory issue.
Last State: Terminated
is displayed in the output, andReason: OOMKilled
is displayed in the container description. It may not be possible to know the correct process ID if the container does not exist or a new Java process is started.See the following as an example:
Containers: cortex: ... State: Running Started: Thu, 10 Oct 2021 11:14:13 +0200 Last State: Terminated Reason: OOMKilled Exit Code: 137 Started: Thu, 10 Oct 2021 11:04:03 +0200 Finished: Thu, 10 Oct 2021 11:14:11 +0200
Run exec into the container.
See the following as an example:
kubectl exec -it ${service_pod_name} -n ${commerce_namespace} /bin/bash
Get the process ID of java on the container.
See the following as an example:
jps -v
If the container does not exist or a new process is started, you can obtain the path to the heap dump file from the log aggregation tool that you have installed. Log aggregation tools are not provided in CloudOps for Kubernetes.
The following example log shows you the path of the heap dump:
Heap dump file created [70236796 bytes in 0.611 secs] Dumping heap to /hdump/CM/java_pid64.hprof ... java.lang.OutOfMemoryError: Java heap space
If you cannot identify the heap dump file from the existing Java process, or from your log aggregation tool, you can guess the heap dump file based on the timestamp that is created.