Skip to content

Commit 182dc48

Browse files
committed
Add extension info metadata to emitted record
1 parent 3891f5e commit 182dc48

File tree

1 file changed

+62
-3
lines changed

1 file changed

+62
-3
lines changed

postgres/datadog_checks/postgres/metadata.py

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,29 @@
2424
from .version_utils import VersionUtils
2525

2626
# default collection intervals in seconds
27+
DEFAULT_EXTENSIONS_COLLECTION_INTERVAL = 600
2728
DEFAULT_SETTINGS_COLLECTION_INTERVAL = 600
2829
DEFAULT_SCHEMAS_COLLECTION_INTERVAL = 600
2930
DEFAULT_RESOURCES_COLLECTION_INTERVAL = 300
3031
DEFAULT_SETTINGS_IGNORED_PATTERNS = ["plpgsql%"]
3132

32-
# PG_SETTINGS_QURERY is used to collect all the settings from the pg_settings table
33+
# PG_EXTENSION_INFO_QUERY is used to collect extension names and versions from
34+
# the pg_extension table. Schema names and roles are retrieved from their re-
35+
# spective catalog tables.
36+
PG_EXTENSION_INFO_QUERY = """
37+
SELECT
38+
e.oid id,
39+
e.extname name,
40+
r.rolname owner,
41+
ns.nspname schema_name,
42+
e.extrelocatable relocatable,
43+
e.extversion version
44+
FROM pg_extension e
45+
LEFT JOIN pg_namespace ns on e.extnamespace = ns.oid
46+
JOIN pg_roles r ON e.extowner = r.oid;
47+
"""
48+
49+
# PG_SETTINGS_QUERY is used to collect all the settings from the pg_settings table
3350
# Edge case: If source is 'session', it uses reset_val
3451
# (which represents the value that the setting would revert to on session end or reset),
3552
# otherwise, it uses the current setting value.
@@ -211,6 +228,9 @@ def __init__(self, check, config, shutdown_callback):
211228
self.pg_settings_ignored_patterns = config.settings_metadata_config.get(
212229
"ignored_settings_patterns", DEFAULT_SETTINGS_IGNORED_PATTERNS
213230
)
231+
self.pg_extensions_collection_interval = config.settings_metadata_config.get(
232+
"collection_interval", DEFAULT_EXTENSIONS_COLLECTION_INTERVAL
233+
)
214234
self.pg_settings_collection_interval = config.settings_metadata_config.get(
215235
"collection_interval", DEFAULT_SETTINGS_COLLECTION_INTERVAL
216236
)
@@ -221,9 +241,12 @@ def __init__(self, check, config, shutdown_callback):
221241
"collection_interval", DEFAULT_RESOURCES_COLLECTION_INTERVAL
222242
)
223243

224-
# by default, send resources every 5 minutes
244+
# by default, send resources every 10 minutes
225245
self.collection_interval = min(
226-
resources_collection_interval, self.pg_settings_collection_interval, self.schemas_collection_interval
246+
resources_collection_interval,
247+
self.pg_extensions_collection_interval,
248+
self.pg_settings_collection_interval,
249+
self.schemas_collection_interval,
227250
)
228251

229252
super(PostgresMetadata, self).__init__(
@@ -240,10 +263,12 @@ def __init__(self, check, config, shutdown_callback):
240263
self._check = check
241264
self._config = config
242265
self.db_pool = self._check.db_pool
266+
self._collect_extensions_enabled = is_affirmative(config.settings_metadata_config.get("enabled", False))
243267
self._collect_pg_settings_enabled = is_affirmative(config.settings_metadata_config.get("enabled", False))
244268
self._collect_schemas_enabled = is_affirmative(config.schemas_metadata_config.get("enabled", False))
245269
self._is_schemas_collection_in_progress = False
246270
self._pg_settings_cached = None
271+
self._time_since_last_extension_query = 0
247272
self._time_since_last_settings_query = 0
248273
self._last_schemas_query_time = 0
249274
self._conn_ttl_ms = self._config.idle_connection_timeout
@@ -268,6 +293,40 @@ def run_job(self):
268293
self.report_postgres_metadata()
269294
self._check.db_pool.prune_connections()
270295

296+
@tracked_method(agent_check_getter=agent_check_getter)
297+
def report_postgres_extensions(self):
298+
# Only query if configured, according to interval
299+
elapsed_s = time.time() - self._time_since_last_extension_query
300+
if elapsed_s >= self.pg_extensions_collection_interval and self._collect_extensions_enabled:
301+
self._extensions_cached = self._collect_postgres_extensions()
302+
event = {
303+
"host": self._check.reported_hostname,
304+
"database_instance": self._check.database_identifier,
305+
"agent_version": datadog_agent.get_version(),
306+
"dbms": "postgres",
307+
"kind": "pg_extension",
308+
"collection_interval": self.collection_interval,
309+
"dbms_version": payload_pg_version(self._check.version),
310+
"tags": self._tags_no_db,
311+
"timestamp": time.time() * 1000,
312+
"cloud_metadata": self._check.cloud_metadata,
313+
"metadata": self._extensions_cached,
314+
}
315+
self._check.database_monitoring_metadata(json.dumps(event, default=default_json_event_encoding))
316+
317+
@tracked_method(agent_check_getter=agent_check_getter)
318+
def _collect_postgres_extensions(self):
319+
with self._check._get_main_db() as conn:
320+
with conn.cursor(cursor_factory=CommenterDictCursor) as cursor:
321+
self._time_since_last_extension_query = time.time()
322+
323+
# Get loaded extensions
324+
cursor.execute(PG_EXTENSION_INFO_QUERY)
325+
rows = cursor.fetchall()
326+
327+
self._log.debug("Loaded %s rows from pg_extension", len(rows))
328+
return [dict(row) for row in rows]
329+
271330
@tracked_method(agent_check_getter=agent_check_getter)
272331
def report_postgres_metadata(self):
273332
# Only query for settings if configured to do so &&

0 commit comments

Comments
 (0)