18
18
from datadog_checks .base import AgentCheck , is_affirmative
19
19
from datadog_checks .base .utils .db import QueryExecutor , QueryManager
20
20
from datadog_checks .base .utils .db .utils import (
21
+ TagManager ,
21
22
default_json_event_encoding ,
22
23
tracked_query ,
23
24
)
@@ -119,7 +120,8 @@ def __init__(self, name, init_config, instances):
119
120
self ._performance_schema_enabled = None
120
121
self ._events_wait_current_enabled = None
121
122
self ._config = MySQLConfig (self .instance , init_config )
122
- self .tags = self ._config .tags
123
+ self .tag_manager = TagManager ()
124
+ self .tag_manager .set_tags_from_list (self ._config .tags , replace = True ) # Initialize from static config tags
123
125
self .add_core_tags ()
124
126
self .cloud_metadata = self ._config .cloud_metadata
125
127
@@ -144,9 +146,6 @@ def __init__(self, name, init_config, instances):
144
146
) # type: TTLCache
145
147
146
148
self ._runtime_queries_cached = None
147
- # Keep a copy of the tags without the internal resource tags so they can be used for paths that don't
148
- # go through the agent internal metrics submission processing those tags
149
- self ._non_internal_tags = copy .deepcopy (self .tags )
150
149
self .set_resource_tags ()
151
150
self ._is_innodb_engine_enabled_cached = None
152
151
@@ -185,7 +184,7 @@ def database_identifier(self):
185
184
if self ._database_identifier is None :
186
185
template = Template (self ._config .database_identifier .get ('template' ) or '$resolved_hostname' )
187
186
tag_dict = {}
188
- tags = self .tags . copy ()
187
+ tags = self .tag_manager . get_tags ()
189
188
# sort tags to ensure consistent ordering
190
189
tags .sort ()
191
190
for t in tags :
@@ -234,26 +233,31 @@ def add_core_tags(self):
234
233
"""
235
234
Add tags that should be attached to every metric/event but which require check calculations outside the config.
236
235
"""
237
- self .tags . append ("database_hostname:{}" . format ( self .database_hostname ) )
238
- self .tags . append ("database_instance:{}" . format ( self .database_identifier ) )
236
+ self .tag_manager . set_tag ("database_hostname" , self .database_hostname , replace = True )
237
+ self .tag_manager . set_tag ("database_instance" , self .database_identifier , replace = True )
239
238
240
239
def set_resource_tags (self ):
241
240
if self .cloud_metadata .get ("gcp" ) is not None :
242
- self .tags .append (
243
- "dd.internal.resource:gcp_sql_database_instance:{}:{}" .format (
241
+ self .tag_manager .set_tag (
242
+ "dd.internal.resource" ,
243
+ "gcp_sql_database_instance:{}:{}" .format (
244
244
self .cloud_metadata .get ("gcp" )["project_id" ], self .cloud_metadata .get ("gcp" )["instance_id" ]
245
- )
245
+ ),
246
246
)
247
247
if self .cloud_metadata .get ("aws" ) is not None :
248
- self .tags .append (
249
- "dd.internal.resource:aws_rds_instance:{}" .format (
248
+ self .tag_manager .set_tag (
249
+ "dd.internal.resource" ,
250
+ "aws_rds_instance:{}" .format (
250
251
self .cloud_metadata .get ("aws" )["instance_endpoint" ],
251
- )
252
+ ),
252
253
)
253
254
elif AWS_RDS_HOSTNAME_SUFFIX in self .resolved_hostname :
254
255
# allow for detecting if the host is an RDS host, and emit
255
256
# the resource properly even if the `aws` config is unset
256
- self .tags .append ("dd.internal.resource:aws_rds_instance:{}" .format (self .resolved_hostname ))
257
+ self .tag_manager .set_tag (
258
+ "dd.internal.resource" ,
259
+ "aws_rds_instance:{}" .format (self .resolved_hostname ),
260
+ )
257
261
self .cloud_metadata ["aws" ] = {
258
262
"instance_endpoint" : self .resolved_hostname ,
259
263
}
@@ -262,32 +266,21 @@ def set_resource_tags(self):
262
266
# some `deployment_type`s map to multiple `resource_type`s
263
267
resource_type = AZURE_DEPLOYMENT_TYPE_TO_RESOURCE_TYPE .get (deployment_type )
264
268
if resource_type :
265
- self .tags .append (
266
- "dd.internal.resource:{}:{}" .format (resource_type , self .cloud_metadata .get ("azure" )["name" ])
269
+ self .tag_manager .set_tag (
270
+ "dd.internal.resource" ,
271
+ "{}:{}" .format (resource_type , self .cloud_metadata .get ("azure" )["name" ]),
267
272
)
268
273
# finally, emit a `database_instance` resource for this instance
269
- self .tags .append (
270
- "dd.internal.resource:database_instance:{}" .format (
274
+ self .tag_manager .set_tag (
275
+ "dd.internal.resource" ,
276
+ "database_instance:{}" .format (
271
277
self .database_identifier ,
272
- )
278
+ ),
273
279
)
274
280
275
281
def set_version (self , db ):
276
- version = get_version (db )
277
- if version == self .version :
278
- return
279
-
280
- if self .version and self .version .flavor != version .flavor :
281
- try :
282
- self .tags .remove ('dbms_flavor:{}' .format (self .version .flavor .lower ()))
283
- except ValueError :
284
- pass
285
-
286
- self .version = version
287
- if not self .version .flavor :
288
- return
289
-
290
- self .tags .append ('dbms_flavor:{}' .format (self .version .flavor .lower ()))
282
+ self .version = get_version (db )
283
+ self .tag_manager .set_tag ("dbms_flavor" , self .version .flavor .lower (), replace = True )
291
284
292
285
def _check_database_configuration (self , db ):
293
286
self ._check_performance_schema_enabled (db )
@@ -344,7 +337,7 @@ def _get_debug_tags(self):
344
337
return ['agent_hostname:{}' .format (datadog_agent .get_hostname ())]
345
338
346
339
def debug_stats_kwargs (self , tags = None ):
347
- tags = self .tags + self ._get_debug_tags () + (tags or [])
340
+ tags = self .tag_manager . get_tags () + self ._get_debug_tags () + (tags or [])
348
341
return {
349
342
'tags' : tags ,
350
343
"hostname" : self .resolved_hostname ,
@@ -384,7 +377,7 @@ def check(self, _):
384
377
self .check_userstat_enabled (db )
385
378
386
379
# Metric collection
387
- tags = copy . deepcopy ( self .tags )
380
+ tags = self .tag_manager . get_tags ( )
388
381
if not self ._config .only_custom_queries :
389
382
self ._collect_metrics (db , tags = tags )
390
383
self ._collect_system_metrics (self ._config .host , db , tags )
@@ -411,13 +404,6 @@ def check(self, _):
411
404
self ._conn = None
412
405
self ._report_warnings ()
413
406
414
- # _set_database_instance_tags sets the tag list for the `database_instance` resource
415
- # based on metadata that is collected on check start. This ensures that we see tags such as
416
- # `replication_role` appear on the database_instance as a host tag.
417
- def _set_database_instance_tags (self , aurora_tags ):
418
- tags = copy .deepcopy (self ._non_internal_tags )
419
- return list (set (tags ) | set (aurora_tags ))
420
-
421
407
def cancel (self ):
422
408
self ._statement_samples .cancel ()
423
409
self ._statement_metrics .cancel ()
@@ -524,7 +510,7 @@ def _service_check_tags(self, server=None):
524
510
server = self ._config .mysql_sock if self ._config .mysql_sock != '' else self ._config .host
525
511
service_check_tags = [
526
512
'port:{}' .format (self ._config .port if self ._config .port else 'unix_socket' ),
527
- ] + self .tags
513
+ ] + self .tag_manager . get_tags ()
528
514
if not self .disable_generic_tags :
529
515
service_check_tags .append ('server:{0}' .format (server ))
530
516
return service_check_tags
@@ -686,7 +672,7 @@ def _collect_metrics(self, db, tags):
686
672
collected_metric ,
687
673
)
688
674
else :
689
- additional_status_dict [status_dict [ "name" ]] = (status_dict [ "metric_name" ] , status_dict ["type" ])
675
+ additional_status_dict [status_name ] = (status_metric , status_dict ["type" ])
690
676
metrics .update (additional_status_dict )
691
677
692
678
if len (self ._config .additional_variable ) > 0 :
@@ -771,7 +757,9 @@ def _collect_group_replica_metrics(self, db, results):
771
757
]
772
758
if above_802 and len (replica_results ) > 2 :
773
759
additional_tags .append ('member_role:{}' .format (replica_results [2 ]))
774
- self .gauge ('mysql.replication.group.member_status' , 1 , tags = additional_tags + self .tags )
760
+ self .gauge (
761
+ 'mysql.replication.group.member_status' , 1 , tags = additional_tags + self .tag_manager .get_tags ()
762
+ )
775
763
776
764
self .service_check (
777
765
self .GROUP_REPLICATION_SERVICE_CHECK_NAME ,
@@ -803,7 +791,9 @@ def _collect_group_replica_metrics(self, db, results):
803
791
vars_to_submit .update (GROUP_REPLICATION_VARS_8_0_2 )
804
792
805
793
# Submit metrics now, so it's possible to attach `channel_name` tag
806
- self ._submit_metrics (vars_to_submit , results , self .tags + ['channel_name:{}' .format (r [0 ])])
794
+ self ._submit_metrics (
795
+ vars_to_submit , results , self .tag_manager .get_tags () + ['channel_name:{}' .format (r [0 ])]
796
+ )
807
797
808
798
return vars_to_submit
809
799
except Exception as e :
@@ -866,7 +856,7 @@ def _submit_replication_status(self, status, additional_tags):
866
856
self .gauge (
867
857
name = self .SLAVE_SERVICE_CHECK_NAME ,
868
858
value = 1 if status == AgentCheck .OK else 0 ,
869
- tags = self .tags + additional_tags ,
859
+ tags = self .tag_manager . get_tags () + additional_tags ,
870
860
hostname = self .reported_hostname ,
871
861
)
872
862
# deprecated in favor of service_check("mysql.replication.replica_running")
@@ -981,13 +971,13 @@ def _collect_dict(self, metric_type, field_metric_map, query, db, tags):
981
971
self .log .exception ("Error while running %s" , query )
982
972
983
973
def _get_runtime_aurora_tags (self , db ):
984
- runtime_tags = []
974
+ runtime_tags = {}
985
975
try :
986
976
with closing (db .cursor (CommenterCursor )) as cursor :
987
977
cursor .execute (SQL_REPLICATION_ROLE_AWS_AURORA )
988
978
replication_role = cursor .fetchone ()[0 ]
989
979
if replication_role in {'writer' , 'reader' }:
990
- runtime_tags . append ( 'replication_role:' + replication_role )
980
+ runtime_tags [ 'replication_role' ] = replication_role
991
981
except Exception :
992
982
self .log .warning ("Error occurred while fetching Aurora runtime tags: %s" , traceback .format_exc ())
993
983
return runtime_tags
@@ -998,15 +988,11 @@ def _update_runtime_aurora_tags(self, aurora_tags):
998
988
First removes any existing Aurora runtime tags by key name, then adds the new tags.
999
989
"""
1000
990
# Extract tag keys from aurora_tags to identify which tags to remove
1001
- aurora_tag_keys = {tag .split (':' )[0 ] for tag in aurora_tags }
1002
-
1003
- # Remove existing Aurora runtime tags from both tag lists
1004
- self .tags = [tag for tag in self .tags if tag .split (':' )[0 ] not in aurora_tag_keys ]
1005
- self ._non_internal_tags = [tag for tag in self ._non_internal_tags if tag .split (':' )[0 ] not in aurora_tag_keys ]
1006
-
1007
- # Add the new Aurora tags using set operations
1008
- self .tags = list (set (self .tags ) | set (aurora_tags ))
1009
- self ._non_internal_tags = list (set (self ._non_internal_tags ) | set (aurora_tags ))
991
+ for tag , value in aurora_tags .items ():
992
+ self .tag_manager .set_tag (tag , value , replace = True )
993
+ self .tag_manager .set_tag (
994
+ "dd.internal.resource" , "database_instance:{}" .format (self .database_identifier ), replace = True
995
+ )
1010
996
1011
997
def _collect_system_metrics (self , host , db , tags ):
1012
998
pid = None
@@ -1417,7 +1403,7 @@ def _send_database_instance_metadata(self):
1417
1403
"collection_interval" : self ._config .database_instance_collection_interval ,
1418
1404
'dbms_version' : self .version .version + '+' + self .version .build ,
1419
1405
'integration_version' : __version__ ,
1420
- "tags" : self ._non_internal_tags ,
1406
+ "tags" : self .tag_manager . get_tags () ,
1421
1407
"timestamp" : time .time () * 1000 ,
1422
1408
"cloud_metadata" : self ._config .cloud_metadata ,
1423
1409
"metadata" : {
0 commit comments