mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-09 10:39:02 -04:00
Implement support for JSON logging.
This commit is contained in:
parent
7fda4b5bd6
commit
a44a6cfab7
3
.github/workflows/ci-alpine.yml
vendored
3
.github/workflows/ci-alpine.yml
vendored
@ -35,12 +35,13 @@ jobs:
|
||||
pcre2-dev \
|
||||
perl \
|
||||
pkgconf \
|
||||
rapidjson-dev \
|
||||
re2-dev \
|
||||
sqlite-dev
|
||||
|
||||
- name: Run configure
|
||||
run: |
|
||||
./configure --enable-extras "argon2 geo_maxmind ldap log_syslog mysql pgsql regex_pcre regex_posix regex_re2 sqlite3 ssl_gnutls ssl_mbedtls ssl_openssl sslrehashsignal"
|
||||
./configure --enable-extras "argon2 geo_maxmind ldap log_json log_syslog mysql pgsql regex_pcre regex_posix regex_re2 sqlite3 ssl_gnutls ssl_mbedtls ssl_openssl sslrehashsignal"
|
||||
./configure --development --disable-auto-extras --disable-ownership --socketengine ${{ matrix.socketengine }}
|
||||
|
||||
- name: Build core
|
||||
|
5
.github/workflows/ci-linux.yml
vendored
5
.github/workflows/ci-linux.yml
vendored
@ -34,11 +34,12 @@ jobs:
|
||||
libsqlite3-dev \
|
||||
libssl-dev \
|
||||
make \
|
||||
pkg-config
|
||||
pkg-config \
|
||||
rapidjson-dev
|
||||
|
||||
- name: Run configure
|
||||
run: |
|
||||
./configure --enable-extras "argon2 geo_maxmind ldap log_syslog mysql pgsql regex_pcre regex_posix regex_re2 sqlite3 ssl_gnutls ssl_mbedtls ssl_openssl sslrehashsignal"
|
||||
./configure --enable-extras "argon2 geo_maxmind ldap log_json log_syslog mysql pgsql regex_pcre regex_posix regex_re2 sqlite3 ssl_gnutls ssl_mbedtls ssl_openssl sslrehashsignal"
|
||||
./configure --development --disable-auto-extras --socketengine ${{ matrix.socketengine }}
|
||||
|
||||
- name: Build core
|
||||
|
4
.github/workflows/ci-macos.yml
vendored
4
.github/workflows/ci-macos.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew update || true
|
||||
for PACKAGE in pkg-config argon2 gnutls libmaxminddb libpq mbedtls mysql-client openssl@3 pcre2 re2 sqlite;
|
||||
for PACKAGE in pkg-config argon2 gnutls libmaxminddb libpq mbedtls mysql-client openssl@3 pcre2 re2 rapidjson sqlite;
|
||||
do
|
||||
brew install $PACKAGE || brew upgrade $PACKAGE
|
||||
|
||||
@ -37,7 +37,7 @@ jobs:
|
||||
|
||||
- name: Run configure
|
||||
run: |
|
||||
./configure --enable-extras "argon2 geo_maxmind ldap log_syslog mysql pgsql regex_pcre regex_posix regex_re2 sqlite3 ssl_gnutls ssl_mbedtls ssl_openssl sslrehashsignal"
|
||||
./configure --enable-extras "argon2 geo_maxmind ldap log_json log_syslog mysql pgsql regex_pcre regex_posix regex_re2 sqlite3 ssl_gnutls ssl_mbedtls ssl_openssl sslrehashsignal"
|
||||
./configure --development --disable-auto-extras --socketengine ${{ matrix.socketengine }}
|
||||
|
||||
- name: Build core
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,6 +17,7 @@
|
||||
/src/modules/m_argon2.cpp
|
||||
/src/modules/m_geo_maxmind.cpp
|
||||
/src/modules/m_ldap.cpp
|
||||
/src/modules/m_log_json.cpp
|
||||
/src/modules/m_log_syslog.cpp
|
||||
/src/modules/m_mysql.cpp
|
||||
/src/modules/m_pgsql.cpp
|
||||
|
1
configure
vendored
1
configure
vendored
@ -395,6 +395,7 @@ if (prompt_bool $interactive, $question, 0) {
|
||||
'm_mysql.cpp' => 'mysql_config --version',
|
||||
'm_pgsql.cpp' => 'pg_config --version',
|
||||
'm_ldap.cpp' => "echo '#include <ldap.h>' | $config{CXX} -E -",
|
||||
'm_log_json.cpp' => 'pkg-config --exists RapidJSON',
|
||||
'm_log_syslog.cpp' => undef,
|
||||
'm_regex_pcre.cpp' => 'pkg-config --exists libpcre2-8',
|
||||
'm_regex_posix.cpp' => undef,
|
||||
|
@ -1366,6 +1366,17 @@
|
||||
# opers are to be authenticated via LDAP, so in case this module is #
|
||||
# not loaded the oper accounts are still protected by a password. #
|
||||
|
||||
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
|
||||
# JSON logging module: Allows writing messages to the system log. #
|
||||
# This module is in extras. Re-run configure with: #
|
||||
# ./configure --enable-extras log_json
|
||||
#<module name="log_json">
|
||||
#
|
||||
#<log method="json"
|
||||
# target="inspircd.json"
|
||||
# level="normal"
|
||||
# type="* -USERINPUT -USEROUTPUT">
|
||||
|
||||
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
|
||||
# SQL logging module: Allows writing messages to an SQL database.. #
|
||||
#<module name="log_sql">
|
||||
|
152
src/modules/extra/m_log_json.cpp
Normal file
152
src/modules/extra/m_log_json.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* InspIRCd -- Internet Relay Chat Daemon
|
||||
*
|
||||
* Copyright (C) 2022 Sadie Powell <sadie@witchery.services>
|
||||
*
|
||||
* This file is part of InspIRCd. InspIRCd 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, version 2.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// $CompilerFlags: find_compiler_flags("RapidJSON")
|
||||
|
||||
|
||||
#include "inspircd.h"
|
||||
|
||||
#include <rapidjson/ostreamwrapper.h>
|
||||
#include <rapidjson/writer.h>
|
||||
|
||||
class JSONMethod final
|
||||
: public Log::Method
|
||||
{
|
||||
private:
|
||||
// The file to which the log is written.
|
||||
FILE* file;
|
||||
|
||||
// How often the file stream should be flushed.
|
||||
const unsigned long flush;
|
||||
|
||||
// The number of lines which have been written since the file stream was created.
|
||||
unsigned long lines = 0;
|
||||
|
||||
/// The name the underlying file.
|
||||
const std::string name;
|
||||
|
||||
public:
|
||||
// RapidJSON API: The type of character that this writer accepts.
|
||||
typedef char Ch;
|
||||
|
||||
JSONMethod(const std::string& n, FILE* fh, unsigned long fl) ATTR_NOT_NULL(3)
|
||||
: file(fh)
|
||||
, flush(fl)
|
||||
, name(n)
|
||||
{
|
||||
}
|
||||
|
||||
~JSONMethod()
|
||||
{
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// RapidJSON API: We implement our own flushing in OnLog.
|
||||
void Flush() { }
|
||||
|
||||
void OnLog(Log::Level level, const std::string& type, const std::string& message) override
|
||||
{
|
||||
static time_t prevtime = 0;
|
||||
static std::string timestr;
|
||||
if (prevtime != ServerInstance->Time())
|
||||
{
|
||||
prevtime = ServerInstance->Time();
|
||||
timestr = InspIRCd::TimeString(prevtime, "%Y-%m-%dT%H:%M:%S%z");
|
||||
}
|
||||
|
||||
rapidjson::Writer writer(*this);
|
||||
writer.StartObject();
|
||||
{
|
||||
writer.Key("time");
|
||||
writer.String(timestr.c_str(), static_cast<rapidjson::SizeType>(timestr.size()));
|
||||
|
||||
writer.Key("type");
|
||||
writer.String(type.c_str(), static_cast<rapidjson::SizeType>(type.size()));
|
||||
|
||||
writer.Key("level");
|
||||
const std::string levelstr = Log::LevelToString(level);
|
||||
writer.String(levelstr.c_str(), static_cast<rapidjson::SizeType>(levelstr.size()));
|
||||
|
||||
writer.Key("message");
|
||||
writer.Key(message.c_str(), static_cast<rapidjson::SizeType>(message.size()));
|
||||
}
|
||||
writer.EndObject();
|
||||
|
||||
#ifdef _WIN32
|
||||
fputs("\r\n", file);
|
||||
#else
|
||||
fputs("\n", file);
|
||||
#endif
|
||||
|
||||
if (!(++lines % flush))
|
||||
fflush(file);
|
||||
|
||||
if (ferror(file))
|
||||
throw CoreException(InspIRCd::Format("Unable to write to %s: %s", name.c_str(), strerror(errno)));
|
||||
}
|
||||
|
||||
// RapidJSON API: Write a character to the file.
|
||||
void Put(Ch c)
|
||||
{
|
||||
fputc(c, file);
|
||||
}
|
||||
};
|
||||
|
||||
class JSONEngine final
|
||||
: public Log::Engine
|
||||
{
|
||||
public:
|
||||
JSONEngine(Module* Creator) ATTR_NOT_NULL(2)
|
||||
: Log::Engine(Creator, "json")
|
||||
{
|
||||
}
|
||||
|
||||
Log::MethodPtr Create(std::shared_ptr<ConfigTag> tag) override
|
||||
{
|
||||
const std::string target = tag->getString("target");
|
||||
if (target.empty())
|
||||
throw CoreException("<log:target> must be specified for JSON logger at " + tag->source.str());
|
||||
|
||||
const std::string fulltarget = ServerInstance->Config->Paths.PrependLog(InspIRCd::TimeString(ServerInstance->Time(), target.c_str()));
|
||||
FILE* fh = fopen(fulltarget.c_str(), "a");
|
||||
if (!fh)
|
||||
{
|
||||
throw CoreException(InspIRCd::Format("Unable to open %s for JSON logger at %s: %s",
|
||||
fulltarget.c_str(), tag->source.str().c_str(), strerror(errno)));
|
||||
}
|
||||
|
||||
const unsigned long flush = tag->getUInt("flush", 20, 1);
|
||||
return std::make_shared<JSONMethod>(fulltarget, fh, flush);
|
||||
}
|
||||
};
|
||||
|
||||
class ModuleLogJSON final
|
||||
: public Module
|
||||
{
|
||||
private:
|
||||
JSONEngine engine;
|
||||
|
||||
public:
|
||||
ModuleLogJSON()
|
||||
: Module(VF_VENDOR, "Provides the ability to write logs to syslog.")
|
||||
, engine(this)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(ModuleLogJSON)
|
@ -12,6 +12,7 @@ libpq/14.2
|
||||
## mbedtls/3.1.0
|
||||
## openssl/1.1.1n # unable to upgrade yet because of dependency issues
|
||||
pcre2/10.40
|
||||
rapidjson/cci.20211112
|
||||
re2/20220201
|
||||
sqlite3/3.38.1
|
||||
|
||||
|
@ -12,6 +12,7 @@ if(EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
|
||||
|
||||
enable_extra("argon2" "ARGON2")
|
||||
enable_extra("geo_maxmind" "LIBMAXMINDDB")
|
||||
enable_extra("log_json" "RAPIDJSON")
|
||||
enable_extra("mysql" "LIBMYSQLCLIENT")
|
||||
enable_extra("pgsql" "LIBPQ")
|
||||
enable_extra("regex_pcre" "PCRE2")
|
||||
|
Loading…
x
Reference in New Issue
Block a user