Skip to content
This repository has been archived by the owner on Jun 30, 2022. It is now read-only.

[DO NOT MERGE] Enterprise Template TelemetryClient/AppInsights conversation analytics capabilities #425

Merged
merged 15 commits into from
Dec 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public void ConfigureServices(IServiceCollection services)
// Typing Middleware (automatically shows typing when the bot is responding/working)
options.Middleware.Add(new ShowTypingMiddleware());
options.Middleware.Add(new SetLocaleMiddleware(defaultLocale ?? "en-us"));
options.Middleware.Add(new TeamsAuthenticationMiddleware());
options.Middleware.Add(new EventDebuggerMiddleware());
options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
<None Update="*.bot">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="LocaleConfigurations\*.bot">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Schema;

namespace Microsoft.Bot.Solutions.Middleware
{
public class TeamsAuthenticationMiddleware : IMiddleware
{
public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken = new CancellationToken())
{
// hook up onSend pipeline
turnContext.OnSendActivities(async (ctx, activities, nextSend) =>
{
foreach (var activity in activities)
{
if (activity.ChannelId != Channels.Msteams)
{
continue;
}

if (activity.Attachments == null)
{
continue;
}

if (!activity.Attachments.Any())
{
continue;
}

if (!activity.Attachments[0].ContentType.Equals("application/vnd.microsoft.card.signin", StringComparison.InvariantCultureIgnoreCase))
{
continue;
}

if (!(activity.Attachments[0].Content is SigninCard card))
{
continue;
}

if (!(card.Buttons is CardAction[] buttons))
{
continue;
}

if (!buttons.Any())
{
continue;
}

// Modify button type to openUrl as signIn is not working in teams
buttons[0].Type = ActionTypes.OpenUrl;
}

// run full pipeline
return await nextSend().ConfigureAwait(false);
});

await next(cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using $safeprojectname$.Middleware.Telemetry;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Bot.Builder.AI.Luis;
using Microsoft.Bot.Builder.AI.QnA;
using Microsoft.Bot.Configuration;
Expand All @@ -30,30 +32,86 @@ public BotServices(BotConfiguration botConfiguration)
{
switch (service.Type)
{
case ServiceTypes.AppInsights:
case ServiceTypes.AppInsights:
{
var appInsights = (AppInsightsService)service;
if (appInsights == null)
{
var appInsights = service as AppInsightsService;
TelemetryClient = new TelemetryClient();
break;
throw new InvalidOperationException("The Application Insights is not configured correctly in your '.bot' file.");
}

case ServiceTypes.Dispatch:
if (string.IsNullOrWhiteSpace(appInsights.InstrumentationKey))
{
var dispatch = service as DispatchService;
var dispatchApp = new LuisApplication(dispatch.AppId, dispatch.SubscriptionKey, dispatch.GetEndpoint());
DispatchRecognizer = new TelemetryLuisRecognizer(dispatchApp);
break;
throw new InvalidOperationException("The Application Insights Instrumentation Key ('instrumentationKey') is required to run this sample. Please update your '.bot' file.");
ryanisgrig marked this conversation as resolved.
Show resolved Hide resolved
}

case ServiceTypes.Luis:
var telemetryConfig = new TelemetryConfiguration(appInsights.InstrumentationKey);
TelemetryClient = new TelemetryClient(telemetryConfig)
{
var luis = service as LuisService;
var luisApp = new LuisApplication(luis.AppId, luis.SubscriptionKey, luis.GetEndpoint());
LuisServices.Add(service.Id, new TelemetryLuisRecognizer(luisApp));
break;
InstrumentationKey = appInsights.InstrumentationKey,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In samples, I was removing this - actually wasn't referencing. So I kept the validation checks, but didn't actually create the TelemetryClient since that is effectively done by the extension methods in startup (and registered in DI) as BotTelemetryClient.


break;
}

case ServiceTypes.Dispatch:
{
var dispatch = service as DispatchService;
if (dispatch == null)
{
throw new InvalidOperationException("The Dispatch service is not configured correctly in your '.bot' file.");
}

case ServiceTypes.QnA:
if (string.IsNullOrWhiteSpace(dispatch.AppId))
{
throw new InvalidOperationException("The Dispatch Luis Model Application Id ('appId') is required to run this sample. Please update your '.bot' file.");
}

if (string.IsNullOrWhiteSpace(dispatch.SubscriptionKey))
{
throw new InvalidOperationException("The Subscription Key ('subscriptionKey') is required to run this sample. Please update your '.bot' file.");
}

var dispatchApp = new LuisApplication(dispatch.AppId, dispatch.SubscriptionKey, dispatch.GetEndpoint());
DispatchRecognizer = new TelemetryLuisRecognizer(dispatchApp);
break;
}

case ServiceTypes.Luis:
{
var luis = service as LuisService;
if (luis == null)
{
throw new InvalidOperationException("The Luis service is not configured correctly in your '.bot' file.");
}

if (string.IsNullOrWhiteSpace(luis.AppId))
{
throw new InvalidOperationException("The Luis Model Application Id ('appId') is required to run this sample. Please update your '.bot' file.");
}

if (string.IsNullOrWhiteSpace(luis.AuthoringKey))
{
throw new InvalidOperationException("The Luis Authoring Key ('authoringKey') is required to run this sample. Please update your '.bot' file.");
}

if (string.IsNullOrWhiteSpace(luis.SubscriptionKey))
{
throw new InvalidOperationException("The Subscription Key ('subscriptionKey') is required to run this sample. Please update your '.bot' file.");
}

if (string.IsNullOrWhiteSpace(luis.Region))
{
throw new InvalidOperationException("The Region ('region') is required to run this sample. Please update your '.bot' file.");
}

var luisApp = new LuisApplication(luis.AppId, luis.SubscriptionKey, luis.GetEndpoint());
var recognizer = new TelemetryLuisRecognizer(luisApp);
LuisServices.Add(service.Id, recognizer);
break;
}

case ServiceTypes.QnA:
{
var qna = service as QnAMakerService;
var qnaEndpoint = new QnAMakerEndpoint()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using $safeprojectname$.Dialogs.Onboarding;
using $safeprojectname$.Dialogs.Shared;
using Luis;
using Microsoft.ApplicationInsights;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;

Expand All @@ -21,14 +22,15 @@ public class MainDialog : RouterDialog
private ConversationState _conversationState;
private MainResponses _responder = new MainResponses();

public MainDialog(BotServices services, ConversationState conversationState, UserState userState)
public MainDialog(BotServices services, ConversationState conversationState, UserState userState, IBotTelemetryClient telemetryClient)
: base(nameof(MainDialog))
{
_services = services ?? throw new ArgumentNullException(nameof(services));
_conversationState = conversationState;
_userState = userState;
TelemetryClient = telemetryClient;

AddDialog(new OnboardingDialog(_services, _userState.CreateProperty<OnboardingState>(nameof(OnboardingState))));
AddDialog(new OnboardingDialog(_services, _userState.CreateProperty<OnboardingState>(nameof(OnboardingState)), telemetryClient));
AddDialog(new EscalateDialog(_services));
}

Expand All @@ -41,7 +43,7 @@ public MainDialog(BotServices services, ConversationState conversationState, Use
protected override async Task RouteAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
{
// Check dispatch result
var dispatchResult = await _services.DispatchRecognizer.RecognizeAsync<Dispatch>(dc.Context, true, CancellationToken.None);
var dispatchResult = await _services.DispatchRecognizer.RecognizeAsync<Dispatch>(dc, true, CancellationToken.None);
var intent = dispatchResult.TopIntent().intent;

if (intent == Dispatch.Intent.l_General)
Expand All @@ -55,7 +57,7 @@ public MainDialog(BotServices services, ConversationState conversationState, Use
}
else
{
var result = await luisService.RecognizeAsync<General>(dc.Context, true, CancellationToken.None);
var result = await luisService.RecognizeAsync<General>(dc, true, CancellationToken.None);

var generalIntent = result?.TopIntent().intent;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
using $safeprojectname$.Dialogs.Shared;
using Microsoft.ApplicationInsights;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;

Expand All @@ -15,7 +16,7 @@ public class OnboardingDialog : EnterpriseDialog
private IStatePropertyAccessor<OnboardingState> _accessor;
private OnboardingState _state;

public OnboardingDialog(BotServices botServices, IStatePropertyAccessor<OnboardingState> accessor)
public OnboardingDialog(BotServices botServices, IStatePropertyAccessor<OnboardingState> accessor, IBotTelemetryClient telemetryClient)
: base(botServices, nameof(OnboardingDialog))
{
_accessor = accessor;
Expand All @@ -29,7 +30,10 @@ public OnboardingDialog(BotServices botServices, IStatePropertyAccessor<Onboardi
FinishOnboardingDialog,
};

AddDialog(new WaterfallDialog(InitialDialogId, onboarding));
// To capture built-in waterfall dialog telemetry, set the telemetry client
// to the new waterfall dialog and add it to the component dialog
TelemetryClient = telemetryClient;
AddDialog(new WaterfallDialog(InitialDialogId, onboarding) { TelemetryClient = telemetryClient });
AddDialog(new TextPrompt(DialogIds.NamePrompt));
AddDialog(new TextPrompt(DialogIds.EmailPrompt));
AddDialog(new TextPrompt(DialogIds.LocationPrompt));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class $safeprojectname$ : IBot
private readonly BotServices _services;
private readonly ConversationState _conversationState;
private readonly UserState _userState;
private readonly IBotTelemetryClient _telemetryClient;
private DialogSet _dialogs;

/// <summary>
Expand All @@ -27,14 +28,15 @@ public class $safeprojectname$ : IBot
/// <param name="botServices">Bot services.</param>
/// <param name="conversationState">Bot conversation state.</param>
/// <param name="userState">Bot user state.</param>
public $safeprojectname$(BotServices botServices, ConversationState conversationState, UserState userState)
public $safeprojectname$(BotServices botServices, ConversationState conversationState, UserState userState, IBotTelemetryClient telemetryClient)
{
_conversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState));
_userState = userState ?? throw new ArgumentNullException(nameof(userState));
_services = botServices ?? throw new ArgumentNullException(nameof(botServices));
_telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));

_dialogs = new DialogSet(_conversationState.CreateProperty<DialogState>(nameof($safeprojectname$)));
_dialogs.Add(new MainDialog(_services, _conversationState, _userState));
_dialogs.Add(new MainDialog(_services, _conversationState, _userState, _telemetryClient));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,27 @@

<ItemGroup>
<PackageReference Include="AdaptiveCards" Version="1.1.0" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.8.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.5.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.8.0" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.8.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.5.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.8.1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.5" />
<PackageReference Include="Microsoft.Azure.CognitiveServices.ContentModerator" Version="1.0.0" />
<PackageReference Include="Microsoft.Azure.CognitiveServices.Language" Version="1.0.1-preview" />
<PackageReference Include="Microsoft.Bot.Builder" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.AI.Luis" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.AI.QnA" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.Azure" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.TemplateManager" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Configuration" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Connector" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Schema" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Builder.AI.Luis" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Builder.AI.QnA" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Builder.ApplicationInsights" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Builder.Azure" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.ApplicationInsights.Core" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Builder.TemplateManager" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Configuration" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Connector" Version="4.2.0" />
<PackageReference Include="Microsoft.Bot.Schema" Version="4.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.1.1" />
<PackageReference Include="Microsoft.Graph" Version="1.10.0" />
<PackageReference Include="Microsoft.Graph" Version="1.12.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ namespace $safeprojectname$.Middleware.Telemetry
/// </summary>
public static class LuisTelemetryConstants
{
public const string IntentPrefix = "LuisIntent"; // Application Insights Custom Event name (with Intent)
public const string IntentProperty = "Intent";
public const string IntentScoreProperty = "IntentScore";
public const string ConversationIdProperty = "ConversationId";
public const string QuestionProperty = "Question";
public const string ActivityIdProperty = "ActivityId";
public const string SentimentLabelProperty = "SentimentLabel";
public const string SentimentScoreProperty = "SentimentScore";
public const string IntentPrefix = "luisIntent"; // Application Insights Custom Event name (with Intent)
public const string IntentProperty = "intent";
public const string IntentScoreProperty = "intentScore";
public const string ConversationIdProperty = "conversationId";
public const string QuestionProperty = "question";
public const string ActivityIdProperty = "activityId";
public const string SentimentLabelProperty = "sentimentLabel";
public const string SentimentScoreProperty = "sentimentScore";
public const string DialogId = "dialogId";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ namespace $safeprojectname$.Middleware.Telemetry
/// </summary>
public static class QnATelemetryConstants
{
public const string ActivityIdProperty = "ActivityId";
public const string UsernameProperty = "Username";
public const string ConversationIdProperty = "ConversationId";
public const string OriginalQuestionProperty = "OriginalQuestion";
public const string QuestionProperty = "Question";
public const string AnswerProperty = "Answer";
public const string ScoreProperty = "Score";
public const string ArticleFoundProperty = "QnAItemFound";
public const string ActivityIdProperty = "activityId";
public const string AnswerProperty = "answer";
public const string ArticleFoundProperty = "articleFound";
public const string ChannelIdProperty = "channelId";
public const string ConversationIdProperty = "conversationId";
public const string OriginalQuestionProperty = "originalQuestion";
public const string QuestionProperty = "question";
public const string ScoreProperty = "score";
public const string UsernameProperty = "username";
}
}
Loading