auditd-plugin-clickhouse/logging.cpp

182 lines
3.2 KiB
C++

/*
* This is an auditd plugin for sending auditd data
* to clickhouse DB.
* Copyright (C) 2020 Aleksei Nikiforov <darktemplar@basealt.ru>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "logging.hpp"
#include <time.h>
#include <boost/scope_exit.hpp>
std::mutex Logger::s_mutex;
Logger::Logger()
: m_initialized(false)
{
}
Logger::~Logger()
{
dump_impl();
}
Logger& Logger::instance()
{
static Logger s_instance;
return s_instance;
}
void Logger::open(const char *filename)
{
std::lock_guard<std::mutex> lock(s_mutex);
instance().open_impl(filename);
}
void Logger::initialize()
{
std::lock_guard<std::mutex> lock(s_mutex);
instance().initialize_impl();
}
void Logger::write(const char *format, ...)
{
std::lock_guard<std::mutex> lock(s_mutex);
va_list args;
va_start(args, format);
instance().write_impl(format, args);
va_end(args);
}
void Logger::dump()
{
std::lock_guard<std::mutex> lock(s_mutex);
instance().dump_impl();
}
void Logger::open_impl(const char *filename)
{
m_logfile_name = filename;
initialize_impl();
}
void Logger::initialize_impl()
{
m_initialized = true;
}
void Logger::write_impl(const char *format, va_list args)
{
FILE *outfile = NULL;
std::string datestring = getdatestring();
if (!m_logfile_name.empty())
{
outfile = fopen(m_logfile_name.c_str(), "at");
}
if (outfile != NULL)
{
fprintf(outfile, "%s: ", datestring.c_str());
vfprintf(outfile, format, args);
fprintf(outfile, "\n");
fclose(outfile);
}
else
{
// save logged data for later use
char *data = NULL;
BOOST_SCOPE_EXIT(&data)
{
if (data != NULL)
{
free(data);
}
} BOOST_SCOPE_EXIT_END;
int result = vasprintf(&data, format, args);
if ((result >= 0) && (data != NULL))
{
m_lines.push_back(std::make_pair(datestring,data));
}
if (m_initialized)
{
dump_impl();
}
}
}
void Logger::dump_impl()
{
FILE *outfile = NULL;
if (!m_logfile_name.empty())
{
outfile = fopen(m_logfile_name.c_str(), "at");
}
for (auto iter = m_lines.begin(); iter != m_lines.end(); ++iter)
{
fprintf((outfile != NULL) ? outfile : stderr, "%s: %s\n", iter->first.c_str(), iter->second.c_str());
}
if (outfile != NULL)
{
fclose(outfile);
}
else
{
fflush(stderr);
}
m_lines.clear();
}
std::string Logger::getdatestring() const
{
std::string result;
time_t t = time(nullptr);
struct tm tm_inst;
auto tm_ptr = localtime_r(&t, &tm_inst);
if (tm_ptr != nullptr)
{
char buffer[4096];
auto buffer_res = strftime(buffer, sizeof(buffer) - 1, "%c %Z", tm_ptr);
if (buffer_res > 0)
{
buffer[buffer_res] = 0;
result = buffer;
}
}
return result;
}