-
Notifications
You must be signed in to change notification settings - Fork 322
Add DD_DOGSTATSD_URL support for unix and udp urls #870
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -25,6 +25,11 @@ | |||||||||||||||
| # pypy has the same module, but capitalized. | ||||||||||||||||
| import Queue as queue # type: ignore[no-redef] | ||||||||||||||||
|
|
||||||||||||||||
| try: | ||||||||||||||||
| from urllib.parse import urlparse # type: ignore | ||||||||||||||||
| except ImportError: | ||||||||||||||||
| # Python 2 has the same functionality stored under a different module. | ||||||||||||||||
| from urlparse import urlparse # type: ignore | ||||||||||||||||
|
|
||||||||||||||||
| # pylint: disable=unused-import | ||||||||||||||||
| from typing import Optional, List, Text, Union | ||||||||||||||||
|
|
@@ -54,6 +59,7 @@ | |||||||||||||||
| UNIX_ADDRESS_SCHEME = "unix://" | ||||||||||||||||
| UNIX_ADDRESS_DATAGRAM_SCHEME = "unixgram://" | ||||||||||||||||
| UNIX_ADDRESS_STREAM_SCHEME = "unixstream://" | ||||||||||||||||
| WINDOWS_NAMEDPIPE_SCHEME = "\\\\.\\pipe\\" | ||||||||||||||||
|
|
||||||||||||||||
| # Buffering-related values (in seconds) | ||||||||||||||||
| DEFAULT_BUFFERING_FLUSH_INTERVAL = 0.3 | ||||||||||||||||
|
|
@@ -188,12 +194,19 @@ def __init__( | |||||||||||||||
|
|
||||||||||||||||
| >>> statsd = DogStatsd() | ||||||||||||||||
|
|
||||||||||||||||
| :envvar DD_DOGSTATSD_URL: the connection information for the dogstatsd server. | ||||||||||||||||
| If set, it overrides the default values. | ||||||||||||||||
| Example for UDP url: `DD_DOGSTATSD_URL=udp://localhost:8125` | ||||||||||||||||
| Example for UDS: `DD_DOGSTATSD_URL=unix:///var/run/datadog/dsd.socket` | ||||||||||||||||
| Windows named pipes are currently unsupported. | ||||||||||||||||
| :type DD_DOGSTATSD_URL: string | ||||||||||||||||
|
|
||||||||||||||||
| :envvar DD_AGENT_HOST: the host of the DogStatsd server. | ||||||||||||||||
| If set, it overrides default value. | ||||||||||||||||
| If set, it overrides default value. DD_DOGSTATSD_URL takes precedence over this value. | ||||||||||||||||
| :type DD_AGENT_HOST: string | ||||||||||||||||
|
|
||||||||||||||||
| :envvar DD_DOGSTATSD_PORT: the port of the DogStatsd server. | ||||||||||||||||
| If set, it overrides default value. | ||||||||||||||||
| If set, it overrides default value. DD_DOGSTATSD_URL takes precedence over this value. | ||||||||||||||||
| :type DD_DOGSTATSD_PORT: integer | ||||||||||||||||
|
|
||||||||||||||||
| :envvar DATADOG_TAGS: Tags to attach to every metric reported by dogstatsd client. | ||||||||||||||||
|
|
@@ -374,22 +387,8 @@ def __init__( | |||||||||||||||
| # Check for deprecated option | ||||||||||||||||
| if max_buffer_size is not None: | ||||||||||||||||
| log.warning("The parameter max_buffer_size is now deprecated and is not used anymore") | ||||||||||||||||
| # Check host and port env vars | ||||||||||||||||
| agent_host = os.environ.get("DD_AGENT_HOST") | ||||||||||||||||
| if agent_host and host == DEFAULT_HOST: | ||||||||||||||||
| host = agent_host | ||||||||||||||||
|
|
||||||||||||||||
| dogstatsd_port = os.environ.get("DD_DOGSTATSD_PORT") | ||||||||||||||||
| if dogstatsd_port and port == DEFAULT_PORT: | ||||||||||||||||
| try: | ||||||||||||||||
| port = int(dogstatsd_port) | ||||||||||||||||
| except ValueError: | ||||||||||||||||
| log.warning( | ||||||||||||||||
| "Port number provided in DD_DOGSTATSD_PORT env var is not an integer: \ | ||||||||||||||||
| %s, using %s as port number", | ||||||||||||||||
| dogstatsd_port, | ||||||||||||||||
| port, | ||||||||||||||||
| ) | ||||||||||||||||
| host, port, socket_path = self._parse_env_connection_overrides(host, port, socket_path) | ||||||||||||||||
|
|
||||||||||||||||
| # Assuming environment variables always override | ||||||||||||||||
| telemetry_host = os.environ.get("DD_TELEMETRY_HOST", telemetry_host) | ||||||||||||||||
|
|
@@ -601,6 +600,74 @@ def disable_telemetry(self): | |||||||||||||||
| def enable_telemetry(self): | ||||||||||||||||
| self._telemetry = True | ||||||||||||||||
|
|
||||||||||||||||
| def _parse_env_connection_overrides(self, host, port, socket_path): | ||||||||||||||||
| dogstatsd_url = os.environ.get("DD_DOGSTATSD_URL") | ||||||||||||||||
|
|
||||||||||||||||
| if ( | ||||||||||||||||
| host == DEFAULT_HOST | ||||||||||||||||
| and port == DEFAULT_PORT | ||||||||||||||||
| and socket_path is None | ||||||||||||||||
| and dogstatsd_url is not None | ||||||||||||||||
| ): | ||||||||||||||||
| parsed = urlparse(dogstatsd_url) | ||||||||||||||||
| # If all values are defaults, prefer DD_DOGSTATSD_URL if present. | ||||||||||||||||
| if parsed.scheme == "unix": | ||||||||||||||||
| log.debug( | ||||||||||||||||
| "Found a DD_DOGSTATSD_URL matching the uds syntax, " | ||||||||||||||||
| "setting socket path %s.", dogstatsd_url | ||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
| ) | ||||||||||||||||
| return host, port, dogstatsd_url | ||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Caller assigns this into |
||||||||||||||||
|
|
||||||||||||||||
| elif dogstatsd_url.startswith(WINDOWS_NAMEDPIPE_SCHEME): | ||||||||||||||||
| log.debug( | ||||||||||||||||
| "DD_DOGSTATSD_URL is configured to utilize a windows named pipe, " | ||||||||||||||||
| "which is not currently supported by datadogpy. Falling back to " | ||||||||||||||||
| "alternate connection identifiers." | ||||||||||||||||
| ) | ||||||||||||||||
|
Comment on lines
+620
to
+626
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the spirit of our documentation guidelines, let the generic "unsupported scheme" message handle this case. And AIUI this was the only place where
Suggested change
|
||||||||||||||||
|
|
||||||||||||||||
| elif parsed.scheme == "udp": | ||||||||||||||||
| try: | ||||||||||||||||
| p_port = parsed.port | ||||||||||||||||
| # Python 2 doesn't automatically perform bounds checking on the port | ||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Not sure which versions we support, but this was fixed in 2014) |
||||||||||||||||
| if p_port is None or p_port < 0 or p_port > 65535: | ||||||||||||||||
| log.debug("Invalid port number provided, reverting to default port") | ||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
| p_port = DEFAULT_PORT | ||||||||||||||||
| except ValueError: | ||||||||||||||||
| log.debug("Invalid port number provided, reverting to default port") | ||||||||||||||||
|
Comment on lines
+635
to
+636
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
| p_port = DEFAULT_PORT | ||||||||||||||||
|
|
||||||||||||||||
| log.debug( | ||||||||||||||||
| "Found a DD_DOGSTATSD_URL matching the udp sytnax, " | ||||||||||||||||
| "setting host and port %s:%d.", parsed.hostname, p_port | ||||||||||||||||
| ) | ||||||||||||||||
|
|
||||||||||||||||
| return parsed.hostname, p_port, socket_path | ||||||||||||||||
| else: | ||||||||||||||||
| log.debug( | ||||||||||||||||
| "Unable to parse DD_DOGSTATSD_URL, did you remember to prefix the url " | ||||||||||||||||
| "with 'unix://' or 'udp://'? Falling back to alternate " | ||||||||||||||||
| "connection identifiers." | ||||||||||||||||
| ) | ||||||||||||||||
|
Comment on lines
+646
to
+650
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense be more specific in the error message? Probably worth a higher log level too.
Suggested change
|
||||||||||||||||
|
|
||||||||||||||||
| # We either have some non-default values or no DD_DOGSTATSD_URL | ||||||||||||||||
| # Check host and port env vars | ||||||||||||||||
| agent_host = os.environ.get("DD_AGENT_HOST") | ||||||||||||||||
| if agent_host and host == DEFAULT_HOST: | ||||||||||||||||
| host = agent_host | ||||||||||||||||
|
|
||||||||||||||||
| dogstatsd_port = os.environ.get("DD_DOGSTATSD_PORT") | ||||||||||||||||
| if dogstatsd_port and port == DEFAULT_PORT: | ||||||||||||||||
| try: | ||||||||||||||||
| port = int(dogstatsd_port) | ||||||||||||||||
| except ValueError: | ||||||||||||||||
| log.warning( | ||||||||||||||||
| "Port number provided in DD_DOGSTATSD_PORT env var is not an integer: \ | ||||||||||||||||
| %s, using %s as port number", | ||||||||||||||||
|
Comment on lines
+664
to
+665
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
| dogstatsd_port, | ||||||||||||||||
| port, | ||||||||||||||||
| ) | ||||||||||||||||
| return host, port, socket_path | ||||||||||||||||
|
|
||||||||||||||||
| # Note: Invocations of this method should be thread-safe | ||||||||||||||||
| def _start_flush_thread(self): | ||||||||||||||||
| if self._disable_aggregation and self.disable_buffering: | ||||||||||||||||
|
|
||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense if an explict request for defaults
Dogstatsd(host='localhost', port=8125)takes precedence over environment variables?