Skip to content

Commit

Permalink
Add the possibilitiy to add global statsd tags
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Valsecchi committed Mar 13, 2019
1 parent e03e4ea commit e6fd4c3
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ To enable and configure the metrics framework, you can use:
* STATSD_ADDRESS (c2c.statsd_address): if defined, send stats to the given statsd server
* STATSD_PREFIX (c2c.statsd_prefix): prefix to add to every metric names
* STATSD_USE_TAGS: If true, automatic metrics will use tags
* STATSD_TAG_{tag_name}: To set a global tag for the service

If enabled, some metrics are automatically generated:

Expand Down
1 change: 1 addition & 0 deletions acceptance_tests/tests/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ app:
STATS_VIEW: 1
STATSD_ADDRESS: ${TEST_IP}:8125
STATSD_PREFIX: acceptance
STATSD_TAG_XYZ: zyx
C2C_SECRET: changeme
C2C_LOG_VIEW_ENABLED: 1
C2C_SQL_PROFILER_ENABLED: 1
Expand Down
26 changes: 23 additions & 3 deletions c2cwsgiutils/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import threading
import time
from abc import abstractmethod, ABCMeta
from typing import Mapping, Sequence, List, Generator, Any, Optional, Callable
from typing import Mapping, Sequence, List, Generator, Any, Optional, Callable, Dict
from typing import Tuple, MutableMapping # noqa # pylint: disable=unused-import

import pyramid.request
Expand All @@ -20,6 +20,7 @@
BACKENDS = {} # type: MutableMapping[str, _BaseBackend]
LOG = logging.getLogger(__name__)
USE_TAGS_ENV = 'STATSD_USE_TAGS'
TAG_PREFIX_ENV = 'STATSD_TAG_'
USE_TAGS = _utils.config_bool(os.environ.get(USE_TAGS_ENV, '0'))
TagType = Optional[Mapping[str, Any]]

Expand Down Expand Up @@ -204,8 +205,9 @@ def get_stats(self, request: pyramid.request.Request) -> Mapping[str, Any]:


class StatsDBackend(_BaseBackend): # pragma: nocover
def __init__(self, address: str, prefix: str) -> None:
def __init__(self, address: str, prefix: str, tags: Dict[str, str] = None) -> None:
self._prefix = prefix
self._tags = tags
if self._prefix != "" and not self._prefix.endswith("."):
self._prefix += "."

Expand All @@ -226,7 +228,16 @@ def _key_entry(key_entry: Any) -> str:
def _key(self, key: Sequence[Any]) -> str:
return (self._prefix + ".".join(map(StatsDBackend._key_entry, key)))[:450]

def _merge_tags(self, tags: TagType) -> TagType:
if tags is None:
return self._tags
elif self._tags is None:
return tags
else:
return dict(self._tags).update(tags)

def _send(self, message: str, tags: TagType) -> None:
tags = self._merge_tags(tags)
message += _format_tags(tags, prefix="|#", tag_sep=",", kv_sep=":",
formatter=StatsDBackend._key_entry)
# noinspection PyBroadException
Expand Down Expand Up @@ -265,8 +276,9 @@ def init_backends(settings: Optional[Mapping[str, str]] = None) -> None:
statsd_address = _utils.env_or_settings(settings, "STATSD_ADDRESS", "c2c.statsd_address", None)
if statsd_address is not None: # pragma: nocover
statsd_prefix = _utils.env_or_settings(settings, "STATSD_PREFIX", "c2c.statsd_prefix", "")
statsd_tags = _get_env_tags()
try:
BACKENDS['statsd'] = StatsDBackend(statsd_address, statsd_prefix)
BACKENDS['statsd'] = StatsDBackend(statsd_address, statsd_prefix, statsd_tags)
except Exception:
LOG.error("Failed configuring the statsd backend. Will continue without it.", exc_info=True)

Expand All @@ -279,3 +291,11 @@ def _format_tags(tags: Optional[Mapping[str, Any]], prefix: str, tag_sep: str, k
for item in sorted(tags.items()))
else:
return ""


def _get_env_tags() -> Dict[str, str]:
tags = {}
for name, value in os.environ.items():
if name.startswith(TAG_PREFIX_ENV):
tags[name[len(TAG_PREFIX_ENV):].lower()] = value
return tags

0 comments on commit e6fd4c3

Please sign in to comment.