From 96dde54af1350860791f6ac275a1d56a8d0e1da9 Mon Sep 17 00:00:00 2001 From: dblack Date: Fri, 21 Apr 2017 08:35:24 -0700 Subject: [PATCH] optional datadog tags for statsd metrics --- THANKS | 1 + docs/source/settings.rst | 11 +++++++++++ gunicorn/config.py | 14 ++++++++++++++ gunicorn/instrument/statsd.py | 7 +++++++ tests/test_statsd.py | 11 +++++++++++ 5 files changed, 44 insertions(+) diff --git a/THANKS b/THANKS index 57ed4dab..2c2a6de5 100644 --- a/THANKS +++ b/THANKS @@ -47,6 +47,7 @@ Dan Callaghan Dan Sully Daniel Quinn Dariusz Suchojad +David Black David Vincelli David Wolever Denis Bilenko diff --git a/docs/source/settings.rst b/docs/source/settings.rst index 6b42b3cc..5e11b421 100644 --- a/docs/source/settings.rst +++ b/docs/source/settings.rst @@ -376,6 +376,17 @@ if not provided). .. versionadded:: 19.2 +dogstatsd_tags +~~~~~~~~~~~~~~ + +* ``--dogstatsd-tags DOGSTATSD_TAGS`` +* ``(empty string)`` + +Comma-delimited list of static dogstatsd (datadog statsd) tags sent with all statsd metrics +See: `Datadog Docs ` + +.. versionadded:: 20 + Process Naming -------------- diff --git a/gunicorn/config.py b/gunicorn/config.py index 8dda626e..52095801 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -1478,6 +1478,20 @@ class StatsdHost(Setting): .. versionadded:: 19.1 """ +# Datadog Statsd (dogstatsd) tags. https://docs.datadoghq.com/developers/dogstatsd/ +class DogstatsdTags(Setting): + name = "dogstatsd_tags" + section = "Logging" + cli = ["--dogstatsd-tags"] + meta = "DOGSTATSD_TAGS" + default = "" + validator = validate_string + desc = """\ + A comma-delimited list of datadog statsd (dogstatsd) tags to append to statsd metrics. + + .. versionadded:: 20 + """ + class StatsdPrefix(Setting): name = "statsd_prefix" section = "Logging" diff --git a/gunicorn/instrument/statsd.py b/gunicorn/instrument/statsd.py index 12b6de4e..7ef0bbb6 100644 --- a/gunicorn/instrument/statsd.py +++ b/gunicorn/instrument/statsd.py @@ -34,6 +34,8 @@ class Statsd(Logger): except Exception: self.sock = None + self.dogstatsd_tags = cfg.dogstatsd_tags + # Log errors and warnings def critical(self, msg, *args, **kwargs): Logger.critical(self, msg, *args, **kwargs) @@ -116,6 +118,11 @@ class Statsd(Logger): try: if isinstance(msg, str): msg = msg.encode("ascii") + + # http://docs.datadoghq.com/guides/dogstatsd/#datagram-format + if self.dogstatsd_tags: + msg = msg + b"|#" + self.dogstatsd_tags.encode('ascii') + if self.sock: self.sock.send(msg) except Exception: diff --git a/tests/test_statsd.py b/tests/test_statsd.py index b75057c8..130bfa6b 100644 --- a/tests/test_statsd.py +++ b/tests/test_statsd.py @@ -59,6 +59,17 @@ def test_statsd_fail(): logger.exception("No impact on logging") +def test_dogstatsd_tags(): + c = Config() + tags = 'yucatan,libertine:rhubarb' + c.set('dogstatsd_tags', tags) + logger = Statsd(c) + logger.sock = MockSocket(False) + logger.info("Twill", extra={"mtype": "gauge", "metric": "barb.westerly", + "value": 2}) + assert logger.sock.msgs[0] == b"barb.westerly:2|g|#" + tags.encode('ascii') + + def test_instrument(): logger = Statsd(Config()) # Capture logged messages