https://github.com/award999 created 
https://github.com/llvm/llvm-project/pull/146884

- Add `winston` dependency (MIT license) to handle logging setup
- Have an `OutputChannel` to log user facing information, errors, warnings
- Write a verose log under the provided `logUri` to capture further diagnostics
- Introduce `verboseLogging` setting to increase `OutputChannel` verbosity and 
write DAP session logs

Issue: #146880

>From 87be6e74be1348e4cd162cec6e58a2370a11cafd Mon Sep 17 00:00:00 2001
From: Adam Ward <award...@apple.com>
Date: Thu, 3 Jul 2025 09:13:41 -0400
Subject: [PATCH] Logging setup for lldb-dap extension

- Add `winston` dependency (MIT license) to handle logging setup
- Have an `OutputChannel` to log user facing information, errors, warnings
- Write a verose log under the provided `logUri` to capture further diagnostics
- Introduce `verboseLogging` setting to increase `OutputChannel` verbosity and 
write DAP session logs

Issue: #146880
---
 lldb/tools/lldb-dap/package-lock.json         | 242 +++++++++++++++++-
 lldb/tools/lldb-dap/package.json              |   9 +-
 .../lldb-dap/src-ts/debug-adapter-factory.ts  |  37 ++-
 .../src-ts/debug-configuration-provider.ts    |  11 +-
 .../lldb-dap/src-ts/debug-session-tracker.ts  |  13 +-
 lldb/tools/lldb-dap/src-ts/extension.ts       |  21 +-
 lldb/tools/lldb-dap/src-ts/logger.ts          |  88 +++++++
 7 files changed, 404 insertions(+), 17 deletions(-)
 create mode 100644 lldb/tools/lldb-dap/src-ts/logger.ts

diff --git a/lldb/tools/lldb-dap/package-lock.json 
b/lldb/tools/lldb-dap/package-lock.json
index af90a9573aee6..f9f071ae7e41a 100644
--- a/lldb/tools/lldb-dap/package-lock.json
+++ b/lldb/tools/lldb-dap/package-lock.json
@@ -15,7 +15,9 @@
         "@vscode/vsce": "^3.2.2",
         "prettier": "^3.4.2",
         "prettier-plugin-curly": "^0.3.1",
-        "typescript": "^5.7.3"
+        "typescript": "^5.7.3",
+        "winston": "^3.17.0",
+        "winston-transport": "^4.9.0"
       },
       "engines": {
         "vscode": "^1.75.0"
@@ -318,6 +320,28 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/@colors/colors": {
+      "version": "1.6.0",
+      "resolved": 
"https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz";,
+      "integrity": 
"sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.1.90"
+      }
+    },
+    "node_modules/@dabh/diagnostics": {
+      "version": "2.0.3",
+      "resolved": 
"https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz";,
+      "integrity": 
"sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "colorspace": "1.1.x",
+        "enabled": "2.0.x",
+        "kuler": "^2.0.0"
+      }
+    },
     "node_modules/@isaacs/cliui": {
       "version": "8.0.2",
       "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz";,
@@ -399,6 +423,13 @@
         "undici-types": "~5.26.4"
       }
     },
+    "node_modules/@types/triple-beam": {
+      "version": "1.3.5",
+      "resolved": 
"https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz";,
+      "integrity": 
"sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/@types/vscode": {
       "version": "1.75.0",
       "resolved": 
"https://registry.npmjs.org/@types/vscode/-/vscode-1.75.0.tgz";,
@@ -642,6 +673,13 @@
       "dev": true,
       "license": "Python-2.0"
     },
+    "node_modules/async": {
+      "version": "3.2.6",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz";,
+      "integrity": 
"sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz";,
@@ -858,6 +896,17 @@
         "node": ">=16"
       }
     },
+    "node_modules/color": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz";,
+      "integrity": 
"sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^1.9.3",
+        "color-string": "^1.6.0"
+      }
+    },
     "node_modules/color-convert": {
       "version": "1.9.3",
       "resolved": 
"https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz";,
@@ -873,6 +922,28 @@
       "integrity": 
"sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
       "dev": true
     },
