mirror of
https://github.com/ntop/ntopng.git
synced 2026-05-20 17:29:13 +00:00
251 lines
6.1 KiB
C++
251 lines
6.1 KiB
C++
/*
|
|
*
|
|
* (C) 2013-20 - 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() {
|
|
traceLevel = TRACE_LEVEL_NORMAL;
|
|
logFile = NULL;
|
|
logFd = NULL;
|
|
traceRedis = NULL;
|
|
|
|
open_log();
|
|
};
|
|
|
|
/* ******************************* */
|
|
|
|
Trace::~Trace() {
|
|
if(logFd) fclose(logFd);
|
|
if(logFile) free(logFile);
|
|
if(traceRedis) 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);
|
|
}
|
|
|
|
/* ******************************* */
|
|
|
|
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[8192];
|
|
char theDate[32], *file = (char*)_file;
|
|
const char *extra_msg = "";
|
|
time_t theTime = time(NULL);
|
|
#ifndef WIN32
|
|
char *syslogMsg;
|
|
#endif
|
|
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, 32, "%d/%b/%Y %H:%M:%S", localtime_r(&theTime, &result));
|
|
|
|
vsnprintf(buf, sizeof(buf)-1, format, 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), "%s [%s:%d] %s%s", theDate, file, line, extra_msg, buf);
|
|
|
|
if(logFd) {
|
|
rotate_mutex.lock(__FILE__, __LINE__); /* Need to lock as a rotation may be in progress */
|
|
numLogLines++;
|
|
fprintf(logFd, "%s\n", out_buf);
|
|
fflush(logFd);
|
|
rotate_logs(false);
|
|
rotate_mutex.unlock(__FILE__, __LINE__);
|
|
} else {
|
|
#ifdef WIN32
|
|
AddToMessageLog(out_buf);
|
|
#else
|
|
syslogMsg = &out_buf[strlen(theDate)+1];
|
|
if(eventTraceLevel == 0 /* TRACE_ERROR */)
|
|
syslog(LOG_ERR, "%s", syslogMsg);
|
|
else if(eventTraceLevel == 1 /* TRACE_WARNING */)
|
|
syslog(LOG_WARNING, "%s", syslogMsg);
|
|
#endif
|
|
}
|
|
|
|
printf("%s\n", out_buf);
|
|
fflush(stdout);
|
|
|
|
if(traceRedis && traceRedis->isOperational() && ntop->getRedis()->isOperational())
|
|
traceRedis->lpush(NTOPNG_TRACE, out_buf, MAX_NUM_NTOPNG_TRACES,
|
|
false /* Do not re-trace errors, re-tracing would yield a deadlock */);
|
|
|
|
va_end(va_ap);
|
|
}
|
|
}
|
|
|
|
/* ******************************* */
|
|
|
|
#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 */
|