読者です 読者をやめる 読者になる 読者になる

yamamoWorks

.NET技術を中心に気まぐれに更新していきます

Glimpseのタイムラインにカスタム項目を追加する

ASP.NET アプリケーションの診断ツールGlimpseのタイムラインを拡張する方法を簡単に紹介します。

下記のようなControllerがあるとします。

public class HomeController : Controller
{
public ActionResult Index()
{
// 何か重い処理A
Thread.Sleep(500);

// 何か重い処理B
Thread.Sleep(1000);

// 何か重い処理C
Thread.Sleep(1500);

return View();
}
}
Glimpse.MVC5をインストールして実行すると、このようなTimelineになります。ASP.NET MVCのFilterやController、Viewが実行された順番や時間が視覚的に見えますね。


しかし、実際のアプリケーションではデータベースやWebサービスにアクセスしてデータを取得したりするので、その処理に掛かった時間を表示したいですね。
それを実現できるようGlimpseにはタイムラインにカスタム項目を追加できる仕組みが用意されています。

簡単なサンプルで試してみましょう。
class GlimpseTimelineFactory : IInspector
{
static private IMessageBroker messageBroker;
static private Func
timerStrategy;

public void Setup(IInspectorContext context)
{
messageBroker = context.MessageBroker;
timerStrategy = context.TimerStrategy;
}

public static GlimpseTimeline Create(string category, string eventName)
{
return new GlimpseTimeline(category, eventName, messageBroker, timerStrategy);
}
}
まず、Glimpse.Core.Extensibility.IInspectorインターフェイスを実装します。
するとアプリケーション実行時にGlimpseが自動的にこのクラスを探し(Web.Configへの登録等は不要)Setupメソッドを実行します。
Setupメソッドで渡されたIInspectorContextのMessageBrokerとTimerStrategyを保持しておきます。

今回はusingで囲ったブロックをタイムラインに表示するようにしてみます。
class GlimpseTimeline : IDisposable
{
private IMessageBroker messageBroker;
private IExecutionTimer timer;
private TimeSpan offset;
private string category;
private string eventName;

internal GlimpseTimeline(string category, string eventName, IMessageBroker messageBroker, Func timerStrategy)
{
this.category = category;
this.eventName = eventName;
this.messageBroker = messageBroker;
this.timer =
timerStrategy();
this.offset = this.timer.Point().Offset;
}

public void Dispose()
{
var timerResult = this.timer.Stop(offset);

this.messageBroker.Publish(
new TraceMessage()
.AsTimelineMessage(this.eventName, new TimelineCategoryItem(this.category, "#ff0000", "#ff0000"))
.AsTimedMessage(timerResult));
}
}
処理の計測を始める為にTimerStrategyを実行し、その時点のOffset値を保持しておきます。
そして、処理が終わったら(今回はusingで囲うのでDispose部分)タイマーを止め、MessageBrokerにメッセージをPublishします。メッセージはGlimpse.Core.Message.ITimelineMessageを実装したクラスになります。
public class TimelineMessage : ITimelineMessage
{
public TimelineCategoryItem EventCategory { get; set; }
public string EventName { get; set; }
public string EventSubText { get; set; }
public TimeSpan Duration { get; set; }
public TimeSpan Offset { get; set; }
public DateTime StartTime { get; set; }
public Guid Id { get; set; }
}
準備が出来たのでControllerを以下のように修正し、実行するとそれぞれの処理がタイムラインに表示されるようになります。
public class HomeController : Controller
{
public ActionResult Index()
{
// 何か重い処理A
using (var timeline = GlimpseTimelineFactory.Create("Test", "A"))
{
Thread.Sleep(500);
}

// 何か重い処理B
using (var timeline = GlimpseTimelineFactory.Create("Test", "B"))
{
Thread.Sleep(1000);
}

// 何か重い処理C
using (var timeline = GlimpseTimelineFactory.Create("Test", "C"))
{
Thread.Sleep(1500);
}

return View();
}
}



赤いラインがが追加されましたね。

実際の開発ではGlimpseへの出力部分をDBアクセスモジュールやWebサービスのクライアントに組み込む等で実装すると良いでしょう。