datadog-checks-base 37.12.0__py2.py3-none-any.whl → 37.13.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
1
  # (C) Datadog, Inc. 2018-present
2
2
  # All rights reserved
3
3
  # Licensed under a 3-clause BSD style license (see LICENSE)
4
- __version__ = "37.12.0"
4
+ __version__ = "37.13.0"
@@ -11,8 +11,9 @@ import socket
11
11
  import threading
12
12
  import time
13
13
  from concurrent.futures.thread import ThreadPoolExecutor
14
+ from enum import Enum, auto
14
15
  from ipaddress import IPv4Address
15
- from typing import Any, Callable, Dict, List, Tuple # noqa: F401
16
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union # noqa: F401
16
17
 
17
18
  from cachetools import TTLCache
18
19
 
@@ -441,3 +442,128 @@ def tracked_query(check, operation, tags=None):
441
442
  yield
442
443
  elapsed_ms = (time.time() - start_time) * 1000
443
444
  check.histogram("dd.{}.operation.time".format(check.name), elapsed_ms, **stats_kwargs)
445
+
446
+
447
+ class TagType(Enum):
448
+ """Enum for different types of tags"""
449
+
450
+ KEYLESS = auto()
451
+
452
+
453
+ class TagManager:
454
+ """
455
+ Manages tags for a check. Tags are stored as a dictionary of key-value pairs
456
+ for key-value tags and as a list of values for keyless tags useful for easy update and deletion.
457
+ There's an internal cache of the tag list to avoid generating the list of tag strings
458
+ multiple times.
459
+ """
460
+
461
+ def __init__(self) -> None:
462
+ self._tags: Dict[Union[str, TagType], List[str]] = {}
463
+ self._cached_tag_list: Optional[tuple[str, ...]] = None
464
+ self._keyless: TagType = TagType.KEYLESS
465
+
466
+ def set_tag(self, key: Optional[str], value: str, replace: bool = False) -> None:
467
+ """
468
+ Set a tag with the given key and value.
469
+ If key is None or empty, the value is stored as a keyless tag.
470
+ Args:
471
+ key (str): The tag key, or None/empty for keyless tags
472
+ value (str): The tag value
473
+ replace (bool): If True, replaces all existing values for this key
474
+ If False, appends the value if it doesn't exist
475
+ """
476
+ if not key:
477
+ key = self._keyless
478
+
479
+ if replace or key not in self._tags:
480
+ self._tags[key] = [value]
481
+ # Invalidate the cache since tags have changed
482
+ self._cached_tag_list = None
483
+ elif value not in self._tags[key]:
484
+ self._tags[key].append(value)
485
+ # Invalidate the cache since tags have changed
486
+ self._cached_tag_list = None
487
+
488
+ def set_tags_from_list(self, tag_list: List[str], replace: bool = False) -> None:
489
+ """
490
+ Set multiple tags from a list of strings.
491
+ Strings can be in "key:value" format or just "value" format.
492
+ Args:
493
+ tag_list (List[str]): List of tags in "key:value" format or just "value"
494
+ replace (bool): If True, replaces all existing tags with the new tags list
495
+ """
496
+ if replace:
497
+ self._tags.clear()
498
+ self._cached_tag_list = None
499
+
500
+ for tag in tag_list:
501
+ if ':' in tag:
502
+ key, value = tag.split(':', 1)
503
+ self.set_tag(key, value)
504
+ else:
505
+ self.set_tag(None, tag)
506
+
507
+ def delete_tag(self, key: Optional[str], value: Optional[str] = None) -> bool:
508
+ """
509
+ Delete a tag or specific value for a tag.
510
+ For keyless tags, use None or empty string as the key.
511
+ Args:
512
+ key (str): The tag key to delete, or None/empty for keyless tags
513
+ value (str, optional): If provided, only deletes this specific value for the key.
514
+ If None, deletes all values for the key.
515
+ Returns:
516
+ bool: True if something was deleted, False otherwise
517
+ """
518
+ if not key:
519
+ key = self._keyless
520
+
521
+ if key not in self._tags:
522
+ return False
523
+
524
+ if value is None:
525
+ # Delete the entire key
526
+ del self._tags[key]
527
+ # Invalidate the cache
528
+ self._cached_tag_list = None
529
+ return True
530
+ else:
531
+ # Delete specific value if it exists
532
+ if value in self._tags[key]:
533
+ self._tags[key].remove(value)
534
+ # Clean up empty lists
535
+ if not self._tags[key]:
536
+ del self._tags[key]
537
+ # Invalidate the cache
538
+ self._cached_tag_list = None
539
+ return True
540
+ return False
541
+
542
+ def _generate_tag_strings(self, tags_dict: Dict[Union[str, TagType], List[str]]) -> tuple[str, ...]:
543
+ """
544
+ Generate a tuple of tag strings from a tags dictionary.
545
+ Args:
546
+ tags_dict (Dict[Union[str, TagType], List[str]]): Dictionary of tags to convert to strings
547
+ Returns:
548
+ tuple[str, ...]: Tuple of tag strings
549
+ """
550
+ return tuple(
551
+ value if key == self._keyless else f"{key}:{value}" for key, values in tags_dict.items() for value in values
552
+ )
553
+
554
+ def get_tags(self) -> List[str]:
555
+ """
556
+ Get a list of tag strings.
557
+ For key-value tags, returns "key:value" format.
558
+ For keyless tags, returns just the value.
559
+ The returned list is always sorted alphabetically.
560
+ Returns:
561
+ list: Sorted list of tag strings
562
+ """
563
+ # Return cached list if available
564
+ if self._cached_tag_list is not None:
565
+ return list(self._cached_tag_list)
566
+
567
+ # Generate and cache regular tags
568
+ self._cached_tag_list = self._generate_tag_strings(self._tags)
569
+ return list(self._cached_tag_list)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datadog-checks-base
3
- Version: 37.12.0
3
+ Version: 37.13.0
4
4
  Summary: The Datadog Check Toolkit
