<commit_before>"use strict";

/**
 * Export a factory function to create a Metrics instance.
 *
 * Default options are:
 *
 * {
 *     host: "localhost",
 *     port: 8125,
 *     enabled: true,
 *     prefix: null,
 *     timeout: 1000,
 * }
 *
 * You may also provide your own dgram socket in options.socket if required.
 *
 * If you don't provide a socket, the internal socket will be closed to free
 * up resources every after the metrics instance has been idle for at least
 * options.timeout milliseconds. A delay of 10*timeout is also used to close
 * the internal socket in order to clear Buffers it has been holding on to.
 *
 * If options.enabled is false, all code will run but API.write will not
 * attempt to write to the socket, and therefore the socket will never be
 * opened. Good for testing locally if you don't care about metrics there.
 */
module.exports = function(options) {
    options = options || {};

    var host = options.host || "localhost";
    var port = options.port || 8125;
    var providedSocket = options.socket || null;
    var prefix = options.prefix || null;
    var enabled = 'enabled' in options ? options.enabled : true;
    var socketTimeout = options.timeout || 1000;
    var log = 'log' in options ? options.log : false;

    var ephemeralSocket = null;
    var lastUse = null;
    var gcTimer = null;
    var closeTimeout = null;
    var middleware = null;

    /**
     * Close the ephemeral socket.
     */
    var closeSocket = function() {
        if (ephemeralSocket) {
            ephemeralSocket.close();
            ephemeralSocket = null;
            closeTimeout = null;
        }
    };

    /**
     * Clear the socket cleanup timer.
     */
    var removeTimer = function() {
        if (gcTimer) {
            clearInterval(gcTimer);
            gcTimer = null;
        }
    };

    /**
     * Garbage collect the socket if possible.
     */
    var gcSocket = function() {
        if (Date.now() - lastUse > socketTimeout) {
            closeSocket();
            removeTimer();
        }
    };

    var getSocket = function() {
        if (providedSocket) {
            return providedSocket;
        } else {
            // create an ephemeral socket
            if (!ephemeralSocket) {
                ephemeralSocket = require("dgram").createSocket("udp4");
                ephemeralSocket.on("error", function(err) {});

                // try to clean up the socket periodically to free up resources
                // if this instance is idle
                gcTimer = setInterval(gcSocket, 250);

                // forcibly close the socket periodically (ignoring last use)
                // to allow sent Buffers to be GC'd
                closeTimeout = setTimeout(closeSocket, 10 * socketTimeout);
            }

            // the ephemeral socket was last used NOW.
            lastUse = Date.now();

            return ephemeralSocket;
        }
    };

    // object that will be returned by require("metrics")()
    var API = {};

    /**
     * Release resources created by the metrics library.
     */
    API.close = function() {
        closeSocket();
        removeTimer();
    };

    Object.defineProperty(API, "enabled", {
        get: function() {
            return enabled;
        },
        set: function(value) {
            enabled = value;
        },
        enumerable: true
    });<commit_msg>Clean up socket handling, use unref() if avail.<commit_after>"use strict";

/**
 * Export a factory function to create a Metrics instance.
 *
 * Default options are:
 *
 * {
 *     host: "localhost",
 *     port: 8125,
 *     enabled: true,
 *     prefix: null,
 *     timeout: 1000
 * }
 * You may also provide your own dgram-ish socket as options.socket if required.
 *
 * If you don't provide a socket, the internal socket will be closed to free
 * up resources every after the metrics instance has been idle for at least
 * options.timeout milliseconds. A delay of 10*timeout is also used to close
 * the internal socket in order to clear Buffers it has been holding on to.
 *
 * If options.enabled is false, all code will run but API.write will not
 * attempt to write to the socket, and therefore the socket will never be
 * opened. Good for testing locally if you don't care about metrics there.
 */
module.exports = function(options) {
    options = options || {};

    var host = options.host || "localhost";
    var port = options.port || 8125;
    var providedSocket = options.socket || null;
    var prefix = options.prefix || null;
    var enabled = 'enabled' in options ? options.enabled : true;
    var socketTimeout = options.timeout || 1000;
    var log = 'log' in options ? options.log : false;

    var ephemeralSocket = null;
    var lastUse = null;
    var gcTimer = null;
    var closeTimeout = null;
    var middleware = null;

    /**
     * Close the ephemeral socket.
     */
    var closeSocket = function() {
        if (ephemeralSocket) {
            ephemeralSocket.close();
            ephemeralSocket = null;

            // this was probably called due to closeTimeout, but clear it just
            // in case
            clearTimeout(closeTimeout);
            closeTimeout = null;
        }
    };

    /**
     * Clear the socket cleanup timer.
     */
    var removeTimer = function() {
        if (gcTimer) {
            clearInterval(gcTimer);
            gcTimer = null;
        }
    };

    /**
     * Garbage collect the socket if possible.
     */
    var gcSocket = function() {
        if (Date.now() - lastUse > socketTimeout) {
            closeSocket();
            removeTimer();
        }
    };

    var getSocket = function() {
        if (providedSocket) {
            return providedSocket;
        } else {
            // create an ephemeral socket
            if (!ephemeralSocket) {
                ephemeralSocket = require("dgram").createSocket("udp4");

                // don't wait for this to be closed
                ephemeralSocket.unref && ephemeralSocket.unref();

                // prevent errors (that we don't care about) from propagating
                ephemeralSocket.on("error", function(err) {});

                // try to clean up the socket periodically to free up resources
                // if this instance is idle
                gcTimer = setInterval(gcSocket, 250);

                // don't wait for the timer to exit
                gcTimer.unref && gcTimer.unref();

                // forcibly close the socket periodically (ignoring last use)
                // to allow sent Buffers to be GC'd
                closeTimeout = setTimeout(closeSocket, 10 * socketTimeout);

                // don't wait for the timer to exit
                closeTimeout.unref && closeTimeout.unref();
            }

            // the ephemeral socket was last used NOW.
            lastUse = Date.now();

            return ephemeralSocket;
        }
    };

    // object that will be returned by require("metrics")()
    var API = {};

    /**
     * Release resources created by the metrics library.
     */
    API.close = function() {
        closeSocket();
        removeTimer();
    };

    Object.defineProperty(API, "enabled", {
        get: function() {
            return enabled;
        },
        set: function(value) {
            enabled = value;
        },
        enumerable: true
    });
{'fraction_non_alphanumeric': 0.09624508607835164, 'fraction_numerical': 0.0065067100447336315, 'mean_word_length': 1.884284597341673, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '6294333', 'n_tokens_mistral': 2027, 'n_tokens_neox': 1875, 'n_words': 695}