<commit_before>/** \file   util.h
 *  \brief  Various utility functions that did not seem to logically fit anywhere else.
 *  \author Dr. <NAME> (<EMAIL>)
 *
 *  \copyright 2014-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#pragma once


#include <mutex>
#include <string>
#include <vector>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include "Compiler.h"


// Macros to create strings describing where and why an error occurred. Must be macros to access __FILE__ and __LINE__.
// This gobble-dee-goop is necessary to turn __LINE__ into a string. See doctor dobs: http://www.ddj.com/dept/cpp/184403864
//
#define Stringize(S) ReallyStringize(S)
#define ReallyStringize(S) #S


/** A thread-safe logger class.
 * \note Set the environment variable LOGGER_FORMAT to control the output format of our logger.  So far we support
 *       "process_pids", "strip_call_site" and "no_decorations".  You may combine any of these, e.g. by separating them with
 *       commas.
 */
class Logger {
public:
    enum LogLevel { LL_ERROR = 1, LL_WARNING = 2, LL_INFO = 3, LL_DEBUG = 4 };
    friend Logger *LoggerInstantiator();
protected:
    static const std::string FUNCTION_NAME_SEPARATOR;

    std::mutex mutex_;
    int fd_;
    bool log_process_pids_, log_no_decorations_, log_strip_call_site_;
    LogLevel min_log_level_;

    void formatMessage(const std::string &level, std::string * const msg);
public:
    Logger();
    virtual ~Logger() = default;
public:
    void redirectOutput(const int new_fd) { fd_ = new_fd; }

    bool getLogNoDecorations() { return log_no_decorations_; }
    void setLogNoDecorations(const bool log_no_decorations) { log_no_decorations_ = log_no_decorations; }

    bool getLogStripCallSite() { return log_strip_call_site_; }
    void setLogStripCallSite(const bool log_strip_call_site) { log_strip_call_site_ = log_strip_call_site; }

    void setMinimumLogLevel(const LogLevel min_log_level) { min_log_level_ = min_log_level; }
    LogLevel getMinimumLogLevel() const { return min_log_level_; }

    //* Emits "msg" and then calls exit(3), also generates a call stack trace if the environment variable BACKTRACE has been set.
    [[noreturn]] virtual void error(const std::string &msg) __attribute__((noreturn));
    [[noreturn]] virtual void error(const std::string &function_name, const std::string &msg) __attribute__((noreturn))
        { error("in " + function_name + FUNCTION_NAME_SEPARATOR + msg); __builtin_unreachable(); }

    virtual void warning(const std::string &msg);
    inline void warning(const std::string &function_name, const std::string &msg)
        { warning("in " + function_name + FUNCTION_NAME_SEPARATOR + msg); }

    virtual void info(const std::string &msg);
    inline void info(const std::string &function_name, const std::string &msg)
        { info("in " + function_name + FUNCTION_NAME_SEPARATOR + msg); }

    /** \note Only writes actual log messages if the environment variable "UTIL_LOG_DEBUG" exists and is set<commit_msg>Straggler.<commit_after>/** \file   util.h
 *  \brief  Various utility functions that did not seem to logically fit anywhere else.
 *  \author Dr. <NAME> (<EMAIL>)
 *
 *  \copyright 2014-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#pragma once


#include <mutex>
#include <string>
#include <vector>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include "Compiler.h"


// Macros to create strings describing where and why an error occurred. Must be macros to access __FILE__ and __LINE__.
// This gobble-dee-goop is necessary to turn __LINE__ into a string. See doctor dobs: http://www.ddj.com/dept/cpp/184403864
//
#define Stringize(S) ReallyStringize(S)
#define ReallyStringize(S) #S


/** A thread-safe logger class.
 * \note Set the environment variable LOGGER_FORMAT to control the output format of our logger.  So far we support
 *       "process_pids", "strip_call_site" and "no_decorations".  You may combine any of these, e.g. by separating them with
 *       commas.
 */
class Logger {
public:
    enum LogLevel { LL_ERROR = 1, LL_WARNING = 2, LL_INFO = 3, LL_DEBUG = 4 };
    friend Logger *LoggerInstantiator();
protected:
    static const std::string FUNCTION_NAME_SEPARATOR;

    std::mutex mutex_;
    int fd_;
    bool log_process_pids_, log_no_decorations_, log_strip_call_site_;
    LogLevel min_log_level_;

    void formatMessage(const std::string &level, std::string * const msg);
public:
    Logger();
    virtual ~Logger() = default;
public:
    void redirectOutput(const int new_fd);

    bool getLogNoDecorations() { return log_no_decorations_; }
    void setLogNoDecorations(const bool log_no_decorations) { log_no_decorations_ = log_no_decorations; }

    bool getLogStripCallSite() { return log_strip_call_site_; }
    void setLogStripCallSite(const bool log_strip_call_site) { log_strip_call_site_ = log_strip_call_site; }

    void setMinimumLogLevel(const LogLevel min_log_level) { min_log_level_ = min_log_level; }
    LogLevel getMinimumLogLevel() const { return min_log_level_; }

    //* Emits "msg" and then calls exit(3), also generates a call stack trace if the environment variable BACKTRACE has been set.
    [[noreturn]] virtual void error(const std::string &msg) __attribute__((noreturn));
    [[noreturn]] virtual void error(const std::string &function_name, const std::string &msg) __attribute__((noreturn))
        { error("in " + function_name + FUNCTION_NAME_SEPARATOR + msg); __builtin_unreachable(); }

    virtual void warning(const std::string &msg);
    inline void warning(const std::string &function_name, const std::string &msg)
        { warning("in " + function_name + FUNCTION_NAME_SEPARATOR + msg); }

    virtual void info(const std::string &msg);
    inline void info(const std::string &function_name, const std::string &msg)
        { info("in " + function_name + FUNCTION_NAME_SEPARATOR + msg); }

    /** \note Only writes actual log messages if the environment variable "UTIL_LOG_DEBUG" exists and is set
{'fraction_non_alphanumeric': 0.09142394822006472, 'fraction_numerical': 0.006202804746494067, 'mean_word_length': 4.154273801250869, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, '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': '4402487', 'n_tokens_mistral': 2266, 'n_tokens_neox': 2193, 'n_words': 789}