Logpointsと自動アタッチの紹介
2018年7月12日 Kenneth Auchenberg, @auchenberg
ここ数ヶ月間、私たちはVisual Studio Codeのデバッグ体験の改善に忙しく取り組んできました。この投稿では、デバッグに対する私たちの考え方、ユーザーから得たフィードバック、そしてVS Codeでデバッグをより簡単にするためのステップについて説明します。
VS Codeの開始以来、デバッグはソースコードを記述・編集する場所、つまりエディターの不可欠な一部であるべきだと考えているため、統合されたデバッグ体験を提供してきました。

VS Codeのデバッグ体験は、デバッグアダプタープロトコル (DAP) を介して、デバッグアダプター (DA) と呼ばれる特定の種類のVS Code拡張機能と通信する汎用デバッガーUIによって提供されます。DAは実際のデバッガーと通信し、DAPとランタイム固有のデバッグプロトコルまたはAPIの間で翻訳を行います。
これは、VS Codeのコアが特定のデバッガーから完全に切り離されていることを意味し、このアーキテクチャにより、図に示すように、デバッグアダプターが利用可能である限り、VS Codeは何でもデバッグできます

観察と問題点
現在、VS Codeを使用して定期的にデバッグを行っている満足している開発者の大規模なグループが存在しますが、私たちの使命の一環として、デバッグをより簡単にして、より多くの開発者が利用できるようにしたいと考えています。
この目的のために、私たちはVS Codeでのデバッグの問題点をよりよく理解し、なぜ一部の開発者がデバッガーをまったく使用しないのかを学ぶために話し合いを開始しました。
以下は私たちの観察結果です。
デバッグ設定が難しい
VS Codeは汎用デバッガーを備えた一般的なエディターであり、特定のスタックやランタイムに特化していません。このため、すべての人に機能する意見のあるデフォルトのデバッグ設定を提供することはできません。
これは、VS Codeではデバッガーの設定だけでなく、適切なパラメーターなどでランタイムを開始する方法も指定する必要があることを意味します。
これが難しいことは認識していますが、すべての人にとってデバッグ設定を完全に排除する方法は見当たりません。しかし、デバッグ設定は簡素化でき、コンテキストによっては最小限に抑えられると信じています。
これについては後で説明します。
起動設定とアタッチ設定の混同
VS Codeでは、デバッグに関して2つの主要な概念があります。 **起動 (Launch)** と **アタッチ (Attach)** で、これらは2つの異なるワークフローと開発者のセグメントを扱います。ワークフローによっては、プロジェクトにどのタイプの構成が適切であるかを知るのが混乱する場合があります。
ブラウザのDevToolsのバックグラウンドから来た場合、ブラウザのインスタンスはすでに開いているため、「ツールから起動する」という概念には慣れていません。DevToolsを開くと、開いているブラウザタブにDevToolsを単に**アタッチ**しているだけです。一方、Javaのバックグラウンドから来た場合、エディターにJavaプロセスを**起動**してもらい、エディターが新しく起動されたプロセスにデバッガーを自動的にアタッチするのはごく普通のことです。
**起動**と**アタッチ**の違いを説明する最良の方法は、起動設定をVS Codeがアタッチする**前に**デバッグモードでアプリを起動する方法のレシピと考えることです。一方、アタッチ設定は、VS Codeのデバッガーを**すでに**実行中のアプリまたはプロセスに接続する方法のレシピです。
起動設定の価値は、適切なデバッグパラメーターでアプリを起動する際の認知的オーバーヘッドの一部を軽減する方法を提供することです。これは、プロジェクトやチームと共有できる、繰り返し可能な設定を作成することによって実現されます。
しかし、開発者たちにアプリケーションの起動方法について話を聞いたところ、あるパターンと重要な観察結果が見られました。
観察: VS Codeを使用している多くの開発者は、統合ターミナルを非常に気に入り、コマンドラインツールに頼ってアプリケーションを起動しています。多くの人にとって、ターミナルでコマンドを実行し、その後エディターからデバッガーをアタッチする方が自然なワークフローです。これは、ブラウザが起動された後にDevToolsを開くのと似ています。
この観察は重要であり、多くのユーザーはエディターでの完全な「魔法のような」起動体験を望んでいないことに気づきました。彼らはエディターをソースコードの編集とデバッグの場所に保ち、ターミナルを使用してアプリを起動したり、ビルドスクリプトを実行したりすることを望んでいます。これは、優れた機能的なUIがターミナルと共存し、うまく統合されるべきだと信じているため、VS Code内に統合ターミナル体験がある理由の1つです。
多くの開発者は状態変化を検査するため、ブレークポイントを使用しません
開発者がアプリケーションをデバッグする方法を見てみると、もう1つの興味深いパターンが見られました。それは、ブレークポイントの代わりにロギングを使用することです。
デバッグのためのロギングは新しい概念ではありませんが、その観察は重要でした。
観察: 従来のデバッグワークフローは、プログラムロジックを検査するために実行を遅らせることに重点を置いているのに対し、ロギングワークフローは通常、プログラムの状態と、アプリケーションの通常の実行中にそれがどのように変化するかを検査することを含みます。ここでの根本的な観察は、2つのテクニックが異なるデバッグ目的に使用されるということです。
この観察は、ほとんどが状態管理の複雑さに対処するJavaScript開発者にとって特に関連性があり、ほとんどのJavaScript開発者がスクリプトデバッガーを使用する代わりに引き続きconsole.logを追加することを好む理由を説明できるかもしれません。
Nodeプロセスへの自動アタッチ
一部の開発者が統合ターミナルを使用してデバッグセッションを起動している方法を振り返ったとき、ユニークな機会が浮上しました。エディターと統合ターミナルからVS Codeが持っているコンテキスト情報を活用することで、コンテキストを検出し、デバッグの意図を推論することができ、Node.js開発者にとって、はるかにシンプルなデバッグ体験を提供できる可能性があります。
そこで、VS Codeの3月のイテレーションで、**Nodeの自動アタッチ (Auto Attach for Node)** と呼ばれる新機能をリリースしました。これにより、NodeデバッガーがVS Codeの統合ターミナルからデバッグモードで起動されたNode.jsプロセスに自動的にアタッチできるようになります。
コマンドパレットから**デバッグ: 自動アタッチの切り替え (Debug: Toggle Auto Attach)** コマンドを実行することで自動アタッチを有効にでき、一度有効にすると、ステータスバーからも自動アタッチを切り替えることができます。

