<commit_before>/*****************************************************************************************
 *                                                                                       *
 * GHOUL                                                                                 *
 * General Helpful Open Utility Library                                                  *
 *                                                                                       *
 * Copyright (c) 2012-2014                                                               *
 *                                                                                       *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                       *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                       *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include "logging/logmanager.h"
#include "logging/log.h"
#include <cassert>
#include <algorithm>
#include <atomic>
#include <map>
#include <vector>

namespace ghoul {
namespace logging {

LogManager* LogManager::_manager = nullptr;

/// \cond DEV
/**
 * The LogManager_P is the private version of the LogManager and uses template
 * instantiation to increase the performance of the logging. Specifying the
 * LogManager::LogLevel as a template argument allows the compiler to optimize the check
 * if a passed message should be relayed or not.
 * The same argument holds for the IMMEDIATEFLUSH that is used to control if the
 * Log::flush() methods should be called after each log(LogManager::LogLevel, std::string,
 * std::string) call to the Logs. After template argument insertion, the appropriate
 * checks will be class-constant and can therefore be optimized.
 * The same technique allows the ignoring of the Debug messages in a Release build.
 * The sole cost of this is a virtual function call in the log message.
 * \tparam LEVEL Determines the lowest level of LogMessages this LogManager accepts
 * \tparam IMMEDIATEFLUSH Controls if the Log::flush() message should be called after each
 * log message.
 */
template <LogManager::LogLevel LEVEL, bool IMMEDIATEFLUSH>
class LogManager_P : public LogManager {
public:
    LogManager_P() : LogManager() {
        _mutex.clear();
    }

    void logMessage(LogLevel level, const std::string& category,
                    const std::string& message);
private:
    std::atomic_flag _mutex;
};

template<LogManager::LogLevel LEVEL, bool IMMEDIATEFLUSH>
void LogManager_P<LEVEL,IMMEDIATEFLUSH>::logMessage(LogManager::LogLevel level,
                                                    const std::string& category,
                                                    const std::string& message)
{
#ifndef _DEBUG
    if (level == LogManager::LogLevel::Debug)
        return;
#endif
    if (level >= LEVEL) {
        // Acquire lock
        while (_mutex.test_and_set()) {}

        std::vector<Log*>::const_iterator it = _logs.begin();
        for (; it != _logs.end(); ++it) {
            (*it)->log(level, category, message);
            if (IMMEDIATEFLUSH)
                (*it)->flush();
        }

        _mutex.clear();
    }
}

/// \endcond

std::string LogManager::stringFromLevel(LogLevel level) {
    switch (level) {
        case LogLevel::Debug:<commit_msg>Remove the restriction that Debug level logging is ignored in Release build on Windows<commit_after>/*****************************************************************************************
 *                                                                                       *
 * GHOUL                                                                                 *
 * General Helpful Open Utility Library                                                  *
 *                                                                                       *
 * Copyright (c) 2012-2014                                                               *
 *                                                                                       *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                       *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                       *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include "logging/logmanager.h"
#include "logging/log.h"
#include <cassert>
#include <algorithm>
#include <atomic>
#include <map>
#include <vector>

namespace ghoul {
namespace logging {

LogManager* LogManager::_manager = nullptr;

/// \cond DEV
/**
 * The LogManager_P is the private version of the LogManager and uses template
 * instantiation to increase the performance of the logging. Specifying the
 * LogManager::LogLevel as a template argument allows the compiler to optimize the check
 * if a passed message should be relayed or not.
 * The same argument holds for the IMMEDIATEFLUSH that is used to control if the
 * Log::flush() methods should be called after each log(LogManager::LogLevel, std::string,
 * std::string) call to the Logs. After template argument insertion, the appropriate
 * checks will be class-constant and can therefore be optimized.
 * The same technique allows the ignoring of the Debug messages in a Release build.
 * The sole cost of this is a virtual function call in the log message.
 * \tparam LEVEL Determines the lowest level of LogMessages this LogManager accepts
 * \tparam IMMEDIATEFLUSH Controls if the Log::flush() message should be called after each
 * log message.
 */
template <LogManager::LogLevel LEVEL, bool IMMEDIATEFLUSH>
class LogManager_P : public LogManager {
public:
    LogManager_P() : LogManager() {
        _mutex.clear();
    }

    void logMessage(LogLevel level, const std::string& category,
                    const std::string& message);
private:
    std::atomic_flag _mutex;
};

template<LogManager::LogLevel LEVEL, bool IMMEDIATEFLUSH>
void LogManager_P<LEVEL,IMMEDIATEFLUSH>::logMessage(LogManager::LogLevel level,
                                                    const std::string& category,
                                                    const std::string& message)
{
    if (level >= LEVEL) {
        // Acquire lock
        while (_mutex.test_and_set()) {}

        std::vector<Log*>::const_iterator it = _logs.begin();
        for (; it != _logs.end(); ++it) {
            (*it)->log(level, category, message);
            if (IMMEDIATEFLUSH)
                (*it)->flush();
        }

        _mutex.clear();
    }
}

/// \endcond

std::string LogManager::stringFromLevel(LogLevel level) {
    switch (level) {
        case LogLevel::Debug:
{'fraction_non_alphanumeric': 0.10692232694182645, 'fraction_numerical': 0.0017332900010833061, 'mean_word_length': 1.7992722862340813, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 74, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4908382', 'n_tokens_mistral': 1974, 'n_tokens_neox': 1905, 'n_words': 821}