<commit_before>package statsd

import (
	"time"
)

type BufferedSender struct {
	flushIntervalBytes  int
	flushIntervalMillis int
	sender              *SimpleSender
	buffer              []byte
	reqs                chan []byte
	shutdown            chan bool
}

func (s *BufferedSender) Send(data []byte) (int, error) {
	s.reqs <- data
	return len(data), nil
}

func (s *BufferedSender) Close() error {
	s.shutdown <- true
	err := s.sender.Close()
	return err
}

func (s *BufferedSender) Start() {
	ticker := time.NewTicker(time.Duration(s.flushIntervalMillis) * time.Millisecond)

	for {
		select {
		case <-ticker.C:
			s.flush()
		case req := <-s.reqs:
			// StatsD supports receiving multiple metrics in a single packet by separating them with a newline.
			s.buffer = append(s.buffer, append(req, []byte("\n")...)...)
			if len(s.buffer) >= s.flushIntervalBytes {
				s.flush()
			}
		case <-s.shutdown:
			break
		}
	}
}

func (s *BufferedSender) flush() (int, error) {
	n, err := s.sender.Send(s.buffer)
	s.buffer = []byte{} // clear the buffer
	return n, err
}

func NewBufferedSender(addr string, flushIntervalBytes, flushIntervalMillis int) (*BufferedSender, error) {
	simpleSender, err := NewSimpleSender(addr)
	if err != nil {
		return nil, err
	}

	sender := &BufferedSender{
		flushIntervalBytes:  flushIntervalBytes,
		flushIntervalMillis: flushIntervalMillis,
		sender:              simpleSender,
		reqs:                make(chan []byte),
		shutdown:            make(chan bool),
	}

	go sender.Start()
	return sender, nil
}

// Returns a pointer to a new Client, and an error.
// addr is a string of the format "hostname:port", and must be parsable by
// net.ResolveUDPAddr.
// prefix is the statsd client prefix. Can be "" if no prefix is desired.
func NewBufferedClient(addr, prefix string, flushIntervalBytes, flushIntervalMillis int) (*Client, error) {
	sender, err := NewBufferedSender(addr, flushIntervalBytes, flushIntervalMillis)
	if err != nil {
		return nil, err
	}

	client := &Client{
		prefix: prefix,
		sender: sender,
	}

	return client, nil
}
<commit_msg>setting defaults for the intervals (1432 bytes and 1000 millis)<commit_after>package statsd

import (
	"time"
)

type BufferedSender struct {
	flushIntervalBytes  int
	flushIntervalMillis int
	sender              *SimpleSender
	buffer              []byte
	reqs                chan []byte
	shutdown            chan bool
}

func (s *BufferedSender) Send(data []byte) (int, error) {
	s.reqs <- data
	return len(data), nil
}

func (s *BufferedSender) Close() error {
	s.shutdown <- true
	err := s.sender.Close()
	return err
}

func (s *BufferedSender) Start() {
	ticker := time.NewTicker(time.Duration(s.flushIntervalMillis) * time.Millisecond)

	for {
		select {
		case <-ticker.C:
			s.flush()
		case req := <-s.reqs:
			// StatsD supports receiving multiple metrics in a single packet by separating them with a newline.
			s.buffer = append(s.buffer, append(req, []byte("\n")...)...)
			if len(s.buffer) >= s.flushIntervalBytes {
				s.flush()
			}
		case <-s.shutdown:
			break
		}
	}
}

func (s *BufferedSender) flush() (int, error) {
	n, err := s.sender.Send(s.buffer)
	s.buffer = []byte{} // clear the buffer
	return n, err
}

func NewBufferedSender(addr string, flushIntervalBytes, flushIntervalMillis int) (*BufferedSender, error) {
	simpleSender, err := NewSimpleSender(addr)
	if err != nil {
		return nil, err
	}

	sender := &BufferedSender{
		flushIntervalBytes:  flushIntervalBytes,
		flushIntervalMillis: flushIntervalMillis,
		sender:              simpleSender,
		reqs:                make(chan []byte),
		shutdown:            make(chan bool),
	}

	go sender.Start()
	return sender, nil
}

func NewBufferedClient(addr, prefix string, flushIntervalBytes, flushIntervalMillis int) (*Client, error) {
	if flushIntervalBytes <= 0 {
		flushIntervalBytes = 1432 // https://github.com/etsy/statsd/blob/master/docs/metric_types.md#multi-metric-packets
	}
	if flushIntervalMillis <= 0 {
		flushIntervalMillis = 1000
	}
	sender, err := NewBufferedSender(addr, flushIntervalBytes, flushIntervalMillis)
	if err != nil {
		return nil, err
	}

	client := &Client{
		prefix: prefix,
		sender: sender,
	}

	return client, nil
}

{'fraction_non_alphanumeric': 0.11977186311787072, 'fraction_numerical': 0.0042775665399239545, 'mean_word_length': 3.2730964467005075, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 5, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3469306', 'n_tokens_mistral': 1456, 'n_tokens_neox': 1366, 'n_words': 391}