Skip to content

Commit ba894ed

Browse files
committed
Expose tablet replica attributes as JSONB
1 parent 74b9d90 commit ba894ed

File tree

7 files changed

+112
-66
lines changed

7 files changed

+112
-66
lines changed

docs/content/stable/explore/observability/yb-tablet-metadata.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ The following table describes the columns of the `yb_tablet_metadata` view.
3737
| end_hash_code | int | Ending hash code (exclusive) for the tablet. (NULL for range-sharded tables.) |
3838
| leader | text | IP address, port of the leader node for the tablet. |
3939
| replicas | text[] | A list of replica IP addresses and port (includes leader) associated with the tablet. |
40-
| active_ssts_size | bigint[] | Per-replica SST files size in bytes, in the same order as replicas. |
41-
| wals_size | bigint[] | Per-replica WAL files size in bytes, in the same order as replicas. |
40+
| attributes | jsonb | Per-replica metrics as a JSONB object. Contains a `"replicas"` key mapping each replica address to its `active_sst_size` and `wal_size` (in bytes). |
4241

4342
## Examples
4443

src/postgres/src/backend/catalog/yb_system_views.sql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ CREATE VIEW yb_tablet_metadata AS
6868
t.end_hash_code,
6969
t.leader,
7070
t.replicas,
71-
t.active_sst_sizes,
72-
t.wal_sizes
71+
t.attributes
7372
FROM
7473
yb_get_tablet_metadata() t
7574
LEFT JOIN

src/postgres/src/backend/utils/misc/pg_yb_utils.c

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8419,13 +8419,13 @@ replica_index_cmp(const void *a, const void *b, void *arg)
84198419
* - end_hash_code: int32
84208420
* - leader: text
84218421
* - replicas: text[]
8422-
* - active_sst_sizes: int8[]
8423-
* - wal_sizes: int8[]
8422+
* - attributes: jsonb (nested structure with per-replica data)
84248423
*
84258424
* The start_hash_code and end_hash_code are the hash codes of the start and end
84268425
* keys of the tablet for hash sharded tables. Leader is provided as a separate
8427-
* column for simpler querying and self-explanatory access. The size arrays are
8428-
* parallel to replicas (same index refers to the same replica).
8426+
* column for simpler querying and self-explanatory access. The attributes column
8427+
* contains a JSONB object with a "replicas" key mapping each replica address to
8428+
* its metrics (active_sst_size, wal_size).
84298429
*/
84308430
Datum
84318431
yb_get_tablet_metadata(PG_FUNCTION_ARGS)
@@ -8435,7 +8435,7 @@ yb_get_tablet_metadata(PG_FUNCTION_ARGS)
84358435
Tuplestorestate *tupstore;
84368436
MemoryContext per_query_ctx;
84378437
MemoryContext oldcontext;
8438-
static int ncols = 11;
8438+
static int ncols = 10;
84398439

84408440
/* check to see if caller supports us returning a tuplestore */
84418441
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
@@ -8504,23 +8504,24 @@ yb_get_tablet_metadata(PG_FUNCTION_ARGS)
85048504
nulls[6] = true;
85058505
}
85068506

8507-
/* Convert replicas array to PostgreSQL text array and size arrays */
8507+
/* Convert replicas array to PostgreSQL text array and JSONB attributes */
85088508
if (tablet->replicas_count > 0)
85098509
{
85108510
size_t nreplicas = tablet->replicas_count;
85118511
int *sort_idxs;
85128512
Datum *text_elems;
8513-
Datum *sst_elems;
8514-
Datum *wal_elems;
8513+
JsonbParseState *jb_state = NULL;
8514+
JsonbValue jb_result;
8515+
JsonbValue jb_key;
8516+
JsonbValue jb_val;
85158517

85168518
Assert(tablet->replicas != NULL);
85178519

85188520
/* The last replica is the leader. */
85198521
values[7] = CStringGetTextDatum(tablet->replicas[nreplicas - 1]);
85208522

85218523
/*
8522-
* Build a sort index so replicas and their sizes stay parallel
8523-
* after lexicographic sorting.
8524+
* Build a sort index so replicas stay in lexicographic order.
85248525
*/
85258526
sort_idxs = palloc(nreplicas * sizeof(int));
85268527
for (size_t idx = 0; idx < nreplicas; idx++)
@@ -8530,43 +8531,76 @@ yb_get_tablet_metadata(PG_FUNCTION_ARGS)
85308531
replica_index_cmp, tablet->replicas);
85318532

