Skip to content

Commit

Permalink
feat(origindetection): implement cardinality common field
Browse files Browse the repository at this point in the history
Signed-off-by: Wassim DHIF <[email protected]>
  • Loading branch information
wdhif committed Jan 23, 2025
1 parent a7a7594 commit d3b3d72
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 44 deletions.
10 changes: 10 additions & 0 deletions datadog/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def initialize(
statsd_constant_tags=None, # type: Optional[List[str]]
return_raw_response=False, # type: bool
hostname_from_config=True, # type: bool
cardinality=None, # type: Optional[str]
**kwargs # type: Any
):
# type: (...) -> None
Expand Down Expand Up @@ -112,6 +113,12 @@ def initialize(
:param hostname_from_config: Set the hostname from the Datadog agent config (agent 5). Will be deprecated
:type hostname_from_config: boolean
:param cardinality: Set the global cardinality for all metrics. \
Possible values are "none", "low", "orchestrator" and "high".
Can also be set via the DATADOG_CARDINALITY or DD_CARDINALITY environment variables.
:type cardinality: string
"""
# API configuration
api._api_key = api_key or api._api_key or os.environ.get("DATADOG_API_KEY", os.environ.get("DD_API_KEY"))
Expand Down Expand Up @@ -146,6 +153,9 @@ def initialize(
statsd.disable_buffering = statsd_disable_buffering
api._return_raw_response = return_raw_response

# Set the global cardinality for all metrics
statsd.cardinality = cardinality or os.environ.get("DATADOG_CARDINALITY", os.environ.get("DD_CARDINALITY"))

# HTTP client and API options
for key, value in iteritems(kwargs):
attribute = "_{}".format(key)
Expand Down
23 changes: 14 additions & 9 deletions datadog/dogstatsd/aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
SetMetric,
)
from datadog.dogstatsd.metric_types import MetricType
from datadog.util.format import validate_cardinality


class Aggregator(object):
def __init__(self):
def __init__(self, cardinality=None):
self.metrics_map = {
MetricType.COUNT: {},
MetricType.GAUGE: {},
Expand All @@ -19,6 +20,7 @@ def __init__(self):
MetricType.GAUGE: threading.RLock(),
MetricType.SET: threading.RLock(),
}
self._cardinality = cardinality

def flush_aggregated_metrics(self):
metrics = []
Expand All @@ -34,29 +36,32 @@ def get_context(self, name, tags):
tags_str = ",".join(tags) if tags is not None else ""
return "{}:{}".format(name, tags_str)

def count(self, name, value, tags, rate, timestamp=0):
def count(self, name, value, tags, rate, timestamp=0, cardinality=None):
return self.add_metric(
MetricType.COUNT, CountMetric, name, value, tags, rate, timestamp
MetricType.COUNT, CountMetric, name, value, tags, rate, timestamp, cardinality
)

def gauge(self, name, value, tags, rate, timestamp=0):
def gauge(self, name, value, tags, rate, timestamp=0, cardinality=None):
return self.add_metric(
MetricType.GAUGE, GaugeMetric, name, value, tags, rate, timestamp
MetricType.GAUGE, GaugeMetric, name, value, tags, rate, timestamp, cardinality
)

def set(self, name, value, tags, rate, timestamp=0):
def set(self, name, value, tags, rate, timestamp=0, cardinality=None):
return self.add_metric(
MetricType.SET, SetMetric, name, value, tags, rate, timestamp
MetricType.SET, SetMetric, name, value, tags, rate, timestamp, cardinality
)

def add_metric(
self, metric_type, metric_class, name, value, tags, rate, timestamp=0
self, metric_type, metric_class, name, value, tags, rate, timestamp=0, cardinality=None
):
context = self.get_context(name, tags)
with self._locks[metric_type]:
if context in self.metrics_map[metric_type]:
self.metrics_map[metric_type][context].aggregate(value)
else:
if cardinality is None:
cardinality = self._cardinality
validate_cardinality(cardinality)
self.metrics_map[metric_type][context] = metric_class(
name, value, tags, rate, timestamp
name, value, tags, rate, timestamp, cardinality
)
Loading

0 comments on commit d3b3d72

Please sign in to comment.