pgbus 0.6.6 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/{javascript → assets/javascripts}/pgbus/stream_source_element.js +9 -3
- data/app/controllers/pgbus/dashboard_controller.rb +4 -0
- data/app/controllers/pgbus/queues_controller.rb +1 -0
- data/app/helpers/pgbus/streams_helper.rb +33 -1
- data/app/views/pgbus/dashboard/_queue_health.html.erb +78 -0
- data/app/views/pgbus/dashboard/show.html.erb +2 -0
- data/app/views/pgbus/queues/show.html.erb +37 -0
- data/config/locales/da.yml +35 -4
- data/config/locales/de.yml +35 -4
- data/config/locales/en.yml +35 -4
- data/config/locales/es.yml +35 -4
- data/config/locales/fi.yml +35 -4
- data/config/locales/fr.yml +35 -4
- data/config/locales/it.yml +35 -4
- data/config/locales/ja.yml +35 -4
- data/config/locales/nb.yml +35 -4
- data/config/locales/nl.yml +35 -4
- data/config/locales/pt.yml +35 -4
- data/config/locales/sv.yml +35 -4
- data/lib/generators/pgbus/templates/migration.rb.erb +6 -0
- data/lib/generators/pgbus/templates/tune_autovacuum.rb.erb +38 -0
- data/lib/generators/pgbus/tune_autovacuum_generator.rb +55 -0
- data/lib/pgbus/autovacuum_tuning.rb +93 -0
- data/lib/pgbus/client.rb +13 -1
- data/lib/pgbus/engine.rb +23 -0
- data/lib/pgbus/generators/migration_detector.rb +38 -3
- data/lib/pgbus/streams/turbo_stream_override.rb +10 -0
- data/lib/pgbus/version.rb +1 -1
- data/lib/pgbus/web/data_source.rb +133 -1
- data/lib/pgbus/web/metrics_serializer.rb +71 -2
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b4d9e527a08c8660868590840ae8f3f311e9f4d7fe20f1f2b83018c9cc30d904
|
|
4
|
+
data.tar.gz: 9113b68be4f3772f74488e4229685220a1daa649d3d8726d2fd044afbe1b070a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 745010fa781503049ab585e6cc08b21420b8d118017be91eaab35d3c94c681836ff5f98c99d5f099fce5249cb45fc7d8b725e06dc569d1c040084a6b2d086911
|
|
7
|
+
data.tar.gz: 50df9a8d99532bf4efa3c03dd0be48e24f123f8ea937f0f7475ff8dfcf1d0242267568f426bdcc76089bacdd1538926b748f032ff977841b08f3665723e4c792
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
// automatically based on the last id: we observed. The native
|
|
36
36
|
// client is more battle-tested for reconnection backoff.
|
|
37
37
|
|
|
38
|
-
import {
|
|
38
|
+
import { Turbo } from "@hotwired/turbo-rails"
|
|
39
|
+
const { connectStreamSource, disconnectStreamSource } = Turbo
|
|
39
40
|
|
|
40
41
|
class PgbusStreamSourceElement extends HTMLElement {
|
|
41
42
|
static get observedAttributes() {
|
|
@@ -51,6 +52,7 @@ class PgbusStreamSourceElement extends HTMLElement {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
connectedCallback() {
|
|
55
|
+
this.closed = false
|
|
54
56
|
connectStreamSource(this)
|
|
55
57
|
const sinceId = this.getAttribute("since-id")
|
|
56
58
|
this.lastEventId = sinceId && sinceId !== "" ? sinceId : null
|
|
@@ -106,7 +108,11 @@ class PgbusStreamSourceElement extends HTMLElement {
|
|
|
106
108
|
|
|
107
109
|
while (!this.closed) {
|
|
108
110
|
const { value, done } = await reader.read()
|
|
109
|
-
if (done)
|
|
111
|
+
if (done) {
|
|
112
|
+
this.removeAttribute("connected")
|
|
113
|
+
this.switchToEventSource()
|
|
114
|
+
return
|
|
115
|
+
}
|
|
110
116
|
|
|
111
117
|
buffer += decoder.decode(value, { stream: true })
|
|
112
118
|
const events = buffer.split("\n\n")
|
|
@@ -131,7 +137,7 @@ class PgbusStreamSourceElement extends HTMLElement {
|
|
|
131
137
|
switchToEventSource() {
|
|
132
138
|
if (this.closed) return
|
|
133
139
|
|
|
134
|
-
const url = this.buildUrl({ includeSince:
|
|
140
|
+
const url = this.buildUrl({ includeSince: true })
|
|
135
141
|
this.eventSource = new EventSource(url, { withCredentials: true })
|
|
136
142
|
|
|
137
143
|
this.eventSource.addEventListener("open", () => {
|
|
@@ -16,11 +16,15 @@ module Pgbus
|
|
|
16
16
|
when "failures"
|
|
17
17
|
@recent_failures = data_source.failed_events(page: 1, per_page: 5)
|
|
18
18
|
render_frame("pgbus/dashboard/recent_failures")
|
|
19
|
+
when "health"
|
|
20
|
+
@health = data_source.queue_health_stats
|
|
21
|
+
render_frame("pgbus/dashboard/queue_health")
|
|
19
22
|
else
|
|
20
23
|
@stats = data_source.summary_stats
|
|
21
24
|
@queues = data_source.queues_with_metrics
|
|
22
25
|
@processes = data_source.processes
|
|
23
26
|
@recent_failures = data_source.failed_events(page: 1, per_page: 5)
|
|
27
|
+
@health = data_source.queue_health_stats
|
|
24
28
|
end
|
|
25
29
|
end
|
|
26
30
|
end
|
|
@@ -46,7 +46,11 @@ module Pgbus
|
|
|
46
46
|
"channel" => "Turbo::StreamsChannel"
|
|
47
47
|
}.merge(html_attributes.transform_keys(&:to_s))
|
|
48
48
|
|
|
49
|
-
render_tag("pgbus-stream-source", attributes)
|
|
49
|
+
element = render_tag("pgbus-stream-source", attributes)
|
|
50
|
+
script = pgbus_stream_source_script_tag
|
|
51
|
+
return element unless script
|
|
52
|
+
|
|
53
|
+
safe_concat(script, element)
|
|
50
54
|
end
|
|
51
55
|
|
|
52
56
|
private
|
|
@@ -118,6 +122,34 @@ module Pgbus
|
|
|
118
122
|
cache[stream_name] ||= Pgbus.stream(stream_name).current_msg_id
|
|
119
123
|
end
|
|
120
124
|
|
|
125
|
+
# Emits a <script type="module"> tag that imports the custom element
|
|
126
|
+
# definition exactly once per request. Without this, <pgbus-stream-source>
|
|
127
|
+
# is an inert unknown element — no SSE connection opens. Uses a
|
|
128
|
+
# thread-local flag cleared by the WatermarkCacheMiddleware.
|
|
129
|
+
def pgbus_stream_source_script_tag
|
|
130
|
+
cache = Thread.current[:pgbus_streams_watermark_cache] ||= {}
|
|
131
|
+
return nil if cache[:script_emitted]
|
|
132
|
+
|
|
133
|
+
cache[:script_emitted] = true
|
|
134
|
+
script = '<script type="module">import "pgbus/stream_source_element"</script>'
|
|
135
|
+
script.respond_to?(:html_safe) ? script.html_safe : script
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Concatenates two HTML-safe strings without losing the safety flag.
|
|
139
|
+
# ActiveSupport::SafeBuffer#+ preserves safety when both operands
|
|
140
|
+
# are safe. Plain string interpolation ("#{a}#{b}") creates a new
|
|
141
|
+
# String, dropping html_safe — which causes Phlex and safe_join to
|
|
142
|
+
# HTML-escape the output.
|
|
143
|
+
def safe_concat(*parts)
|
|
144
|
+
if defined?(ActiveSupport::SafeBuffer)
|
|
145
|
+
buf = ActiveSupport::SafeBuffer.new
|
|
146
|
+
parts.each { |p| buf.safe_concat(p) }
|
|
147
|
+
buf
|
|
148
|
+
else
|
|
149
|
+
parts.join
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
121
153
|
def render_tag(name, attributes)
|
|
122
154
|
attr_string = attributes.map { |k, v| %(#{k}="#{CGI.escape_html(v.to_s)}") }.join(" ")
|
|
123
155
|
html = "<#{name} #{attr_string}></#{name}>"
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<turbo-frame id="dashboard-health" data-auto-refresh data-src="<%= pgbus.root_path(frame: 'health') %>">
|
|
2
|
+
<div class="mb-8">
|
|
3
|
+
<h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-3"><%= t("pgbus.dashboard.queue_health.title") %></h2>
|
|
4
|
+
|
|
5
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4 mb-4">
|
|
6
|
+
<div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
7
|
+
<p class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.dashboard.queue_health.dead_tuples") %></p>
|
|
8
|
+
<p class="mt-1 text-3xl font-semibold <%= @health[:total_dead_tuples] > 10_000 ? 'text-amber-600 dark:text-amber-400' : 'text-gray-900 dark:text-white' %>">
|
|
9
|
+
<%= pgbus_number(@health[:total_dead_tuples]) %>
|
|
10
|
+
</p>
|
|
11
|
+
<p class="text-xs text-gray-400 dark:text-gray-500"><%= pgbus_number(@health[:total_live_tuples]) %> <%= t("pgbus.dashboard.queue_health.live") %></p>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
15
|
+
<p class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.dashboard.queue_health.worst_bloat") %></p>
|
|
16
|
+
<p class="mt-1 text-3xl font-semibold <%= @health[:worst_bloat_ratio] > 0.2 ? 'text-red-600 dark:text-red-400' : @health[:worst_bloat_ratio] > 0.1 ? 'text-amber-600 dark:text-amber-400' : 'text-green-600 dark:text-green-400' %>">
|
|
17
|
+
<%= (@health[:worst_bloat_ratio] * 100).round(1) %>%
|
|
18
|
+
</p>
|
|
19
|
+
<% if @health[:tables_needing_vacuum] > 0 %>
|
|
20
|
+
<p class="text-xs text-amber-500"><%= t("pgbus.dashboard.queue_health.tables_need_vacuum", count: @health[:tables_needing_vacuum]) %></p>
|
|
21
|
+
<% end %>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
25
|
+
<p class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.dashboard.queue_health.last_vacuum") %></p>
|
|
26
|
+
<p class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white">
|
|
27
|
+
<% if @health[:oldest_vacuum_ago_sec] %>
|
|
28
|
+
<%= pgbus_duration(@health[:oldest_vacuum_ago_sec]) %>
|
|
29
|
+
<% else %>
|
|
30
|
+
—
|
|
31
|
+
<% end %>
|
|
32
|
+
</p>
|
|
33
|
+
<p class="text-xs text-gray-400 dark:text-gray-500"><%= t("pgbus.dashboard.queue_health.oldest_vacuum_ago") %></p>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
37
|
+
<p class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.dashboard.queue_health.mvcc_horizon") %></p>
|
|
38
|
+
<p class="mt-1 text-3xl font-semibold <%= (@health[:oldest_transaction_age_sec] || 0) > 60 ? 'text-red-600 dark:text-red-400' : (@health[:oldest_transaction_age_sec] || 0) > 30 ? 'text-amber-600 dark:text-amber-400' : 'text-green-600 dark:text-green-400' %>">
|
|
39
|
+
<% if @health[:oldest_transaction_age_sec] %>
|
|
40
|
+
<%= pgbus_duration(@health[:oldest_transaction_age_sec]) %>
|
|
41
|
+
<% else %>
|
|
42
|
+
—
|
|
43
|
+
<% end %>
|
|
44
|
+
</p>
|
|
45
|
+
<p class="text-xs text-gray-400 dark:text-gray-500"><%= t("pgbus.dashboard.queue_health.oldest_open_txn") %></p>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<% if @health[:tables].any? %>
|
|
50
|
+
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
51
|
+
<table class="pgbus-table min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
52
|
+
<thead class="bg-gray-50 dark:bg-gray-900">
|
|
53
|
+
<tr>
|
|
54
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.dashboard.queue_health.headers.table") %></th>
|
|
55
|
+
<th class="px-4 py-3 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.dashboard.queue_health.headers.kind") %></th>
|
|
56
|
+
<th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.dashboard.queue_health.headers.live") %></th>
|
|
57
|
+
<th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.dashboard.queue_health.headers.dead") %></th>
|
|
58
|
+
<th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.dashboard.queue_health.headers.bloat") %></th>
|
|
59
|
+
<th class="px-4 py-3 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.dashboard.queue_health.headers.last_vacuum") %></th>
|
|
60
|
+
</tr>
|
|
61
|
+
</thead>
|
|
62
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
63
|
+
<% @health[:tables].each do |t| %>
|
|
64
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50 dark:bg-gray-900">
|
|
65
|
+
<td class="px-4 py-3 text-sm font-mono text-gray-900 dark:text-white"><%= t[:table] %></td>
|
|
66
|
+
<td class="px-4 py-3 text-sm text-gray-500 dark:text-gray-400"><%= t("pgbus.dashboard.queue_health.kinds.#{t[:kind]}") %></td>
|
|
67
|
+
<td class="px-4 py-3 text-sm text-right text-gray-700 dark:text-gray-300"><%= pgbus_number(t[:live_tuples]) %></td>
|
|
68
|
+
<td class="px-4 py-3 text-sm text-right <%= t[:dead_tuples] > 1000 ? 'text-amber-600 dark:text-amber-400 font-semibold' : 'text-gray-700 dark:text-gray-300' %>"><%= pgbus_number(t[:dead_tuples]) %></td>
|
|
69
|
+
<td class="px-4 py-3 text-sm text-right <%= t[:bloat_ratio] > 0.2 ? 'text-red-600 dark:text-red-400 font-semibold' : t[:bloat_ratio] > 0.1 ? 'text-amber-600 dark:text-amber-400' : 'text-gray-500 dark:text-gray-400' %>"><%= (t[:bloat_ratio] * 100).round(1) %>%</td>
|
|
70
|
+
<td class="px-4 py-3 text-sm text-right text-gray-500 dark:text-gray-400"><%= t[:last_vacuum_ago_sec] ? pgbus_duration(t[:last_vacuum_ago_sec]) : "—" %></td>
|
|
71
|
+
</tr>
|
|
72
|
+
<% end %>
|
|
73
|
+
</tbody>
|
|
74
|
+
</table>
|
|
75
|
+
</div>
|
|
76
|
+
<% end %>
|
|
77
|
+
</div>
|
|
78
|
+
</turbo-frame>
|
|
@@ -36,6 +36,43 @@
|
|
|
36
36
|
</div>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
+
<!-- Table Health -->
|
|
40
|
+
<% if @health && @health[:tables].any? %>
|
|
41
|
+
<div class="mb-6 overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
42
|
+
<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
|
|
43
|
+
<h2 class="text-sm font-semibold text-gray-900 dark:text-white"><%= t("pgbus.queues.show.table_health.title") %></h2>
|
|
44
|
+
<% if @health[:oldest_transaction_age_sec] %>
|
|
45
|
+
<p class="text-xs text-gray-500 mt-1">
|
|
46
|
+
<%= t("pgbus.queues.show.table_health.oldest_txn") %>
|
|
47
|
+
<span class="font-mono <%= @health[:oldest_transaction_age_sec] > 60 ? 'text-red-600 dark:text-red-400' : @health[:oldest_transaction_age_sec] > 30 ? 'text-amber-600 dark:text-amber-400' : 'text-green-600 dark:text-green-400' %>"><%= pgbus_duration(@health[:oldest_transaction_age_sec]) %></span>
|
|
48
|
+
</p>
|
|
49
|
+
<% end %>
|
|
50
|
+
</div>
|
|
51
|
+
<table class="pgbus-table min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
52
|
+
<thead class="bg-gray-50 dark:bg-gray-900">
|
|
53
|
+
<tr>
|
|
54
|
+
<th class="px-4 py-2 text-left text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.table") %></th>
|
|
55
|
+
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.live") %></th>
|
|
56
|
+
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.dead") %></th>
|
|
57
|
+
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.bloat") %></th>
|
|
58
|
+
<th class="px-4 py-2 text-right text-xs font-medium uppercase text-gray-500"><%= t("pgbus.queues.show.table_health.headers.last_vacuum") %></th>
|
|
59
|
+
</tr>
|
|
60
|
+
</thead>
|
|
61
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
62
|
+
<% @health[:tables].each do |t| %>
|
|
63
|
+
<tr class="dark:bg-gray-900">
|
|
64
|
+
<td class="px-4 py-2 text-sm font-mono text-gray-900 dark:text-white"><%= t[:table] %></td>
|
|
65
|
+
<td class="px-4 py-2 text-sm text-right text-gray-700 dark:text-gray-300"><%= pgbus_number(t[:live_tuples]) %></td>
|
|
66
|
+
<td class="px-4 py-2 text-sm text-right <%= t[:dead_tuples] > 1000 ? 'text-amber-600 dark:text-amber-400 font-semibold' : 'text-gray-700 dark:text-gray-300' %>"><%= pgbus_number(t[:dead_tuples]) %></td>
|
|
67
|
+
<td class="px-4 py-2 text-sm text-right <%= t[:bloat_ratio] > 0.2 ? 'text-red-600 dark:text-red-400 font-semibold' : t[:bloat_ratio] > 0.1 ? 'text-amber-600 dark:text-amber-400' : 'text-gray-500 dark:text-gray-400' %>"><%= (t[:bloat_ratio] * 100).round(1) %>%</td>
|
|
68
|
+
<td class="px-4 py-2 text-sm text-right text-gray-500 dark:text-gray-400"><%= t[:last_vacuum_ago_sec] ? pgbus_duration(t[:last_vacuum_ago_sec]) : "—" %></td>
|
|
69
|
+
</tr>
|
|
70
|
+
<% end %>
|
|
71
|
+
</tbody>
|
|
72
|
+
</table>
|
|
73
|
+
</div>
|
|
74
|
+
<% end %>
|
|
75
|
+
|
|
39
76
|
<!-- Messages in Queue -->
|
|
40
77
|
<div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
|
|
41
78
|
<table class="pgbus-table min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
data/config/locales/da.yml
CHANGED
|
@@ -10,6 +10,28 @@ da:
|
|
|
10
10
|
pid: PID
|
|
11
11
|
status: Status
|
|
12
12
|
title: Aktive processer
|
|
13
|
+
queue_health:
|
|
14
|
+
dead_tuples: Døde tupler
|
|
15
|
+
headers:
|
|
16
|
+
bloat: Bloat
|
|
17
|
+
dead: Døde
|
|
18
|
+
kind: Type
|
|
19
|
+
last_vacuum: Sidste Vacuum
|
|
20
|
+
live: Levende
|
|
21
|
+
table: Tabel
|
|
22
|
+
kinds:
|
|
23
|
+
archive: Arkiv
|
|
24
|
+
queue: Kø
|
|
25
|
+
last_vacuum: Sidste Vacuum
|
|
26
|
+
live: Levende
|
|
27
|
+
mvcc_horizon: MVCC Horisont
|
|
28
|
+
oldest_open_txn: Ældste åbne transaktion
|
|
29
|
+
oldest_vacuum_ago: Ældste tabel-vacuum
|
|
30
|
+
tables_need_vacuum:
|
|
31
|
+
one: "%{count} tabel har brug for vacuum"
|
|
32
|
+
other: "%{count} tabeller har brug for vacuum"
|
|
33
|
+
title: Køhelbred
|
|
34
|
+
worst_bloat: Værste Bloat
|
|
13
35
|
queues_table:
|
|
14
36
|
empty: Ingen køer fundet
|
|
15
37
|
headers:
|
|
@@ -337,6 +359,15 @@ da:
|
|
|
337
359
|
resume: Genoptag
|
|
338
360
|
retry: Prøv igen
|
|
339
361
|
retry_confirm: Nulstil synlighedstimeout og prøv igen?
|
|
362
|
+
table_health:
|
|
363
|
+
headers:
|
|
364
|
+
bloat: Bloat
|
|
365
|
+
dead: Døde
|
|
366
|
+
last_vacuum: Sidste Vacuum
|
|
367
|
+
live: Levende
|
|
368
|
+
table: Tabel
|
|
369
|
+
oldest_txn: 'Ældste åbne transaktion:'
|
|
370
|
+
title: Tabelhelbred
|
|
340
371
|
total: 'Total:'
|
|
341
372
|
visible: 'Synlig:'
|
|
342
373
|
recurring_tasks:
|
|
@@ -345,10 +376,6 @@ da:
|
|
|
345
376
|
one: "%{count} opgave konfigureret"
|
|
346
377
|
other: "%{count} opgaver konfigureret"
|
|
347
378
|
title: Gentagne opgaver
|
|
348
|
-
toggle:
|
|
349
|
-
disabled: Opgave deaktiveret
|
|
350
|
-
enabled: Opgave aktiveret
|
|
351
|
-
failed: Kunne ikke ændre opgave
|
|
352
379
|
show:
|
|
353
380
|
back: Tilbage
|
|
354
381
|
configuration: Konfiguration
|
|
@@ -392,3 +419,7 @@ da:
|
|
|
392
419
|
task: Opgave
|
|
393
420
|
never: Aldrig
|
|
394
421
|
run_now: Kør nu
|
|
422
|
+
toggle:
|
|
423
|
+
disabled: Opgave deaktiveret
|
|
424
|
+
enabled: Opgave aktiveret
|
|
425
|
+
failed: Kunne ikke ændre opgave
|
data/config/locales/de.yml
CHANGED
|
@@ -10,6 +10,28 @@ de:
|
|
|
10
10
|
pid: PID
|
|
11
11
|
status: Status
|
|
12
12
|
title: Aktive Prozesse
|
|
13
|
+
queue_health:
|
|
14
|
+
dead_tuples: Tote Tupel
|
|
15
|
+
headers:
|
|
16
|
+
bloat: Bloat
|
|
17
|
+
dead: Tot
|
|
18
|
+
kind: Art
|
|
19
|
+
last_vacuum: Letztes Vacuum
|
|
20
|
+
live: Aktiv
|
|
21
|
+
table: Tabelle
|
|
22
|
+
kinds:
|
|
23
|
+
archive: Archiv
|
|
24
|
+
queue: Warteschlange
|
|
25
|
+
last_vacuum: Letztes Vacuum
|
|
26
|
+
live: Aktiv
|
|
27
|
+
mvcc_horizon: MVCC-Horizont
|
|
28
|
+
oldest_open_txn: Älteste offene Transaktion
|
|
29
|
+
oldest_vacuum_ago: Ältestes Tabellen-Vacuum
|
|
30
|
+
tables_need_vacuum:
|
|
31
|
+
one: "%{count} Tabelle benötigt Vacuum"
|
|
32
|
+
other: "%{count} Tabellen benötigen Vacuum"
|
|
33
|
+
title: Warteschlangen-Gesundheit
|
|
34
|
+
worst_bloat: Schlimmster Bloat
|
|
13
35
|
queues_table:
|
|
14
36
|
empty: Keine Warteschlangen gefunden
|
|
15
37
|
headers:
|
|
@@ -337,6 +359,15 @@ de:
|
|
|
337
359
|
resume: Fortsetzen
|
|
338
360
|
retry: Wiederholen
|
|
339
361
|
retry_confirm: Sichtbarkeits-Timeout zurücksetzen und erneut versuchen?
|
|
362
|
+
table_health:
|
|
363
|
+
headers:
|
|
364
|
+
bloat: Bloat
|
|
365
|
+
dead: Tot
|
|
366
|
+
last_vacuum: Letztes Vacuum
|
|
367
|
+
live: Aktiv
|
|
368
|
+
table: Tabelle
|
|
369
|
+
oldest_txn: 'Älteste offene Transaktion:'
|
|
370
|
+
title: Tabellen-Gesundheit
|
|
340
371
|
total: 'Insgesamt:'
|
|
341
372
|
visible: 'Sichtbar:'
|
|
342
373
|
recurring_tasks:
|
|
@@ -345,10 +376,6 @@ de:
|
|
|
345
376
|
one: "%{count} Aufgabe konfiguriert"
|
|
346
377
|
other: "%{count} Aufgaben konfiguriert"
|
|
347
378
|
title: Wiederkehrende Aufgaben
|
|
348
|
-
toggle:
|
|
349
|
-
disabled: Aufgabe deaktiviert
|
|
350
|
-
enabled: Aufgabe aktiviert
|
|
351
|
-
failed: Aufgabe konnte nicht umgeschaltet werden
|
|
352
379
|
show:
|
|
353
380
|
back: Zurück
|
|
354
381
|
configuration: Konfiguration
|
|
@@ -392,3 +419,7 @@ de:
|
|
|
392
419
|
task: Aufgabe
|
|
393
420
|
never: Nie
|
|
394
421
|
run_now: Jetzt ausführen
|
|
422
|
+
toggle:
|
|
423
|
+
disabled: Aufgabe deaktiviert
|
|
424
|
+
enabled: Aufgabe aktiviert
|
|
425
|
+
failed: Aufgabe konnte nicht umgeschaltet werden
|
data/config/locales/en.yml
CHANGED
|
@@ -10,6 +10,28 @@ en:
|
|
|
10
10
|
pid: PID
|
|
11
11
|
status: Status
|
|
12
12
|
title: Active Processes
|
|
13
|
+
queue_health:
|
|
14
|
+
dead_tuples: Dead Tuples
|
|
15
|
+
headers:
|
|
16
|
+
bloat: Bloat
|
|
17
|
+
dead: Dead
|
|
18
|
+
kind: Kind
|
|
19
|
+
last_vacuum: Last Vacuum
|
|
20
|
+
live: Live
|
|
21
|
+
table: Table
|
|
22
|
+
kinds:
|
|
23
|
+
archive: Archive
|
|
24
|
+
queue: Queue
|
|
25
|
+
last_vacuum: Last Vacuum
|
|
26
|
+
live: Live
|
|
27
|
+
mvcc_horizon: MVCC Horizon
|
|
28
|
+
oldest_open_txn: Oldest open transaction
|
|
29
|
+
oldest_vacuum_ago: Oldest table vacuum
|
|
30
|
+
tables_need_vacuum:
|
|
31
|
+
one: "%{count} table needs vacuum"
|
|
32
|
+
other: "%{count} tables need vacuum"
|
|
33
|
+
title: Queue Health
|
|
34
|
+
worst_bloat: Worst Bloat
|
|
13
35
|
queues_table:
|
|
14
36
|
empty: No queues found
|
|
15
37
|
headers:
|
|
@@ -399,6 +421,15 @@ en:
|
|
|
399
421
|
resume: Resume
|
|
400
422
|
retry: Retry
|
|
401
423
|
retry_confirm: Reset visibility timeout and retry?
|
|
424
|
+
table_health:
|
|
425
|
+
headers:
|
|
426
|
+
bloat: Bloat
|
|
427
|
+
dead: Dead
|
|
428
|
+
last_vacuum: Last Vacuum
|
|
429
|
+
live: Live
|
|
430
|
+
table: Table
|
|
431
|
+
oldest_txn: 'Oldest open transaction:'
|
|
432
|
+
title: Table Health
|
|
402
433
|
total: 'Total:'
|
|
403
434
|
visible: 'Visible:'
|
|
404
435
|
recurring_tasks:
|
|
@@ -407,10 +438,6 @@ en:
|
|
|
407
438
|
one: "%{count} task configured"
|
|
408
439
|
other: "%{count} tasks configured"
|
|
409
440
|
title: Recurring Tasks
|
|
410
|
-
toggle:
|
|
411
|
-
disabled: Task disabled
|
|
412
|
-
enabled: Task enabled
|
|
413
|
-
failed: Failed to toggle task
|
|
414
441
|
show:
|
|
415
442
|
back: Back
|
|
416
443
|
configuration: Configuration
|
|
@@ -454,3 +481,7 @@ en:
|
|
|
454
481
|
task: Task
|
|
455
482
|
never: Never
|
|
456
483
|
run_now: Run Now
|
|
484
|
+
toggle:
|
|
485
|
+
disabled: Task disabled
|
|
486
|
+
enabled: Task enabled
|
|
487
|
+
failed: Failed to toggle task
|
data/config/locales/es.yml
CHANGED
|
@@ -10,6 +10,28 @@ es:
|
|
|
10
10
|
pid: PID
|
|
11
11
|
status: Estado
|
|
12
12
|
title: Procesos activos
|
|
13
|
+
queue_health:
|
|
14
|
+
dead_tuples: Tuplas muertas
|
|
15
|
+
headers:
|
|
16
|
+
bloat: Bloat
|
|
17
|
+
dead: Muertas
|
|
18
|
+
kind: Tipo
|
|
19
|
+
last_vacuum: Último Vacuum
|
|
20
|
+
live: Activas
|
|
21
|
+
table: Tabla
|
|
22
|
+
kinds:
|
|
23
|
+
archive: Archivo
|
|
24
|
+
queue: Cola
|
|
25
|
+
last_vacuum: Último Vacuum
|
|
26
|
+
live: Activas
|
|
27
|
+
mvcc_horizon: Horizonte MVCC
|
|
28
|
+
oldest_open_txn: Transacción abierta más antigua
|
|
29
|
+
oldest_vacuum_ago: Vacuum de tabla más antiguo
|
|
30
|
+
tables_need_vacuum:
|
|
31
|
+
one: "%{count} tabla necesita vacuum"
|
|
32
|
+
other: "%{count} tablas necesitan vacuum"
|
|
33
|
+
title: Salud de Colas
|
|
34
|
+
worst_bloat: Peor Bloat
|
|
13
35
|
queues_table:
|
|
14
36
|
empty: No se encontraron colas
|
|
15
37
|
headers:
|
|
@@ -337,6 +359,15 @@ es:
|
|
|
337
359
|
resume: Reanudar
|
|
338
360
|
retry: Reintentar
|
|
339
361
|
retry_confirm: "¿Restablecer tiempo de visibilidad y reintentar?"
|
|
362
|
+
table_health:
|
|
363
|
+
headers:
|
|
364
|
+
bloat: Bloat
|
|
365
|
+
dead: Muertas
|
|
366
|
+
last_vacuum: Último Vacuum
|
|
367
|
+
live: Activas
|
|
368
|
+
table: Tabla
|
|
369
|
+
oldest_txn: 'Transacción abierta más antigua:'
|
|
370
|
+
title: Salud de Tablas
|
|
340
371
|
total: 'Total:'
|
|
341
372
|
visible: 'Visible:'
|
|
342
373
|
recurring_tasks:
|
|
@@ -345,10 +376,6 @@ es:
|
|
|
345
376
|
one: Tarea %{count} configurada
|
|
346
377
|
other: Tareas %{count} configuradas
|
|
347
378
|
title: Tareas recurrentes
|
|
348
|
-
toggle:
|
|
349
|
-
disabled: Tarea deshabilitada
|
|
350
|
-
enabled: Tarea habilitada
|
|
351
|
-
failed: No se pudo cambiar la tarea
|
|
352
379
|
show:
|
|
353
380
|
back: Atrás
|
|
354
381
|
configuration: Configuración
|
|
@@ -392,3 +419,7 @@ es:
|
|
|
392
419
|
task: Tarea
|
|
393
420
|
never: Nunca
|
|
394
421
|
run_now: Ejecutar ahora
|
|
422
|
+
toggle:
|
|
423
|
+
disabled: Tarea deshabilitada
|
|
424
|
+
enabled: Tarea habilitada
|
|
425
|
+
failed: No se pudo cambiar la tarea
|
data/config/locales/fi.yml
CHANGED
|
@@ -10,6 +10,28 @@ fi:
|
|
|
10
10
|
pid: PID
|
|
11
11
|
status: Tila
|
|
12
12
|
title: Aktiiviset prosessit
|
|
13
|
+
queue_health:
|
|
14
|
+
dead_tuples: Kuolleet tuplat
|
|
15
|
+
headers:
|
|
16
|
+
bloat: Bloat
|
|
17
|
+
dead: Kuolleet
|
|
18
|
+
kind: Tyyppi
|
|
19
|
+
last_vacuum: Viimeisin Vacuum
|
|
20
|
+
live: Elävät
|
|
21
|
+
table: Taulu
|
|
22
|
+
kinds:
|
|
23
|
+
archive: Arkisto
|
|
24
|
+
queue: Jono
|
|
25
|
+
last_vacuum: Viimeisin Vacuum
|
|
26
|
+
live: Elävät
|
|
27
|
+
mvcc_horizon: MVCC-horisontti
|
|
28
|
+
oldest_open_txn: Vanhin avoin transaktio
|
|
29
|
+
oldest_vacuum_ago: Vanhin taulun vacuum
|
|
30
|
+
tables_need_vacuum:
|
|
31
|
+
one: "%{count} taulu tarvitsee vacuum-käsittelyn"
|
|
32
|
+
other: "%{count} taulua tarvitsee vacuum-käsittelyn"
|
|
33
|
+
title: Jonon kunto
|
|
34
|
+
worst_bloat: Pahin Bloat
|
|
13
35
|
queues_table:
|
|
14
36
|
empty: Jonot eivät löytyneet
|
|
15
37
|
headers:
|
|
@@ -337,6 +359,15 @@ fi:
|
|
|
337
359
|
resume: Jatka
|
|
338
360
|
retry: Yritä uudelleen
|
|
339
361
|
retry_confirm: Nollaa näkyvyysaika ja yritä uudelleen?
|
|
362
|
+
table_health:
|
|
363
|
+
headers:
|
|
364
|
+
bloat: Bloat
|
|
365
|
+
dead: Kuolleet
|
|
366
|
+
last_vacuum: Viimeisin Vacuum
|
|
367
|
+
live: Elävät
|
|
368
|
+
table: Taulu
|
|
369
|
+
oldest_txn: 'Vanhin avoin transaktio:'
|
|
370
|
+
title: Taulun kunto
|
|
340
371
|
total: 'Yhteensä:'
|
|
341
372
|
visible: 'Näkyvissä:'
|
|
342
373
|
recurring_tasks:
|
|
@@ -345,10 +376,6 @@ fi:
|
|
|
345
376
|
one: "%{count} tehtävä määritetty"
|
|
346
377
|
other: "%{count} tehtävää määritetty"
|
|
347
378
|
title: Toistuvat tehtävät
|
|
348
|
-
toggle:
|
|
349
|
-
disabled: Tehtävä poistettu käytöstä
|
|
350
|
-
enabled: Tehtävä otettu käyttöön
|
|
351
|
-
failed: Tehtävän vaihto epäonnistui
|
|
352
379
|
show:
|
|
353
380
|
back: Takaisin
|
|
354
381
|
configuration: Asetukset
|
|
@@ -392,3 +419,7 @@ fi:
|
|
|
392
419
|
task: Tehtävä
|
|
393
420
|
never: Ei koskaan
|
|
394
421
|
run_now: Suorita nyt
|
|
422
|
+
toggle:
|
|
423
|
+
disabled: Tehtävä poistettu käytöstä
|
|
424
|
+
enabled: Tehtävä otettu käyttöön
|
|
425
|
+
failed: Tehtävän vaihto epäonnistui
|
data/config/locales/fr.yml
CHANGED
|
@@ -10,6 +10,28 @@ fr:
|
|
|
10
10
|
pid: PID
|
|
11
11
|
status: Statut
|
|
12
12
|
title: Processus actifs
|
|
13
|
+
queue_health:
|
|
14
|
+
dead_tuples: Tuples mortes
|
|
15
|
+
headers:
|
|
16
|
+
bloat: Bloat
|
|
17
|
+
dead: Mortes
|
|
18
|
+
kind: Type
|
|
19
|
+
last_vacuum: Dernier Vacuum
|
|
20
|
+
live: Actives
|
|
21
|
+
table: Table
|
|
22
|
+
kinds:
|
|
23
|
+
archive: Archive
|
|
24
|
+
queue: File d'attente
|
|
25
|
+
last_vacuum: Dernier Vacuum
|
|
26
|
+
live: Actives
|
|
27
|
+
mvcc_horizon: Horizon MVCC
|
|
28
|
+
oldest_open_txn: Plus ancienne transaction ouverte
|
|
29
|
+
oldest_vacuum_ago: Plus ancien vacuum de table
|
|
30
|
+
tables_need_vacuum:
|
|
31
|
+
one: "%{count} table nécessite un vacuum"
|
|
32
|
+
other: "%{count} tables nécessitent un vacuum"
|
|
33
|
+
title: Santé des files d'attente
|
|
34
|
+
worst_bloat: Pire Bloat
|
|
13
35
|
queues_table:
|
|
14
36
|
empty: Aucune file d'attente trouvée
|
|
15
37
|
headers:
|
|
@@ -337,6 +359,15 @@ fr:
|
|
|
337
359
|
resume: Reprendre
|
|
338
360
|
retry: Réessayer
|
|
339
361
|
retry_confirm: Réinitialiser le délai de visibilité et réessayer ?
|
|
362
|
+
table_health:
|
|
363
|
+
headers:
|
|
364
|
+
bloat: Bloat
|
|
365
|
+
dead: Mortes
|
|
366
|
+
last_vacuum: Dernier Vacuum
|
|
367
|
+
live: Actives
|
|
368
|
+
table: Table
|
|
369
|
+
oldest_txn: 'Plus ancienne transaction ouverte :'
|
|
370
|
+
title: Santé des tables
|
|
340
371
|
total: 'Total :'
|
|
341
372
|
visible: 'Visible :'
|
|
342
373
|
recurring_tasks:
|
|
@@ -345,10 +376,6 @@ fr:
|
|
|
345
376
|
one: Tâche %{count} configurée
|
|
346
377
|
other: Tâches %{count} configurées
|
|
347
378
|
title: Tâches récurrentes
|
|
348
|
-
toggle:
|
|
349
|
-
disabled: Tâche désactivée
|
|
350
|
-
enabled: Tâche activée
|
|
351
|
-
failed: Impossible de basculer la tâche
|
|
352
379
|
show:
|
|
353
380
|
back: Retour
|
|
354
381
|
configuration: Configuration
|
|
@@ -392,3 +419,7 @@ fr:
|
|
|
392
419
|
task: Tâche
|
|
393
420
|
never: Jamais
|
|
394
421
|
run_now: Exécuter maintenant
|
|
422
|
+
toggle:
|
|
423
|
+
disabled: Tâche désactivée
|
|
424
|
+
enabled: Tâche activée
|
|
425
|
+
failed: Impossible de basculer la tâche
|