Skip to content

Commit

Permalink
Report pg_class xmin (#19218)
Browse files Browse the repository at this point in the history
Add a postgresql.relation.xmin reporting the xmin of the relation's
row in pg_class. This will allow to detect if and when a relation was
modified through a DDL as most of DDL will modify the relation's
pg_class.

Other processes may modify pg_class, like ANALYZE to update tuple
estimations. However, those updates are done in place and won't bump the
row's xmin.
  • Loading branch information
bonnefoa authored Dec 10, 2024
1 parent 685547d commit aecd37d
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 1 deletion.
1 change: 1 addition & 0 deletions postgres/changelog.d/19218.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add postgresql.relation.xmin metric
4 changes: 3 additions & 1 deletion postgres/datadog_checks/postgres/relationsmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@
pg_stat_get_vacuum_count(C.reltoastrelid),
pg_stat_get_autovacuum_count(C.reltoastrelid),
EXTRACT(EPOCH FROM age(CURRENT_TIMESTAMP, pg_stat_get_last_vacuum_time(C.reltoastrelid))),
EXTRACT(EPOCH FROM age(CURRENT_TIMESTAMP, pg_stat_get_last_autovacuum_time(C.reltoastrelid)))
EXTRACT(EPOCH FROM age(CURRENT_TIMESTAMP, pg_stat_get_last_autovacuum_time(C.reltoastrelid))),
C.xmin
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
LEFT JOIN pg_locks L ON C.oid = L.relation AND L.locktype = 'relation'
Expand Down Expand Up @@ -234,6 +235,7 @@
{'name': 'toast.autovacuumed', 'type': 'monotonic_count'},
{'name': 'toast.last_vacuum_age', 'type': 'gauge'},
{'name': 'toast.last_autovacuum_age', 'type': 'gauge'},
{'name': 'relation.xmin', 'type': 'gauge'},
],
}

Expand Down
1 change: 1 addition & 0 deletions postgres/metadata.csv
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ postgresql.queries.time,count,,nanosecond,,"The total query execution time per q
postgresql.relation.all_visible,gauge,,,,"Number of pages that are marked as all visible in the table's visibility map. This is only an estimation used by the planner and is updated by VACUUM or ANALYZE. This metric is tagged with db, schema, table, partition_of",0,postgres,relation all_visible,
postgresql.relation.pages,gauge,,,,"Size of a table in pages (1 page == 8KB by default). This is only an estimation used by the planner and is updated by VACUUM or ANALYZE. This metric is tagged with db, schema, table, partition_of.",0,postgres,relation pages,
postgresql.relation.tuples,gauge,,,,"Number of live rows in the table. This is only an estimation used by the planner and is updated by VACUUM or ANALYZE. If the table has never been vacuumed or analyze, -1 will be reported. This metric is tagged with db, schema, table, partition_of",0,postgres,relation tuples,
postgresql.relation.xmin,gauge,,,,"Transaction ID of the latest relation's modification in pg_class. This metric is tagged with db, schema, table",0,postgres,relation xmin,
postgresql.relation_size,gauge,,byte,,"The disk space used by the specified table. TOAST data, indexes, free space map and visibility map are not included. This metric is tagged with db, schema, table.",0,postgres,relation size,
postgresql.replication.backend_xmin_age,gauge,,,,The age of the standby server's xmin horizon (relative to latest stable xid) reported by hot_standby_feedback.,-1,postgres,repl backend xmin,
postgresql.replication.wal_flush_lag,gauge,,second,,Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written and flushed it (but not yet applied it). This can be used to gauge the delay that synchronous_commit level on incurred while committing if this server was configured as a synchronous standby. Only available with postgresql 10 and newer.,-1,postgres,repl flush lag,
Expand Down
29 changes: 29 additions & 0 deletions postgres/tests/test_relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,35 @@ def test_relations_metrics_regex(aggregator, integration_check, pg_instance):
_check_metrics_for_relation_wo_index(aggregator, expected_tags[relation])


@pytest.mark.integration
@pytest.mark.usefixtures('dd_environment')
def test_relations_xmin(aggregator, integration_check, pg_instance):
pg_instance['relations'] = ['persons']

conn = _get_superconn(pg_instance)
cursor = conn.cursor()
cursor.execute("SELECT xmin FROM pg_class WHERE relname='persons'")
start_xmin = float(cursor.fetchone()[0])

# Check that initial xmin metric match
check = integration_check(pg_instance)
check.check(pg_instance)
expected_tags = _get_expected_tags(check, pg_instance, db=pg_instance['dbname'], table='persons', schema='public')
aggregator.assert_metric('postgresql.relation.xmin', count=1, value=start_xmin, tags=expected_tags)
aggregator.reset()

# Run multiple DDL modifying the persons relation which will increase persons' xmin in pg_class
cursor.execute("ALTER TABLE persons REPLICA IDENTITY FULL;")
cursor.execute("ALTER TABLE persons REPLICA IDENTITY DEFAULT;")
cursor.close()
conn.close()

check.check(pg_instance)

# xmin metric should be greater than initial xmin
assert_metric_at_least(aggregator, 'postgresql.relation.xmin', lower_bound=start_xmin + 1, tags=expected_tags)


@pytest.mark.integration
@pytest.mark.usefixtures('dd_environment')
def test_max_relations(aggregator, integration_check, pg_instance):
Expand Down

0 comments on commit aecd37d

Please sign in to comment.