<reponame>wavefront-mike/wavefront-collector-fork-hq
"""
This module contains the classes that write metrics to their final endpoint.
"""
import socket
import threading

#pylint: disable=too-many-arguments
class MetricsWriter(object):
    """
    Writer for managing the socket connection to metrics receiver.
    """

    def __init__(self, host, port, dry_run=False):
        super(MetricsWriter, self).__init__()
        self.is_dry_run = dry_run
        self.host = host
        self.port = port
        self.sock = None

    def transmit_metric(self, name, value, timestamp, source, point_tags):
        """
        Transmit metric to the proxy.

        Arguments:
        name - the metric name (a.b.c)
        value - the numeric value for this metric
        timestamp - the timestamp for this metric
        source - this metric's host or source name
        point_tags - dictionary of key/value pairs
        """

        line = self._generate_line(name, value, timestamp, source, point_tags)
        if self.is_dry_run:
            thread_id = hex(threading.current_thread().ident)
            # command line mode you want to see this in stdout
            # in daemon mode you want to see this in a log
            # TODO: revisit and write to log when daemonized?
            print '[{} {}:{}] {}'.format(thread_id, self.host, self.port, line)

        else:
            self.sock.sendall('%s\n' % line)

    def _generate_line(self, name, value, timestamp, source, point_tags):
        """
        This should be overridden by the derived classes.  Generates the
        metric put line for the writer.

        Arguments:
        name - the metric name (a.b.c)
        value - the numeric value for this metric
        timestamp - the timestamp for this metric
        source - this metric's host or source name
        point_tags - dictionary of key/value pairs
        """

        pass

    def start(self):
        """
        Connect and open the socket
        """

        if not self.is_dry_run:
            self.sock = socket.socket()
            self.sock.settimeout(10.0)
            self.sock.connect((self.host, self.port))

    def stop(self):
        """
        Stop and shutdown the open socket
        """

        if self.sock is not None and not self.is_dry_run:
            self.sock.shutdown(socket.SHUT_RDWR)
            self.sock.close()

    def __enter__(self):
        """
        Python with block enter routine
        """

        self.start()
        return self

    def __exit__(self, the_type, value, traceback):
        """
        Python with block exit routine
        """

        self.stop()


class WavefrontMetricsWriter(MetricsWriter):
    """
    This is the metrics writer for the Wavefront proxy format.
    """

    def __init__(self, host, port, dry_run=False):
        super(WavefrontMetricsWriter, self).__init__(host, port, dry_run)

    def _generate_line(self, name, value, timestamp, source, point_tags):
        """
        Generates the line in the Wavefront proxy format.
        """
        line = '{} {} {} source="{}"'.format(
            name, value, long(timestamp), source)
        if point_tags is not None:
            for tag_key, tag_value in point_tags.iteritems():
                line = line + ' "{}"="{}"'.format(tag_key, tag_value)
        return line

class OpenTSDBMetricsWriter(MetricsWriter):
    """
    This is the metrics writer for the OpenTSDB format.
    """

    def __init__(self, host, port, dry_run=False):
        super(OpenTSDBMetricsWriter, self).__init__(host, port, dry_run)

    def _generate_line(self, name, value, timestamp, source, point_tags):
        """
        Generates the line in the OpenTSDB format.
        put <metric> <timestamp> <value> <tagk1=tagv1[ tagk2=tagv2 ...]
        """
        line = 'put {} {} {} host="{}"'.format(name, timestamp, value, source)
        if point_tags is not None:
            for tag_key, tag_value in point_tags.iteritems():
                line = line + ' "{}"="{}"'.format(tag_key, tag_value)
        return line

"""
This module contains the classes that write metrics to their final endpoint.
"""
import socket
import threading

