@@ -164,11 +164,13 @@ def __init__(self, name, init_config, instances):
164164 token_provider = self .build_token_provider (),
165165 )
166166 self .metrics_cache = PostgresMetricsCache (self ._config )
167- # Initialize statement metrics collector before server version is known.
168- self .statement_metrics = PostgresStatementMetrics (self , self ._config )
169- self .statement_samples = PostgresStatementSamples (self , self ._config )
170- self .metadata_samples = PostgresMetadata (self , self ._config )
171- self .data_observability = PostgresDataObservability (self , self ._config )
167+ # Only tests read these; the registry owns the jobs. Remove them once DatabaseCheck
168+ # exposes a public job accessor. Jobs the configuration does not enable stay None.
169+ self .statement_metrics = None
170+ self .statement_samples = None
171+ self .metadata_samples = None
172+ self .data_observability = None
173+ self ._register_async_jobs ()
172174 self ._relations_manager = RelationsManager (self ._config .relations , self ._config .max_relations )
173175 self ._clean_state ()
174176 self ._query_manager = QueryManager (self , lambda _ : None , queries = []) # query executor is set later
@@ -510,7 +512,7 @@ def cancel(self):
510512 cancel().
511513 """
512514 self .log .debug ("Marking check as cancelled" )
513- self ._cancel_async_jobs ()
515+ self .cancel_async_jobs ()
514516 needs_finalize = False
515517 with self ._cancel_lock :
516518 self ._cancelled = True
@@ -522,31 +524,22 @@ def cancel(self):
522524 else :
523525 self .log .debug ("cancel() deferred finalize, check is still running" )
524526
525- @property
526- def _async_jobs (self ):
527- """Return the async jobs active for this check's configuration."""
528- jobs = []
527+ def _register_async_jobs (self ):
528+ """Build and register the async jobs enabled by this check's configuration."""
529529 if self ._config .dbm :
530- jobs .extend ([self .statement_metrics , self .statement_samples , self .metadata_samples ])
531- elif self ._config .data_observability .enabled :
532- jobs .append (self .metadata_samples )
530+ # Built before the server version is known; _initialize_statement_metrics replaces it
531+ # with the collector that suits the version.
532+ self .statement_metrics = self .register_async_job (PostgresStatementMetrics (self , self ._config ))
533+ self .statement_samples = self .register_async_job (PostgresStatementSamples (self , self ._config ))
534+ if self ._config .dbm or self ._config .data_observability .enabled :
535+ self .metadata_samples = self .register_async_job (PostgresMetadata (self , self ._config ))
533536 if self ._config .data_observability .enabled :
534- jobs .append (self .data_observability )
535- return jobs
536-
537- def _cancel_async_jobs (self ):
538- """Signal async jobs to stop. Safe to call while check() is running."""
539- for job in self ._async_jobs :
540- job .cancel ()
537+ self .data_observability = self .register_async_job (PostgresDataObservability (self , self ._config ))
541538
542539 def _finalize (self ):
543540 """Tear down check state. Must not run while check() is executing."""
544541 self .log .debug ("Finalizing check: closing connections and clearing state" )
545- for job in self ._async_jobs :
546- if job ._job_loop_future :
547- job ._job_loop_future .result ()
548- job ._job_loop_future = None
549- job ._shutdown ()
542+ self .shutdown_async_jobs ()
550543 self ._clean_state ()
551544 self .check_initializations .clear ()
552545 # TODO: move diagnosis cleanup into AgentCheck.cancel() in the base class
@@ -635,6 +628,8 @@ def load_version(self):
635628 self .set_metadata ('version' , self .raw_version )
636629
637630 def _initialize_statement_metrics (self ):
631+ if not self ._config .dbm :
632+ return
638633 custom_pgss_view = self ._config .pg_stat_statements_view != 'pg_stat_statements'
639634 if self ._config .query_metrics .incremental_query_metrics and self .version < V10 :
640635 self .log .warning (
@@ -652,11 +647,14 @@ def _initialize_statement_metrics(self):
652647
653648 if self ._config .query_metrics .incremental_query_metrics and self .version >= V10 and not custom_pgss_view :
654649 self .log .info ("Using incremental query metrics collector" )
655- self . statement_metrics = PostgresStatementMetricsV2 (self , self ._config )
650+ collector = PostgresStatementMetricsV2 (self , self ._config )
656651 else :
657652 if not self ._config .query_metrics .incremental_query_metrics :
658653 self .log .info ("Using legacy query metrics collector (full pg_stat_statements load)" )
659- self .statement_metrics = PostgresStatementMetrics (self , self ._config )
654+ collector = PostgresStatementMetrics (self , self ._config )
655+ # Both collectors use the same job name, so registering replaces the instance built in
656+ # _register_async_jobs.
657+ self .statement_metrics = self .register_async_job (collector )
660658
661659 def initialize_is_aurora (self ):
662660 if self .is_aurora is None :
@@ -1242,14 +1240,7 @@ def check(self, _):
12421240 if not self ._config .only_custom_queries :
12431241 self ._collect_stats (tags )
12441242 if not self ._cancelled :
1245- if self ._config .dbm :
1246- self .statement_metrics .run_job_loop (tags )
1247- self .statement_samples .run_job_loop (tags )
1248- self .metadata_samples .run_job_loop (tags )
1249- elif self ._config .data_observability .enabled :
1250- self .metadata_samples .run_job_loop (tags )
1251- if self ._config .data_observability .enabled :
1252- self .data_observability .run_job_loop (tags )
1243+ self .run_async_jobs (tags )
12531244 if self ._config .collect_wal_metrics is True :
12541245 # collect wal metrics for pg < 10 only when explicitly enabled
12551246 # (requires local filesystem access to the WAL directory)
0 commit comments