datadog-checks-base 37.5.0__py2.py3-none-any.whl → 37.6.1__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.5.0"
4
+ __version__ = "37.6.1"
@@ -1,21 +1,27 @@
1
1
  # (C) Datadog, Inc. 2020-present
2
2
  # All rights reserved
3
3
  # Licensed under a 3-clause BSD style license (see LICENSE)
4
+ from collections import ChainMap
5
+
4
6
  from ....utils.functions import no_op
5
7
 
6
8
 
7
9
  class LabelAggregator:
8
10
  def __init__(self, check, config):
9
11
  share_labels = config.get('share_labels', {})
10
- if not isinstance(share_labels, dict):
11
- raise TypeError('Setting `share_labels` must be a mapping')
12
- elif not share_labels:
12
+ self.target_info = config.get('target_info', False)
13
+ self.target_info_labels = {}
14
+
15
+ self._validate_type(share_labels, dict, "Setting `share_labels` must be a mapping")
16
+ self._validate_type(self.target_info, bool, "Setting `target_info` must be a boolean")
17
+
18
+ if not share_labels and not self.target_info:
13
19
  self.populate = no_op
14
20
  return
15
21
 
16
22
  self.cache_shared_labels = config.get('cache_shared_labels', True)
17
23
  self.shared_labels_cached = False
18
-
24
+ self.info_metric = {'target_info': {}}
19
25
  self.metric_config = {}
20
26
  for metric, config in share_labels.items():
21
27
  data = self.metric_config[metric] = {}
@@ -31,6 +37,7 @@ class LabelAggregator:
31
37
  raise TypeError(f'Option `values` for metric `{metric}` of setting `share_labels` must be an array')
32
38
 
33
39
  allowed_values = set()
40
+
34
41
  for i, value in enumerate(values, 1):
35
42
  value = str(value)
36
43
 
@@ -72,34 +79,32 @@ class LabelAggregator:
72
79
 
73
80
  self.unconditional_labels = {}
74
81
 
82
+ def _validate_type(self, value, expected_type, error_message):
83
+ if not isinstance(value, expected_type):
84
+ raise TypeError(error_message)
85
+
75
86
  def __call__(self, metrics):
76
87
  if self.cache_shared_labels:
77
88
  if self.shared_labels_cached:
78
89
  yield from metrics
79
90
  else:
80
- metric_config = self.metric_config.copy()
91
+ metric_config, target_info_metric = self.copy_configs()
81
92
 
82
93
  for metric in metrics:
83
- if metric_config and metric.name in metric_config:
84
- self.collect(metric, metric_config.pop(metric.name))
85
-
94
+ self.process_metric(metric, metric_config, target_info_metric)
86
95
  yield metric
87
96
 
88
97
  self.shared_labels_cached = True
89
98
  else:
90
99
  try:
91
- metric_config = self.metric_config.copy()
92
-
93
- # Cache every encountered metric until the desired labels have been collected
100
+ metric_config, target_info_metric = self.copy_configs()
94
101
  cached_metrics = []
95
102
 
96
103
  for metric in metrics:
97
- if metric.name in metric_config:
98
- self.collect(metric, metric_config.pop(metric.name))
99
-
104
+ self.process_metric(metric, metric_config, target_info_metric)
100
105
  cached_metrics.append(metric)
101
106
 
102
- if not metric_config:
107
+ if not (metric_config or target_info_metric):
103
108
  break
104
109
 
105
110
  yield from cached_metrics
@@ -108,6 +113,24 @@ class LabelAggregator:
108
113
  self.label_sets.clear()
109
114
  self.unconditional_labels.clear()
110
115
 
116
+ def copy_configs(self):
117
+ return self.metric_config.copy(), self.info_metric.copy()
118
+
119
+ def process_metric(self, metric, *configs):
120
+ """
121
+ Collects labels from shared_labels + target_info metrics
122
+ """
123
+ for config in configs:
124
+ if config and metric.name in config:
125
+ self.collect(metric, config.pop(metric.name))
126
+
127
+ def process_target_info(self, metric):
128
+ """
129
+ Updates cached target info metrics
130
+ """
131
+ if metric.samples[0].labels != self.target_info_labels:
132
+ self.target_info_labels = metric.samples[0].labels
133
+
111
134
  def collect(self, metric, config):
