Skip to content

Commit

Permalink
log_rotation (swoole#3311)
Browse files Browse the repository at this point in the history
* log_rotation

* add log_rotation option

* Check data format string length

* fix mem leak
  • Loading branch information
matyhtf authored May 12, 2020
1 parent 3074d50 commit 4562bd6
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 11 deletions.
32 changes: 32 additions & 0 deletions core-tests/src/core/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ TEST(log, date_format)
ASSERT_TRUE(n);
}

TEST(log, date_format_long_string)
{
swLog_reset();
swLog_set_level(SW_LOG_ERROR);
swoole::String content(swString_new(256));
auto str = content.get();

swString_repeat(str, "x", 1, 120);
swString_append_ptr(str, SW_STRL("day %d of %B in the year %Y. Time: %I:%S %p"));

int retval = swLog_set_date_format(str->str);

ASSERT_EQ(retval, SW_ERR);
ASSERT_EQ(SwooleG.error, SW_ERROR_INVALID_PARAMS);
}

TEST(log, date_with_microseconds)
{
swLog_reset();
Expand All @@ -60,3 +76,19 @@ TEST(log, date_with_microseconds)
std::regex e("\\[\\S+\\s\\d{2}:\\d{2}:\\d{2}\\<\\.(\\d+)\\>\\s@\\d+\\.\\d+\\]\tWARNING\thello world");
ASSERT_TRUE(std::regex_search(content.value(), e));
}

TEST(log, rotation)
{
swLog_reset();
swLog_set_rotation(SW_LOG_ROTATION_DAILY);
swLog_open(file);

swLog_put(SW_LOG_WARNING, SW_STRL("hello world"));

ASSERT_EQ(access(swLog_get_file(), R_OK), -1);
ASSERT_EQ(errno, ENOENT);
ASSERT_EQ(access(swLog_get_real_file(), R_OK), 0);

swLog_close();
unlink(swLog_get_real_file());
}
11 changes: 10 additions & 1 deletion include/swoole.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,12 @@ enum swLog_level
SW_LOG_ERROR,
SW_LOG_NONE,
};

enum swLog_rotation_type
{
SW_LOG_ROTATION_SINGLE = 0,
SW_LOG_ROTATION_DAILY,
};
//-------------------------------------------------------------------------------
enum swWorker_status
{
Expand Down Expand Up @@ -1366,7 +1372,10 @@ void swLog_reopen(enum swBool_type redirect);
void swLog_close(void);
void swLog_reset();
void swLog_set_level(int lv);
void swLog_set_date_format(const char *format);
int swLog_set_date_format(const char *format);
void swLog_set_rotation(int rotation);
const char* swLog_get_real_file();
const char* swLog_get_file();
void swLog_set_date_with_microseconds(bool enable);

//----------------------Tool Function---------------------
Expand Down
93 changes: 83 additions & 10 deletions src/core/log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@
#include <chrono>

#define SW_LOG_BUFFER_SIZE (SW_ERROR_MSG_SIZE+256)
#define SW_LOG_DATE_STRLEN 64
#define SW_LOG_DATE_STRLEN 128
#define SW_LOG_DEFAULT_DATE_FORMAT "%F %T"

static bool opened = false;
static bool date_with_microseconds = false;
static std::string date_format = SW_LOG_DEFAULT_DATE_FORMAT;
static std::string log_file = "";
static std::string log_real_file;
static int log_rotation = SW_LOG_ROTATION_SINGLE;

static std::string swLog_gen_real_file(const std::string &file);

int swLog_open(const char *_log_file)
{
Expand All @@ -35,19 +39,34 @@ int swLog_open(const char *_log_file)
swLog_close();
}

SwooleG.log_fd = open(_log_file, O_APPEND | O_RDWR | O_CREAT, 0666);
log_file = _log_file;

if (log_rotation)
{
log_real_file = swLog_gen_real_file(log_file);
}
else
{
log_real_file = log_file;
}

SwooleG.log_fd = open(log_real_file.c_str(), O_APPEND | O_RDWR | O_CREAT, 0666);
if (SwooleG.log_fd < 0)
{
printf("open(%s) failed. Error: %s[%d]\n", _log_file, strerror(errno), errno);
printf("open(%s) failed. Error: %s[%d]\n", log_real_file.c_str(), strerror(errno), errno);
SwooleG.log_fd = STDOUT_FILENO;
opened = false;
log_file = "";
log_real_file = "";

return SW_ERR;
}
else
{
opened = true;

opened = true;
log_file = _log_file;

return SW_OK;
return SW_OK;
}
}