85328533
text_elems = palloc(nreplicas * sizeof(Datum));
8533-
sst_elems = palloc(nreplicas * sizeof(Datum));
8534-
wal_elems = palloc(nreplicas * sizeof(Datum));
8534+
8535+
/* Build JSONB: {"replicas": {"addr": {"active_sst_size": N, "wal_size": N}, ...}} */
8536+
pushJsonbValue(&jb_state, WJB_BEGIN_OBJECT, NULL);
8537+
8538+
jb_key.type = jbvString;
8539+
jb_key.val.string.val = "replicas";
8540+
jb_key.val.string.len = 8;
8541+
pushJsonbValue(&jb_state, WJB_KEY, &jb_key);
8542+
8543+
pushJsonbValue(&jb_state, WJB_BEGIN_OBJECT, NULL);
85358544

85368545
for (size_t idx = 0; idx < nreplicas; idx++)
85378546
{
85388547
int si = sort_idxs[idx];
8548+
int64 sst_size;
8549+
int64 wal_size;
85398550

85408551
text_elems[idx] = CStringGetTextDatum(tablet->replicas[si]);
8541-
sst_elems[idx] = UInt64GetDatum(
8542-
tablet->replica_sst_sizes
8543-
? tablet->replica_sst_sizes[si] : 0);
8544-
wal_elems[idx] = UInt64GetDatum(
8545-
tablet->replica_wal_sizes
8546-
? tablet->replica_wal_sizes[si] : 0);
8552+
8553+
sst_size = tablet->replica_sst_sizes
8554+
? tablet->replica_sst_sizes[si] : 0;
8555+
wal_size = tablet->replica_wal_sizes
8556+
? tablet->replica_wal_sizes[si] : 0;
8557+
8558+
/* Replica address as key */
8559+
jb_key.type = jbvString;
8560+
jb_key.val.string.val = (char *) tablet->replicas[si];
8561+
jb_key.val.string.len = strlen(tablet->replicas[si]);
8562+
pushJsonbValue(&jb_state, WJB_KEY, &jb_key);
8563+
8564+
/* Per-replica object */
8565+
pushJsonbValue(&jb_state, WJB_BEGIN_OBJECT, NULL);
8566+
8567+
jb_key.type = jbvString;
8568+
jb_key.val.string.val = "active_sst_size";
8569+
jb_key.val.string.len = 15;
8570+
pushJsonbValue(&jb_state, WJB_KEY, &jb_key);
8571+
jb_val.type = jbvNumeric;
8572+
jb_val.val.numeric = DatumGetNumeric(
8573+
DirectFunctionCall1(int8_numeric, Int64GetDatum(sst_size)));
8574+
pushJsonbValue(&jb_state, WJB_VALUE, &jb_val);
8575+
8576+
jb_key.type = jbvString;
8577+
jb_key.val.string.val = "wal_size";
8578+
jb_key.val.string.len = 8;
8579+
pushJsonbValue(&jb_state, WJB_KEY, &jb_key);
8580+
jb_val.type = jbvNumeric;
8581+
jb_val.val.numeric = DatumGetNumeric(
8582+
DirectFunctionCall1(int8_numeric, Int64GetDatum(wal_size)));
8583+
pushJsonbValue(&jb_state, WJB_VALUE, &jb_val);
8584+
8585+
pushJsonbValue(&jb_state, WJB_END_OBJECT, NULL);
85478586
}
85488587

8588+
pushJsonbValue(&jb_state, WJB_END_OBJECT, NULL); /* end replicas */
8589+
jb_result = *pushJsonbValue(&jb_state, WJB_END_OBJECT, NULL); /* end outer */
8590+
85498591
values[8] = PointerGetDatum(
85508592
construct_array(text_elems, (int) nreplicas,
85518593
TEXTOID, -1, false, TYPALIGN_INT));
8552-
values[9] = PointerGetDatum(
8553-
construct_array(sst_elems, (int) nreplicas,
8554-
INT8OID, 8, FLOAT8PASSBYVAL, TYPALIGN_DOUBLE));
8555-
values[10] = PointerGetDatum(
8556-
construct_array(wal_elems, (int) nreplicas,
8557-
INT8OID, 8, FLOAT8PASSBYVAL, TYPALIGN_DOUBLE));
8594+
values[9] = JsonbPGetDatum(JsonbValueToJsonb(&jb_result));
85588595

85598596
pfree(sort_idxs);
85608597
pfree(text_elems);
8561-
pfree(sst_elems);
8562-
pfree(wal_elems);
85638598
}
85648599
else
85658600
{
85668601
nulls[7] = true;
85678602
nulls[8] = true;
85688603
nulls[9] = true;
8569-
nulls[10] = true;
85708604
}
85718605