112
135
  allowed_values = config.get('values')
113
136
 
@@ -147,13 +170,28 @@ class LabelAggregator:
147
170
  if label in labels:
148
171
  self.unconditional_labels[label] = value
149
172
  else:
150
- for sample in self.allowed_samples(metric, allowed_values):
151
- for label, value in sample.labels.items():
152
- self.unconditional_labels[label] = value
173
+ # Store target_info metric labels to be applied to other metrics in payload
174
+ if metric.name == 'target_info':
175
+ self.target_info_labels.update(
176
+ {
177
+ label: value
178
+ for sample in self.allowed_samples(metric, allowed_values)
179
+ for label, value in sample.labels.items()
180
+ }
181
+ )
182
+ else:
183
+ # Store shared labels in a seperate attribute
184
+ self.unconditional_labels.update(
185
+ {
186
+ label: value
187
+ for sample in self.allowed_samples(metric, allowed_values)
188
+ for label, value in sample.labels.items()
189
+ }
190
+ )
153
191
 
154
192
  def populate(self, labels):
155
193
  label_set = frozenset(labels.items())
156
- labels.update(self.unconditional_labels)
194
+ labels.update(ChainMap(self.unconditional_labels, self.target_info_labels))
157
195
 
158
196
  for matching_label_set, shared_labels in self.label_sets:
159
197
  # Check for subset without incurring the cost of a `.issubset` lookup and call
@@ -58,6 +58,7 @@ class OpenMetricsScraper:
58
58
 
59
59
  # Parse the configuration
60
60
  self.endpoint = config['openmetrics_endpoint']
61
+ self.target_info = config.get('target_info', False)
61
62
 
62
63
  self.metric_transformer = MetricTransformer(self.check, config)
63
64
  self.label_aggregator = LabelAggregator(self.check, config)
@@ -238,7 +239,13 @@ class OpenMetricsScraper:
238
239
  """
239
240
  runtime_data = {'flush_first_value': self.flush_first_value, 'static_tags': self.static_tags}
240
241
 
241
- for metric in self.consume_metrics(runtime_data):
242
+ # Determine which consume method to use based on target_info config
243
+ if self.target_info:
244
+ consume_method = self.consume_metrics_w_target_info
245
+ else:
246
+ consume_method = self.consume_metrics
247
+
248
+ for metric in consume_method(runtime_data):
242
249
  transformer = self.metric_transformer.get(metric)
243
250
  if transformer is None:
244
251
  continue
@@ -248,23 +255,52 @@ class OpenMetricsScraper:
248
255
  self.flush_first_value = True
249
256
 
250
257
  def consume_metrics(self, runtime_data):
258
+ """
259
+ Yield the processed metrics and filter out excluded metrics, without checking for target_info metrics.
260
+ """
261
+
262
+ metric_parser = self.parse_metrics()
263
+
264
+ if not self.flush_first_value and self.use_process_start_time:
265
+ metric_parser = first_scrape_handler(metric_parser, runtime_data, datadog_agent.get_process_start_time())
266
+ if self.label_aggregator.configured:
267
+ metric_parser = self.label_aggregator(metric_parser)
268
+
269
+ for metric in metric_parser:
270
+ # Skip excluded metrics
271
+ if metric.name in self.exclude_metrics or (
272
+ self.exclude_metrics_pattern is not None and self.exclude_metrics_pattern.search(metric.name)
273
+ ):
274
+ self.submit_telemetry_number_of_ignored_metric_samples(metric)
275
+ continue
276
+
277
+ yield metric
278
+
279
+ def consume_metrics_w_target_info(self, runtime_data):
251
280
  """
252
281
  Yield the processed metrics and filter out excluded metrics.
