Adds check to TranscriptLoggerMiddleware doesn't log continue conversation event activities (#4797)

* Adds check to TranscriptLoggerMiddleware doesn't log contine conversation event activities.

Changes include:
- Added check in TranscriptLoggerMiddleware to filter incoming ContinueConversation events.
- Introduced EventActivityNames class with constant strings for ContinueConversation so we don't have those strings hardcoded.
- Added also CreateConversation to the EventActivityNames helper (not related to this issue but saw it and decided to add it since it is better to have constants).
- Refactored ConversationReferenceEx to use the new constant (and use more straightforward code to create the event).
- Added tests for new logic in TranscriptLoggerMiddleware.
- Updated Skills testing projects to use the new constant

* Renamed EventActivityNames to ActivityEventNames

* Updated a couple of files that I missed after the rename.
This commit is contained in:
Gabo Gilabert 2020-10-19 18:31:19 -04:00 коммит произвёл GitHub
Родитель 1f92e66b28
Коммит 569f6a523e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 100 добавлений и 36 удалений

Просмотреть файл

@ -28,7 +28,7 @@ namespace Microsoft.BotBuilderSamples.AdaptiveRootBot.Middleware
{
// Note: skill responses will show as ContinueConversation events; we don't log those.
// We only log incoming messages from users.
if (turnContext.Activity.Type != ActivityTypes.Event && turnContext.Activity.Name != "ContinueConversation")
if (!(turnContext.Activity.Type == ActivityTypes.Event && turnContext.Activity.Name == ActivityEventNames.ContinueConversation))
{
var message = $"User said: {turnContext.Activity.Text} Type: \"{turnContext.Activity.Type}\" Name: \"{turnContext.Activity.Name}\"";
_logger.LogInformation(message);

Просмотреть файл

@ -28,7 +28,7 @@ namespace Microsoft.BotBuilderSamples.DialogRootBot.Middleware
{
// Note: skill responses will show as ContinueConversation events; we don't log those.
// We only log incoming messages from users.
if (turnContext.Activity.Type != ActivityTypes.Event && turnContext.Activity.Name != "ContinueConversation")
if (!(turnContext.Activity.Type == ActivityTypes.Event && turnContext.Activity.Name == ActivityEventNames.ContinueConversation))
{
var message = $"User said: {turnContext.Activity.Text} Type: \"{turnContext.Activity.Type}\" Name: \"{turnContext.Activity.Name}\"";
_logger.LogInformation(message);

Просмотреть файл

@ -1278,7 +1278,7 @@ namespace Microsoft.Bot.Builder
// Create a conversation update activity to represent the result.
var eventActivity = Activity.CreateEventActivity();
eventActivity.Name = "CreateConversation";
eventActivity.Name = ActivityEventNames.CreateConversation;
eventActivity.ChannelId = channelId;
eventActivity.ServiceUrl = serviceUrl;
eventActivity.Id = result.ActivityId ?? Guid.NewGuid().ToString("n");

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Schema;
@ -17,7 +16,7 @@ namespace Microsoft.Bot.Builder
/// </summary>
public class TranscriptLoggerMiddleware : IMiddleware
{
private static readonly JsonSerializerSettings _jsonSettings = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore };
private static readonly JsonSerializerSettings _jsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
private readonly ITranscriptLogger _logger;
/// <summary>
@ -41,22 +40,23 @@ namespace Microsoft.Bot.Builder
/// <seealso cref="Bot.Schema.IActivity"/>
public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate nextTurn, CancellationToken cancellationToken)
{
Queue<IActivity> transcript = new Queue<IActivity>();
var transcript = new Queue<IActivity>();
// log incoming activity at beginning of turn
if (turnContext.Activity != null)
{
if (turnContext.Activity.From == null)
{
turnContext.Activity.From = new ChannelAccount();
}
turnContext.Activity.From ??= new ChannelAccount();
if (string.IsNullOrEmpty((string)turnContext.Activity.From.Properties["role"]))
{
turnContext.Activity.From.Properties["role"] = "user";
}
LogActivity(transcript, CloneActivity(turnContext.Activity));
// We should not log ContinueConversation events used by skills to initialize the middleware.
if (!(turnContext.Activity.Type == ActivityTypes.Event && turnContext.Activity.Name == ActivityEventNames.ContinueConversation))
{
LogActivity(transcript, CloneActivity(turnContext.Activity));
}
}
// hook up onSend pipeline
@ -95,12 +95,12 @@ namespace Microsoft.Bot.Builder
// add MessageDelete activity
// log as MessageDelete activity
var deleteActivity = new Activity
{
Type = ActivityTypes.MessageDelete,
Id = reference.ActivityId,
}
.ApplyConversationReference(reference, isIncoming: false)
.AsMessageDeleteActivity();
{
Type = ActivityTypes.MessageDelete,
Id = reference.ActivityId,
}
.ApplyConversationReference(reference, isIncoming: false)
.AsMessageDeleteActivity();
LogActivity(transcript, deleteActivity);
});
@ -163,11 +163,7 @@ namespace Microsoft.Bot.Builder
private static void LogActivity(Queue<IActivity> transcript, IActivity activity)
{
if (activity.Timestamp == null)
{
activity.Timestamp = DateTime.UtcNow;
}
activity.Timestamp ??= DateTime.UtcNow;
transcript.Enqueue(activity);
}
}

Просмотреть файл

@ -275,7 +275,7 @@ namespace Microsoft.Bot.Connector
Dictionary<string, object> tracingParameters = new Dictionary<string, object>();
tracingParameters.Add("parameters", parameters);
tracingParameters.Add("cancellationToken", cancellationToken);
ServiceClientTracing.Enter(_invocationId, this, "CreateConversation", tracingParameters);
ServiceClientTracing.Enter(_invocationId, this, ActivityEventNames.CreateConversation, tracingParameters);
}
// Construct URL
var _baseUrl = Client.BaseUri.AbsoluteUri;

