tech.guitarrapc.cóm

Technical updates

Riderのブレークポイントログと同様の機能をVisual Studioのトレースポイントで行う

Riderのブレークポイントログについての記事を読んだのですが、Visual Studioにも同様の機能があります。Visual Studioでも同じことができないか、と悩んでいる人に向けての紹介です。

Unityで開発していると「ちょっとここの値を確認したいな」と思って、ログ追加のためにDebug.Logを書く → コンパイルが走る → 数十秒待つ → その間に思考が途切れる、という経験はありませんか? Visual Studioのトレースポイントを使えば、Riderのブレークポイントログと同様に、コードを書き換えずに値を確認できます。ブレークポイントを置いたらログを設定するだけで簡単なので、ぜひお試しください。

Visual Studioのトレースポイント

Microsoft Learnに、Visual Studioのトレースポイントについて説明があります。 本記事はVisual Studio 20261で、C#を用いて紹介します。本機能は、マネージド言語(C#、Visual Basic、F#)とネイティブコード、およびJavaScriptやPythonなどの言語でサポートされています。

サンプルプログラム

ASP.NET Core Web APIのデフォルトプロジェクトをサンプルとして用いて「リクエストの時にデバッグしたい」という実ケースあるあるを想定しましょう。 プログラムは、http://localhost:5000/weatherforecastにアクセスすると、5日分の天気予報を返すものです。

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

// Configure the HTTP request pipeline.
var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

app.Run();

internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

Visual Studioで「コンパイルしないログ」を出す

やることはシンプルです。Riderの場合と同様に次の手順です。

  • ブレークポイントを置く
  • そのブレークポイントにログ出力を設定
  • デバッガを起動する

C#を書いているとブレークポイントは普段から使いますよね。トレースポイントは、このブレークポイントにログを設定するだけです。 コードを書き換えず、Debug.Logも書かず、コンパイルも走りません。

やってみましょう。

まずは、ブレークポイントを置きます。

ログを出したい行にブレークポイントを置く

ブレークポイントの赤い丸にマウスホバーして、Settings (日本語なら設定)をクリックします。

赤い丸にマウスを合わせてSettingsをクリック

いくつかチェックボックスがあります。Actions (アクション)チェックボックスをオンにします。

Actionsチェックボックスをオンにする

Continue code execution (コードの実行を続行)はオンのままにします。

Actionsチェックボックスをオンにすると出力ウィンドウへのメッセージを入力できる

Show a message on the Output Window: 出力メッセージにログ出力したい内容を記述します。

出力メッセージを付ける

文字列だけでなく、調べたい変数も{}で囲むと展開されます。例えば、forecast変数を見たいなら{forecast}と書きます。 インテリセンスも効くので、割と自由に指定できます。

変数も指定できる

その後、F5キーでデバッガを起動します。 これで、出力ウィンドウ (Output Window)にログが出力されます。

ブラウザやcurlでhttp://localhost:5000/weatherforecastにアクセスしてみましょう。

Unityでトレースポイントを出す

UnityでVisual Studioを使っているときのトレースポイントの例を示します。

雑なスクリプトを用意します。

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Sample : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        int counter = 0;
        for (int i = 0; i <= 10; i++)
        {
            counter += 1;
        }
    }
}

先ほどの例同様にブレークポイントを設定、ログメッセージを設定します。

Unityのトレースポイント例

Visual StudioのデバッガをUnityにアタッチしてから、Unityを再生モードにしましょう。

Attach to Unity

出力ウィンドウに設定したログが出力されます。コンパイル時間ゼロでログ出力できるようになりました。

出力ウィンドウへの出力例

出力ウィンドウが流れてしまう

出力ウィンドウには、デフォルトではスレッドIDが出力され、あっという間に流れてしまいます。

デフォルトでスレッドIDが流れる

特に、Unityにデバッグしていると頻繁にスレッドログが流れて邪魔なので、トレースログを見るときは非表示にするといいでしょう。 出力ウィンドウで右クリックして、Thread Exit Messages(スレッド終了メッセージ)のチェックを外します。

出力ウィンドウを右クリックしてThread Exit Messagesをオフにします

出力ウィンドウの時計アイコンを有効にすると、出力時刻が表示されて便利なのでこちらもどうぞ

出力ウィンドウの時計アイコンを有効にする

キーワード

アクションにはキーワードを使えます。以下はMicrosoft Learnからの引用です。 この中で$FUNCTION$CALLSTACKあたりはかなり便利でおすすめです。ブレークポイントで止めることなく関数名や呼び出し履歴をログに出せるのは強い。

Keyword 表示される内容
$ADDRESS 現在の命令
$CALLER 関数名の呼び出し
$CALLSTACK 呼び出し履歴
$FUNCTION 現在の関数名
$PID プロセス ID
$PNAME プロセス名
$TID スレッド ID
$TNAME スレッド名
$TICK ティック数 (Windows GetTickCount から)

条件を付ける

Conditions(条件)でログを特定の条件でだけ出力できます。例えばループ処理で毎回ログが出るのはうざいですが、N回目のループだけログを出したい、という場合に便利です。

例えば以下のように、i == 10という条件を付けると、iが10のときだけログが出力されます。

条件の設定例

出力ウィンドウを見ると、10回目のループでだけログが出力されていることがわかります。

出力ウィンドウの例

特定のブレークポイントを通った時だけログを出すこともできます。これを使うと特定のコードパスを経由した呼び出しだけログを出せるため、呼び出し元が複数ある場合にめちゃめちゃ便利です。

ブレークポイントを条件にする

まとめ

Visual Studioのトレースポイントを使うと、コードを書き換えずにログを出力できます。 Riderに限らずVisual Studioにも同様の機能があるので、ぜひ試してみてください。

参考


  1. Visual Studio 2022でも同様です。