#pylint: disable=too-many-arguments
class MetricsWriter(object):
    """
    Writer for managing the socket connection to metrics receiver.
    """

    def __init__(self, host, port, dry_run=False):
        super(MetricsWriter, self).__init__()
        self.is_dry_run = dry_run
        self.host = host
        self.port = port
        self.sock = None

    def transmit_metric(self, name, value, timestamp, source, point_tags):
        """
        Transmit metric to the proxy.

        Arguments:
        name - the metric name (a.b.c)
        value - the numeric value for this metric
        timestamp - the timestamp for this metric
        source - this metric's host or source name
        point_tags - dictionary of key/value pairs
        """

        line = self._generate_line(name, value, timestamp, source, point_tags)
        if self.is_dry_run:
            thread_id = hex(threading.current_thread().ident)
            # command line mode you want to see this in stdout
            # in daemon mode you want to see this in a log
            # TODO: revisit and write to log when daemonized?
            print '[{} {}:{}] {}'.format(thread_id, self.host, self.port, line)

        else:
            self.sock.sendall('%s\n' % line)

    def _generate_line(self, name, value, timestamp, source, point_tags):
        """
        This should be overridden by the derived classes.  Generates the
        metric put line for the writer.

        Arguments:
        name - the metric name (a.b.c)
        value - the numeric value for this metric
        timestamp - the timestamp for this metric
        source - this metric's host or source name
        point_tags - dictionary of key/value pairs
        """

        pass

    def start(self):
        """
        Connect and open the socket
        """

        if not self.is_dry_run:
            self.sock = socket.socket()
            self.sock.settimeout(10.0)
            self.sock.connect((self.host, self.port))

    def stop(self):
        """
        Stop and shutdown the open socket
        """

        if self.sock is not None and not self.is_dry_run:
            self.sock.shutdown(socket.SHUT_RDWR)
            self.sock.close()

    def __enter__(self):
        """
        Python with block enter routine
        """

        self.start()
        return self

    def __exit__(self, the_type, value, traceback):
        """
        Python with block exit routine
        """

        self.stop()


class WavefrontMetricsWriter(MetricsWriter):
    """
    This is the metrics writer for the Wavefront proxy format.
    """

    def __init__(self, host, port, dry_run=False):
        super(WavefrontMetricsWriter, self).__init__(host, port, dry_run)

    def _generate_line(self, name, value, timestamp, source, point_tags):
        """
        Generates the line in the Wavefront proxy format.
        """
        line = '{} {} {} source="{}"'.format(
            name, value, long(timestamp), source)
        if point_tags is not None:
            for tag_key, tag_value in point_tags.iteritems():
                line = line + ' "{}"="{}"'.format(tag_key, tag_value)
        return line

class OpenTSDBMetricsWriter(MetricsWriter):
    """
    This is the metrics writer for the OpenTSDB format.
    """

    def __init__(self, host, port, dry_run=False):
        super(OpenTSDBMetricsWriter, self).__init__(host, port, dry_run)

    def _generate_line(self, name, value, timestamp, source, point_tags):
        """
        Generates the line in the OpenTSDB format.
        put <metric> <timestamp> <value> <tagk1=tagv1[ tagk2=tagv2 ...]
        """
        line = 'put {} {} {} host="{}"'.format(name, timestamp, value, source)
        if point_tags is not None:
            for tag_key, tag_value in point_tags.iteritems():
                line = line + ' "{}"="{}"'.format(tag_key, tag_value)
        return line
This module contains the classes that write metrics to their final endpoint. #pylint: disable=too-many-arguments Writer for managing the socket connection to metrics receiver. Transmit metric to the proxy.          Arguments:         name - the metric name (a.b.c)         value - the numeric value for this metric         timestamp - the timestamp for this metric         source - this metric's host or source name         point_tags - dictionary of key/value pairs # command line mode you want to see this in stdout # in daemon mode you want to see this in a log # TODO: revisit and write to log when daemonized? This should be overridden by the derived classes.  Generates the         metric put line for the writer.          Arguments:         name - the metric name (a.b.c)         value - the numeric value for this metric         timestamp - the timestamp for this metric         source - this metric's host or source name         point_tags - dictionary of key/value pairs Connect and open the socket Stop and shutdown the open socket Python with block enter routine Python with block exit routine This is the metrics writer for the Wavefront proxy format. Generates the line in the Wavefront proxy format. This is the metrics writer for the OpenTSDB format. Generates the line in the OpenTSDB format.         put <metric> <timestamp> <value> <tagk1=tagv1[ tagk2=tagv2 ...]