282
+ Additionally, handle target_info metrics.
253
283
  """
254
284
 
255
285
  metric_parser = self.parse_metrics()
286
+
256
287
  if not self.flush_first_value and self.use_process_start_time:
257
288
  metric_parser = first_scrape_handler(metric_parser, runtime_data, datadog_agent.get_process_start_time())
258
289
  if self.label_aggregator.configured:
259
290
  metric_parser = self.label_aggregator(metric_parser)
260
291
 
261
292
  for metric in metric_parser:
293
+ # Skip excluded metrics
262
294
  if metric.name in self.exclude_metrics or (
263
295
  self.exclude_metrics_pattern is not None and self.exclude_metrics_pattern.search(metric.name)
264
296
  ):
265
297
  self.submit_telemetry_number_of_ignored_metric_samples(metric)
266
298
  continue
267
299
 
300
+ # Process target_info metrics
301
+ if metric.name == 'target_info':
302
+ self.label_aggregator.process_target_info(metric)
303
+
268
304
  yield metric
269
305
 
270
306
  def parse_metrics(self):
@@ -312,7 +348,6 @@ class OpenMetricsScraper:
312
348
  """
313
349
  Yield a sample of processed data.
314
350
  """
315
-
316
351
  label_normalizer = get_label_normalizer(metric.type)
317
352
 
318
353
  for sample in metric.samples:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datadog-checks-base
3
- Version: 37.5.0
3
+ Version: 37.6.1
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>
@@ -13,16 +13,16 @@ Classifier: License :: OSI Approved :: BSD License
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Topic :: System :: Monitoring
15
15
  Provides-Extra: db
16
- Requires-Dist: mmh3==5.0.1; extra == 'db'
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.0; extra == 'deps'
19
+ Requires-Dist: cachetools==5.5.1; extra == 'deps'
20
20
  Requires-Dist: cryptography==43.0.1; extra == 'deps'
21
21
  Requires-Dist: ddtrace==2.10.6; extra == 'deps'
22
22
  Requires-Dist: jellyfish==1.1.3; extra == 'deps'
23
23
  Requires-Dist: prometheus-client==0.21.1; extra == 'deps'
24
24
  Requires-Dist: protobuf==5.29.3; extra == 'deps'
25
- Requires-Dist: pydantic==2.10.5; extra == 'deps'
25
+ Requires-Dist: pydantic==2.10.6; extra == 'deps'
26
26
  Requires-Dist: python-dateutil==2.9.0.post0; extra == 'deps'
27
27
  Requires-Dist: pywin32==308; (sys_platform == 'win32') and extra == 'deps'
28
28
  Requires-Dist: pyyaml==6.0.2; extra == 'deps'
@@ -34,7 +34,7 @@ Requires-Dist: uptime==3.0.1; extra == 'deps'
34
34
  Requires-Dist: wrapt==1.17.2; extra == 'deps'
35
35
  Provides-Extra: http
36
36
  Requires-Dist: aws-requests-auth==0.4.3; extra == 'http'
37
- Requires-Dist: botocore==1.36.1; extra == 'http'
37
+ Requires-Dist: botocore==1.36.16; extra == 'http'
38
38
  Requires-Dist: oauthlib==3.2.2; extra == 'http'
39
39
  Requires-Dist: pyjwt==2.10.1; extra == 'http'
40
40
  Requires-Dist: pyopenssl==24.2.1; extra == 'http'
@@ -43,9 +43,9 @@ Requires-Dist: requests-kerberos==0.15.0; extra == 'http'
43
43
  Requires-Dist: requests-ntlm==1.3.0; extra == 'http'
44
44
  Requires-Dist: requests-oauthlib==2.0.0; extra == 'http'
45
45
  Provides-Extra: json
46
- Requires-Dist: orjson==3.10.14; extra == 'json'
46
+ Requires-Dist: orjson==3.10.15; extra == 'json'
47
47
  Provides-Extra: kube
48
- Requires-Dist: kubernetes==31.0.0; extra == 'kube'
48
+ Requires-Dist: kubernetes==32.0.0; extra == 'kube'
49
49
  Requires-Dist: requests-oauthlib==2.0.0; extra == 'kube'
50
50
  Description-Content-Type: text/markdown
51
51
 
@@ -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=5AzFfItx9URe8lFWie_oC3dNfFosQs7be2xVIkuGnko,138
6
+ datadog_checks/base/__about__.py,sha256=L56e6SJ2L24q3EfI391-ib0_nBXjubulAGFIAmNCTgA,138
7
7
  datadog_checks/base/__init__.py,sha256=rSTDo6-2p_RX6I6wnuXrNMglaatoLRyZFTE5wbHZY8s,1466
8
8
  datadog_checks/base/agent.py,sha256=nX9x_BYYizRKGNYfXq5z7S0FZ9xcX_wd2tuxpGe3_8k,350
9
9
  datadog_checks/base/config.py,sha256=qcAA4X9sXQZRdwQe8DgiGd2980VBp1SQA0d695tX_tU,604
@@ -38,9 +38,9 @@ datadog_checks/base/checks/openmetrics/mixins.py,sha256=bkrE_cQ6peW147BACY-G0tHy
38
38
  datadog_checks/base/checks/openmetrics/v2/__init__.py,sha256=P81FBhJLA9MGpz4L7o_7C-pvEwd4A_8jWFWQZ1jg0Eg,115
39
39
  datadog_checks/base/checks/openmetrics/v2/base.py,sha256=UXytG0ze00rXU13VB0BM_ZK_Y_qC6wfxA-OidFm_MyY,4096
40
40
  datadog_checks/base/checks/openmetrics/v2/first_scrape_handler.py,sha256=In-tZXMzieSdL2OXJlIAFi78KbQVwuJnGP0iaLH9974,941
41
- datadog_checks/base/checks/openmetrics/v2/labels.py,sha256=0F0ISh03wS2vVsjbns3FrYDn6gvxj0Xv-2fkA2Hh9D8,7310
41
+ datadog_checks/base/checks/openmetrics/v2/labels.py,sha256=JAIlxAtzQAFoEj1d9IYLZCGt-2M3-ClyyGjZ-VzKNQY,8907
42
42
  datadog_checks/base/checks/openmetrics/v2/metrics.py,sha256=uDVZOHHRWMW8YUQZBY9jCLzecN5DueRNjImxBm1K82k,2189
43
- datadog_checks/base/checks/openmetrics/v2/scraper.py,sha256=d4PcJM_b7wkHUBQ5b_IZo_VW_07jQj_gwTgfDrkp1BA,23279
43
+ datadog_checks/base/checks/openmetrics/v2/scraper.py,sha256=nj7dmKuHeoI_A8bWUzZh16Q3r94-27dV7FepvdOnv9I,24733
44
44
  datadog_checks/base/checks/openmetrics/v2/transform.py,sha256=qv7Y1yvqWm-269mGU7Oq0it8x3VkWUZU2m2d3q-VJZ0,8377
45
45
  datadog_checks/base/checks/openmetrics/v2/utils.py,sha256=tpk3htJAz_KwCRqFs2CTjajHkLCs_2TbGdBp514rWOQ,3565
46
46
  datadog_checks/base/checks/openmetrics/v2/transformers/__init__.py,sha256=hPZn8WLvQfrzLSaJxtFbYYAtK1dt8IQXSULL79srZjs,493
@@ -200,6 +200,6 @@ datadog_checks/utils/tracing.py,sha256=HQbQakKM-Lw75MDkItaYJYipS6YO24Z_ymDVxDsx5
200
200
  datadog_checks/utils/prometheus/__init__.py,sha256=8WwXnM9g1sfS5267QYCJX_hd8MZl5kRgBgQ_SzdNdXs,161
201
201
  datadog_checks/utils/prometheus/functions.py,sha256=4vWsTGLgujHwdYZo0tlAQkqDPHofqUJM3k9eItJqERQ,197
202
202
  datadog_checks/utils/prometheus/metrics_pb2.py,sha256=xg3UdUHe4TjeR4s13LUKZ2U1WVSt6U6zjsVRG6lX6dc,173
203
- datadog_checks_base-37.5.0.dist-info/METADATA,sha256=GZWGd2TVn8CrN5OELUHpk6gXVM5OejdzkZnkcHXfpWc,3590
204
- datadog_checks_base-37.5.0.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
205
- datadog_checks_base-37.5.0.dist-info/RECORD,,
203
+ datadog_checks_base-37.6.1.dist-info/METADATA,sha256=iMylQRYC88icbKrkMES-dTg1SzDEhgsInJI-6c_Vh0o,3591
204
+ datadog_checks_base-37.6.1.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
205
+ datadog_checks_base-37.6.1.dist-info/RECORD,,