1- //! TODO docs!
1+ //! Asynchronous Metric Sink implementation that uses Unix Datagram sockets.
22
33use cadence:: {
44 MetricResult ,
@@ -21,41 +21,37 @@ use tokio::{
2121 net:: UnixDatagram ,
2222 sync:: mpsc:: {
2323 channel,
24- Receiver ,
2524 Sender ,
2625 } ,
27- time:: {
28- timeout_at,
29- Duration ,
30- Instant ,
31- } ,
3226} ;
3327
3428use crate :: {
3529 builder:: Builder ,
30+ define_worker,
3631 worker:: {
3732 Cmd ,
3833 TrySend ,
3934 } ,
4035} ;
4136
4237impl < T : AsRef < Path > + Send + Sync + Unpin + ' static > Builder < T , UnixDatagram > {
43- /// TODO docs!
38+ /// Creates a customized instance of the [TokioBatchUnixMetricSink](crate::unix::TokioBatchUnixMetricSink).
4439 pub fn build (
4540 self ,
4641 ) -> MetricResult < (
4742 TokioBatchUnixMetricSink ,
4843 Pin < Box < dyn Future < Output = ( ) > + Send + Sync + ' static > > ,
4944 ) > {
5045 let ( tx, rx) = channel ( self . queue_cap ) ;
51- let worker_fut = worker ( rx, self . addr , self . sock , self . buf_size , self . max_delay ) ;
46+ let worker_fut = worker ( rx, self . sock , self . addr , self . buf_size , self . max_delay ) ;
5247
5348 Ok ( ( TokioBatchUnixMetricSink { tx } , Box :: pin ( worker_fut) ) )
5449 }
5550}
5651
57- /// Metric sink that allows clients to enqueue metrics without blocking, and processing
58- /// them asynchronously over a Unix Domain Socket using Tokio runtime.
52+ /// Metric sink that allows clients to enqueue metrics without blocking, and sending
53+ /// them asynchronously over a [Unix Domain Socket](https://docs.datadoghq.com/developers/dogstatsd/unix_socket)
54+ /// using Tokio runtime.
5955///
6056/// It also accumulates individual metrics for a configured maximum amount of time
6157/// before submitting them as a single [batch](https://github.com/statsd/statsd/blob/master/docs/metric_types.md#multi-metric-packets).
@@ -112,24 +108,26 @@ impl UnwindSafe for TokioBatchUnixMetricSink {}
112108impl RefUnwindSafe for TokioBatchUnixMetricSink { }
113109
114110impl TokioBatchUnixMetricSink {
115- /// Creates a new metric sink for the given statsd host using a previously bound Unix socket.
111+ /// Creates a new metric sink for the given statsd socket path using an unbound Unix socket.
116112 /// Other sink parameters are defaulted.
117113 pub fn from < T : AsRef < Path > + Send + Sync + Unpin + ' static > (
118- host : T ,
114+ path : T ,
119115 socket : UnixDatagram ,
120116 ) -> MetricResult < (
121117 Self ,
122118 Pin < Box < dyn Future < Output = ( ) > + Send + Sync + ' static > > ,
123119 ) > {
124- Self :: builder ( host , socket) . build ( )
120+ Self :: builder ( path , socket) . build ( )
125121 }
126122
127- /// TODO docs!
123+ /// Returns a builder for creating a new metric sink for the given statsd socket path
124+ /// using an unbound Unix socket. The builder may be used to customize various
125+ /// configuration parameters before creating an instance of this sink.
128126 pub fn builder < T : AsRef < Path > + Send + Sync + Unpin + ' static > (
129127 path : T ,
130- sock : UnixDatagram ,
128+ socket : UnixDatagram ,
131129 ) -> Builder < T , UnixDatagram > {
132- Builder :: new ( path, sock )
130+ Builder :: new ( path, socket )
133131 }
134132}
135133
@@ -151,88 +149,11 @@ impl MetricSink for TokioBatchUnixMetricSink {
151149 }
152150}
153151
154- async fn do_send < T : AsRef < Path > + Unpin > ( socket : & mut UnixDatagram , addr : & T , buf : & mut String ) {
155- match socket. send_to ( buf. as_bytes ( ) , addr) . await {
156- Ok ( n) => {
157- debug ! ( "sent {} bytes" , n) ;
158- }
159-
160- Err ( e) => {
161- error ! ( "failed to send metrics: {:?}" , e) ;
162- }
163- }
164-
165- buf. clear ( ) ;
166- }
167-
168- async fn worker (
169- mut rx : Receiver < Cmd > ,
170- addr : impl AsRef < Path > + Unpin ,
171- mut socket : UnixDatagram ,
172- buf_size : usize ,
173- max_delay : Duration ,
174- ) {
175- let mut buf = String :: with_capacity ( buf_size) ;
176- let now = Instant :: now ( ) ;
177- let mut deadline = now. checked_add ( max_delay) . unwrap_or ( now) ;
178- loop {
179- match timeout_at ( deadline, rx. recv ( ) ) . await {
180- Ok ( Some ( Cmd :: Write ( msg) ) ) => {
181- trace ! ( "write: {}" , msg) ;
182-
183- let msg_len = msg. len ( ) ;
184- if msg_len > buf. capacity ( ) {
185- warn ! ( "metric exceeds buffer capacity: {}" , msg) ;
186- } else {
187- let buf_len = buf. len ( ) ;
188- if buf_len > 0 {
189- if buf_len + 1 + msg_len > buf. capacity ( ) {
190- do_send ( & mut socket, & addr, & mut buf) . await ;
191- let now = Instant :: now ( ) ;
192- deadline = now. checked_add ( max_delay) . unwrap_or ( now) ;
193- } else {
194- buf. push ( '\n' ) ;
195- }
196- }
197-
198- buf. push_str ( & msg) ;
199- }
200- }
201-
202- Ok ( Some ( Cmd :: Flush ) ) => {
203- trace ! ( "flush" ) ;
204-
205- if !buf. is_empty ( ) {
206- do_send ( & mut socket, & addr, & mut buf) . await ;
207- }
208-
209- let now = Instant :: now ( ) ;
210- deadline = now. checked_add ( max_delay) . unwrap_or ( now) ;
211- }
212-
213- Ok ( None ) => {
214- debug ! ( "stop" ) ;
215-
216- if !buf. is_empty ( ) {
217- do_send ( & mut socket, & addr, & mut buf) . await ;
218- }
219-
220- break ;
221- }
222-
223- Err ( _) => {
224- trace ! ( "timeout" ) ;
225-
226- if !buf. is_empty ( ) {
227- do_send ( & mut socket, & addr, & mut buf) . await ;
228- }
229-
230- let now = Instant :: now ( ) ;
231- deadline = now. checked_add ( max_delay) . unwrap_or ( now) ;
232- }
233- }
234- }
235- }
152+ define_worker ! (
153+ UnixDatagram ,
154+ impl AsRef <Path > + Unpin ,
155+ impl AsRef <Path > + Unpin
156+ ) ;
236157
237158#[ cfg( test) ]
238159mod tests {
0 commit comments