1_File:

Estimated Time: 15 minutes

Intercepting and analyzing messages

In this lab, we’ll look at some different ways that the Bot Framework allows us to intercept and log data from conversations that the bot has with users. We’ll start by looking at how, without implementing any memory solution, we’re able to view messages and what’s contained in them. This is good for testing purposes, but not ideal for production environments.

After, we’ll look at a very simple implementation of how we can write data from conversations to a file. Specifically, we’ll put messages users send to the bot in a list, and store the list, along with a few other items, in a temporary file (though you could change this to a specific file path as needed).

Lab 1.1: Using the Bot Framework Emulator

Let’s take a look and what information we can glean, for testing purposes, without adding anything to our bot.

Open your PictureBot.sln in Visual Studio. Since we’ve published our bot, we’ll need to add some information to the PictureBot.bot file in order to test our changes locally. In the file, you should see the following contents:

{
  "name": "PictureBot",
  "secretKey": "",
  "services": [
    {
      "appId": "",
      "id": "http://localhost:3978/api/messages",
      "type": "endpoint",
      "appPassword": "",
      "endpoint": "http://localhost:3978/api/messages",
      "name": "PictureBot"
    }
  ]
}

This is what comes in the file when you start from the Template for the v4 SDK. All we have to do is add our appId and appPassword for the Azure Bot Service that we published our bot to. Do that now.

Run your bot, and open the bot in the Bot Framework Emulator, as you have done in previous labs.

A few things you should note:

Emulator

You can read more about testing, debugging, and logging with the emulator here.

Lab 1.2: Logging to a File

Note: We’ve used guidance from the documentation to determine some of the best practices mentioned in this lab.

The memory storage provider uses in-memory storage that gets disposed of when the bot is restarted. This is good for testing purposes only. If you want to persist data but do not want to hook your bot up to a database, you can use the file storage provider. While this provider is also intended for testing purposes, it persists state data to a file so that you can inspect it. The data is written out to file using JSON format.

Since we want to use this process for every message, we’ll use the ConfigureServices method in our Startup class to add storing information to a file. Open that file. Notice that currently we’re using:

IStorage dataStore = new MemoryStorage();

with

middleware.Add(new UserState<UserData>(dataStore));
middleware.Add(new ConversationState<ConversationInfo>(dataStore));

So our current implementation is to use in-memory storage. Again, this memory storage here is recommended for local bot debugging only. When the bot is restarted, anything stored in memory will be gone.

To store our information to a temp file, we’ll need to replace the current IStorage line with:

IStorage dataStore = new FileStorage(System.IO.Path.GetTempPath());

Add the above code and run the bot. In the emulator, go through a sample conversation with the bot.

Next, stop the bot, and open File Explorer. In the location bar type %temp% and hit Enter on your keyboard. This takes you to the location of your temporary files. We recommend sorting the contents so the most recent items are at the top.

The two files you’re looking for start with “conversation” and “user.”

File Explorer view

Inspect the contents of the files (using VSCode, Visual Studio, Notepad, or another JSON editor/viewer). What do you see in there? What don’t you see that you were expecting/hoping to see?

Lab 1.3: Logging Utterances to a File

For the purposes of this lab, we are going to focus on updating the “user” file only.

Next, we may want to add the actual utterances that users are sending to the bot. This could be useful to determine what types of conversations and actions users are trying to complete with the bot.

We can do this by updating what we’re storing in our UserData object in PictureState.cs and by adding information to the object in PictureBot.cs.

In PictureState.cs, after the following code:

public class UserData
    {

        public string Greeted { get; set; } = "not greeted";

add:

// A list of things that users have said to the bot
public List<string> UtteranceList { get; private set; } = new List<string>();

In the above, we’re simple creating a list where we’ll store the list of messages that users send to the bot.

In this example we’re choosing to use the state manager to read and write data, but you could alternatively read and write directly from storage without using state manager.

If you choose to write directly to storage, you could set up eTags depending on your scenario. By setting the eTag property to *, you could allow other instances of the bot to overwrite previously written data, meaning that the last writer wins. We won’t get into it here, but you can read more about managing concurrency.

The final thing we have to do before we run the bot is add messages to our list with our OnTurn action. Open PictureBot.cs.

In PictureBot.cs, after the following code:

public async Task OnTurn(ITurnContext context)
{

    if (context.Activity.Type is ActivityTypes.Message)
    {
        // Get the user and conversation state from the turn context.
        var state = UserState<UserData>.Get(context);
        var conversationInfo = ConversationState<ConversationInfo>.Get(context);

add:

var utterance = context.Activity.Text;
state.UtteranceList.Add(utterance);

The first line takes the incoming message from a user and stores it in a variable called utterance. The next line adds the utterance to the existing list that we created in PictureState.cs.

Run the bot and have a sample conversation with the bot. Stop the bot and check the latest temp file starting with “user.” What do we have now?

Continue to 2_Azure

Back to README