<commit_before>﻿using Pipelines.Sockets.Unofficial;
using Pipelines.Sockets.Unofficial.Buffers;
using StackExchange.Metrics.Infrastructure;
using System;
using System.Buffers;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace StackExchange.Metrics.Handlers
{
    /// <summary>
    /// Implements <see cref="BufferedMetricHandler" /> by sending data to a statsd endpoint.
    /// </summary>
    public class StatsdMetricHandler : BufferedMetricHandler
    {
        const int ValueDecimals = 5;
        static readonly byte[] s_counter = Encoding.UTF8.GetBytes("c");
        static readonly byte[] s_gauge = Encoding.UTF8.GetBytes("g");
        static readonly byte[] s_pipe = Encoding.UTF8.GetBytes("|");
        static readonly byte[] s_colon = Encoding.UTF8.GetBytes(":");
        static readonly byte[] s_newLine = Encoding.UTF8.GetBytes("\n");
        static readonly byte[] s_hash = Encoding.UTF8.GetBytes("#");
        static readonly byte[] s_comma = Encoding.UTF8.GetBytes(",");
        static readonly StandardFormat s_valueFormat = StandardFormat.Parse("F" + ValueDecimals);

        string _host;
        ushort _port;
        ValueTask<ClientSocketData> _clientSocketDataTask;
        PayloadTypeMetadata _metricMetadata;
        PayloadTypeMetadata _metadataMetadata;

        /// <summary>
        /// Constructs a new <see cref="StatsdMetricHandler" /> pointing at the specified host and port.
        /// </summary>
        /// <param name="host">
        /// Host of a statsd endpoint.
        /// </param>
        /// <param name="port">
        /// Port of a stats endpoint.
        /// </param>
        public StatsdMetricHandler(string host, ushort port)
        {
            _host = host;
            _port = port;
            _clientSocketDataTask = CreateClientSocketDataAsync();
            // make sure our statsd data doesn't tear over packets
            MaxPayloadSize = 1400;
        }

        /// <summary>
        /// Host to which we should send metrics to.
        /// </summary>
        public string Host
        {
            get => _host;
            set
            {
                _host = value;
                _clientSocketDataTask = CreateClientSocketDataAsync();
            }
        }

        /// <summary>
        /// Port to which we should send metrics to.
        /// </summary>
        public ushort Port
        {
            get => _port;
            set
            {
                _port = value;
                _clientSocketDataTask = CreateClientSocketDataAsync();
            }
        }

        /// <inheritdoc />
        protected override void PrepareSequence(ref ReadOnlySequence<byte> sequence, PayloadType payloadType)
        {
        }

        /// <inheritdoc />
        protected override ValueTask SendAsync(PayloadType payloadType, ReadOnlySequence<byte> sequence)
        {
            if (payloadType == PayloadType.Metadata)
            {
                // statsd implementations don't know how to handle metadata!
                return default;
            }
<commit_msg>Trim UDP newlines<commit_after>﻿using Pipelines.Sockets.Unofficial;
using Pipelines.Sockets.Unofficial.Buffers;
using StackExchange.Metrics.Infrastructure;
using System;
using System.Buffers;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace StackExchange.Metrics.Handlers
{
    /// <summary>
    /// Implements <see cref="BufferedMetricHandler" /> by sending data to a statsd endpoint.
    /// </summary>
    public class StatsdMetricHandler : BufferedMetricHandler
    {
        const int ValueDecimals = 5;
        static readonly byte[] s_counter = Encoding.UTF8.GetBytes("c");
        static readonly byte[] s_gauge = Encoding.UTF8.GetBytes("g");
        static readonly byte[] s_pipe = Encoding.UTF8.GetBytes("|");
        static readonly byte[] s_colon = Encoding.UTF8.GetBytes(":");
        static readonly byte[] s_newLine = Encoding.UTF8.GetBytes("\n");
        static readonly byte[] s_hash = Encoding.UTF8.GetBytes("#");
        static readonly byte[] s_comma = Encoding.UTF8.GetBytes(",");
        static readonly StandardFormat s_valueFormat = StandardFormat.Parse("F" + ValueDecimals);

        string _host;
        ushort _port;
        ValueTask<ClientSocketData> _clientSocketDataTask;
        PayloadTypeMetadata _metricMetadata;
        PayloadTypeMetadata _metadataMetadata;

        /// <summary>
        /// Constructs a new <see cref="StatsdMetricHandler" /> pointing at the specified host and port.
        /// </summary>
        /// <param name="host">
        /// Host of a statsd endpoint.
        /// </param>
        /// <param name="port">
        /// Port of a stats endpoint.
        /// </param>
        public StatsdMetricHandler(string host, ushort port)
        {
            _host = host;
            _port = port;
            _clientSocketDataTask = CreateClientSocketDataAsync();
            // make sure our statsd data doesn't tear over packets
            MaxPayloadSize = 1400;
        }

        /// <summary>
        /// Host to which we should send metrics to.
        /// </summary>
        public string Host
        {
            get => _host;
            set
            {
                _host = value;
                _clientSocketDataTask = CreateClientSocketDataAsync();
            }
        }

        /// <summary>
        /// Port to which we should send metrics to.
        /// </summary>
        public ushort Port
        {
            get => _port;
            set
            {
                _port = value;
                _clientSocketDataTask = CreateClientSocketDataAsync();
            }
        }

        /// <inheritdoc />
        protected override void PrepareSequence(ref ReadOnlySequence<byte> sequence, PayloadType payloadType)
        {
            sequence = sequence.Trim('\n');
        }

        /// <inheritdoc />
        protected override ValueTask SendAsync(PayloadType payloadType, ReadOnlySequence<byte> sequence)
        {
            if (payloadType == PayloadType.Metadata)
            {
                // statsd implementations don't know how to handle metadata!
                return default;
            }

{'fraction_non_alphanumeric': 0.10112009956440572, 'fraction_numerical': 0.00373366521468575, 'mean_word_length': 1.9572217111315546, 'pattern_counts': {'":': 2, '<': 41, '<?xml version=': 0, '>': 45, 'https://': 0, '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': '4937075', 'n_tokens_mistral': 1705, 'n_tokens_neox': 1648, 'n_words': 442}