*2019/7/27 Web からダウンロードできるサンプルが変わっていたため、こちらの記事もアップデートします。
前回は Bot Connector のボット利用状況分析を紹介しましたが、今回から、より詳細な利用状況を分析するために、Application Insights を駆使する方法を紹介します。
今回は「基本ボット (C#)」で動作をためしました。事前に Bot Web App を作成してソースをダウンロードしてください。
ApplicationInsights の組み込み
NuGet パッケージとして公開されている Microsoft.Bot.Builder.Integration.ApplicationInsights.Core を使ってボットに Application Insights を組み込みます。
1. プロジェクトの NuGet パッケージ管理より、Microsoft.Bot.Builder.Integration.ApplicationInsights.Core を追加。
2. Startup.cs の ConfigureServices メソッドで、ダイアログやボットを追加する前に以下コードを追加。また Configuration プロパティが規定で存在しないため、プロパティとしても追加。
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
...
// Add Application Insights
services.AddBotApplicationInsights(Configuration);
...
}
3. appsettings.json に ApplicationInsights の項目を追加。自身のキーを指定。
{
...
"ApplicationInsights": {
"InstrumentationKey": "2953fafa-ed74-431b-a25c-93ab2fda29ef"
}
}
以上で Application Insights の設定は完了です。
AddBotApplicationInsights で何をしているか
AddBotApplicationInsights は他のパターンの引数を取ることもできます。
GitHub: AddBotApplicationInsights
メソッドを見てわかる通り、IBotTelemetryClient
を IoC に登録しています。
public static IServiceCollection AddBotApplicationInsights(this IServiceCollection services, IConfiguration config)
{
if (config == null)
{
throw new ArgumentNullException(nameof(config));
}
string instrumentationKey = config.GetValue<string>("ApplicationInsights:instrumentationKey");
CreateBotTelemetry(services);
IBotTelemetryClient telemetryClient = null;
if (!string.IsNullOrWhiteSpace(instrumentationKey))
{
services.AddApplicationInsightsTelemetry(instrumentationKey);
telemetryClient = new BotTelemetryClient(new TelemetryClient());
}
else
{
telemetryClient = NullBotTelemetryClient.Instance;
}
services.AddSingleton(telemetryClient);
return services;
}
また他のミドルウェアやイニシャライザーも登録。これらのコードでユーザーから受けた情報を加工して Application Insights に渡すデータを作っています。
private static void CreateBotTelemetry(IServiceCollection services)
{
// Enables Bot Telemetry to save user/session id's as the bot user id and session
services.AddTransient<TelemetrySaveBodyASPMiddleware>();
services.AddSingleton<ITelemetryInitializer, OperationCorrelationTelemetryInitializer>();
services.AddSingleton<ITelemetryInitializer, TelemetryBotIdInitializer>();
}
ただここのコードを見てわかるとおり、これだけでは Application Insights に対して情報を送るコードはありません。
LUIS の結果を Application Insights に送る
サンプルでは LUIS のクエリ結果を取るために LuisRecognizer
を使いますが、引数に TelemetryClient
を渡すことで解析できるようになります。
1. FlightBookingRecognizer.cs で TelemetryClient を使うように変更。
- コンストラクタで IBotTelemetryClient を受け取る
- LuisRecognizer にオプションとして BotTelemetryClient を渡す
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.AI.Luis;
using Microsoft.Extensions.Configuration;
namespace Microsoft.BotBuilderSamples
{
public class FlightBookingRecognizer : IRecognizer
{
private readonly LuisRecognizer _recognizer;
public FlightBookingRecognizer(IConfiguration configuration, IBotTelemetryClient telemetryClient)
{
var luisIsConfigured = !string.IsNullOrEmpty(configuration["LuisAppId"]) && !string.IsNullOrEmpty(configuration["LuisAPIKey"]) && !string.IsNullOrEmpty(configuration["LuisAPIHostName"]);
if (luisIsConfigured)
{
var luisApplication = new LuisApplication(
configuration["LuisAppId"],
configuration["LuisAPIKey"],
"https://" + configuration["LuisAPIHostName"]);
// LuisRecognizer を作成する際、TelemetryClient を指定。
_recognizer = new LuisRecognizer(luisApplication, new LuisPredictionOptions() { TelemetryClient = telemetryClient });
}
}
// Returns true if luis is configured in the appsettings.json and initialized.
public virtual bool IsConfigured => _recognizer != null;
public virtual async Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, CancellationToken cancellationToken)
=> await _recognizer.RecognizeAsync(turnContext, cancellationToken);
public virtual async Task<T> RecognizeAsync<T>(ITurnContext turnContext, CancellationToken cancellationToken)
where T : IRecognizerConvert, new()
=> await _recognizer.RecognizeAsync<T>(turnContext, cancellationToken);
}
}
2. Dialog を実行している DialogBot.cs で渡された Dialog に対して TelemetryClient を設定。
- コンストラクタで IBotTelemetryClient を受け取る
public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger, IBotTelemetryClient telemetryClient)
{
ConversationState = conversationState;
UserState = userState;
Dialog = dialog;
Logger = logger;
dialog.TelemetryClient = telemetryClient;
}
3. DialogBot を継承している DialogAndWelcomeBot.cs でも同様にコンストラクタに設定。
public DialogAndWelcomeBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger, IBotTelemetryClient telemetryClient)
: base(conversationState, userState, dialog, logger, telemetryClient)
{
}
※以前のサンプルに含まれていた DialogExtension.cs は v4.4 からライブラリに統合されました。
GitHub: DialogExtensions
LuisRecognizer でのロギング
LuisRecognizer は ITelemetryRecognizer
を継承し、TelemetryClient.TrackEvent にて自然言語処理の解析結果を Application Insights に保存しています。
結果の解析
結果は Application Insights をクエリすればすぐに分かります。
1. Azure Portal からログ先の Application Insights を開き、「分析」をクリック。
2. GitHub: Application Insights Analytics にあるクエリを実行。
customEvents
| where timestamp >= ago(24h)
| where name startswith "LuisResult"
| extend intent = tostring(customDimensions.['intent'])
| summarize count() by intent
| order by count_ desc
| render piechart
TelemetryLoggerMiddleware
ユーザーからのメッセージ受信時や送信時にログするためには、TelemetryLoggerMiddleware ミドルウェアを使います。
1. AdapterWithErrorHandler.cs に TelemetryLoggerMiddleware を追加
- IBotTelemetryClient をコンストラクタで受け取る
- Use を使ってミドルウェアを追加
using System;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Microsoft.BotBuilderSamples
{
public class AdapterWithErrorHandler : BotFrameworkHttpAdapter
{
public AdapterWithErrorHandler(IConfiguration configuration, ILogger<BotFrameworkHttpAdapter> logger, IBotTelemetryClient telemetryClient, ConversationState conversationState = null)
: base(configuration, logger)
{
OnTurnError = async (turnContext, exception) =>
{
...
};
Use(new TelemetryLoggerMiddleware(telemetryClient));
}
}
}
2. ボットを利用
結果の解析
1. 分析で以下のクエリを実行。以下はイベント毎の解析。
customEvents
| where timestamp >= ago(24h)
| where name startswith "BotMessage"
| summarize count() by name, bin(timestamp, 10m)
| render timechart
3. チャネル毎の場合
customEvents
| where timestamp >= ago(1d)
| where name startswith "BotMessage"
| extend channelId = tostring(customDimensions.['channelId'])
| summarize count() by channelId, bin(timestamp, 10m)
| render timechart
その他のロギング
GitHub: telemetrylogging にもある通り、Custom Events として各種イベントが取得できます。
- 外部依存サービスのトラック
- ウォーターフォールダイアログの実行状況
クエリは GitHub: applicationinsights を参照してください。
まとめ
Application Insights を統合することで詳細が確認できるようになり、より詳しく利用状況が見えるようになりました。次回は Power BI でその状況を見てみます。