Просмотреть файл

@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Bot.Schema
{
/// <summary>
/// Define values for common event names used by activities of type <see cref="ActivityTypes.Event"/>.
/// </summary>
public static class ActivityEventNames
{
/// <summary>
/// The event name for continuing a conversation.
/// </summary>
public const string ContinueConversation = "ContinueConversation";
/// <summary>
/// The event name for creating a conversation.
/// </summary>
public const string CreateConversation = "CreateConversation";
}
}

Просмотреть файл

@ -16,17 +16,18 @@ namespace Microsoft.Bot.Schema
/// <returns>Continuation activity.</returns>
public Activity GetContinuationActivity()
{
var activity = Activity.CreateEventActivity();
activity.Name = "ContinueConversation";
activity.Id = Guid.NewGuid().ToString();
activity.ChannelId = this.ChannelId;
(activity as Activity).Locale = this.Locale;
activity.ServiceUrl = this.ServiceUrl;
activity.Conversation = this.Conversation;
activity.Recipient = this.Bot;
activity.From = this.User;
activity.RelatesTo = this;
return (Activity)activity;
return new Activity(ActivityTypes.Event)
{
Name = ActivityEventNames.ContinueConversation,
Id = Guid.NewGuid().ToString(),
ChannelId = ChannelId,
Locale = Locale,
ServiceUrl = ServiceUrl,
Conversation = Conversation,
Recipient = Bot,
From = User,
RelatesTo = this
};
}
}
}

Просмотреть файл

@ -59,7 +59,7 @@ namespace Microsoft.Bot.Builder.Azure.Tests
var messageJson = Encoding.UTF8.GetString(Convert.FromBase64String(message.MessageText));
var activity = JsonConvert.DeserializeObject<Activity>(messageJson);
Assert.Equal(ActivityTypes.Event, activity.Type);
Assert.Equal("ContinueConversation", activity.Name);
Assert.Equal(ActivityEventNames.ContinueConversation, activity.Name);
Assert.Equal("foo", activity.Value);
Assert.NotNull(activity.RelatesTo);
var cr2 = activity.GetConversationReference();

Просмотреть файл

@ -64,7 +64,7 @@ namespace Microsoft.Bot.Builder.Tests
const string conversationIdName = "Id";
const string conversationIdValue = "NewConversationId";
const string tenantIdValue = "theTenantId";
const string eventActivityName = "CreateConversation";
const string eventActivityName = ActivityEventNames.CreateConversation;
Task<HttpResponseMessage> CreateResponseMessage()
{

Просмотреть файл

@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Adapters;
using Microsoft.Bot.Schema;
using Xunit;
namespace Microsoft.Bot.Builder.Tests
{
public class TranscriptLoggerMiddlewareTests
{
[Fact]
public async Task ShouldNotLogContinueConversation()
{
var transcriptStore = new MemoryTranscriptStore();
var sut = new TranscriptLoggerMiddleware(transcriptStore);
var conversationId = Guid.NewGuid().ToString();
var adapter = new TestAdapter(TestAdapter.CreateConversation(conversationId))
.Use(sut);
await new TestFlow(adapter, async (context, cancellationToken) =>
{
await context.SendActivityAsync("bar", cancellationToken: cancellationToken);
})
.Send("foo")
.AssertReply(async activity =>
{
Assert.Equal("bar", ((Activity)activity).Text);
var activities = await transcriptStore.GetTranscriptActivitiesAsync(activity.ChannelId, conversationId);
Assert.Equal(2, activities.Items.Length);
})
.Send(new Activity(ActivityTypes.Event) { Name = ActivityEventNames.ContinueConversation })
.AssertReply(async activity =>
{
// Ensure the event hasn't been added to the transcript.
var activities = await transcriptStore.GetTranscriptActivitiesAsync(activity.ChannelId, conversationId);
Assert.DoesNotContain(activities.Items, a => ((Activity)a).Type == ActivityTypes.Event && ((Activity)a).Name == ActivityEventNames.ContinueConversation);
Assert.Equal(3, activities.Items.Length);
})
.StartTestAsync();
}
}
}