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

Add blocking socket mode and background sender #787

Merged
merged 13 commits into from
Aug 17, 2023
Merged

Conversation

vickenty
Copy link
Contributor

@vickenty vickenty commented Jul 19, 2023

What does this PR do?

Add options to improve dogstatsd packet deliverability.

Description of the Change

Allow dogstatsd socket to be used in a blocking mode with a timeout. This improves our chances to send the packet if the socket queue is full (e.g. after a burst in packets).

Add a background thread to handle the writes, with a queue to act as a buffer.

Together, this allows users to reduce dropped packets to zero while maintaining low latency for the user application, at the cost of higher cpu and memory usage.

Alternate Designs

Possible Drawbacks

Verification Process

Additional Notes

Release Notes

Review checklist (to be filled by reviewers)

  • Feature or bug fix MUST have appropriate tests (unit, integration, etc...)
  • PR title must be written as a CHANGELOG entry (see why)
  • Files changes must correspond to the primary purpose of the PR as described in the title (small unrelated changes should have their own PR)
  • PR must have one changelog/ label attached. If applicable it should have the backward-incompatible label attached.
  • PR should not have do-not-merge/ label attached.
  • If Applicable, issue must have kind/ and severity/ labels attached at least.

@vickenty vickenty force-pushed the vickenty/timeout branch 2 times, most recently from b0ff7cd to 8cf0201 Compare July 31, 2023 15:34
@vickenty vickenty changed the title Add option to use socket timeouts. Improve dogstatsd deliverability Jul 31, 2023
settimeout(0) is equivalent to setblocking(0), so need only one call.

Neither UDP or nor unix datagram sockets block on connect, so handling
timeout in get_socket is not necessary.
Align reported metrics with the go client.
@vickenty vickenty force-pushed the vickenty/timeout branch 2 times, most recently from eefd108 to a7f6b62 Compare August 2, 2023 11:36
Python2.7 does not allow other positional parameters after *expression.
@vickenty vickenty marked this pull request as ready for review August 2, 2023 12:58
@vickenty vickenty requested review from a team as code owners August 2, 2023 12:58
@vickenty vickenty changed the title Improve dogstatsd deliverability Add blocking socket mode and background sender Aug 2, 2023
@vickenty vickenty added the changelog/Added Added features results into a minor version bump label Aug 2, 2023
therve
therve previously approved these changes Aug 15, 2023
remeh
remeh previously approved these changes Aug 16, 2023
Copy link
Contributor

@remeh remeh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made a few polishing comments but that's a neat implementation.

datadog/dogstatsd/base.py Outdated Show resolved Hide resolved
datadog/dogstatsd/base.py Outdated Show resolved Hide resolved
datadog/dogstatsd/base.py Outdated Show resolved Hide resolved
self._xmit_packet(packet + '\n', False)
if self._queue is not None:
try:
self._queue.put(packet + '\n', self._queue_blocking, self._queue_timeout)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: about the packet + '\n', it might be worth doing it directly at the only direct call to _send_to_server in the flush method:

self._send_to_server("\n".join(self._buffer) + '\n')

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_send_to_server is also used in a bunch of places indirectly via the _send alias when buffering is disabled.

Copy link
Contributor

@remeh remeh Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right, but it doesn't stop us from having the call to _send_to_server in the flush method to add the \n as shown above. No strong opinion here, feel free to discard 👍

self._xmit_packet_with_telemetry(self._queue.get())
self._queue.task_done()

def wait_for_pending(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider documenting the new need (when using the threaded sender) to use this method to make sure everything's flushed properly and no buffered metrics are lost on shutdown?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, done

Co-authored-by: Rémy Mathieu <remy.mathieu@datadoghq.com>
@vickenty vickenty dismissed stale reviews from remeh and therve via 89c56e0 August 16, 2023 16:01
Co-authored-by: Rémy Mathieu <remy.mathieu@datadoghq.com>
@vickenty vickenty merged commit 11a38d0 into master Aug 17, 2023
10 checks passed
@vickenty vickenty deleted the vickenty/timeout branch August 17, 2023 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog/Added Added features results into a minor version bump
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants