|
| 1 | +import os |
| 2 | +import pickle |
| 3 | + |
| 4 | +""" |
| 5 | +Ray Distributed Debugger VSCode Extension (Recommended) |
| 6 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 7 | +
|
| 8 | +1. Starting with Ray 2.39, Anyscale has introduced the `Ray Distributed Debugger <https://docs.ray.io/en/latest/ray-observability/ray-distributed-debugger.html>`_ VSCode extension. Follow the extension’s installation instructions, then add your cluster using the dashboard URL you obtained earlier. |
| 9 | +
|
| 10 | + .. image:: https://github.com/eric-haibin-lin/verl-community/blob/main/docs/ray/debugger.png?raw=true |
| 11 | + :alt: Ray Distributed Debugger VSCode extension screenshot |
| 12 | +
|
| 13 | +2. Prerequisites. |
| 14 | +
|
| 15 | + Ensure the following are installed (see the extension README for more detail): |
| 16 | +
|
| 17 | + - Visual Studio Code |
| 18 | + - `ray[default]` >= 2.9.1 |
| 19 | + - `debugpy` >= 1.8.0 |
| 20 | +
|
| 21 | + .. image:: https://github.com/aoshen524/verl/blob/main/docs/start/c7098b755ff689859837773a916c857.png?raw=true |
| 22 | + :alt: VSCode with Ray prerequisites |
| 23 | +
|
| 24 | +3. Environment Variables. |
| 25 | +
|
| 26 | + To enable post‑mortem debugging, set: |
| 27 | +
|
| 28 | + .. code-block:: bash |
| 29 | +
|
| 30 | + export RAY_DEBUG_POST_MORTEM=1 |
| 31 | +
|
| 32 | + .. admonition:: Note |
| 33 | + :class: important |
| 34 | +
|
| 35 | + Be sure to remove any legacy flags before starting Ray: |
| 36 | +
|
| 37 | + - `RAY_DEBUG=legacy` |
| 38 | + - `--ray-debugger-external` |
| 39 | +
|
| 40 | +4. Configuring BreakpointsSet up breakpoint() in your code, and submit job to cluster. Then the extension will show the breakpoint information. |
| 41 | +
|
| 42 | +
|
| 43 | + 1. Insert `breakpoint()` calls into your remote functions. |
| 44 | + 2. Submit your job to the cluster. |
| 45 | +
|
| 46 | + The extension will detect active breakpoints and display them in VSCode. |
| 47 | +
|
| 48 | + .. image:: https://github.com/aoshen524/verl/blob/main/docs/start/4ddad74395c79a1402331c0ce73316f.png?raw=true |
| 49 | + :alt: Detected breakpoint in VSCode |
| 50 | +
|
| 51 | + **Note:** Breakpoints are only supported inside functions decorated with `@ray.remote`. |
| 52 | +
|
| 53 | +5. Launching the Debugger. |
| 54 | +
|
| 55 | + Run your job directly from the command line (do not use a `launch.json`): |
| 56 | +
|
| 57 | + .. code-block:: bash |
| 58 | +
|
| 59 | + python job.py |
| 60 | +
|
| 61 | +6. Attaching to a Breakpoint. |
| 62 | +
|
| 63 | + Once the process hits the first `breakpoint()`, click the Ray Distributed Debugger icon in the VSCode sidebar to attach the debugger. |
| 64 | +
|
| 65 | + .. image:: https://github.com/aoshen524/verl/blob/main/docs/start/4ddad74395c79a1402331c0ce73316f.png?raw=true |
| 66 | + :alt: Attaching VSCode debugger to Ray process |
| 67 | +
|
| 68 | +7. Debugging With Multiple breakpoint(). |
| 69 | +
|
| 70 | + For each subsequent task, first disconnect the current debugger session, then click the extension icon again to attach to the next breakpoint. |
| 71 | +
|
| 72 | + .. image:: https://github.com/aoshen524/verl/blob/main/docs/start/6e83c910a62c82fecb89c6619e001cd.png?raw=true |
| 73 | + :alt: Disconnecting and reconnecting the debugger |
| 74 | +""" |
| 75 | + |
| 76 | +def vscode_conditional_breakpoint(tag=None, once=True): |
| 77 | + |
| 78 | + env_tag = f'HIT_BREAKPOINT_REC_{tag}' |
| 79 | + if not os.getenv('RAY_DEBUG_POST_MORTEM'): return |
| 80 | + if tag is None: |
| 81 | + if once: |
| 82 | + if os.getenv(env_tag, "") != "1": |
| 83 | + os.environ[env_tag] = "1" |
| 84 | + breakpoint() |
| 85 | + return |
| 86 | + else: |
| 87 | + breakpoint() |
| 88 | + return |
| 89 | + else: |
| 90 | + debug_tags = os.getenv('DEBUG_TAGS', '').split('|') |
| 91 | + if tag in debug_tags: |
| 92 | + if once: |
| 93 | + if os.getenv(env_tag, "") != "1": |
| 94 | + os.environ[env_tag] = "1" |
| 95 | + breakpoint() |
| 96 | + return |
| 97 | + else: |
| 98 | + breakpoint() |
| 99 | + return |
| 100 | + |
| 101 | + |
| 102 | +def objdump(obj, file="objdump.tmp"): |
| 103 | + with open(file, "wb+") as f: |
| 104 | + pickle.dump(obj, f) |
| 105 | + return |
| 106 | + |
| 107 | + |
| 108 | +def objload(file="objdump.tmp"): |
| 109 | + import os |
| 110 | + if not os.path.exists(file): |
| 111 | + return |
| 112 | + with open(file, "rb") as f: |
| 113 | + return pickle.load(f) |
0 commit comments