mirror of
https://github.com/ntop/ntopng.git
synced 2026-05-22 02:38:59 +00:00
265 lines
6.7 KiB
C++
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 */
|