From 3a07f675e67aa0fcd1ac7446ad7aa66925c52a2a Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 30 Jul 2025 12:23:27 +0530 Subject: [PATCH] feat: add enhanced logging --- enterprise/app/helpers/captain/chat_helper.rb | 49 ++++++++++++++++++- .../conversation/response_builder_job.rb | 2 +- .../captain/llm/assistant_chat_service.rb | 3 +- .../app/services/llm/base_open_ai_service.rb | 19 +++++++ 4 files changed, 69 insertions(+), 4 deletions(-) diff --git a/enterprise/app/helpers/captain/chat_helper.rb b/enterprise/app/helpers/captain/chat_helper.rb index f90b8d07e..b2305ed0c 100644 --- a/enterprise/app/helpers/captain/chat_helper.rb +++ b/enterprise/app/helpers/captain/chat_helper.rb @@ -2,18 +2,54 @@ module Captain::ChatHelper def request_chat_completion log_chat_completion_request + tools = @tool_registry&.registered_tools || [] + temperature = @assistant&.config&.[]('temperature').to_f || 1 + + # Log request details + log_captain_activity(Llm::BaseOpenAiService::REQUEST, { + conversation_id: @conversation&.id, + assistant_id: @assistant&.id, + assistant_name: @assistant&.name, + model: @model, + temperature: temperature, + messages_count: @messages.size, + tools_count: tools.size, + messages: @messages, + tools: tools.map { |tool| tool.dig(:function, :name) } + }) + + start_time = Time.current response = @client.chat( parameters: { model: @model, messages: @messages, - tools: @tool_registry&.registered_tools || [], + tools: tools, response_format: { type: 'json_object' }, - temperature: @assistant&.config&.[]('temperature').to_f || 1 + temperature: temperature } ) + duration_ms = ((Time.current - start_time) * 1000).round + + # Log response details + log_captain_activity(Llm::BaseOpenAiService::RESPONSE, { + conversation_id: @conversation&.id, + duration_ms: duration_ms, + response: response, + usage: response.dig('usage') + }) handle_response(response) rescue StandardError => e + log_captain_activity(Llm::BaseOpenAiService::ERROR, { + conversation_id: @conversation&.id, + error_class: e.class.name, + error_message: e.message, + error_backtrace: e.backtrace&.first(5), + context: { + model: @model, + assistant_id: @assistant&.id + } + }) Rails.logger.error "#{self.class.name} Assistant: #{@assistant.id}, Error in chat completion: #{e}" raise e end @@ -61,6 +97,15 @@ module Captain::ChatHelper 'assistant_thinking' ) result = @tool_registry.send(function_name, arguments) + + # Log tool call details + log_captain_activity(Llm::BaseOpenAiService::TOOL_CALL, { + conversation_id: @conversation&.id, + tool_name: function_name, + arguments: arguments, + result: result.to_s.truncate(1000) + }) + persist_message( { content: I18n.t('captain.copilot.completed_tool_call', function_name: function_name), diff --git a/enterprise/app/jobs/captain/conversation/response_builder_job.rb b/enterprise/app/jobs/captain/conversation/response_builder_job.rb index b207bd2a4..b5a38c4fd 100644 --- a/enterprise/app/jobs/captain/conversation/response_builder_job.rb +++ b/enterprise/app/jobs/captain/conversation/response_builder_job.rb @@ -26,7 +26,7 @@ class Captain::Conversation::ResponseBuilderJob < ApplicationJob delegate :account, :inbox, to: :@conversation def generate_and_process_response - @response = Captain::Llm::AssistantChatService.new(assistant: @assistant).generate_response( + @response = Captain::Llm::AssistantChatService.new(assistant: @assistant, conversation: @conversation).generate_response( message_history: collect_previous_messages ) diff --git a/enterprise/app/services/captain/llm/assistant_chat_service.rb b/enterprise/app/services/captain/llm/assistant_chat_service.rb index ca8fafaa0..f0c07394d 100644 --- a/enterprise/app/services/captain/llm/assistant_chat_service.rb +++ b/enterprise/app/services/captain/llm/assistant_chat_service.rb @@ -3,10 +3,11 @@ require 'openai' class Captain::Llm::AssistantChatService < Llm::BaseOpenAiService include Captain::ChatHelper - def initialize(assistant: nil) + def initialize(assistant: nil, conversation: nil) super() @assistant = assistant + @conversation = conversation @messages = [system_message] @response = '' register_tools diff --git a/enterprise/app/services/llm/base_open_ai_service.rb b/enterprise/app/services/llm/base_open_ai_service.rb index 04909cbf4..ed0e32b5d 100644 --- a/enterprise/app/services/llm/base_open_ai_service.rb +++ b/enterprise/app/services/llm/base_open_ai_service.rb @@ -1,6 +1,12 @@ class Llm::BaseOpenAiService DEFAULT_MODEL = 'gpt-4o-mini'.freeze + # Captain logging event types + REQUEST = 'REQUEST'.freeze + RESPONSE = 'RESPONSE'.freeze + TOOL_CALL = 'TOOL_CALL'.freeze + ERROR = 'ERROR'.freeze + def initialize @client = OpenAI::Client.new( access_token: InstallationConfig.find_by!(name: 'CAPTAIN_OPEN_AI_API_KEY').value, @@ -8,6 +14,7 @@ class Llm::BaseOpenAiService log_errors: Rails.env.development? ) setup_model + @enhanced_logging_enabled = ENV['CAPTAIN_ENHANCED_LOGGING'].present? rescue StandardError => e raise "Failed to initialize OpenAI client: #{e.message}" end @@ -22,4 +29,16 @@ class Llm::BaseOpenAiService config_value = InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_MODEL')&.value @model = (config_value.presence || DEFAULT_MODEL) end + + def log_captain_activity(event_type, log_data = {}) + return unless @enhanced_logging_enabled + + conversation_id = log_data[:conversation_id] + prefix = conversation_id ? "[##{conversation_id}]" : '' + + # Add timestamp to all log data + log_data[:timestamp] = Time.current.iso8601 + + Rails.logger.info "[CAPTAIN_DEBUG] #{prefix} [#{event_type}] #{JSON.pretty_generate(log_data)}" + end end