<commit_before># -*- coding: utf-8 -
#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.

"Bare-bones implementation of statsD's protocol, client-side"

import socket
from gunicorn.glogging import Logger

# Instrumentation constants
STATSD_DEFAULT_PORT = 8125
METRIC_VAR = "metric"
VALUE_VAR = "value"
MTYPE_VAR = "mtype"
GAUGE_TYPE = "gauge"
COUNTER_TYPE = "counter"
HISTOGRAM_TYPE = "histogram"

class Statsd(Logger):
    """statsD-based instrumentation, that passes as a logger
    """
    def __init__(self, cfg):
        """host, port: statsD server
        """
        Logger.__init__(self, cfg)
        try:
            host, port = cfg.statsd_host
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.sock.connect((host, int(port)))
        except Exception:
            self.sock = None

    # Log errors and warnings
    def critical(self, msg, *args, **kwargs):
        Logger.critical(self, msg, *args, **kwargs)
        self.increment("gunicorn.log.critical", 1)

    def error(self, msg, *args, **kwargs):
        Logger.error(self, msg, *args, **kwargs)
        self.increment("gunicorn.log.error", 1)

    def warning(self, msg, *args, **kwargs):
        Logger.warning(self, msg, *args, **kwargs)
        self.increment("gunicorn.log.warning", 1)

    def exception(self, msg, *args, **kwargs):
        Logger.exception(self, msg, *args, **kwargs)
        self.increment("gunicorn.log.exception", 1)

    # Special treatement for info, the most common log level
    def info(self, msg, *args, **kwargs):
        """Log a given statistic if metric, value and type are present
        """
        Logger.info(self, msg, *args, **kwargs)
        extra = kwargs.get("extra", None)
        if extra is not None:
            metric = extra.get(METRIC_VAR, None)
            value = extra.get(VALUE_VAR, None)
            typ = extra.get(MTYPE_VAR, None)
            if metric and value and typ:
                if typ == GAUGE_TYPE:
                    self.gauge(metric, value)
                elif typ == COUNTER_TYPE:
                    self.increment(metric, value)
                elif typ == HISTOGRAM_TYPE:
                    self.histogram(metric, value)
                else:
                    pass

    # skip the run-of-the-mill logs
    def debug(self, msg, *args, **kwargs):
        Logger.debug(self, msg, *args, **kwargs)

    def log(self, lvl, msg, *args, **kwargs):
        Logger.log(self, lvl, msg, *args, **kwargs)

    # access logging
    def access(self, resp, req, environ, request_time):
        """Measure request duration
        request_time is a datetime.timedelta
        """
        Logger.access(self, resp, req, environ, request_time)
        duration_in_s = request_time.seconds + float(request_time.microseconds)/10**6
        self.histogram("gunicorn.request.duration", duration_in_s)
        self.increment("gunicorn.requests", 1)
        self.increment("gunicorn.request.status.%d" % int(resp.status.split()[0]), 1)

    # statsD methods
    # you can use those directly if you want
    def gauge(self, name, value):
        try:
            if self.sock:
                self.sock.send("{0}:{1}|g".format(name, value))
        except Exception:
            pass

    def increment(self, name, value, sampling_rate=1.0):
        try:
            if self.sock:
                self.sock.send("{0}:{1}|c|@{2}".format(name, value, sampling_rate))
        except Exception:
            pass

    def decrement(self, name, value, sampling_rate=1.0):
        try:
            if self.sock:
                self.sock.send("{0}:-{1}|c|@{2}".format(name, value, sampling_rate))
        except Exception:
            pass
<commit_msg>Send statsd timing metrics in milliseconds<commit_after># -*- coding: utf-8 -
#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.

"Bare-bones implementation of statsD's protocol, client-side"

import socket
from gunicorn.glogging import Logger

# Instrumentation constants
STATSD_DEFAULT_PORT = 8125
METRIC_VAR = "metric"
VALUE_VAR = "value"
MTYPE_VAR = "mtype"
GAUGE_TYPE = "gauge"
COUNTER_TYPE = "counter"
HISTOGRAM_TYPE = "histogram"

class Statsd(Logger):
    """statsD-based instrumentation, that passes as a logger
    """
    def __init__(self, cfg):
        """host, port: statsD server
        """
        Logger.__init__(self, cfg)
        try:
            host, port = cfg.statsd_host
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.sock.connect((host, int(port)))
        except Exception:
            self.sock = None

    # Log errors and warnings
    def critical(self, msg, *args, **kwargs):
        Logger.critical(self, msg, *args, **kwargs)
        self.increment("gunicorn.log.critical", 1)

    def error(self, msg, *args, **kwargs):
        Logger.error(self, msg, *args, **kwargs)
        self.increment("gunicorn.log.error", 1)

    def warning(self, msg, *args, **kwargs):
        Logger.warning(self, msg, *args, **kwargs)
        self.increment("gunicorn.log.warning", 1)

    def exception(self, msg, *args, **kwargs):
        Logger.exception(self, msg, *args, **kwargs)
        self.increment("gunicorn.log.exception", 1)

    # Special treatement for info, the most common log level
    def info(self, msg, *args, **kwargs):
        """Log a given statistic if metric, value and type are present
        """
        Logger.info(self, msg, *args, **kwargs)
        extra = kwargs.get("extra", None)
        if extra is not None:
            metric = extra.get(METRIC_VAR, None)
            value = extra.get(VALUE_VAR, None)
            typ = extra.get(MTYPE_VAR, None)
            if metric and value and typ:
                if typ == GAUGE_TYPE:
                    self.gauge(metric, value)
                elif typ == COUNTER_TYPE:
                    self.increment(metric, value)
                elif typ == HISTOGRAM_TYPE:
                    self.histogram(metric, value)
                else:
                    pass

    # skip the run-of-the-mill logs
    def debug(self, msg, *args, **kwargs):
        Logger.debug(self, msg, *args, **kwargs)

    def log(self, lvl, msg, *args, **kwargs):
        Logger.log(self, lvl, msg, *args, **kwargs)

    # access logging
    def access(self, resp, req, environ, request_time):
        """Measure request duration
        request_time is a datetime.timedelta
        """
        Logger.access(self, resp, req, environ, request_time)
        duration_in_ms = request_time.seconds * 1000 + float(request_time.microseconds)/10**3
        self.histogram("gunicorn.request.duration", duration_in_ms)
        self.increment("gunicorn.requests", 1)
        self.increment("gunicorn.request.status.%d" % int(resp.status.split()[0]), 1)

    # statsD methods
    # you can use those directly if you want
    def gauge(self, name, value):
        try:
            if self.sock:
                self.sock.send("{0}:{1}|g".format(name, value))
        except Exception:
            pass

    def increment(self, name, value, sampling_rate=1.0):
        try:
            if self.sock:
                self.sock.send("{0}:{1}|c|@{2}".format(name, value, sampling_rate))
        except Exception:
            pass

    def decrement(self, name, value, sampling_rate=1.0):
        try:
            if self.sock:
                self.sock.send("{0}:-{1}|c|@{2}".format(name, value, sampling_rate))
        except Exception:
            pass

{'fraction_non_alphanumeric': 0.12476894639556377, 'fraction_numerical': 0.007657776604172168, 'mean_word_length': 2.304973821989529, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '2948799', 'n_tokens_mistral': 2362, 'n_tokens_neox': 2244, 'n_words': 606}