/// <summary>
        /// Records incoming and outgoing activities to the Application Insights store.
        /// </summary>
        /// <param name="context">The context object for this turn.</param>
        /// <param name="nextTurn">The delegate to call to continue the bot middleware pipeline.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        /// <seealso cref="ITurnContext"/>
        /// <seealso cref="Bot.Schema.IActivity"/>
        public async Task OnTurnAsync(ITurnContext context, NextDelegate nextTurn, CancellationToken cancellationToken)
        {
            BotAssert.ContextNotNull(context);

            context.TurnState.Add(TelemetryLoggerMiddleware.AppInsightsServiceKey, _telemetryClient);

            // log incoming activity at beginning of turn
            if (context.Activity != null)
            {
                var activity = context.Activity;

                // Log the Application Insights Bot Message Received
                _telemetryClient.TrackEventEx(TelemetryLoggerConstants.BotMsgReceiveEvent, activity, null, this.FillReceiveEventProperties(activity));
            }

            // hook up onSend pipeline
            context.OnSendActivities(async(ctx, activities, nextSend) =>
            {
                // run full pipeline
                var responses = await nextSend().ConfigureAwait(false);

                foreach (var activity in activities)
                {
                    _telemetryClient.TrackEventEx(TelemetryLoggerConstants.BotMsgSendEvent, activity, null, this.FillSendEventProperties(activity));
                }

                return(responses);
            });

            // hook up update activity pipeline
            context.OnUpdateActivity(async(ctx, activity, nextUpdate) =>
            {
                // run full pipeline
                var response = await nextUpdate().ConfigureAwait(false);

                _telemetryClient.TrackEventEx(TelemetryLoggerConstants.BotMsgUpdateEvent, activity, null, this.FillUpdateEventProperties(activity));

                return(response);
            });

            // hook up delete activity pipeline
            context.OnDeleteActivity(async(ctx, reference, nextDelete) =>
            {
                // run full pipeline
                await nextDelete().ConfigureAwait(false);

                var deleteActivity = new Activity
                {
                    Type = ActivityTypes.MessageDelete,
                    Id   = reference.ActivityId,
                }
                .ApplyConversationReference(reference, isIncoming: false)
                .AsMessageDeleteActivity();

                _telemetryClient.TrackEventEx(TelemetryLoggerConstants.BotMsgDeleteEvent, deleteActivity as Activity, null, this.FillDeleteEventProperties(deleteActivity));
            });

            if (nextTurn != null)
            {
                await nextTurn(cancellationToken).ConfigureAwait(false);
            }
        }