85728606
tuplestore_putvalues(tupstore, tupdesc, values, nulls);

src/postgres/src/include/catalog/pg_proc.dat

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12234,9 +12234,9 @@
1223412234
proname => 'yb_get_tablet_metadata', prorows => '100',
1223512235
proretset => 't', provolatile => 'v', proparallel => 'r',
1223612236
prorettype => 'record', proargtypes => '',
12237-
proallargtypes => '{text,text,text,text,text,int4,int4,text,_text,_int8,_int8}',
12238-
proargnames => '{tablet_id,object_uuid,namespace,object_name,type,start_hash_code,end_hash_code,leader,replicas,active_sst_sizes,wal_sizes}',
12239-
proargmodes => '{o,o,o,o,o,o,o,o,o,o,o}',
12237+
proallargtypes => '{text,text,text,text,text,int4,int4,text,_text,jsonb}',
12238+
proargnames => '{tablet_id,object_uuid,namespace,object_name,type,start_hash_code,end_hash_code,leader,replicas,attributes}',
12239+
proargmodes => '{o,o,o,o,o,o,o,o,o,o}',
1224012240
prosrc => 'yb_get_tablet_metadata'},
1224112241

1224212242
{ oid => '8101', descr => 'Get the UUID of the local tserver',

src/postgres/src/test/regress/expected/yb.orig.tablet_metadata.out

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,44 @@ ORDER BY start_hash_code NULLS FIRST;
1515
test_table_1 | yugabyte | 32768 | 65536
1616
(3 rows)
1717

18-
-- Test that active_sst_sizes and wal_sizes columns are present and aligned with replicas
18+
-- Test that attributes column is present with correct type and structure
1919
SELECT
2020
relname,
21-
pg_typeof(active_sst_sizes) AS sst_type,
22-
pg_typeof(wal_sizes) AS wal_type,
23-
array_length(active_sst_sizes, 1) = array_length(replicas, 1) AS sst_match,
24-
array_length(wal_sizes, 1) = array_length(replicas, 1) AS wal_match
21+
pg_typeof(attributes) AS attr_type,
22+
jsonb_typeof(attributes->'replicas') AS replicas_type,
23+
(SELECT count(*) FROM jsonb_object_keys(attributes->'replicas'))::int
24+
= array_length(replicas, 1) AS key_count_match
2525
FROM yb_tablet_metadata
2626
WHERE relname = 'test_table_1'
2727
ORDER BY start_hash_code NULLS FIRST
2828
LIMIT 1;
29-
relname | sst_type | wal_type | sst_match | wal_match
30-
--------------+----------+----------+-----------+-----------
31-
test_table_1 | bigint[] | bigint[] | t | t
29+
relname | attr_type | replicas_type | key_count_match
30+
--------------+-----------+---------------+-----------------
31+
test_table_1 | jsonb | object | t
3232
(1 row)
3333

3434
-- Test that all size values are non-negative for each replica
35-
SELECT r.val AS replica, s.val AS sst_size, w.val AS wal_size
35+
SELECT replica, (attrs->>'active_sst_size')::bigint AS sst_size,
36+
(attrs->>'wal_size')::bigint AS wal_size
3637
FROM yb_tablet_metadata tm,
37-
unnest(tm.replicas) WITH ORDINALITY AS r(val, ord),
38-
unnest(tm.active_sst_sizes) WITH ORDINALITY AS s(val, ord),
39-
unnest(tm.wal_sizes) WITH ORDINALITY AS w(val, ord)
38+
unnest(tm.replicas) AS replica,
39+
LATERAL (SELECT tm.attributes->'replicas'->replica AS attrs) a
4040
WHERE tm.relname = 'test_table_1'
41-
AND r.ord = s.ord AND r.ord = w.ord
42-
AND (s.val < 0 OR w.val < 0);
41+
AND ((attrs->>'active_sst_size')::bigint < 0
42+
OR (attrs->>'wal_size')::bigint < 0);
4343
replica | sst_size | wal_size
4444
---------+----------+----------
4545
(0 rows)
4646

47+
-- Test that every replica in the replicas array has an entry in attributes
48+
SELECT replica
49+
FROM yb_tablet_metadata tm, unnest(tm.replicas) AS replica
50+
WHERE tm.relname = 'test_table_1'
51+
AND NOT (tm.attributes->'replicas' ? replica);
52+
replica
53+
---------
54+
(0 rows)
55+
4756
-- Test that every replica address corresponds to a live tserver
4857
SELECT unnest(replicas) AS orphan_replica
4958
FROM yb_tablet_metadata

src/postgres/src/test/regress/sql/yb.orig.tablet_metadata.sql

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,33 @@ SELECT
1010
FROM yb_tablet_metadata WHERE relname IN ('test_table_1', 'test_table_2')
1111
ORDER BY start_hash_code NULLS FIRST;
1212

13-
-- Test that active_sst_sizes and wal_sizes columns are present and aligned with replicas
13+
-- Test that attributes column is present with correct type and structure
1414
SELECT
1515
relname,
16-
pg_typeof(active_sst_sizes) AS sst_type,
17-
pg_typeof(wal_sizes) AS wal_type,
18-
array_length(active_sst_sizes, 1) = array_length(replicas, 1) AS sst_match,
19-
array_length(wal_sizes, 1) = array_length(replicas, 1) AS wal_match
16+
pg_typeof(attributes) AS attr_type,
17+
jsonb_typeof(attributes->'replicas') AS replicas_type,
18+
(SELECT count(*) FROM jsonb_object_keys(attributes->'replicas'))::int
19+
= array_length(replicas, 1) AS key_count_match
2020
FROM yb_tablet_metadata
2121
WHERE relname = 'test_table_1'
2222
ORDER BY start_hash_code NULLS FIRST
2323
LIMIT 1;
2424

2525
-- Test that all size values are non-negative for each replica
26-
SELECT r.val AS replica, s.val AS sst_size, w.val AS wal_size
26+
SELECT replica, (attrs->>'active_sst_size')::bigint AS sst_size,
27+
(attrs->>'wal_size')::bigint AS wal_size
2728
FROM yb_tablet_metadata tm,
28-
unnest(tm.replicas) WITH ORDINALITY AS r(val, ord),
29-
unnest(tm.active_sst_sizes) WITH ORDINALITY AS s(val, ord),
30-
unnest(tm.wal_sizes) WITH ORDINALITY AS w(val, ord)
29+
unnest(tm.replicas) AS replica,
30+
LATERAL (SELECT tm.attributes->'replicas'->replica AS attrs) a
3131
WHERE tm.relname = 'test_table_1'
32-
AND r.ord = s.ord AND r.ord = w.ord
33-
AND (s.val < 0 OR w.val < 0);
32+
AND ((attrs->>'active_sst_size')::bigint < 0
33+
OR (attrs->>'wal_size')::bigint < 0);
34+
35+
-- Test that every replica in the replicas array has an entry in attributes
36+
SELECT replica
37+
FROM yb_tablet_metadata tm, unnest(tm.replicas) AS replica
38+
WHERE tm.relname = 'test_table_1'
39+
AND NOT (tm.attributes->'replicas' ? replica);
3440

3541
-- Test that every replica address corresponds to a live tserver
3642
SELECT unnest(replicas) AS orphan_replica

src/yb/yql/pgwrapper/ysql_migrations/V97__29665__yb_tablet_metadata_sizes.sql

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
BEGIN;
22
SET LOCAL yb_non_ddl_txn_for_sys_tables_allowed TO true;
33

4-
-- Add active_sst_sizes and wal_sizes columns to yb_get_tablet_metadata().
4+
-- Replace active_sst_sizes and wal_sizes with single attributes jsonb column.
55
UPDATE pg_catalog.pg_proc SET
6-
proallargtypes = '{25,25,25,25,25,23,23,25,1009,1016,1016}',
7-
proargmodes = '{o,o,o,o,o,o,o,o,o,o,o}',
8-
proargnames = '{tablet_id,object_uuid,namespace,object_name,type,start_hash_code,end_hash_code,leader,replicas,active_sst_sizes,wal_sizes}'
6+
proallargtypes = '{25,25,25,25,25,23,23,25,1009,3802}',
7+
proargmodes = '{o,o,o,o,o,o,o,o,o,o}',
8+
proargnames = '{tablet_id,object_uuid,namespace,object_name,type,start_hash_code,end_hash_code,leader,replicas,attributes}'
99
WHERE proname = 'yb_get_tablet_metadata' AND pronamespace = 11;
1010
COMMIT;
1111

12-
-- Recreate the view to include the new columns.
12+
-- Recreate the view to include the new column.
1313
CREATE OR REPLACE VIEW pg_catalog.yb_tablet_metadata
1414
WITH (use_initdb_acl = true) AS
1515
SELECT
@@ -28,8 +28,7 @@ WITH (use_initdb_acl = true) AS
2828
t.end_hash_code,
2929
t.leader,
3030
t.replicas,
31-
t.active_sst_sizes,
32-
t.wal_sizes
31+
t.attributes
3332
FROM
3433
yb_get_tablet_metadata() t
3534
LEFT JOIN

0 commit comments

Comments
 (0)