1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00
srs/trunk/src/app/srs_app_log.cpp
2023-01-01 08:49:13 +08:00

182 lines
4.2 KiB
C++

//
// Copyright (c) 2013-2023 The SRS Authors
//
// SPDX-License-Identifier: MIT or MulanPSL-2.0
//
#include <srs_app_log.hpp>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <srs_app_config.hpp>
#include <srs_kernel_error.hpp>
#include <srs_app_utility.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_app_threads.hpp>
// the max size of a line of log.
#define LOG_MAX_SIZE 8192
// the tail append to each log.
#define LOG_TAIL '\n'
// reserved for the end of log data, it must be strlen(LOG_TAIL)
#define LOG_TAIL_SIZE 1
SrsFileLog::SrsFileLog()
{
level_ = SrsLogLevelTrace;
log_data = new char[LOG_MAX_SIZE];
fd = -1;
log_to_file_tank = false;
utc = false;
mutex_ = new SrsThreadMutex();
}
SrsFileLog::~SrsFileLog()
{
srs_freepa(log_data);
if (fd > 0) {
::close(fd);
fd = -1;
}
if (_srs_config) {
_srs_config->unsubscribe(this);
}
srs_freep(mutex_);
}
srs_error_t SrsFileLog::initialize()
{
if (_srs_config) {
_srs_config->subscribe(this);
log_to_file_tank = _srs_config->get_log_tank_file();
utc = _srs_config->get_utc_time();
std::string level = _srs_config->get_log_level();
std::string level_v2 = _srs_config->get_log_level_v2();
level_ = level_v2.empty() ? srs_get_log_level(level) : srs_get_log_level_v2(level_v2);
}
return srs_success;
}
void SrsFileLog::reopen()
{
if (fd > 0) {
::close(fd);
}
if (!log_to_file_tank) {
return;
}
open_log_file();
}
void SrsFileLog::log(SrsLogLevel level, const char* tag, const SrsContextId& context_id, const char* fmt, va_list args)
{
if (level < level_ || level >= SrsLogLevelDisabled) {
return;
}
SrsThreadLocker(mutex_);
int size = 0;
bool header_ok = srs_log_header(
log_data, LOG_MAX_SIZE, utc, level >= SrsLogLevelWarn, tag, context_id, srs_log_level_strings[level], &size
);
if (!header_ok) {
return;
}
// Something not expected, drop the log.
int r0 = vsnprintf(log_data + size, LOG_MAX_SIZE - size, fmt, args);
if (r0 <= 0 || r0 >= LOG_MAX_SIZE - size) {
return;
}
size += r0;
// Add errno and strerror() if error. Check size to avoid security issue https://github.com/ossrs/srs/issues/1229
if (level == SrsLogLevelError && errno != 0 && size < LOG_MAX_SIZE) {
r0 = snprintf(log_data + size, LOG_MAX_SIZE - size, "(%s)", strerror(errno));
// Something not expected, drop the log.
if (r0 <= 0 || r0 >= LOG_MAX_SIZE - size) {
return;
}
size += r0;
}
write_log(fd, log_data, size, level);
}
void SrsFileLog::write_log(int& fd, char *str_log, int size, int level)
{
// ensure the tail and EOF of string
// LOG_TAIL_SIZE for the TAIL char.
// 1 for the last char(0).
size = srs_min(LOG_MAX_SIZE - 1 - LOG_TAIL_SIZE, size);
// add some to the end of char.
str_log[size++] = LOG_TAIL;
// if not to file, to console and return.
if (!log_to_file_tank) {
// if is error msg, then print color msg.
// \033[31m : red text code in shell
// \033[32m : green text code in shell
// \033[33m : yellow text code in shell
// \033[0m : normal text code
if (level <= SrsLogLevelTrace) {
printf("%.*s", size, str_log);
} else if (level == SrsLogLevelWarn) {
printf("\033[33m%.*s\033[0m", size, str_log);
} else{
printf("\033[31m%.*s\033[0m", size, str_log);
}
fflush(stdout);
return;
}
// open log file. if specified
if (fd < 0) {
open_log_file();
}
// write log to file.
if (fd > 0) {
::write(fd, str_log, size);
}
}
void SrsFileLog::open_log_file()
{
if (!_srs_config) {
return;
}
std::string filename = _srs_config->get_log_file();
if (filename.empty()) {
return;
}
fd = ::open(filename.c_str(),
O_RDWR | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
);
}