5
5
  Project-URL: Source, https://github.com/DataDog/integrations-core
6
6
  Author-email: Datadog <packages@datadoghq.com>
@@ -16,14 +16,14 @@ Provides-Extra: db
16
16
  Requires-Dist: mmh3==5.1.0; extra == 'db'
17
17
  Provides-Extra: deps
18
18
  Requires-Dist: binary==1.0.1; extra == 'deps'
19
- Requires-Dist: cachetools==5.5.2; extra == 'deps'
20
- Requires-Dist: cryptography==44.0.3; extra == 'deps'
21
- Requires-Dist: ddtrace==3.7.2; extra == 'deps'
19
+ Requires-Dist: cachetools==6.0.0; extra == 'deps'
20
+ Requires-Dist: cryptography==45.0.3; extra == 'deps'
21
+ Requires-Dist: ddtrace==3.8.0; extra == 'deps'
22
22
  Requires-Dist: jellyfish==1.2.0; extra == 'deps'
23
23
  Requires-Dist: lazy-loader==0.4; extra == 'deps'
24
- Requires-Dist: prometheus-client==0.21.1; extra == 'deps'
25
- Requires-Dist: protobuf==6.30.2; extra == 'deps'
26
- Requires-Dist: pydantic==2.11.4; extra == 'deps'
24
+ Requires-Dist: prometheus-client==0.22.0; extra == 'deps'
25
+ Requires-Dist: protobuf==6.31.0; extra == 'deps'
26
+ Requires-Dist: pydantic==2.11.5; extra == 'deps'
27
27
  Requires-Dist: python-dateutil==2.9.0.post0; extra == 'deps'
28
28
  Requires-Dist: pywin32==310; (sys_platform == 'win32') and extra == 'deps'
29
29
  Requires-Dist: pyyaml==6.0.2; extra == 'deps'
@@ -35,10 +35,10 @@ Requires-Dist: urllib3==2.4.0; extra == 'deps'
35
35
  Requires-Dist: wrapt==1.17.2; extra == 'deps'
36
36
  Provides-Extra: http
37
37
  Requires-Dist: aws-requests-auth==0.4.3; extra == 'http'
38
- Requires-Dist: botocore==1.38.8; extra == 'http'
38
+ Requires-Dist: botocore==1.38.24; extra == 'http'
39
39
  Requires-Dist: oauthlib==3.2.2; extra == 'http'
40
40
  Requires-Dist: pyjwt==2.10.1; extra == 'http'
41
- Requires-Dist: pyopenssl==25.0.0; extra == 'http'
41
+ Requires-Dist: pyopenssl==25.1.0; extra == 'http'
42
42
  Requires-Dist: pysocks==1.7.1; extra == 'http'
43
43
  Requires-Dist: requests-kerberos==0.15.0; extra == 'http'
44
44
  Requires-Dist: requests-ntlm==1.3.0; extra == 'http'
