Skip to content
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

Revert dogstatsd telemetry #530

Merged
merged 1 commit into from
Feb 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,3 @@ pip-log.txt
.eggs/
.env/
.idea/
*.swp
7 changes: 0 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,6 @@ After the client is created, you can start sending events to your Datadog Event

After the client is created, you can start sending Service Checks to Datadog. See the dedicated [Service Check Submission: DogStatsD documentation](https://docs.datadoghq.com/developers/service_checks/dogstatsd_service_checks_submission/?tab=python) to see how to submit a Service Check to Datadog.

### Monitoring this client

This client automatically injects telemetry about itself in the DogStatsD stream.
Those metrics will not be counted as custom and will not be billed. This feature can be disabled using the `statsd.disable_telemetry()` method.

See [Telemetry documentation](https://docs.datadoghq.com/developers/dogstatsd/high_throughput/?tab=python#client-side-telemetry) to learn more about it.

## Thread Safety

`DogStatsD` and `ThreadStats` are thread-safe.
91 changes: 13 additions & 78 deletions datadog/dogstatsd/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from datadog.dogstatsd.context import TimedContextManagerDecorator
from datadog.dogstatsd.route import get_default_route
from datadog.util.compat import text
from datadog.util.config import get_version

# Logging
log = logging.getLogger('datadog.dogstatsd')
Expand All @@ -36,7 +35,7 @@ class DogStatsd(object):

def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT, max_buffer_size=50, namespace=None,
constant_tags=None, use_ms=False, use_default_route=False,
socket_path=None, default_sample_rate=1, disable_telemetry=False):
socket_path=None, default_sample_rate=1):
"""
Initialize a DogStatsd object.

Expand Down Expand Up @@ -107,12 +106,10 @@ def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT, max_buffer_size=50, nam
self.socket_path = socket_path
self.host = None
self.port = None
transport = "uds"
else:
self.socket_path = None
self.host = self.resolve_host(host, use_default_route)
self.port = int(port)
transport = "udp"

# Socket
self.socket = None
Expand All @@ -135,21 +132,6 @@ def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT, max_buffer_size=50, nam
self.use_ms = use_ms
self.default_sample_rate = default_sample_rate

# init telemetry
self._client_tags = [
"client:py",
"client_version:{}".format(get_version()),
"client_transport:{}".format(transport),
]
self._reset_telementry()
self._telemetry = not disable_telemetry

def disable_telemetry(self):
self._telemetry = False

def enable_telemetry(self):
self._telemetry = True

def __enter__(self):
self.open_buffer(self.max_buffer_size)
return self
Expand Down Expand Up @@ -321,17 +303,6 @@ def close_socket(self):
log.error("Unexpected error: %s", str(e))
self.socket = None

def _serialize_metric(self, metric, metric_type, value, tags, sample_rate=1):
# Create/format the metric packet
return "%s%s:%s|%s%s%s" % (
(self.namespace + ".") if self.namespace else "",
metric,
value,
metric_type,
("|@" + text(sample_rate)) if sample_rate != 1 else "",
("|#" + ",".join(tags)) if tags else "",
)

def _report(self, metric, metric_type, value, tags, sample_rate):
"""
Create a metric packet and send it.
Expand All @@ -341,9 +312,6 @@ def _report(self, metric, metric_type, value, tags, sample_rate):
if value is None:
return

if self._telemetry:
self.metrics_count += 1

if sample_rate is None:
sample_rate = self.default_sample_rate

Expand All @@ -352,53 +320,27 @@ def _report(self, metric, metric_type, value, tags, sample_rate):

# Resolve the full tag list
tags = self._add_constant_tags(tags)
payload = self._serialize_metric(metric, metric_type, value, tags, sample_rate)

# Create/format the metric packet
payload = "%s%s:%s|%s%s%s" % (
(self.namespace + ".") if self.namespace else "",
metric,
value,
metric_type,
("|@" + text(sample_rate)) if sample_rate != 1 else "",
("|#" + ",".join(tags)) if tags else "",
)

# Send it
self._send(payload)

def _reset_telementry(self):
self.metrics_count = 0
self.events_count = 0
self.service_checks_count = 0
self.bytes_sent = 0
self.bytes_dropped = 0
self.packets_sent = 0
self.packets_dropped = 0

def _flush_telemetry(self):
telemetry_tags = self._add_constant_tags(self._client_tags)
return "\n%s\n%s\n%s\n%s\n%s\n%s\n%s" % (
self._serialize_metric("datadog.dogstatsd.client.metrics",
"c", self.metrics_count, telemetry_tags),
self._serialize_metric("datadog.dogstatsd.client.events",
"c", self.events_count, telemetry_tags),
self._serialize_metric("datadog.dogstatsd.client.service_checks",
"c", self.service_checks_count, telemetry_tags),
self._serialize_metric("datadog.dogstatsd.client.bytes_sent",
"c", self.bytes_sent, telemetry_tags),
self._serialize_metric("datadog.dogstatsd.client.bytes_dropped",
"c", self.bytes_dropped, telemetry_tags),
self._serialize_metric("datadog.dogstatsd.client.packets_sent",
"c", self.packets_sent, telemetry_tags),
self._serialize_metric("datadog.dogstatsd.client.packets_dropped",
"c", self.packets_dropped, telemetry_tags),
)

def _send_to_server(self, packet):
if self._telemetry:
packet += self._flush_telemetry()
try:
# If set, use socket directly
(self.socket or self.get_socket()).send(packet.encode(self.encoding))
if self._telemetry:
self._reset_telementry()
self.packets_sent += 1
self.bytes_sent += len(packet)
return
except socket.timeout:
# dogstatsd is overflowing, drop the packets (mimicks the UDP behaviour)
pass
return
except (socket.herror, socket.gaierror) as se:
log.warning("Error submitting packet: {}, dropping the packet and closing the socket".format(se))
self.close_socket()
Expand All @@ -410,10 +352,7 @@ def _send_to_server(self, packet):
self.close_socket()
except Exception as e:
log.error("Unexpected error: %s", str(e))

if self._telemetry:
self.bytes_dropped += len(packet)
self.packets_dropped += 1
return

def _send_to_buffer(self, packet):
self.buffer.append(packet)
Expand Down Expand Up @@ -466,8 +405,6 @@ def event(self, title, text, alert_type=None, aggregation_key=None,
raise Exception(u'Event "%s" payload is too big (more than 8KB), '
'event discarded' % title)

if self._telemetry:
self.events_count += 1
self._send(string)

def service_check(self, check_name, status, tags=None, timestamp=None,
Expand All @@ -493,8 +430,6 @@ def service_check(self, check_name, status, tags=None, timestamp=None,
if message:
string = u'{0}|m:{1}'.format(string, message)

if self._telemetry:
self.service_checks_count += 1
self._send(string)

def _add_constant_tags(self, tags):
Expand Down
Loading