{"id":19793602,"url":"https://github.com/darky/the-most-convenient-debug","last_synced_at":"2026-03-19T11:45:24.948Z","repository":{"id":150092697,"uuid":"467557356","full_name":"darky/the-most-convenient-debug","owner":"darky","description":"The most convenient way to debug applications","archived":false,"fork":false,"pushed_at":"2022-03-18T16:15:11.000Z","size":27,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-13T14:57:04.061Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darky.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-03-08T14:58:30.000Z","updated_at":"2022-05-17T10:04:24.000Z","dependencies_parsed_at":"2023-06-05T07:45:22.011Z","dependency_job_id":null,"html_url":"https://github.com/darky/the-most-convenient-debug","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/darky/the-most-convenient-debug","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darky%2Fthe-most-convenient-debug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darky%2Fthe-most-convenient-debug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darky%2Fthe-most-convenient-debug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darky%2Fthe-most-convenient-debug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darky","download_url":"https://codeload.github.com/darky/the-most-convenient-debug/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darky%2Fthe-most-convenient-debug/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266516307,"owners_count":23941393,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T07:10:30.981Z","updated_at":"2026-02-07T18:03:21.346Z","avatar_url":"https://github.com/darky.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# The most convenient way to debug applications\n\n![ezgif com-gif-maker](https://user-images.githubusercontent.com/1832800/159041027-ed8c5888-9edf-4e5d-b0a4-2283a94ca094.gif)\n\n\nIn this article, I will show you an interesting way to debug applications. This is somewhat different from the usual methods that you use in your daily work.\n\n## How do we debug today\n\n* 🖨️ Print to stdout\n* ▶️ Step-by-step debugger in IDE\n* 🔙 Maybe even time-travel debugger\n* 📜 Viewing logs\n\n## Disadvantages of current debug techniqes\n\n#### 🖨️ Print to stdout\n\n* 🐌 Slower debug performance\n* ↔️ Context switch between your code and stdout\n* 🔁 Often need to rerun your program again and again\n\n#### ▶️ Step-by-step debugger in IDE\n\n* 🐌 Slower debug performance\n* 🔁 Often need to rerun your program again and again\n\n#### 🔙 Time-travel debugger\n\n* 🏋️ Often very hard to implement\n* 💲 Often not free\n\n#### 📜 Viewing logs\n\n* 🐌 Slower debug performance\n* ↔️ Context switch between your code and logs\n\n## Another way to debug - Smart Logs\n\n![image](https://user-images.githubusercontent.com/1832800/157913106-dbf1c6b5-0774-424b-9f58-0c8cf63a7e34.png)\n\nAs you see on the screenshot, **Smart Logs** attached to functions and trace call of every function: parameters, response, possible error and so on. Pros:\n\n* 🚀 Faster debug performance\n* 🤝 No context switch between your code and logs\n* 😊 No need to run the program again and again\n\n## Implementation example\n\nFurther we will see an implementation example. **It's based on JavaScript/TypeScript and Node.js runtime**, but it can be implemented on lot programming languages and runtimes. **VSCode used as IDE**, but other IDE should be suitable too for this purpose.\n\n#### Requirements\n\n* 🔎 Ability to reflect function location in code (https://github.com/midrissi/func-loc)\n* 🗒️ Line note ability in IDE (https://marketplace.visualstudio.com/items?itemName=tkrkt.linenote)\n\n#### Code\n\n```javascript\nimport { locate } from 'func-loc';\nimport { appendFile, mkdir } from 'fs/promises';\nimport endent from 'endent';\n\nconst ln = fn =\u003e {\n  return function (...params) {\n    const resp = fn.apply(this, params);\n\n    Promise.allSettled([locate(fn), resp]).then(async ([loc, respOrErr]) =\u003e {\n      await mkdir(`${process.cwd()}/.vscode/linenote`, { recursive: true });\n      await appendFile(\n        loc.value.path.replace(process.cwd(), `${process.cwd()}/.vscode/linenote`) + `#L${loc.value.line}.md`,\n        endent.default`\n          params: ${params},\n          ${respOrErr.value ? `response: ${respOrErr.value}` : `error: ${respOrErr.reason}`}\n          \\\\n\\\\n\n        `\n      );\n    });\n\n    return resp;\n  };\n};\n```\n\n* `ln` (alias to line note) is wrapper of target function `fn`\n* `ln` intercepts parameters and response of `fn` or possible error inside `fn`\n* `ln` reflects `fn` location in code\n* using `fn` code location, `ln` create/append **Line Note** file on proper line with paramaters and response of `fn` in content\n\n## By the way\n\n* In code above ☝️ parameters and response interpolated to string \"as is\". On real production code you deal with complex JSON structures, which should be properly serialized\n* You can add your own additional info: duration, timestamp and so on\n* You can write TypeScript class decorator, which wrap all class methods for **Smart Logs** support\n* On example used FILO via `appendFile`, but with https://github.com/hemanth/node-prepend-file you can change to FIFO\n* You may get `EBUSY` error via concurrent access to same **Line Note** file. This sutation can be fixed via repeat strategy, using something like https://github.com/sindresorhus/p-retry\n* You can write custom import to **Smart Logs**. For example: ELK logs -\u003e **Smart Logs**\n\n\n## What about compiled to JavaScript languages like TypeScript?\n\n**func-loc** supports source maps https://github.com/midrissi/func-loc#using-source-maps\n\n## What about frontend?\n\n**func-loc** uses Node.js inspector underhood https://nodejs.org/dist/latest-v17.x/docs/api/inspector.html\n\nBut despite this, I think you can use **Smart Logs** with frontend using Electron, which support Node.js API and Browser API simuateniously https://www.electronjs.org/\n\n## What if my programming language / runtime can't reflect function location dynamically?\n\nMaybe it can reflect function location statically via compiler/transpiler/macro and so on.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarky%2Fthe-most-convenient-debug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarky%2Fthe-most-convenient-debug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarky%2Fthe-most-convenient-debug/lists"}