+    "node_modules/color-string": {
+      "version": "1.9.1",
+      "resolved": 
"https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz";,
+      "integrity": 
"sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "^1.0.0",
+        "simple-swizzle": "^0.2.2"
+      }
+    },
+    "node_modules/colorspace": {
+      "version": "1.1.4",
+      "resolved": 
"https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz";,
+      "integrity": 
"sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color": "^3.1.3",
+        "text-hex": "1.0.x"
+      }
+    },
     "node_modules/combined-stream": {
       "version": "1.0.8",
       "resolved": 
"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz";,
@@ -1114,6 +1185,13 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/enabled": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz";,
+      "integrity": 
"sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/end-of-stream": {
       "version": "1.4.4",
       "resolved": 
"https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz";,
@@ -1207,6 +1285,20 @@
         "pend": "~1.2.0"
       }
     },
+    "node_modules/fecha": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz";,
+      "integrity": 
"sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fn.name": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz";,
+      "integrity": 
"sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/foreground-child": {
       "version": "3.3.0",
       "resolved": 
"https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz";,
@@ -1494,8 +1586,7 @@
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz";,
       "integrity": 
"sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "node_modules/ini": {
       "version": "1.3.8",
@@ -1504,6 +1595,13 @@
       "dev": true,
       "optional": true
     },
+    "node_modules/is-arrayish": {
+      "version": "0.3.2",
+      "resolved": 
"https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz";,
+      "integrity": 
"sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/is-docker": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz";,
@@ -1530,6 +1628,19 @@
         "node": ">=8"
       }
     },
+    "node_modules/is-stream": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz";,
+      "integrity": 
"sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus";
+      }
+    },
     "node_modules/is-wsl": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz";,
@@ -1673,6 +1784,13 @@
         "prebuild-install": "^7.0.1"
       }
     },
+    "node_modules/kuler": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz";,
+      "integrity": 
"sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/leven": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz";,
@@ -1741,6 +1859,24 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/logform": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz";,
+      "integrity": 
"sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@colors/colors": "1.6.0",
+        "@types/triple-beam": "^1.3.2",
+        "fecha": "^4.2.0",
+        "ms": "^2.1.1",
+        "safe-stable-stringify": "^2.3.1",
+        "triple-beam": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 12.0.0"
+      }
+    },
     "node_modules/lru-cache": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz";,
@@ -1951,6 +2087,16 @@
         "wrappy": "1"
       }
     },
+    "node_modules/one-time": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz";,
+      "integrity": 
"sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "fn.name": "1.x.x"
+      }
+    },
     "node_modules/open": {
       "version": "8.4.2",
       "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz";,
@@ -2200,7 +2346,6 @@
       "resolved": 
"https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz";,
       "integrity": 
"sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
       "dev": true,
-      "optional": true,
       "dependencies": {
         "inherits": "^2.0.3",
         "string_decoder": "^1.1.1",
@@ -2230,6 +2375,16 @@
         }
       ]
     },
+    "node_modules/safe-stable-stringify": {
+      "version": "2.5.0",
+      "resolved": 
"https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz";,
+      "integrity": 
"sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/sax": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz";,
@@ -2410,6 +2565,26 @@
         "simple-concat": "^1.0.0"
       }
     },
+    "node_modules/simple-swizzle": {
+      "version": "0.2.2",
+      "resolved": 
"https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz";,
+      "integrity": 
"sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "is-arrayish": "^0.3.1"
+      }
+    },
+    "node_modules/stack-trace": {
+      "version": "0.0.10",
+      "resolved": 
"https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz";,
+      "integrity": 
"sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/stoppable": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz";,
@@ -2426,7 +2601,6 @@
       "resolved": 
"https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz";,
       "integrity": 
"sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
       "dev": true,
-      "optional": true,
       "dependencies": {
         "safe-buffer": "~5.2.0"
       }
@@ -2587,6 +2761,13 @@
         "node": ">=6"
       }
     },
+    "node_modules/text-hex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz";,
+      "integrity": 
"sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/tmp": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz";,
@@ -2597,6 +2778,16 @@
         "node": ">=14.14"
       }
     },
+    "node_modules/triple-beam": {
+      "version": "1.4.1",
+      "resolved": 
"https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz";,
+      "integrity": 
"sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
     "node_modules/tslib": {
       "version": "2.8.1",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz";,
@@ -2683,8 +2874,7 @@
       "version": "1.0.2",
       "resolved": 
"https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz";,
       "integrity": 
"sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "node_modules/uuid": {
       "version": "8.3.2",
@@ -2712,6 +2902,44 @@
         "node": ">= 8"
       }
     },
