From 47544cf87b9949b85bb0eabc2bd2757dfad39509 Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Fri, 2 Jan 2026 19:11:48 +1100 Subject: [PATCH 1/4] commit home changes --- lib/outboxer/publisher.rb | 32 +++++++------ lib/outboxer/web/views/home.erb | 68 ++++++++++++++++++++++------ lib/outboxer/web/views/publisher.erb | 2 +- 3 files changed, 72 insertions(+), 30 deletions(-) diff --git a/lib/outboxer/publisher.rb b/lib/outboxer/publisher.rb index 4f7a836c..1378f1b3 100644 --- a/lib/outboxer/publisher.rb +++ b/lib/outboxer/publisher.rb @@ -95,7 +95,7 @@ def find_by_id(id:) def all ActiveRecord::Base.connection_pool.with_connection do ActiveRecord::Base.transaction do - publishers = Models::Publisher.includes(:signals).all + publishers = Models::Publisher.includes(:signals).order(created_at: :asc).all publishers.map do |publisher| { @@ -295,9 +295,7 @@ def create_heartbeat_thread(id:, hostname:, process_id:, ActiveRecord::Base.connection_pool.with_connection do ActiveRecord::Base.transaction do start_rtt = process.clock_gettime(process::CLOCK_MONOTONIC) - publisher = Models::Publisher.lock.find(id) - end_rtt = process.clock_gettime(process::CLOCK_MONOTONIC) rtt = end_rtt - start_rtt @@ -315,19 +313,19 @@ def create_heartbeat_thread(id:, hostname:, process_id:, time_delta = [current_utc_time - last_updated_at, heartbeat_interval].max publisher_thread = Models::Thread - .select( - "COALESCE(SUM(queued_message_count), 0) AS queued_message_count, - COALESCE(SUM(publishing_message_count), 0) AS publishing_message_count, - COALESCE(SUM(published_message_count), 0) AS published_message_count, - COALESCE(SUM(failed_message_count), 0) AS failed_message_count, - MAX(updated_at) AS last_updated_at" - ) + .select(" + COALESCE(SUM(publishing_message_count), 0) AS publishing_message_count, + COALESCE(SUM(published_message_count), 0) AS published_message_count, + COALESCE(SUM(failed_message_count), 0) AS failed_message_count, + + MAX(publishing_message_count_last_updated_at) AS publishing_message_count_last_updated_at, + MAX(published_message_count_last_updated_at) AS published_message_count_last_updated_at, + MAX(failed_message_count_last_updated_at) AS failed_message_count_last_updated_at") .where(hostname: hostname, process_id: process_id) .group(:hostname, :process_id) .take current_counts = { - "queued" => publisher_thread&.queued_message_count || 0, "publishing" => publisher_thread&.publishing_message_count || 0, "published" => publisher_thread&.published_message_count || 0, "failed" => publisher_thread&.failed_message_count || 0 @@ -339,10 +337,14 @@ def create_heartbeat_thread(id:, hostname:, process_id:, h[status] = ((count - prev) / time_delta).round(0) end - latency = 0 + timestamps = [ + publisher_thread.publishing_message_count_last_updated_at, + publisher_thread.published_message_count_last_updated_at, + publisher_thread.failed_message_count_last_updated_at + ].compact - if !publisher_thread.nil? - latency = (current_utc_time - publisher_thread.last_updated_at).round(0) + if !timestamps.empty? + last_message_update = timestamps.max end publisher.update!( @@ -364,7 +366,7 @@ def create_heartbeat_thread(id:, hostname:, process_id:, "count" => current_counts["failed"], "throughput" => throughput_by_status["failed"] }, - "latency" => latency, + "last_message_update" => last_message_update&.iso8601, "cpu" => cpu, "rss" => rss, "rtt" => rtt diff --git a/lib/outboxer/web/views/home.erb b/lib/outboxer/web/views/home.erb index 3fdeb04f..a3677df5 100644 --- a/lib/outboxer/web/views/home.erb +++ b/lib/outboxer/web/views/home.erb @@ -14,14 +14,11 @@ <% else %> Name - Created - Updated Status + Created + Last Updates Throughput - Latency - CPU - RSS - RTT + Metrics Action <% end %> @@ -30,19 +27,62 @@ <% publishers.each do |publisher| %> + "> <%= publisher[:name] %> - - <%= Outboxer::Web.time_ago_in_words(publisher[:created_at]) %> - <%= Outboxer::Web.time_ago_in_words(publisher[:updated_at]) %> + + +
+
+ Concurrency: <%= publisher[:settings]['concurrency'] %>, + Tick: <%= publisher[:settings]['tick_interval'] %>s, + Poll: <%= publisher[:settings]['poll_interval'] %>s, + Heartbeat: <%= publisher[:settings]['heartbeat_interval'] %>s +
+
<%= publisher[:status] %> - <%= Outboxer::Web.pretty_throughput(per_second: publisher[:metrics]['published']['throughput']) %> - <%= Outboxer::Web.pretty_duration_from_seconds(seconds: publisher[:metrics]['latency']) %> - <%= publisher[:metrics]['cpu'].round(0) %>% - <%= Outboxer::Web.human_readable_size(kilobytes: publisher[:metrics]['rss']) %> - <%= Outboxer::Web.pretty_duration_from_seconds(seconds: publisher[:metrics]['rtt']) %> + <%= Outboxer::Web.time_ago_in_words(publisher[:created_at]) %> + +
+ + +
+ Heartbeat: + <%= Outboxer::Web.time_ago_in_words(publisher[:updated_at]) %> +
+ + +
+ Message: + <% if publisher[:metrics]['last_message_update'] %> + <%= Outboxer::Web.time_ago_in_words(Time.iso8601(publisher[:metrics]['last_message_update'])) %> + <% else %> + - + <% end %> +
+ <%= Outboxer::Web.pretty_throughput(per_second: publisher[:metrics]['published']['throughput']) %> + +
+ +
+ CPU: + <%= publisher[:metrics]['cpu'].round(0) %>% +
+ +
+ RSS: + <%= Outboxer::Web.human_readable_size(kilobytes: publisher[:metrics]['rss']) %> +
+ +
+ RTT: + <%= Outboxer::Web.pretty_duration_from_seconds(seconds: publisher[:metrics]['rtt']) %> +
+ +
+
diff --git a/lib/outboxer/web/views/publisher.erb b/lib/outboxer/web/views/publisher.erb index 2f2c5f38..49056dbb 100644 --- a/lib/outboxer/web/views/publisher.erb +++ b/lib/outboxer/web/views/publisher.erb @@ -117,7 +117,7 @@ <%= Outboxer::Web.human_readable_size(kilobytes: publisher[:metrics]['rss']) %> - RTT + Database RTT <%= Outboxer::Web.pretty_duration_from_seconds(seconds: publisher[:metrics]['rtt']) %> From e82e3021f03afcc8cc5fa7886f2240c68e74779e Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Fri, 2 Jan 2026 20:05:15 +1100 Subject: [PATCH 2/4] update UI --- lib/outboxer/message.rb | 2 +- lib/outboxer/web/views/home.erb | 14 ++++++-------- lib/outboxer/web/views/layout.erb | 24 ++++++++++++++++-------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/lib/outboxer/message.rb b/lib/outboxer/message.rb index cc2f8d0c..c4c570f8 100644 --- a/lib/outboxer/message.rb +++ b/lib/outboxer/message.rb @@ -745,7 +745,7 @@ def metrics_by_status(time: Time) "COALESCE(SUM(failed_message_count), 0) AS failed", "COALESCE(SUM(" \ "queued_message_count + publishing_message_count + " \ - "published_message_count + failed_message_count), 0) AS total" + "failed_message_count), 0) AS total" ).take counts_hash = counts.attributes.symbolize_keys.transform_values(&:to_i) diff --git a/lib/outboxer/web/views/home.erb b/lib/outboxer/web/views/home.erb index a3677df5..eeb41fe6 100644 --- a/lib/outboxer/web/views/home.erb +++ b/lib/outboxer/web/views/home.erb @@ -16,7 +16,7 @@ Name Status Created - Last Updates + Updated Throughput Metrics Action @@ -27,19 +27,17 @@ <% publishers.each do |publisher| %> - "> <%= publisher[:name] %> -
- Concurrency: <%= publisher[:settings]['concurrency'] %>, - Tick: <%= publisher[:settings]['tick_interval'] %>s, - Poll: <%= publisher[:settings]['poll_interval'] %>s, - Heartbeat: <%= publisher[:settings]['heartbeat_interval'] %>s + Concurrency: <%= publisher[:settings]['concurrency'] %>, + Poll: <%= publisher[:settings]['poll_interval'] %>s, + Heartbeat: <%= publisher[:settings]['heartbeat_interval'] %>s, + Tick: <%= publisher[:settings]['tick_interval'] %>s
<%= publisher[:status] %> @@ -152,7 +150,7 @@ Status Count - Last Update + Updated Latency diff --git a/lib/outboxer/web/views/layout.erb b/lib/outboxer/web/views/layout.erb index 9ebfb294..b3fa80d4 100644 --- a/lib/outboxer/web/views/layout.erb +++ b/lib/outboxer/web/views/layout.erb @@ -55,7 +55,6 @@
Outboxer - <%= Outboxer::Web.pretty_number(number: message_metrics_by_status[:published][:count]) %>