How to debug a aws lambda function?
I think there is some misconception, pardon for switching from node.js context to python (the title is not specific to node so many folks will end up here anyway).
You CAN debug actual deployed AWS lambdas line-by-line. The approach involves running a debug server pydevd on the development machine and lambdas communicating with a debug-server over long-running TCP connection.
Is it supported by various IDEs, we use is with PyCharm Pro, so setup for it (hypothetically you should be able to setup VSCode similarly):
Debug configuration with Path mapping: right-top corner run/debug configuration dropdown -> Edit Configurations -> + (add new configuration) -> Python remote debug -> specify host name / port for your dev machine (which needs globally exposed: setup path forwarding on your router or use ngrok if previous option is not available). Make sure to setup path mappings, that is how your IDE can map the remote scripts to local sources.
pip install pydevd
. (For pycharm, you will need to install IDE-version specific custom distribution like:pip install pydevd-pycharm~=193.5233.109
)Add the
RemoteDebugSession
context manager abstraction(since debug session is over long-running tcp connection, its needs to be closed explicitly in your lambda otherwise lambda will timeout) like:
# from config import config
from logging import getLogger
logger = getLogger(__name__)
class RemoteDebugSession:
def __init__(self):
self.active = False
if not self.is_available():
logger.warning(f"Remote debugging is not available")
return
try:
# pydevd_pycharm exposes only settrace() from pydevd, import pydevd directly instead
# import pydevd_pycharm
import pydevd
self.pydevd = pydevd
except Exception as e:
logger.warning(f"Remote debugging is unavailable")
logger.warning(e)
self.pydevd = None
def __enter__(self):
if not self.is_available() or self.pydevd is None:
return
self.pydevd.settrace(config.REMOTE_DEBUG_HOST, port=config.REMOTE_DEBUG_PORT,
suspend=False,
stdoutToServer=True,
stderrToServer=True)
logger.warning("Starting remote dubugging session")
self.active = True
def __exit__(self, exc_type, exc_val, exc_tb):
if not self.active:
return
if exc_type or exc_val or exc_tb:
logger.warning(
f"Remote debugging on {config.REMOTE_DEBUG_HOST}:{config.REMOTE_DEBUG_HOST} failed")
logger.warning(exc_type)
logger.warning(exc_val)
logger.warning(exc_tb)
else:
logger.warning(f"Remote debugging on {config.REMOTE_DEBUG_HOST}:{config.REMOTE_DEBUG_HOST} closed")
self.pydevd.stoptrace()
@staticmethod
def is_available():
return hasattr(config, 'REMOTE_DEBUG_ENABLED') \
and hasattr(config, 'REMOTE_DEBUG_HOST') \
and hasattr(config, 'REMOTE_DEBUG_PORT') \
and config.REMOTE_DEBUG_ENABLED \
and config.REMOTE_DEBUG_HOST \
and config.REMOTE_DEBUG_PORT
You need to have config object with REMOTE_DEBUG_ENABLED, REMOTE_DEBUG_HOST, REMOTE_DEBUG_PORT set.
(pydevd.settrace is used with suspend=False
so the executing won't stop unless we set a breakpoint)
- Wrap your feature of interest with it like:
with RemoteDebugSession() as session:
# your code to examine
pass
In practice, when building web servers, this can be inside an individual API handler, which will allow you to debug multiple simultaneous incoming requests as other lambdas will block on connection.
Please REFRAIN from using this in production. Apart from security risk, remote evaluation can allow you to do all sort of nasty things.
Lambda local can be used to test the lambda code in local machine.