+    "node_modules/winston": {
+      "version": "3.17.0",
+      "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz";,
+      "integrity": 
"sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@colors/colors": "^1.6.0",
+        "@dabh/diagnostics": "^2.0.2",
+        "async": "^3.2.3",
+        "is-stream": "^2.0.0",
+        "logform": "^2.7.0",
+        "one-time": "^1.0.0",
+        "readable-stream": "^3.4.0",
+        "safe-stable-stringify": "^2.3.1",
+        "stack-trace": "0.0.x",
+        "triple-beam": "^1.3.0",
+        "winston-transport": "^4.9.0"
+      },
+      "engines": {
+        "node": ">= 12.0.0"
+      }
+    },
+    "node_modules/winston-transport": {
+      "version": "4.9.0",
+      "resolved": 
"https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz";,
+      "integrity": 
"sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "logform": "^2.7.0",
+        "readable-stream": "^3.6.2",
+        "triple-beam": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 12.0.0"
+      }
+    },
     "node_modules/wrap-ansi": {
       "version": "8.1.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz";,
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index b150dee792c34..9e1439d1f797f 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -34,7 +34,9 @@
     "@vscode/vsce": "^3.2.2",
     "prettier": "^3.4.2",
     "prettier-plugin-curly": "^0.3.1",
-    "typescript": "^5.7.3"
+    "typescript": "^5.7.3",
+    "winston": "^3.17.0",
+    "winston-transport": "^4.9.0"
   },
   "activationEvents": [
     "onDebug",
@@ -110,6 +112,11 @@
             "additionalProperties": {
               "type": "string"
             }
+          },
+          "lldb-dap.verboseLogging": {
+            "type": "boolean",
+            "description": "Enable verbose logging to the \"LLDB-DAP\" output 
channel for the running debug session. Also will write LLDB-DAP session logs to 
the Extension's log folder if the `lldb-dap.log-path` setting is not explicitly 
set.",
+            "default": false
           }
         }
       },
diff --git a/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts 
b/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
index b5db45b56d6a6..81460da8a2323 100644
--- a/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
+++ b/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
@@ -5,6 +5,7 @@ import * as child_process from "child_process";
 import * as fs from "node:fs/promises";
 import { ConfigureButton, OpenSettingsButton } from "./ui/show-error-message";
 import { ErrorWithNotification } from "./ui/error-with-notification";
+import { Logger } from "./logger";
 
 const exec = util.promisify(child_process.execFile);
 
@@ -156,16 +157,34 @@ async function getDAPArguments(
     .get<string[]>("arguments", []);
 }
 
