ntopng/src/Trace.cpp
Luca Deri 3aadd4e8be Added tracings
Added details parameter to NetworkInterface::lua() and subclasses
2024-02-15 07:10:24 +01:00

265 lines
6.7 KiB
C++

/*
*
* (C) 2013-24 - ntop.org
*
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "ntop_includes.h"
/* ******************************* */
Trace::Trace() {
if(trace_new_delete) ntop->getTrace()->traceEvent(TRACE_NORMAL, "[new] %s", __FILE__);
traceLevel = TRACE_LEVEL_NORMAL;
logFile = NULL;
logFd = NULL;
traceRedis = NULL;
dontFreeRedis = false;
open_log();
};
/* ******************************* */
Trace::~Trace() {
if (logFd) fclose(logFd);
if (logFile) free(logFile);
if (traceRedis && (!dontFreeRedis))
delete traceRedis;
};
/* ******************************* */
void Trace::rotate_logs(bool forceRotation) {
char buf1[MAX_PATH], buf2[MAX_PATH];
const int max_num_lines = TRACES_PER_LOG_FILE_HIGH_WATERMARK;
if (!logFd)
return;
else if ((!forceRotation) && (numLogLines < max_num_lines))
return;
fclose(logFd);
logFd = NULL;
for (int i = MAX_NUM_NTOPNG_LOG_FILES - 1; i >= 1; i--) {
snprintf(buf1, sizeof(buf1), "%s.%u", logFile, i);
snprintf(buf2, sizeof(buf2), "%s.%u", logFile, i + 1);
if (Utils::file_exists(buf1)) rename(buf1, buf2);
} /* for */
if (Utils::file_exists(logFile)) {
snprintf(buf1, sizeof(buf1), "%s.1", logFile);
rename(logFile, buf1);
}
open_log();
}
/* ******************************* */
void Trace::open_log() {
if (logFile) {
logFd = fopen(logFile, "a");
if (!logFd)
traceEvent(TRACE_ERROR, "Unable to create log %s", logFile);
else
chmod(logFile, CONST_DEFAULT_FILE_MODE);
numLogLines = 0;
}
}
/* ******************************* */
void Trace::set_log_file(const char *log_file) {
if (log_file && log_file[0] != '\0') {
rotate_logs(true);
if (logFile) free(logFile);
logFile = strndup(log_file, MAX_PATH);
open_log();
}
}
/* ******************************* */
void Trace::set_trace_level(u_int8_t id) {
if (id > MAX_TRACE_LEVEL) id = MAX_TRACE_LEVEL;
traceLevel = id;
}
/* ******************************* */
void Trace::initRedis(const char *redis_host, const char *redis_password,
u_int16_t redis_port, u_int8_t _redis_db_id) {
Utils::initRedis(&traceRedis, redis_host, redis_password, redis_port,
_redis_db_id, false);
dontFreeRedis = false; /* Free traceRedis on shutdown */
}
/* ******************************* */
void Trace::traceEvent(int eventTraceLevel, const char *_file, const int line,
const char *format, ...) {
va_list va_ap;
#ifndef WIN32
struct tm result;
#endif
if ((eventTraceLevel <= traceLevel) && (traceLevel > 0)) {
char buf[8100], out_buf[9000];
char theDate[32], *file = (char *)_file;
const char *extra_msg = "";
time_t theTime = time(NULL);
char filebuf[MAX_PATH];
const char *backslash = strrchr(_file,
#ifdef WIN32
'\\'
#else
'/'
#endif
);
if (backslash != NULL) {
snprintf(filebuf, sizeof(filebuf), "%s", &backslash[1]);
file = (char *)filebuf;
}
va_start(va_ap, format);
/* We have two paths - one if we're logging, one if we aren't
* Note that the no-log case is those systems which don't support it
* (WIN32), those without the headers !defined(USE_SYSLOG) those where it's
* parametrically off...
*/
memset(buf, 0, sizeof(buf));
strftime(theDate, sizeof(theDate), "%d/%b/%Y %H:%M:%S", localtime_r(&theTime, &result));
vsnprintf(buf, sizeof(buf) - 1, format, va_ap);
va_end(va_ap);
if (eventTraceLevel == 0 /* TRACE_ERROR */)
extra_msg = "ERROR: ";
else if (eventTraceLevel == 1 /* TRACE_WARNING */)
extra_msg = "WARNING: ";
while (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = '\0';
snprintf(out_buf, sizeof(out_buf) - 1, "%s [%s:%d] %s%s", theDate, file,
line, extra_msg, buf);
logEvent(eventTraceLevel, out_buf);
printf("%s\n", out_buf);
fflush(stdout);
if (traceRedis
&& traceRedis->isOperational()
&& ntop->getRedis()->isOperational()) {
if (traceRedis->llen(NTOPNG_TRACE) >= MAX_NUM_NTOPNG_TRACES) {
memset(buf, 0, sizeof(buf));
traceRedis->rpop(NTOPNG_TRACE,buf, sizeof(buf));
}
traceRedis->lpush(NTOPNG_TRACE, out_buf, MAX_NUM_NTOPNG_TRACES,
false /* Do not re-trace errors, re-tracing would yield a deadlock */);
}
}
}
/* ******************************* */
void Trace::logEvent(int eventTraceLevel, char *log_line) {
if (logFd) {
rotate_mutex.lock(__FILE__, __LINE__); /* Need to lock as a rotation may be in progress */
numLogLines++;
fprintf(logFd, "%s\n", log_line);
fflush(logFd);
rotate_logs(false);
rotate_mutex.unlock(__FILE__, __LINE__);
} else {
#ifdef WIN32
AddToMessageLog(log_line);
#else
if (eventTraceLevel == 0 /* TRACE_ERROR */)
syslog(LOG_ERR, "%s", log_line);
else if (eventTraceLevel == 1 /* TRACE_WARNING */)
syslog(LOG_WARNING, "%s", log_line);
#endif
}
}
/* ******************************* */
void Trace::setRedis(Redis *r) {
traceRedis = r;
dontFreeRedis = true; /* No need to free traceRedis as this is a shared pointer */
}
/* ******************************* */
#ifdef WIN32
/* service_win32.cpp */
extern "C" {
extern short isWinNT();
extern BOOL bConsole;
};
/* ******************************* */
void Trace::AddToMessageLog(LPTSTR lpszMsg) {
HANDLE hEventSource;
TCHAR szMsg[4096];
#ifdef UNICODE
LPCWSTR lpszStrings[1];
#else
LPCSTR lpszStrings[1];
#endif
if (!isWinNT()) {
char *msg = (char *)lpszMsg;
printf("%s", msg);
if (msg[strlen(msg) - 1] != '\n') printf("\n");
return;
}
if (!szMsg) {
hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));
snprintf(szMsg, sizeof(szMsg), TEXT("%s: %s"), SZSERVICENAME, lpszMsg);
lpszStrings[0] = szMsg;
if (hEventSource != NULL) {
ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0,
EVENT_GENERIC_INFORMATION, NULL, 1, 0, lpszStrings, NULL);
DeregisterEventSource(hEventSource);
}
}
}
/* ******************************* */
#endif /* WIN32 */