mapnik/src/debug.cpp
2024-07-22 10:20:47 +01:00

160 lines
3.9 KiB
C++

/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2024 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/stringify_macro.hpp>
// stl
#include <ctime>
#include <stdexcept>
#include <fstream>
#include <cstdlib>
// clang-format off
#ifndef MAPNIK_LOG_FORMAT
#define MAPNIK_LOG_FORMAT Mapnik LOG> %Y-%m-%d %H:%M:%S:
#endif
// clang-format on
#ifndef MAPNIK_DEFAULT_LOG_SEVERITY
#ifdef MAPNIK_DEBUG
#define MAPNIK_DEFAULT_LOG_SEVERITY 0
#else
#define MAPNIK_DEFAULT_LOG_SEVERITY 2
#endif
#endif
namespace mapnik {
#ifdef MAPNIK_THREADSAFE
std::mutex logger::severity_mutex_;
std::mutex logger::format_mutex_;
std::atomic<bool> logger::severity_env_check_{true};
std::atomic<bool> logger::format_env_check_{true};
std::atomic<logger::severity_type> logger::severity_level_
{
#else
bool logger::severity_env_check_{true};
bool logger::format_env_check_{true};
logger::severity_type logger::severity_level_{
#endif
#if MAPNIK_DEFAULT_LOG_SEVERITY == 0
logger::debug
#elif MAPNIK_DEFAULT_LOG_SEVERITY == 1
logger::warn
#elif MAPNIK_DEFAULT_LOG_SEVERITY == 2
logger::error
#elif MAPNIK_DEFAULT_LOG_SEVERITY == 3
logger::none
#else
#error "Wrong default log severity level specified!"
#endif
};
logger::severity_map logger::object_severity_level_ = logger::severity_map();
std::string logger::format_ = MAPNIK_STRINGIFY(MAPNIK_LOG_FORMAT);
std::string logger::str()
{
#ifdef MAPNIK_CHECK_ENV
// update the format from getenv if this is the first time
if (logger::format_env_check_)
{
logger::format_env_check_ = false;
const char* log_format = std::getenv("MAPNIK_LOG_FORMAT");
if (log_format != nullptr)
{
logger::format_ = log_format;
}
}
#endif
char buf[256];
const time_t tm = time(0);
std::strftime(buf, sizeof(buf), logger::format_.c_str(), localtime(&tm));
return buf;
}
// output
std::ofstream logger::file_output_;
std::string logger::file_name_;
std::streambuf* logger::saved_buf_ = 0;
void logger::use_file(std::string const& filepath)
{
// save clog rdbuf
if (saved_buf_ == 0)
{
saved_buf_ = std::clog.rdbuf();
}
// use a file to output as clog rdbuf
if (file_name_ != filepath)
{
file_name_ = filepath;
if (file_output_.is_open())
{
file_output_.close();
}
file_output_.open(file_name_.c_str(), std::ios::out | std::ios::app);
if (file_output_)
{
std::clog.rdbuf(file_output_.rdbuf());
}
else
{
std::stringstream s;
s << "cannot redirect log to file " << file_name_;
throw std::runtime_error(s.str());
}
}
}
void logger::use_console()
{
// save clog rdbuf
if (saved_buf_ == 0)
{
saved_buf_ = std::clog.rdbuf();
}
// close the file to force a flush
if (file_output_.is_open())
{
file_output_.close();
}
std::clog.rdbuf(saved_buf_);
}
} // namespace mapnik