From 8ae80ce6fcf427d80d50fb0847a5401b8ab77a96 Mon Sep 17 00:00:00 2001 From: st0012 Date: Mon, 16 Mar 2026 11:18:33 +0000 Subject: [PATCH 1/4] Silence stats progress bar in server mode The stats object created during initial parsing prints a progress bar with \r on a tty, which collides with the server's own stderr output. Set verbosity to 0 (quiet) since the server handles its own logging. --- lib/rdoc/server.rb | 2 ++ lib/rdoc/stats.rb | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/rdoc/server.rb b/lib/rdoc/server.rb index 3d08d18248..3c6df59adc 100644 --- a/lib/rdoc/server.rb +++ b/lib/rdoc/server.rb @@ -67,6 +67,8 @@ def initialize(rdoc, port) @store = rdoc.store @port = port + # Silence stats output — the server prints its own timing. + @rdoc.stats.verbosity = 0 @generator = create_generator @template_dir = File.expand_path(@generator.template_dir) @page_cache = {} diff --git a/lib/rdoc/stats.rb b/lib/rdoc/stats.rb index d5e9d358ac..683fe4a19a 100644 --- a/lib/rdoc/stats.rb +++ b/lib/rdoc/stats.rb @@ -39,10 +39,17 @@ def initialize(store, num_files, verbosity = 1) @start = Time.now @undoc_params = 0 + self.verbosity = verbosity + end + + ## + # Sets the verbosity level, rebuilding the display outputter. + + def verbosity=(verbosity) @display = case verbosity - when 0 then Quiet.new num_files - when 1 then Normal.new num_files - else Verbose.new num_files + when 0 then Quiet.new @num_files + when 1 then Normal.new @num_files + else Verbose.new @num_files end end From 819b0d841ea7eb484847e1af597116a05fa7753c Mon Sep 17 00:00:00 2001 From: st0012 Date: Mon, 16 Mar 2026 11:18:45 +0000 Subject: [PATCH 2/4] Print response time for page requests in server mode Log status, path, and duration for page requests only (not assets or status polls). Example: 200 /RDoc.html (12.3ms) --- lib/rdoc/server.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/rdoc/server.rb b/lib/rdoc/server.rb index 3c6df59adc..a392f00200 100644 --- a/lib/rdoc/server.rb +++ b/lib/rdoc/server.rb @@ -104,6 +104,12 @@ def start private + def measure + start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) + yield + ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time) * 1000).round(1) + end + def create_generator gen = RDoc::Generator::Aliki.new(@store, @options) gen.file_output = false @@ -140,7 +146,14 @@ def handle_client(client) return write_response(client, 405, 'text/plain', 'Method Not Allowed') end - status, content_type, body = route(path) + if path.start_with?('/__') || %r{\A/(?:css|js)/}.match?(path) + status, content_type, body = route(path) + else + duration_ms = measure do + status, content_type, body = route(path) + end + $stderr.puts "#{status} #{path} (#{duration_ms}ms)" + end write_response(client, status, content_type, body) rescue => e write_response(client, 500, 'text/html', <<~HTML) From 2e1fe471125780c0105e52f1c775bfff4d7c7d17 Mon Sep 17 00:00:00 2001 From: st0012 Date: Mon, 16 Mar 2026 11:18:50 +0000 Subject: [PATCH 3/4] Print re-parse duration in server mode Show relative file paths and timing after re-parsing changed files. Example: Re-parsed lib/rdoc.rb (17.5ms) --- lib/rdoc/server.rb | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/rdoc/server.rb b/lib/rdoc/server.rb index a392f00200..2eab33c68d 100644 --- a/lib/rdoc/server.rb +++ b/lib/rdoc/server.rb @@ -362,19 +362,23 @@ def reparse_and_refresh(changed_files, removed_files) end unless changed_files.empty? - $stderr.puts "Re-parsing: #{changed_files.join(', ')}" - changed_files.each do |f| - begin + changed_file_names = [] + duration_ms = measure do + changed_files.each do |f| relative = @rdoc.relative_path_for(f) - @store.clear_file_contributions(relative, keep_position: true) - @rdoc.parse_file(f) - @file_mtimes[f] = File.mtime(f) rescue nil - rescue => e - $stderr.puts "Error parsing #{f}: #{e.message}" + changed_file_names << relative + begin + @store.clear_file_contributions(relative, keep_position: true) + @rdoc.parse_file(f) + @file_mtimes[f] = File.mtime(f) rescue nil + rescue => e + $stderr.puts "Error parsing #{f}: #{e.message}" + end end - end - @store.cleanup_stale_contributions + @store.cleanup_stale_contributions + end + $stderr.puts "Re-parsed #{changed_file_names.join(', ')} (#{duration_ms}ms)" end @store.complete(@options.visibility) From be7f56778c8bae8267e3a19b5246e58b30b564a5 Mon Sep 17 00:00:00 2001 From: st0012 Date: Mon, 16 Mar 2026 11:28:57 +0000 Subject: [PATCH 4/4] Suppress Errno::EPIPE in server response writes The browser may close the connection before the server finishes writing (e.g. during live-reload navigation). This is harmless, so rescue it silently instead of printing a noisy thread backtrace. --- lib/rdoc/server.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rdoc/server.rb b/lib/rdoc/server.rb index 2eab33c68d..9dbb342908 100644 --- a/lib/rdoc/server.rb +++ b/lib/rdoc/server.rb @@ -200,6 +200,8 @@ def write_response(client, status, content_type, body) client.write(header) client.write(body_bytes) client.flush + rescue Errno::EPIPE + # Client disconnected before we finished writing — harmless. end ##