@@ -3,7 +3,7 @@ datadog_checks/config.py,sha256=PrAXGdlLnoV2VMQff_noSaSJJ0wg4BAiGnw7jCQLSik,196
3
3
  datadog_checks/errors.py,sha256=eFwmnrX-batIgbu-iJyseqAPNO_4rk1UuaKK89evLhg,155
4
4
  datadog_checks/log.py,sha256=orvOgMKGNEsqSTLalCAQpWP-ouorpG1A7Gn-j2mRD80,301
5
5
  datadog_checks/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
6
- datadog_checks/base/__about__.py,sha256=0wN6vQOLTtAvgoiMmU7PlRS1klD-UO17t5Mi4SU7w_4,139
6
+ datadog_checks/base/__about__.py,sha256=lB4-_xYUmOUSD8CzIo0yXKB4H2tiej7dQ2fEkgCdyHw,139
7
7
  datadog_checks/base/__init__.py,sha256=yWegSLE-TZWIGSvAiJj9PSrUxzlOo_UVJLt2zORZ8Ek,363
8
8
  datadog_checks/base/__init__.pyi,sha256=eH8XhrtvnD6uE6FWfEyCmKwOaaLJxNolS08D6IRHZuU,995
9
9
  datadog_checks/base/agent.py,sha256=nX9x_BYYizRKGNYfXq5z7S0FZ9xcX_wd2tuxpGe3_8k,350
@@ -143,7 +143,7 @@ datadog_checks/base/utils/db/statement_metrics.py,sha256=U7EtERkmFzfCtfyd3094fBa
143
143
  datadog_checks/base/utils/db/timed_cache.py,sha256=a9Ks5KKUvExB6GOATXTSCLamVtLD919Dn6HpweGKtFw,2114
144
144
  datadog_checks/base/utils/db/transform.py,sha256=kNdiBZVoZm1oNRNWIatrAfgORjbkRKhs1AgW_aQCj3I,23879
145
145
  datadog_checks/base/utils/db/types.py,sha256=OLX2Oq58JQPFBD4oqUpCLkAP7ovRGN_i1vFk1E0N8Lg,267
146
- datadog_checks/base/utils/db/utils.py,sha256=hTPEtamyPN4x9tCE9BuHbd6d523TPxw8DojBuJO2qf0,16934
146
+ datadog_checks/base/utils/db/utils.py,sha256=z1CIC_VdMHHYuvoRHZKpdnk_bHj-_M07JFSPNMjIUP4,21657
147
147
  datadog_checks/base/utils/discovery/__init__.py,sha256=vPCOdsThBcBjFJRPhDm6IsZGOwk8HlvciwCe_l8dKLk,211
148
148
  datadog_checks/base/utils/discovery/__init__.pyi,sha256=ScVLU1Njj9ekZmewltb0cULI6BylssVHfn4CcPNeyr8,173
149
149
  datadog_checks/base/utils/discovery/cache.py,sha256=f9L3A7YZpZ-mpZpFIwjsa5ab9cZMGkqdetdr9EpalbI,887
@@ -217,6 +217,6 @@ datadog_checks/utils/tracing.py,sha256=HQbQakKM-Lw75MDkItaYJYipS6YO24Z_ymDVxDsx5
217
217
  datadog_checks/utils/prometheus/__init__.py,sha256=8WwXnM9g1sfS5267QYCJX_hd8MZl5kRgBgQ_SzdNdXs,161
218
218
  datadog_checks/utils/prometheus/functions.py,sha256=4vWsTGLgujHwdYZo0tlAQkqDPHofqUJM3k9eItJqERQ,197
219
219
  datadog_checks/utils/prometheus/metrics_pb2.py,sha256=xg3UdUHe4TjeR4s13LUKZ2U1WVSt6U6zjsVRG6lX6dc,173
220
- datadog_checks_base-37.12.0.dist-info/METADATA,sha256=C9JrO70hO0CXDtJsgKBCNXFzrZzJs-Zw8JSXPlGu5ek,4244
221
- datadog_checks_base-37.12.0.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
222
- datadog_checks_base-37.12.0.dist-info/RECORD,,
220
+ datadog_checks_base-37.13.0.dist-info/METADATA,sha256=fEpcawGlBAaVY_ESNFrALlVN9FGTQBSt5fUByiRAPA0,4245
221
+ datadog_checks_base-37.13.0.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
222
+ datadog_checks_base-37.13.0.dist-info/RECORD,,