Skip to content

Commit d8b986e

Browse files
committed
feat(origindetection): implement cardinality common field
Signed-off-by: Wassim DHIF <[email protected]>
1 parent 9a3f236 commit d8b986e

File tree

10 files changed

+197
-76
lines changed

10 files changed

+197
-76
lines changed

datadog/__init__.py

+10
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def initialize(
4747
statsd_constant_tags=None, # type: Optional[List[str]]
4848
return_raw_response=False, # type: bool
4949
hostname_from_config=True, # type: bool
50+
cardinality=None, # type: Optional[str]
5051
**kwargs # type: Any
5152
):
5253
# type: (...) -> None
@@ -117,6 +118,12 @@ def initialize(
117118
118119
:param hostname_from_config: Set the hostname from the Datadog agent config (agent 5). Will be deprecated
119120
:type hostname_from_config: boolean
121+
122+
:param cardinality: Set the global cardinality for all metrics. \
123+
Possible values are "none", "low", "orchestrator" and "high".
124+
Can also be set via the DATADOG_CARDINALITY or DD_CARDINALITY environment variables.
125+
:type cardinality: string
126+
120127
"""
121128
# API configuration
122129
api._api_key = api_key or api._api_key or os.environ.get("DATADOG_API_KEY", os.environ.get("DD_API_KEY"))
@@ -151,6 +158,9 @@ def initialize(
151158
statsd.disable_buffering = statsd_disable_buffering
152159
api._return_raw_response = return_raw_response
153160

161+
# Set the global cardinality for all metrics
162+
statsd.cardinality = cardinality or os.environ.get("DATADOG_CARDINALITY", os.environ.get("DD_CARDINALITY"))
163+
154164
# HTTP client and API options
155165
for key, value in iteritems(kwargs):
156166
attribute = "_{}".format(key)

datadog/dogstatsd/aggregator.py

+25-17
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
)
1212
from datadog.dogstatsd.metric_types import MetricType
1313
from datadog.dogstatsd.max_sample_metric_context import MaxSampleMetricContexts
14+
from datadog.util.format import validate_cardinality
1415

1516

1617
class Aggregator(object):
17-
def __init__(self, max_samples_per_context=0):
18+
def __init__(self, max_samples_per_context=0, cardinality=None):
1819
self.max_samples_per_context = max_samples_per_context
1920
self.metrics_map = {
2021
MetricType.COUNT: {},
@@ -31,6 +32,7 @@ def __init__(self, max_samples_per_context=0):
3132
MetricType.GAUGE: threading.RLock(),
3233
MetricType.SET: threading.RLock(),
3334
}
35+
self._cardinality = cardinality
3436

3537
def flush_aggregated_metrics(self):
3638
metrics = []
@@ -58,53 +60,59 @@ def get_context(self, name, tags):
5860
tags_str = ",".join(tags) if tags is not None else ""
5961
return "{}:{}".format(name, tags_str)
6062

61-
def count(self, name, value, tags, rate, timestamp=0):
63+
def count(self, name, value, tags, rate, timestamp=0, cardinality=None):
6264
return self.add_metric(
63-
MetricType.COUNT, CountMetric, name, value, tags, rate, timestamp
65+
MetricType.COUNT, CountMetric, name, value, tags, rate, timestamp, cardinality
6466
)
6567

66-
def gauge(self, name, value, tags, rate, timestamp=0):
68+
def gauge(self, name, value, tags, rate, timestamp=0, cardinality=None):
6769
return self.add_metric(
68-
MetricType.GAUGE, GaugeMetric, name, value, tags, rate, timestamp
70+
MetricType.GAUGE, GaugeMetric, name, value, tags, rate, timestamp, cardinality
6971
)
7072

71-
def set(self, name, value, tags, rate, timestamp=0):
73+
def set(self, name, value, tags, rate, timestamp=0, cardinality=None):
7274
return self.add_metric(
73-
MetricType.SET, SetMetric, name, value, tags, rate, timestamp
75+
MetricType.SET, SetMetric, name, value, tags, rate, timestamp, cardinality
7476
)
7577

7678
def add_metric(
77-
self, metric_type, metric_class, name, value, tags, rate, timestamp=0
79+
self, metric_type, metric_class, name, value, tags, rate, timestamp=0, cardinality=None
7880
):
7981
context = self.get_context(name, tags)
8082
with self._locks[metric_type]:
8183
if context in self.metrics_map[metric_type]:
8284
self.metrics_map[metric_type][context].aggregate(value)
8385
else:
86+
if cardinality is None:
87+
cardinality = self._cardinality
88+
validate_cardinality(cardinality)
8489
self.metrics_map[metric_type][context] = metric_class(
85-
name, value, tags, rate, timestamp
90+
name, value, tags, rate, timestamp, cardinality
8691
)
8792

88-
def histogram(self, name, value, tags, rate):
93+
def histogram(self, name, value, tags, rate, cardinality=None):
8994
return self.add_max_sample_metric(
90-
MetricType.HISTOGRAM, name, value, tags, rate
95+
MetricType.HISTOGRAM, name, value, tags, rate, cardinality
9196
)
9297

93-
def distribution(self, name, value, tags, rate):
98+
def distribution(self, name, value, tags, rate, cardinality=None):
9499
return self.add_max_sample_metric(
95-
MetricType.DISTRIBUTION, name, value, tags, rate
100+
MetricType.DISTRIBUTION, name, value, tags, rate, cardinality
96101
)
97102

98-
def timing(self, name, value, tags, rate):
103+
def timing(self, name, value, tags, rate, cardinality=None):
99104
return self.add_max_sample_metric(
100-
MetricType.TIMING, name, value, tags, rate
105+
MetricType.TIMING, name, value, tags, rate, cardinality
101106
)
102107

103108
def add_max_sample_metric(
104-
self, metric_type, name, value, tags, rate
109+
self, metric_type, name, value, tags, rate, cardinality=None
105110
):
106111
if rate is None:
107112
rate = 1
108113
context_key = self.get_context(name, tags)
109114
metric_context = self.max_sample_metric_map[metric_type]
110-
return metric_context.sample(name, value, tags, rate, context_key, self.max_samples_per_context)
115+
if cardinality is None:
116+
cardinality = self._cardinality
117+
validate_cardinality(cardinality)
118+
return metric_context.sample(name, value, tags, rate, context_key, self.max_samples_per_context, cardinality)

0 commit comments

Comments
 (0)