/// <inheritdoc/> public async Task <UserDetails> GetUserDetails(string userId, string conversationId = null) { UserCacheEntry cacheEntry; bool result = _userCache.TryGetValue(userId.ToLower(), out cacheEntry); if (result) { return(cacheEntry.user); } else { UserDetails currUser = new UserDetails(); string uri = $"/users/{userId}"; try { HttpResponseMessage response = await MakeGetCallToFreshChat(uri); string responseContent = await response.Content.ReadAsStringAsync(); var jsonResponse = JToken.Parse(responseContent); currUser.Id = userId; currUser.ReferenceId = (string)jsonResponse["reference_id"]; currUser.FirstName = !string.IsNullOrWhiteSpace(currUser.ReferenceId) && currUser.ReferenceId.Split("sites/").Length > 1 ? currUser.ReferenceId.Split("sites/")[1] : (string)jsonResponse["first_name"]; currUser.LastName = string.Empty; currUser.Email = string.Empty; currUser.Avatar = new Avatar() { Url = (string)jsonResponse["avatar"].Value <JToken>("url") }; // Add to cache for future lookups AddOrUpdateUser(currUser.Id, currUser); // Update the _resourceConversationCache if (!string.IsNullOrWhiteSpace(conversationId)) { AddOrUpdateResourceUri(conversationId, currUser.ReferenceId); } return(currUser); } catch (Exception ex) { InternalEventBody kustoLog = new InternalEventBody(); kustoLog.EventType = "FreshChatLoggingUnhandledException"; kustoLog.EventContent = $"FreshChatException. Unhandled {ex.GetType().ToString()} exception while calling FreshChat server to fetch sender details. URI: {uri}"; await LogToKusto(kustoLog); throw ex; } } }
/// <inheritdoc/> public async Task <AgentDetails> GetAgentDetails(string agentId) { AgentCacheEntry cacheEntry; bool result = _agentCache.TryGetValue(agentId.ToLower(), out cacheEntry); if (result) { return(cacheEntry.agent); } else { AgentDetails currAgent = new AgentDetails(); string uri = $"/agents/{agentId}"; try { HttpResponseMessage response = await MakeGetCallToFreshChat(uri); string responseContent = await response.Content.ReadAsStringAsync(); var jsonResponse = JToken.Parse(responseContent); currAgent.Id = agentId; currAgent.FirstName = (string)jsonResponse["first_name"]; currAgent.LastName = (string)jsonResponse["last_name"]; currAgent.Email = (string)jsonResponse["email"]; currAgent.Avatar = new Avatar() { Url = (string)jsonResponse["avatar"].Value <JToken>("url") }; // Add to cache for future lookups AddOrUpdateAgent(currAgent.Id, currAgent); return(currAgent); } catch (Exception ex) { InternalEventBody kustoLog = new InternalEventBody(); kustoLog.EventType = "FreshChatLoggingUnhandledException"; kustoLog.EventContent = $"FreshChatException. Unhandled {ex.GetType().ToString()} exception while calling FreshChat server to fetch sender details. URI: {uri}"; await LogToKusto(kustoLog); throw ex; } } }
public async Task <IActionResult> LogEvent([FromBody] InternalEventBody postBody) { var eventType = postBody.EventType; var eventContent = postBody.EventContent; switch (postBody.EventType) { case "UnhandledException": var unhandledException = JsonConvert.DeserializeObject <InternalAPIException>(eventContent); DiagnosticsETWProvider.Instance.LogInternalAPIHandledException(unhandledException.RequestId, unhandledException.ExceptionType, unhandledException.ExceptionDetails); break; case "HandledException": var handledException = JsonConvert.DeserializeObject <InternalAPIException>(eventContent); DiagnosticsETWProvider.Instance.LogInternalAPIHandledException(handledException.RequestId, handledException.ExceptionType, handledException.ExceptionDetails); break; case "TrainingException": var trainingException = JsonConvert.DeserializeObject <InternalAPITrainingException>(eventContent); DiagnosticsETWProvider.Instance.LogInternalAPITrainingException(trainingException.RequestId, trainingException.TrainingId, trainingException.ProductId, trainingException.ExceptionType, trainingException.ExceptionDetails); break; case "Insights": var insights = JsonConvert.DeserializeObject <InternalAPIInsights>(eventContent); DiagnosticsETWProvider.Instance.LogInternalAPIInsights(insights.RequestId, insights.Message); break; case "APISummary": var apiSummary = JsonConvert.DeserializeObject <InternalAPISummary>(eventContent); DiagnosticsETWProvider.Instance.LogInternalAPISummary(apiSummary.RequestId, apiSummary.OperationName, apiSummary.StatusCode, apiSummary.LatencyInMilliseconds, apiSummary.StartTime, apiSummary.EndTime, apiSummary.Content); break; case "TrainingSummary": var trainingSummary = JsonConvert.DeserializeObject <InternalAPITrainingSummary>(eventContent); DiagnosticsETWProvider.Instance.LogInternalAPITrainingSummary(trainingSummary.RequestId, trainingSummary.TrainingId, trainingSummary.ProductId, trainingSummary.LatencyInMilliseconds, trainingSummary.StartTime, trainingSummary.EndTime, trainingSummary.Content); break; default: DiagnosticsETWProvider.Instance.LogInternalAPIMessage(eventContent); break; } return(Ok()); }
/// <inheritdoc/> public async Task <bool> LogToKusto(InternalEventBody logMessage) { try { string body = JsonConvert.SerializeObject(logMessage); var response = await _diagnosticClient.Execute("POST", "/internal/logger", body); response.EnsureSuccessStatusCode(); return(true); } catch (JsonSerializationException jsException) { throw new JsonSerializationException("FreshChatException. Failed to serialize data while sending a request to log in Kusto.", jsException); } catch (HttpRequestException hException) { throw new HttpRequestException("FreshChatException. Failed to send a log in Kusto.", hException); } catch (Exception ex) { throw new Exception("FreshChatException. Unknown exception. Review for more details.", ex); } }
public async Task <IActionResult> ChatHook([FromBody] JToken body) { if (body != null) { try { DateTime startTime = DateTime.Now; FreshChatPayload incomingPayload = incomingPayload = body.ToObject <FreshChatPayload>(); ChatMessageToLog logMsg = null; InternalEventBody kustoLog = new InternalEventBody(); switch (incomingPayload.Action) { case Actions.MessageCreate: MessageCreateData msgData = (MessageCreateData)incomingPayload.Data; logMsg = new ChatMessageToLog(msgData.Message.Id, msgData.Message.ChannelId, msgData.Message.ConversationId, msgData.Message.CreatedTime, msgData.Message.MessageType); logMsg.Sender = await GetMessageSenderDetails(msgData.Message.ActorId, msgData.Message.ActorType, logMsg.ConversationId); logMsg.ResourceUri = _freshChatClientService.GetResourceUri(logMsg.ConversationId); if (msgData.Message.MsgParts != null && msgData.Message.MsgParts.Count > 0) { logMsg.TextContent = ExtractAllTextContent(msgData.Message.MsgParts); logMsg.ImageUrls = ExtractAllImageUrls(msgData.Message.MsgParts); } if (msgData.Message.ReplyParts != null && msgData.Message.ReplyParts.Count > 0) { logMsg.TextContent = ExtractAllTextContent(msgData.Message.ReplyParts); logMsg.ImageUrls = ExtractAllImageUrls(msgData.Message.ReplyParts); } break; case Actions.ConversationReopen: ReopenDetails reopenData = ((ConvReopenData)incomingPayload.Data).Reopen; logMsg = new ChatMessageToLog(string.Empty, reopenData.Conversation.ChannelId, reopenData.Conversation.ConversationId, incomingPayload.ActionTime, MessageTypes.Private); logMsg.TextContent = new List <string>(); logMsg.Sender = await GetMessageSenderDetails(reopenData.ReopenerId, reopenData.Reopener, logMsg.ConversationId); logMsg.ResourceUri = _freshChatClientService.GetResourceUri(logMsg.ConversationId); logMsg.TextContent.Add($"Conversation re-opened by {reopenData.Reopener.ToString()}."); break; case Actions.ConversationAssignment: AssignmentDetails assignmentData = ((ConvAssignmentData)incomingPayload.Data).Assignment; logMsg = new ChatMessageToLog(string.Empty, assignmentData.Conversation.ChannelId, assignmentData.Conversation.ConversationId, incomingPayload.ActionTime, MessageTypes.Private); string assignedToDetails = string.Empty; if (string.IsNullOrWhiteSpace(assignmentData.Conversation.AssignedAgentId)) { // Conversation assigned to a group and waiting to be assigned to an agent logMsg.Sender = await GetMessageSenderDetails(string.IsNullOrWhiteSpace(incomingPayload.Actor.ActorId)?assignmentData.Conversation.AssignedGroupId : incomingPayload.Actor.ActorId, incomingPayload.Actor.ActorType, logMsg.ConversationId); logMsg.ResourceUri = _freshChatClientService.GetResourceUri(logMsg.ConversationId); assignedToDetails = " to group"; } else { // Conversation assigned to an agent. logMsg.Sender = await GetMessageSenderDetails(string.IsNullOrWhiteSpace(incomingPayload.Actor.ActorId)?assignmentData.Conversation.AssignedGroupId : incomingPayload.Actor.ActorId, incomingPayload.Actor.ActorType, logMsg.ConversationId); logMsg.ResourceUri = _freshChatClientService.GetResourceUri(logMsg.ConversationId); PersonDetails assignedAgent = await GetMessageSenderDetails(assignmentData.Conversation.AssignedAgentId, ActorTypes.Agent, logMsg.ConversationId); assignedToDetails = $" to agent {assignedAgent.FirstName} {assignedAgent.LastName} ({assignedAgent.Email})"; } logMsg.TextContent = new List <string>(); logMsg.TextContent.Add($"Conversation assigned {assignedToDetails}."); break; case Actions.ConversationResolution: ResolveDetails resolveData = ((ConvResolutionData)incomingPayload.Data).Resolve; logMsg = new ChatMessageToLog(string.Empty, resolveData.Conversation.ChannelId, resolveData.Conversation.ConversationId, incomingPayload.ActionTime, MessageTypes.Private); logMsg.Sender = await GetMessageSenderDetails(resolveData.ResolverId, resolveData.Resolver, logMsg.ConversationId); logMsg.ResourceUri = _freshChatClientService.GetResourceUri(logMsg.ConversationId); logMsg.TextContent = new List <string>(); logMsg.TextContent.Add($"Conversation resolved by {resolveData.Resolver.ToString()}."); break; default: kustoLog.EventType = "FreshChatLoggingUnhandledException"; // Remove PII function will likely garble the text body and make the object non serializable however it will be helpful for a human to debug the problem. kustoLog.EventContent = $"FreshChatException. Unhandled message type {incomingPayload.Action.ToString()}. Unable to handle. Body : {_freshChatClientService.RemovePII(JsonConvert.SerializeObject(body))}"; _freshChatClientService.LogToKusto(kustoLog); throw new Exception($"FreshChatException. Unhandled message type {incomingPayload.Action.ToString()}. Unable to handle."); } if (logMsg == null) { return(new BadRequestResult()); } else { logMsg.TimeInMilliSeconds = DateTime.Now.Subtract(startTime).TotalMilliseconds; kustoLog.EventType = "FreshChatMessage"; kustoLog.EventContent = JsonConvert.SerializeObject(logMsg); _freshChatClientService.LogToKusto(kustoLog); return(Content(JsonConvert.SerializeObject(logMsg))); } } catch (JsonSerializationException sException) { InternalEventBody kustoLog = new InternalEventBody(); kustoLog.EventType = "FreshChatLoggingUnhandledException"; // Remove PII function will likely garble the text body and make the object non serializable however it will be helpful for a human to debug the problem. kustoLog.EventContent = JsonConvert.SerializeObject(new JsonSerializationException("FreshChatException. Failed to deserialize the incoming data.", sException)); _freshChatClientService.LogToKusto(kustoLog); throw new JsonSerializationException("FreshChatException. Failed to deserialize the incoming data.", sException); } catch (Exception ex) { InternalEventBody kustoLog = new InternalEventBody(); kustoLog.EventType = "FreshChatLoggingUnhandledException"; // Remove PII function will likely garble the text body and make the object non serializable however it will be helpful for a human to debug the problem. kustoLog.EventContent = JsonConvert.SerializeObject(new ArgumentException("FreshChatException. Unknwon error while trying to read the incoming post body ", ex)); _freshChatClientService.LogToKusto(kustoLog); throw new ArgumentException("FreshChatException. Unknwon error while trying to read the incoming post body ", ex); } } else { return(BadRequest("Empty post body")); } }