+/**
+ * Formats the given date as a string in the form "YYYYMMdd".
+ *
+ * @param date The date to format as a string.
+ * @returns The formatted date.
+ */
+function formatDate(date: Date): string {
+    const year = date.getFullYear().toString().padStart(4, "0");
+    const month = (date.getMonth() + 1).toString().padStart(2, "0");
+    const day = date.getDate().toString().padStart(2, "0");
+    const hour = date.getHours().toString().padStart(2, "0");
+    const minute = date.getMinutes().toString().padStart(2, "0");
+    const seconds = date.getSeconds().toString().padStart(2, "0");
+    return year + month + day + hour + minute + seconds;
+}
+
 /**
  * Creates a new {@link vscode.DebugAdapterExecutable} based on the provided 
workspace folder and
  * debug configuration. Assumes that the given debug configuration is for a 
local launch of lldb-dap.
  *
+ * @param logger The {@link Logger} to get default session log location
  * @param workspaceFolder The {@link vscode.WorkspaceFolder} that the debug 
session will be launched within
  * @param configuration The {@link vscode.DebugConfiguration} that will be 
launched
  * @throws An {@link ErrorWithNotification} if something went wrong
  * @returns The {@link vscode.DebugAdapterExecutable} that can be used to 
launch lldb-dap
  */
 export async function createDebugAdapterExecutable(
+  logger: Logger,
   workspaceFolder: vscode.WorkspaceFolder | undefined,
   configuration: vscode.DebugConfiguration,
 ): Promise<vscode.DebugAdapterExecutable> {
@@ -174,6 +193,8 @@ export async function createDebugAdapterExecutable(
   let env: { [key: string]: string } = {};
   if (log_path) {
     env["LLDBDAP_LOG"] = log_path;
+  } else if 
(vscode.workspace.getConfiguration("lldb-dap").get("verboseLogging", false)) {
+    env["LLDBDAP_LOG"] = logger.logFilePath(`lldb-dap-session-${formatDate(new 
Date())}.log`);
   }
   const configEnvironment =
     config.get<{ [key: string]: string }>("environment") || {};
@@ -188,6 +209,11 @@ export async function createDebugAdapterExecutable(
   };
   const dbgArgs = await getDAPArguments(workspaceFolder, configuration);
 
+  logger.info(`lldb-dap path: ${dapPath}`);
+  logger.info(`lldb-dap args: ${dbgArgs}`);
+  logger.info(`cwd: ${dbgOptions.cwd}`);
+  logger.info(`env: ${JSON.stringify(configEnvironment)}`);
+
   return new vscode.DebugAdapterExecutable(dapPath, dbgArgs, dbgOptions);
 }
 
@@ -198,18 +224,26 @@ export async function createDebugAdapterExecutable(
 export class LLDBDapDescriptorFactory
   implements vscode.DebugAdapterDescriptorFactory
 {
+  constructor(private readonly logger: Logger) {}
+
   async createDebugAdapterDescriptor(
     session: vscode.DebugSession,
     executable: vscode.DebugAdapterExecutable | undefined,
   ): Promise<vscode.DebugAdapterDescriptor | undefined> {
+    this.logger.info(`Creating debug adapter for session "${session.name}"`);
+    this.logger.debug(`Session "${session.name}" debug configuration:`);
+    this.logger.debug(JSON.stringify(session.configuration, undefined, 2));
     if (executable) {
-      throw new Error(
+      const error = new Error(
         "Setting the debug adapter executable in the package.json is not 
supported.",
       );
+      this.logger.error(error);
+      throw error;
     }
 
     // Use a server connection if the debugAdapterPort is provided
     if (session.configuration.debugAdapterPort) {
+      this.logger.info(`Spawning debug adapter server on port 
${session.configuration.debugAdapterPort}`);
       return new vscode.DebugAdapterServer(
         session.configuration.debugAdapterPort,
         session.configuration.debugAdapterHostname,
@@ -217,6 +251,7 @@ export class LLDBDapDescriptorFactory
     }
 
     return createDebugAdapterExecutable(
+      this.logger,
       session.workspaceFolder,
       session.configuration,
     );
diff --git a/lldb/tools/lldb-dap/src-ts/debug-configuration-provider.ts 
b/lldb/tools/lldb-dap/src-ts/debug-configuration-provider.ts
index 316ffaf47c3d2..65a63a85c9036 100644
--- a/lldb/tools/lldb-dap/src-ts/debug-configuration-provider.ts
+++ b/lldb/tools/lldb-dap/src-ts/debug-configuration-provider.ts
@@ -5,6 +5,7 @@ import { LLDBDapServer } from "./lldb-dap-server";
 import { createDebugAdapterExecutable } from "./debug-adapter-factory";
 import { ConfigureButton, showErrorMessage } from "./ui/show-error-message";
 import { ErrorWithNotification } from "./ui/error-with-notification";
+import { Logger } from "./logger";
 
 const exec = util.promisify(child_process.execFile);
 
@@ -71,13 +72,16 @@ const configurations: Record<string, DefaultConfig> = {
 export class LLDBDapConfigurationProvider
   implements vscode.DebugConfigurationProvider
 {
-  constructor(private readonly server: LLDBDapServer) {}
+  constructor(private readonly server: LLDBDapServer, private readonly logger: 
Logger) {}
 
   async resolveDebugConfiguration(
     folder: vscode.WorkspaceFolder | undefined,
     debugConfiguration: vscode.DebugConfiguration,
     token?: vscode.CancellationToken,
   ): Promise<vscode.DebugConfiguration> {
+    this.logger.info(`Resolving debug configuration for 
"${debugConfiguration.name}"`);
+    this.logger.debug("Initial debug configuration:");
+    this.logger.debug(JSON.stringify(debugConfiguration, undefined, 2));
     let config = vscode.workspace.getConfiguration("lldb-dap");
     for (const [key, cfg] of Object.entries(configurations)) {
       if (Reflect.has(debugConfiguration, key)) {
@@ -152,6 +156,7 @@ export class LLDBDapConfigurationProvider
         // Always try to create the debug adapter executable as this will show 
the user errors
         // if there are any.
         const executable = await createDebugAdapterExecutable(
+          this.logger,
           folder,
           debugConfiguration,
         );
@@ -184,8 +189,12 @@ export class LLDBDapConfigurationProvider
         }
       }
 
+      this.logger.debug("Resolved debug configuration:");
+      this.logger.debug(JSON.stringify(debugConfiguration, undefined, 2));
+
       return debugConfiguration;
     } catch (error) {
+      this.logger.error(error);
       // Show a better error message to the user if possible
       if (!(error instanceof ErrorWithNotification)) {
         throw error;
diff --git a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts 
b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts
index 50db1e1c3a7b0..a5424b6ce4ae8 100644
--- a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts
+++ b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts
@@ -1,10 +1,12 @@
 import { DebugProtocol } from "@vscode/debugprotocol";
 import * as vscode from "vscode";
+import { Logger } from "./logger";
 
 /** A helper type for mapping event types to their corresponding data type. */
 // prettier-ignore
 interface EventMap {
   "module": DebugProtocol.ModuleEvent;
+  "exited": DebugProtocol.ExitedEvent;
 }
 
 /** A type assertion to check if a ProtocolMessage is an event or if it is a 
specific event. */
@@ -47,7 +49,7 @@ export class DebugSessionTracker
   onDidChangeModules: vscode.Event<vscode.DebugSession | undefined> =
     this.modulesChanged.event;
 
-  constructor() {
+  constructor(private logger: Logger) {
     this.onDidChangeModules(this.moduleChangedListener, this);
     vscode.debug.onDidChangeActiveDebugSession((session) =>
       this.modulesChanged.fire(session),
@@ -62,8 +64,12 @@ export class DebugSessionTracker
   createDebugAdapterTracker(
     session: vscode.DebugSession,
   ): vscode.ProviderResult<vscode.DebugAdapterTracker> {
+    this.logger.info(`Starting debug session "${session.name}"`);
+    let stopping = false;
     return {
+      onError: (error) => !stopping && this.logger.error(error), // Can throw 
benign read errors when shutting down
       onDidSendMessage: (message) => this.onDidSendMessage(session, message),
+      onWillStopSession: () => stopping = true,
       onExit: () => this.onExit(session),
     };
   }
@@ -134,6 +140,11 @@ export class DebugSessionTracker
       }
       this.modules.set(session, modules);
       this.modulesChanged.fire(session);
+    } else if (isEvent(message, "exited")) {
+      // The vscode.DebugAdapterTracker#onExit event is sometimes called with
+      // exitCode = undefined but the exit event from LLDB-DAP always has the 
"exitCode"
+      const { exitCode } = message.body;
+      this.logger.info(`Session "${session.name}" exited with code 
${exitCode}`);
     }
   }
 }
diff --git a/lldb/tools/lldb-dap/src-ts/extension.ts 
b/lldb/tools/lldb-dap/src-ts/extension.ts
index c8e5146e29cea..fe5f3a0100907 100644
--- a/lldb/tools/lldb-dap/src-ts/extension.ts
+++ b/lldb/tools/lldb-dap/src-ts/extension.ts
@@ -1,3 +1,4 @@
+import * as path from "path";
 import * as vscode from "vscode";
 
 import { LLDBDapDescriptorFactory } from "./debug-adapter-factory";
@@ -10,28 +11,31 @@ import {
   ModulesDataProvider,
   ModuleProperty,
 } from "./ui/modules-data-provider";
+import { Logger } from "./logger";
 
 /**
  * This class represents the extension and manages its life cycle. Other 
extensions
  * using it as as library should use this class as the main entry point.
  */
 export class LLDBDapExtension extends DisposableContext {
-  constructor() {
+  constructor(logger: Logger, outputChannel: vscode.OutputChannel) {
     super();
 
     const lldbDapServer = new LLDBDapServer();
-    const sessionTracker = new DebugSessionTracker();
+    const sessionTracker = new DebugSessionTracker(logger);
 
     this.pushSubscription(
+      logger,
+      outputChannel,
       lldbDapServer,
       sessionTracker,
       vscode.debug.registerDebugConfigurationProvider(
         "lldb-dap",
-        new LLDBDapConfigurationProvider(lldbDapServer),
+        new LLDBDapConfigurationProvider(lldbDapServer, logger),
       ),
       vscode.debug.registerDebugAdapterDescriptorFactory(
         "lldb-dap",
-        new LLDBDapDescriptorFactory(),
+        new LLDBDapDescriptorFactory(logger),
       ),
       vscode.debug.registerDebugAdapterTrackerFactory(
         "lldb-dap",
@@ -54,6 +58,11 @@ export class LLDBDapExtension extends DisposableContext {
 /**
  * This is the entry point when initialized by VS Code.
  */
-export function activate(context: vscode.ExtensionContext) {
-  context.subscriptions.push(new LLDBDapExtension());
+export async function activate(context: vscode.ExtensionContext) {
+  await vscode.workspace.fs.createDirectory(context.logUri);
+  const outputChannel = vscode.window.createOutputChannel("LLDB-DAP");
+  const logger = new Logger((name) => path.join(context.logUri.fsPath, name), 
outputChannel);
+  logger.info("LLDB-Dap extension activating...");
+  context.subscriptions.push(new LLDBDapExtension(logger, outputChannel));
+  logger.info("LLDB-Dap extension activated");
 }
diff --git a/lldb/tools/lldb-dap/src-ts/logger.ts 
b/lldb/tools/lldb-dap/src-ts/logger.ts
new file mode 100644
index 0000000000000..15da25ff0e28d
--- /dev/null
+++ b/lldb/tools/lldb-dap/src-ts/logger.ts
@@ -0,0 +1,88 @@
+import * as vscode from "vscode";
+import * as winston from "winston";
+import * as Transport from "winston-transport";
+
+class OutputChannelTransport extends Transport {
+    constructor(private readonly ouptutChannel: vscode.OutputChannel) {
+        super();
+    }
+
+    public log(info: any, next: () => void): void {
+        this.ouptutChannel.appendLine(info[Symbol.for('message')]);
+        next();
+    }
+}
+
+export class Logger implements vscode.Disposable {
+    private disposables: vscode.Disposable[] = [];
+    private logger: winston.Logger;
+
+    constructor(public readonly logFilePath: (name: string) => string, 
ouptutChannel: vscode.OutputChannel) {
+        const ouptutChannelTransport = new 
OutputChannelTransport(ouptutChannel);
+        ouptutChannelTransport.level = this.outputChannelLevel();
+        this.logger = winston.createLogger({
+            transports: [
+                new winston.transports.File({ filename: 
logFilePath("lldb-dap-extension.log"), level: "debug" }), // File logging at 
the 'debug' level
+                ouptutChannelTransport
+            ],
+            format: winston.format.combine(
+                winston.format.errors({ stack: true }),
+                winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
+                winston.format.printf(msg => `[${msg.timestamp}][${msg.level}] 
${msg.message} ${msg.stack ? msg.stack : ''}`),
+            ),
+        });
+        if (process.env.NODE_ENV !== 'production') {
+            this.logger.add(new winston.transports.Console({
+                level: "error"
+            }));
+        }
+        this.disposables.push(
+            {
+                dispose: () => this.logger.close()
+            },
+            vscode.workspace.onDidChangeConfiguration(e => {
+                if (e.affectsConfiguration("lldb-dap.verboseLogging")) {
+                    ouptutChannelTransport.level = this.outputChannelLevel();
+                }
+            })
+        );
+    }
+
+    debug(message: any) {
+        this.logger.debug(this.normalizeMessage(message));
+    }
+
+    info(message: any) {
+        this.logger.info(this.normalizeMessage(message));
+    }
+
+    warn(message: any) {
+        this.logger.warn(this.normalizeMessage(message));
+    }
+
+    error(message: any) {
+        if (message instanceof Error) {
+            this.logger.error(message);
+            return;
+        }
+        this.logger.error(this.normalizeMessage(message));
+    }
+
+    private normalizeMessage(message: any) {
+        if (typeof message === "string") {
+            return message;
+        } else if (typeof message === "object") {
+            return JSON.stringify(message);
+        }
+        return `${message}`;
+    }
+
+    private outputChannelLevel(): string {
+        return 
vscode.workspace.getConfiguration("lldb-dap").get("verboseLogging", false) ?
+            "debug" : "info";
+    }
+
+    dispose() {
+        this.disposables.forEach(d => d.dispose());
+    }
+}
\ No newline at end of file

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to