diff --git a/docs/_getting_started/configuration.md b/docs/_getting_started/configuration.md index e34b30ad6..9e1910726 100644 --- a/docs/_getting_started/configuration.md +++ b/docs/_getting_started/configuration.md @@ -202,6 +202,10 @@ RubyLLM.configure do |config| # Or use Rails logger config.logger = Rails.logger # Overrides log_file and log_level + + # Set custom timeout for log filtering + # which is useful when working with large payloads + config.log_regexp_timeout = 4 # seconds end ``` @@ -354,6 +358,7 @@ RubyLLM.configure do |config| config.log_file = String config.log_level = Symbol config.log_stream_debug = Boolean + config.log_regexp_timeout = Integer end ``` @@ -363,4 +368,4 @@ Now that you've configured RubyLLM, you're ready to: - [Start chatting with AI models]({% link _core_features/chat.md %}) - [Work with different providers and models]({% link _advanced/models.md %}) -- [Set up Rails integration]({% link _advanced/rails.md %}) \ No newline at end of file +- [Set up Rails integration]({% link _advanced/rails.md %}) diff --git a/lib/ruby_llm/configuration.rb b/lib/ruby_llm/configuration.rb index eda2c3354..dc1cc2e44 100644 --- a/lib/ruby_llm/configuration.rb +++ b/lib/ruby_llm/configuration.rb @@ -43,7 +43,8 @@ class Configuration :logger, :log_file, :log_level, - :log_stream_debug + :log_stream_debug, + :log_regexp_timeout def initialize @request_timeout = 120 @@ -64,6 +65,7 @@ def initialize @log_file = $stdout @log_level = ENV['RUBYLLM_DEBUG'] ? Logger::DEBUG : Logger::INFO @log_stream_debug = ENV['RUBYLLM_STREAM_DEBUG'] == 'true' + @log_regexp_timeout = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2.0') ? (Regexp.timeout || 1.0) : nil end def instance_variables diff --git a/lib/ruby_llm/connection.rb b/lib/ruby_llm/connection.rb index 52252781c..fd18c8d45 100644 --- a/lib/ruby_llm/connection.rb +++ b/lib/ruby_llm/connection.rb @@ -66,8 +66,19 @@ def setup_logging(faraday) errors: true, headers: false, log_level: :debug do |logger| - logger.filter(%r{[A-Za-z0-9+/=]{100,}}, 'data":"[BASE64 DATA]"') - logger.filter(/[-\d.e,\s]{100,}/, '[EMBEDDINGS ARRAY]') + if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2.0') + logger.filter( + Regexp.new('[A-Za-z0-9+/=]{100,}', timeout: @config.log_regexp_timeout), + 'data":"[BASE64 DATA]"' + ) + logger.filter(Regexp.new('[-\\d.e,\\s]{100,}', timeout: @config.log_regexp_timeout), '[EMBEDDINGS ARRAY]') + else + if @config.log_regexp_timeout + RubyLLM.logger.warn("log_regexp_timeout is not supported on Ruby #{RUBY_VERSION}") + end + logger.filter(Regexp.new('[A-Za-z0-9+/=]{100,}'), 'data":"[BASE64 DATA]"') + logger.filter(Regexp.new('[-\\d.e,\\s]{100,}'), '[EMBEDDINGS ARRAY]') + end end end diff --git a/spec/ruby_llm/context_spec.rb b/spec/ruby_llm/context_spec.rb index 2bbb25626..a05c8a6fd 100644 --- a/spec/ruby_llm/context_spec.rb +++ b/spec/ruby_llm/context_spec.rb @@ -10,20 +10,24 @@ # Get current config values original_model = RubyLLM.config.default_model original_api_key = RubyLLM.config.openai_api_key + original_log_regexp_timeout = RubyLLM.config.log_regexp_timeout # Create context with modified config context = RubyLLM.context do |config| config.default_model = 'modified-model' config.openai_api_key = 'modified-key' + config.log_regexp_timeout = 5.0 end # Verify global config is unchanged expect(RubyLLM.config.default_model).to eq(original_model) expect(RubyLLM.config.openai_api_key).to eq(original_api_key) + expect(RubyLLM.config.log_regexp_timeout).to eq(original_log_regexp_timeout) # Verify context has modified config expect(context.config.default_model).to eq('modified-model') expect(context.config.openai_api_key).to eq('modified-key') + expect(context.config.log_regexp_timeout).to eq(5.0) end end @@ -95,6 +99,7 @@ it 'allows multiple contexts with different configurations' do context1 = RubyLLM.context do |config| config.default_model = 'gpt-4.1-nano' + config.log_regexp_timeout = 5.0 end context2 = RubyLLM.context do |config| @@ -105,7 +110,11 @@ chat2 = context2.chat expect(chat1.model.id).to eq('gpt-4.1-nano') + expect(context1.config.log_regexp_timeout).not_to eq(Regexp.timeout) + expect(context1.config.log_regexp_timeout).to eq(5.0) + expect(chat2.model.id).to eq('claude-3-5-haiku-20241022') + expect(context2.config.log_regexp_timeout).to eq(Regexp.timeout) end it 'ensures changes in one context do not affect another' do