<commit_before>#include "log.hpp"
#include "array_utilities.hpp"
#include <boost/noncopyable.hpp>

// We deliberately do NOT use "jewel/assert.hpp" here,
// as we might one day want a call the assert to invoke
// logging facilities, and we don't want to create
// circularity here.
#include <cassert>

#include <fstream>
#include <ios>
#include <iostream>
#include <string>

using boost::noncopyable;
using jewel::num_elements;
using std::cerr;
using std::clog;
using std::cout;
using std::endl;
using std::ios;
using std::ofstream;
using std::ostream;
using std::string;


namespace jewel
{

namespace
{

	struct StreamHolder: noncopyable
	{
		explicit StreamHolder(ostream* p_os);
		~StreamHolder();
		void kill();
		ostream* os;
	};

	StreamHolder::StreamHolder(ostream* p_os): os(p_os)
	{
	}

	StreamHolder::~StreamHolder()
	{
		JEWEL_LOG_MESSAGE(Log::info, "Destroying logging StreamHolder.");
		kill();
	}

	void
	StreamHolder::kill()
	{
		if (os)
		{
			os->flush();
			if ((os != &cerr) && (os != &clog) && (os != &cout))
			{
				JEWEL_LOG_MESSAGE
				(	Log::info,
					"Deleting underlying logging stream."
				);
				delete os;
			}
			os = 0;
		}
		assert (0 == os);
		return;
	}



}  // end anonymous namespace

void
Log::set_filepath(string const& p_filepath)
{
	static string filepath = "";
	if (p_filepath != filepath)
	{
		filepath = p_filepath;
		if (!filepath.empty())
		{
			ofstream* f = new ofstream(p_filepath.c_str());
			f->exceptions(ios::iostate(0));
			stream_aux(f);
		}
	}
	return;
}

void
Log::set_threshold(Level p_level)
{
	threshold_aux() = p_level;
	return;
}

void
Log::log
(	Level p_severity,
	string const& p_message,
	string const& p_function,
	string const& p_file,
	int p_line,
	string const& p_compilation_date,
	string const& p_compilation_time
)
{
	log
	(	p_severity,
		p_message.c_str(),
		p_function.c_str(),
		p_file.c_str(),
		p_line,
		p_compilation_date.c_str(),
		p_compilation_time.c_str()
	);
	return;
}

void
Log::log
(	Level p_severity,
	char const* p_message,
	char const* p_function,
	char const* p_file,
	int p_line,
	char const* p_compilation_date,
	char const* p_compilation_time
)
{
	if (p_severity >= threshold_aux())
	{
		ostream* const osp = stream_aux();
		if (!osp)
		{
			return;
		}
		assert (!osp->bad());  // guaranteed by stream_aux().
		assert (!osp->exceptions());  // guaranteed by stream_aux().
		*osp << "{\n"
			<< "\tseverity: \"" << severity_string(p_severity) << "\"\n"
			<< "\tmessage: \"" << p_message << "\",\n"
			<< "\tfunction: \"" << p_function << "\",\n"
			<< "\tfile: \"" << p_file << "\",\n"
			<< "\tline: " << p_line << ",\n"
			<< "\tcompilation_date: \"" << p_compilation_date << "\",\n"
			<< "\tcompilation_time: \"" << p_compilation_time << "\"\n"
			<< "},"
			<< endl;
	}
	return;
}


char const*
Log::severity_string(Level p_level)
{
	static char const* strings[] =
	{	"trace",
		"info",
		"warning",
		"error"
	};
	if (p_level >= num_elements(strings))
	{
		return "unrecognized";<commit_msg>Fixed some errors in formatting of JSON output of jewel::Log.<commit_after>#include "log.hpp"
#include "array_utilities.hpp"
#include <boost/noncopyable.hpp>

// We deliberately do NOT use "jewel/assert.hpp" here,
// as we might one day want a call the assert to invoke
// logging facilities, and we don't want to create
// circularity here.
#include <cassert>

#include <fstream>
#include <ios>
#include <iostream>
#include <string>

using boost::noncopyable;
using jewel::num_elements;
using std::cerr;
using std::clog;
using std::cout;
using std::endl;
using std::ios;
using std::ofstream;
using std::ostream;
using std::string;


namespace jewel
{

namespace
{

	struct StreamHolder: noncopyable
	{
		explicit StreamHolder(ostream* p_os);
		~StreamHolder();
		void kill();
		ostream* os;
	};

	StreamHolder::StreamHolder(ostream* p_os): os(p_os)
	{
	}

	StreamHolder::~StreamHolder()
	{
		JEWEL_LOG_MESSAGE(Log::info, "Destroying logging StreamHolder.");
		kill();
	}

	void
	StreamHolder::kill()
	{
		if (os)
		{
			os->flush();
			if ((os != &cerr) && (os != &clog) && (os != &cout))
			{
				JEWEL_LOG_MESSAGE
				(	Log::info,
					"Deleting underlying logging stream."
				);
				delete os;
			}
			os = 0;
		}
		assert (0 == os);
		return;
	}



}  // end anonymous namespace

void
Log::set_filepath(string const& p_filepath)
{
	static string filepath = "";
	if (p_filepath != filepath)
	{
		filepath = p_filepath;
		if (!filepath.empty())
		{
			ofstream* f = new ofstream(p_filepath.c_str());
			f->exceptions(ios::iostate(0));
			stream_aux(f);
		}
	}
	return;
}

void
Log::set_threshold(Level p_level)
{
	threshold_aux() = p_level;
	return;
}

void
Log::log
(	Level p_severity,
	string const& p_message,
	string const& p_function,
	string const& p_file,
	int p_line,
	string const& p_compilation_date,
	string const& p_compilation_time
)
{
	log
	(	p_severity,
		p_message.c_str(),
		p_function.c_str(),
		p_file.c_str(),
		p_line,
		p_compilation_date.c_str(),
		p_compilation_time.c_str()
	);
	return;
}

void
Log::log
(	Level p_severity,
	char const* p_message,
	char const* p_function,
	char const* p_file,
	int p_line,
	char const* p_compilation_date,
	char const* p_compilation_time
)
{
	if (p_severity >= threshold_aux())
	{
		ostream* const osp = stream_aux();
		if (!osp)
		{
			return;
		}
		assert (!osp->bad());  // guaranteed by stream_aux().
		assert (!osp->exceptions());  // guaranteed by stream_aux().
		*osp << "{\n"
			<< "\t\"severity\": \"" << severity_string(p_severity) << "\",\n"
			<< "\t\"message\": \"" << p_message << "\",\n"
			<< "\t\"function\": \"" << p_function << "\",\n"
			<< "\t\"file\": \"" << p_file << "\",\n"
			<< "\t\"line\": " << p_line << ",\n"
			<< "\t\"compilation_date\": \"" << p_compilation_date << "\",\n"
			<< "\t\"compilation_time\": \"" << p_compilation_time << "\"\n"
			<< "},"
			<< endl;
	}
	return;
}


char const*
Log::severity_string(Level p_level)
{
	static char const* strings[] =
	{	"trace",
		"info",
		"warning",
		"error"
	};
	if (p_level >= num_elements(strings))
	{
		return "unrecognized";
{'fraction_non_alphanumeric': 0.17663536002636349, 'fraction_numerical': 0.0009886307464162135, 'mean_word_length': 3.7682639434406915, 'pattern_counts': {'":': 7, '<': 111, '<?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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3235851', 'n_tokens_mistral': 2560, 'n_tokens_neox': 2347, 'n_words': 522}