この機能は、node --inspectで起動されたすべてのNode.jsプロセスをデバッグの意図と解釈するため、デバッグ設定を完全に排除します。統合ターミナルと組み合わせることで、開発者が独自の方法でアプリを起動しながら、同時にデバッグ設定を排除できる、はるかにシンプルなデバッグ体験となります!🎉
NPMスクリプトとデバッグ
多くのNode.js開発者は、アプリケーションを起動したり、デバッグセッションを開始したりするためにnpmスクリプトに依存しています。その点についても朗報があります。自動アタッチはnpmスクリプトでも機能します。npm run debugを実行し、"debug"スクリプトが"node --inspect"または--inspectを含むその他のコマンドである場合、自動アタッチがそれを検出し、デバッガーをアタッチします 🎉
また、一部の開発者がnpmスクリプトを見つけて実行するためのより視覚的な方法を望んでいることを認識し、2018年4月のイテレーションで、UIから直接npmスクリプトを参照および実行できる新しいNPMスクリプトエクスプローラーを追加しました。デバッグ設定を簡素化する取り組みの一環として、デバッグ設定を作成することなく、エクスプローラーから直接Node.jsデバッグを開始することも可能にしました。
--inspectのようなデバッグ引数を含むnpmスクリプトがある場合、これを自動的に検出し、デバッガーを起動するデバッグアクションを提供します。以下に示すとおりです。

Logpointsの紹介
ロギングが重要なデバッグ手法であるという学びに基づいて、既存のデバッグ体験に状態検査を追加する機会を見出しました。VS Codeの3月のイテレーションで、Logpointsと呼ぶデバッグ機能の最初の実装をリリースしました。
Logpointはブレークポイントの一種で、デバッガーで「停止」するのではなく、メッセージをコンソールに記録します。

Logpointsの概念は新しいものではなく、ここ数年間、Visual Studio、Edge DevTools、GDBなどのツールで、トレースポイントやLogpointsなど、いくつかの名前でこの概念の異なるフレーバーが見られました。
Logpointsを使用する理由と時期
Logpointsは、多くの場合、アプリケーションの特定の部分で実行を停止したくないが、代わりにアプリケーションのライフサイクル全体で状態がどのように変化するかを検査したいという観察に基づいています。
Logpointsを使用すると、アプリケーションの起動前にロギングステートメントを追加したかのように、オンデマンドでロギングステートメントをアプリケーションロジックに「注入」できます。Logpointsは実行時に注入され、ソースコードには永続化されないため、事前に計画する必要はなく、必要なときにLogpointsを注入できます。もう1つの利点は、デバッグ終了後にソースコードをクリーンアップする心配がないことです。
JavaScript開発者にとっては、console.logを置き去りにすることを心配する必要がなくなります。Logpointsを使用するだけです!さらに良いことに、console.logとLogpointsを組み合わせることができます。すでにconsole.logを含むソースコードのブロックにLogpointを挿入すると、デバッグコンソール内に両方のタイプのロギングステートメントが表示されます。
クラウド環境でのLogpoints
Logpointsは、クラウド環境 (または実際には任意のリモート環境) で特に役立ちます。アプリケーションを再デプロイすることなく、ロギングをリモート環境に注入できるためです。同様に重要なのは、Logpointsを使用するとスクリプトの実行を停止しないため、通常のブレークポイントで実行中のアプリケーションを停止する場合とは異なり、ユーザーには影響がありません。
Azure上のNode.jsでLogpointsを使用する方法の詳細については、こちらで読むことができます。
サポートされている言語
VS CodeでのLogpointsの最初のリリース以来、VS Codeデバッグアダプターによる採用が増加しており、現在、以下の言語でLogpointがサポートされています。
- Node.jsデバッガー
- Chromeデバッガー
- Firefoxデバッガー
- Microsoft Edgeデバッガー
- React Nativeデバッガー
- Pythonデバッガー
- Dartデバッガー
- Luaデバッガー
- Javaデバッガー
- メインフレーム用デバッガー
VS CodeでのLogpoints
VS Code用のデバッグアダプターにLogpointサポートを追加することに興味がある場合は、プロトコルのこれらの変更をご覧ください。また、上記のデバッグアダプターを見て、各ランタイムがLogpointsをどのように実装することを選択したかを確認することもできます。
次のステップ
今のところはこれで終わりですが、まだ作業は終わっていません。7月のイテレーションでは、ユーザーフィードバックに基づいて、検出可能性を向上させるために自動アタッチの改善を行います (#53640)。
自動アタッチ、NPMスクリプトエクスプローラー、Logpointsの導入により、VS Codeでのデバッグがより簡単になることを願っています。いつものように、皆様からのフィードバックをお待ちしておりますので、GitHubまたはTwitterの@codeまでご連絡ください。
VS Codeチームを代表して: ハッピーコーディング!
/Kenneth Auchenberg - Twitterの@auchenberg