void swLog_close(void)
Expand All @@ -74,16 +93,40 @@ void swLog_set_level(int level)
SwooleG.log_level = level;
}

void swLog_set_rotation(int _rotation)
{
log_rotation = _rotation == 0 ? SW_LOG_ROTATION_SINGLE : SW_LOG_ROTATION_DAILY;
}

void swLog_reset()
{
date_format = SW_LOG_DEFAULT_DATE_FORMAT;
date_with_microseconds = false;
log_rotation = SW_LOG_ROTATION_SINGLE;
SwooleG.log_level = SW_LOG_INFO;
}

void swLog_set_date_format(const char *format)
int swLog_set_date_format(const char *format)
{
date_format = format;
char date_str[SW_LOG_DATE_STRLEN];
time_t now_sec;

now_sec = time(NULL);
size_t l_data_str = std::strftime(date_str, sizeof(date_str), format, std::localtime(&now_sec));

if (l_data_str == 0)
{
swoole_error_log(SW_LOG_WARNING, SW_ERROR_INVALID_PARAMS, "The date format string[length=%ld] is too long",
strlen(format));

return SW_ERR;
}
else
{
date_format = format;

return SW_OK;
}
}

void swLog_set_date_with_microseconds(bool enable)
Expand All @@ -100,6 +143,7 @@ void swLog_reopen(enum swBool_type redirect)
{
return;
}

std::string new_log_file(log_file);
swLog_close();
swLog_open(new_log_file.c_str());
Expand All @@ -112,6 +156,26 @@ void swLog_reopen(enum swBool_type redirect)
}
}

const char* swLog_get_real_file()
{
return log_real_file.c_str();
}

const char* swLog_get_file()
{
return log_file.c_str();
}

static std::string swLog_gen_real_file(const std::string &file)
{
char date_str[16];
auto now_sec = time(NULL);
size_t l_data_str = std::strftime(date_str, sizeof(date_str), "%Y%m%d", std::localtime(&now_sec));
std::string real_file = file + "." + std::string(date_str, l_data_str);

return real_file;
}

void swLog_put(int level, const char *content, size_t length)
{
const char *level_str;
Expand Down Expand Up @@ -141,7 +205,7 @@ void swLog_put(int level, const char *content, size_t length)
case SW_LOG_ERROR:
level_str = "ERROR";
break;
// case SW_LOG_INFO:
case SW_LOG_INFO:
default:
level_str = "INFO";
break;
Expand All @@ -151,6 +215,15 @@ void swLog_put(int level, const char *content, size_t length)
auto now_sec = std::chrono::system_clock::to_time_t(now);
size_t l_data_str = std::strftime(date_str, sizeof(date_str), date_format.c_str(), std::localtime(&now_sec));

if (log_rotation)
{
std::string tmp = swLog_gen_real_file(log_file);
if (tmp != log_real_file)
{
swLog_reopen(SW_FALSE);
}
}

if (date_with_microseconds)
{
auto now_us = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
Expand Down
7 changes: 7 additions & 0 deletions swoole.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ void php_swoole_set_global_option(HashTable *vht)
{
swLog_set_date_with_microseconds(zval_is_true(ztmp));
}
if (php_swoole_array_get_value(vht, "log_rotation", ztmp))
{
swLog_set_rotation(zval_get_long(ztmp));
}
if (php_swoole_array_get_value(vht, "display_errors", ztmp))
{
SWOOLE_G(display_errors) = zval_is_true(ztmp);
Expand Down Expand Up @@ -540,6 +544,9 @@ PHP_MINIT_FUNCTION(swoole)
SW_REGISTER_LONG_CONSTANT("SWOOLE_LOG_ERROR", SW_LOG_ERROR);
SW_REGISTER_LONG_CONSTANT("SWOOLE_LOG_NONE", SW_LOG_NONE);

SW_REGISTER_LONG_CONSTANT("SWOOLE_LOG_ROTATION_SINGLE", SW_LOG_ROTATION_SINGLE);
SW_REGISTER_LONG_CONSTANT("SWOOLE_LOG_ROTATION_DAILY", SW_LOG_ROTATION_DAILY);

SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_NONE", SW_IPC_NONE);
SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_UNIXSOCK", SW_IPC_UNIXSOCK);
SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_SOCKET", SW_IPC_SOCKET);
Expand Down

0 comments on commit 4562bd6

Please sign in to comment.