Skip to content

Commit 5ca3587

Browse files
committed
!36 feat(main):1.11.14, 为main框架添加log.max_len参数;同时添加/log/max_len终端命令
* feat(main):1.11.14, 为main框架添加log.max_len参数;同时添加/log/max_len终端命令 * fix(base,log):1.11.13, 解决日志内容过长,不输出的问题 * tidy(base): 优化log_impl.cpp格式,加注释 * fix(base): 实现日志过长,进行截断打印的功能,解决日志内容过长丢弃的问题
1 parent 988c58e commit 5ca3587

23 files changed

+293
-176
lines changed

modules/base/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ set(TBOX_LIBRARY_NAME tbox_base)
3030
set(TBOX_BASE_HEADERS
3131
version.h
3232
log.h
33-
log_imp.h
33+
log_impl.h
3434
log_output.h
3535
defines.h
3636
scope_exit.hpp
@@ -50,7 +50,7 @@ set(TBOX_BASE_HEADERS
5050

5151
set(TBOX_BASE_SOURCES
5252
version.cpp
53-
log_imp.cpp
53+
log_impl.cpp
5454
log_output.cpp
5555
backtrace.cpp
5656
catch_throw.cpp

modules/base/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ HAVE_EXECINFO_H ?= yes
3131
HEAD_FILES = \
3232
version.h \
3333
log.h \
34-
log_imp.h \
34+
log_impl.h \
3535
log_output.h \
3636
defines.h \
3737
scope_exit.hpp \
@@ -51,7 +51,7 @@ HEAD_FILES = \
5151

5252
CPP_SRC_FILES = \
5353
version.cpp \
54-
log_imp.cpp \
54+
log_impl.cpp \
5555
log_output.cpp \
5656
backtrace.cpp \
5757
catch_throw.cpp \

modules/base/log_imp.cpp modules/base/log_impl.cpp

+51-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* project authors may be found in the CONTRIBUTORS.md file in the root
1818
* of the source tree.
1919
*/
20-
#include "log_imp.h"
20+
#include "log_impl.h"
2121

2222
#include <sys/time.h>
2323
#include <sys/syscall.h>
@@ -29,7 +29,8 @@
2929
#include <mutex>
3030

3131
namespace {
32-
constexpr uint32_t LOG_MAX_LEN = (100 << 10);
32+
33+
size_t _LogTextMaxLength = (100 << 10); //! 限定单条日志最大长度,默认为100KB
3334

3435
std::mutex _lock;
3536
uint32_t _id_alloc = 0;
@@ -76,8 +77,8 @@ const char LOG_LEVEL_LEVEL_CODE[LOG_LEVEL_MAX] = {
7677
};
7778

7879
const char* LOG_LEVEL_COLOR_CODE[LOG_LEVEL_MAX] = {
79-
"31", //! FATAL
80-
"7;91", //! ERROR 文字黑,背景亮红
80+
"7;91", //! FATAL 文字黑,背景亮红
81+
"31", //! ERROR
8182
"7;93", //! WARN 文字黑,背景亮黄
8283
"93", //! NOTICE 亮黄
8384
"7;92", //! IMPORTANT 文字黑,背景亮绿
@@ -86,6 +87,22 @@ const char* LOG_LEVEL_COLOR_CODE[LOG_LEVEL_MAX] = {
8687
"35", //! TRACE 洋葱红
8788
};
8889

90+
extern "C" {
91+
92+
size_t LogSetMaxLength(size_t max_len)
93+
{
94+
std::lock_guard<std::mutex> lg(_lock);
95+
auto origin_len = _LogTextMaxLength;
96+
_LogTextMaxLength = max_len;
97+
return origin_len;
98+
}
99+
100+
size_t LogGetMaxLength()
101+
{
102+
std::lock_guard<std::mutex> lg(_lock);
103+
return _LogTextMaxLength;
104+
}
105+
89106
/**
90107
* \brief 日志格式化打印接口的实现
91108
*
@@ -120,42 +137,66 @@ void LogPrintfFunc(const char *module_id, const char *func_name, const char *fil
120137
.level = level,
121138
.text_len = 0,
122139
.text_ptr = nullptr,
140+
.text_trunc = false,
123141
};
124142

125143
if (fmt != nullptr) {
126144
if (with_args) {
127-
uint32_t buff_size = 1024; //! 初始大小,可应对绝大数情况
145+
uint32_t buff_size = std::min(2048lu, _LogTextMaxLength) + 1;
146+
128147
for (;;) {
129148
va_list args;
130149
char buffer[buff_size];
131150

132151
va_start(args, fmt);
133-
size_t len = vsnprintf(buffer, buff_size, fmt, args);
152+
size_t len = 0;
153+
154+
len = ::vsnprintf(buffer, buff_size, fmt, args);
155+
156+
if (content.text_trunc)
157+
len = _LogTextMaxLength;
158+
134159
va_end(args);
135160

161+
//! 如果buffer的空间够用,则正常派发日志
162+
//! 否则要对buffer空间进行扩张,或是对内容进行截断
136163
if (len < buff_size) {
137164
content.text_len = len;
138165
content.text_ptr = buffer;
139166
Dispatch(content);
140167
break;
141168
}
142169

143-
buff_size = len + 1; //! 要多留一个结束符 \0,否则 vsnprintf() 会少一个字符
144-
if (buff_size > LOG_MAX_LEN) {
145-
std::cerr << "WARN: log text length " << buff_size << ", too long!" << std::endl;
146-
break;
170+
//! 没有超过MaxLength,则进行扩张
171+
if (len <= _LogTextMaxLength) {
172+
buff_size = len + 1; //! 要多留一个结束符 \0,否则 vsnprintf() 会少一个字符
173+
174+
} else { //! 否则进行截断处理
175+
buff_size = _LogTextMaxLength + 1; //! 同上
176+
content.text_trunc = true;
147177
}
148178
}
179+
149180
} else {
150181
content.text_len = ::strlen(fmt);
182+
183+
//! 如果超出最大长度,要限制
184+
if (content.text_len > _LogTextMaxLength) {
185+
content.text_len = _LogTextMaxLength;
186+
content.text_trunc = true;
187+
}
188+
151189
content.text_ptr = fmt;
152190
Dispatch(content);
153191
}
192+
154193
} else {
155194
Dispatch(content);
156195
}
157196
}
158197

198+
}
199+
159200
uint32_t LogAddPrintfFunc(LogPrintfFuncType func, void *ptr)
160201
{
161202
std::lock_guard<std::mutex> lg(_lock);

modules/base/log_imp.h modules/base/log_impl.h

+10-3
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
* project authors may be found in the CONTRIBUTORS.md file in the root
1818
* of the source tree.
1919
*/
20-
#ifndef TBOX_BASE_LOG_IMP_20180201
21-
#define TBOX_BASE_LOG_IMP_20180201
20+
#ifndef TBOX_BASE_LOG_IMPL_20180201
21+
#define TBOX_BASE_LOG_IMPL_20180201
2222

2323
/**
2424
* 本文件只声明了函数 LogSetPrintfFunc() 该函数用于指定日志输出函数
@@ -27,6 +27,7 @@
2727

2828
#include <stdarg.h>
2929
#include <stdint.h>
30+
#include <stddef.h>
3031

3132
#include "log.h"
3233

@@ -49,6 +50,7 @@ struct LogContent {
4950
int level; //!< 日志等级
5051
uint32_t text_len; //!< 内容大小
5152
const char *text_ptr; //!< 内容地址
53+
bool text_trunc; //!< 是否截断
5254
};
5355

5456
//! 日志等级颜色表
@@ -58,6 +60,11 @@ extern const char* LOG_LEVEL_COLOR_CODE[LOG_LEVEL_MAX];
5860
//! 定义日志输出函数
5961
typedef void (*LogPrintfFuncType)(const LogContent *content, void *ptr);
6062

63+
//! 设置最大长度
64+
size_t LogSetMaxLength(size_t max_len);
65+
//! 获取最大长度
66+
size_t LogGetMaxLength();
67+
6168
//! 添加与删除日志输出函数
6269
uint32_t LogAddPrintfFunc(LogPrintfFuncType func, void *ptr);
6370
bool LogRemovePrintfFunc(uint32_t id);
@@ -66,4 +73,4 @@ bool LogRemovePrintfFunc(uint32_t id);
6673
}
6774
#endif
6875

69-
#endif //TBOX_BASE_LOG_IMP_20180201
76+
#endif //TBOX_BASE_LOG_IMPL_20180201

modules/base/log_output.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#include <mutex>
3131
#include <iostream>
3232

33-
#include "log_imp.h"
33+
#include "log_impl.h"
3434

3535
#define TIMESTAMP_STRING_SIZE 27
3636

@@ -64,7 +64,10 @@ namespace {
6464
printf("%s() ", content->func_name);
6565

6666
if (content->text_len > 0)
67-
printf("%s ", content->text_ptr);
67+
printf("%.*s ", content->text_len, content->text_ptr);
68+
69+
if (content->text_trunc == 1)
70+
printf("(TRUNCATED) ");
6871

6972
if (content->file_name != nullptr)
7073
printf("-- %s:%d", content->file_name, content->line);

modules/base/log_output_test.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020
#include <gtest/gtest.h>
2121
#include "log.h"
22+
#include "log_impl.h"
2223
#include "log_output.h"
2324

2425
TEST(Log, AllLevel)
@@ -60,3 +61,21 @@ TEST(Log, error)
6061
LogErrno(1, "has value:%d", 123);
6162
LogOutput_Disable();
6263
}
64+
65+
TEST(Log, Truncate)
66+
{
67+
LogOutput_Enable();
68+
69+
std::string long_str(1025, 'l');
70+
std::string normal_str(1024, 'n');
71+
72+
auto origin_len = LogSetMaxLength(1024);
73+
74+
LogInfo(normal_str.c_str());
75+
LogNotice(long_str.c_str());
76+
LogInfo("%s", normal_str.c_str());
77+
LogNotice("%s", long_str.c_str());
78+
79+
LogSetMaxLength(origin_len);
80+
LogOutput_Disable();
81+
}

modules/log/async_file_sink.cpp

+8-10
Original file line numberDiff line numberDiff line change
@@ -91,30 +91,28 @@ void AsyncFileSink::updateInnerValues()
9191
CHECK_CLOSE_RESET_FD(fd_);
9292
}
9393

94-
void AsyncFileSink::appendLog(const char *str, size_t len)
94+
void AsyncFileSink::endline()
9595
{
96-
buffer_.reserve(buffer_.size() + len - 1);
97-
std::back_insert_iterator<std::vector<char>> back_insert_iter(buffer_);
98-
std::copy(str, str + len - 1, back_insert_iter);
96+
cache_.push_back('\n');
9997
}
10098

101-
void AsyncFileSink::flushLog()
99+
void AsyncFileSink::flush()
102100
{
103101
if (pid_ == 0 || !checkAndCreateLogFile())
104102
return;
105103

106-
auto wsize = ::write(fd_, buffer_.data(), buffer_.size());
107-
if (wsize != static_cast<ssize_t>(buffer_.size())) {
104+
auto wsize = ::write(fd_, cache_.data(), cache_.size());
105+
if (wsize != static_cast<ssize_t>(cache_.size())) {
108106
cerr << "Err: write file error." << endl;
109107
return;
110108
}
111109

112-
total_write_size_ += buffer_.size();
113-
114-
buffer_.clear();
110+
total_write_size_ += cache_.size();
115111

116112
if (total_write_size_ >= file_max_size_)
117113
CHECK_CLOSE_RESET_FD(fd_);
114+
115+
cache_.clear();
118116
}
119117

120118
bool AsyncFileSink::checkAndCreateLogFile()

modules/log/async_file_sink.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ class AsyncFileSink : public AsyncSink {
4444
protected:
4545
void updateInnerValues();
4646

47-
virtual void appendLog(const char *str, size_t len) override;
48-
virtual void flushLog() override;
47+
virtual void endline() override;
48+
virtual void flush() override;
4949

5050
bool checkAndCreateLogFile();
5151

modules/log/async_file_sink_test.cpp

+17-30
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,6 @@ TEST(AsyncFileSink, AllLevel)
6666
ch.cleanup();
6767
}
6868

69-
TEST(AsyncFileSink, LongString)
70-
{
71-
AsyncFileSink ch;
72-
73-
ch.setFilePath("/tmp/tbox");
74-
ch.setFilePrefix("test");
75-
ch.enable();
76-
77-
for (size_t s = 900; s < 1200; ++s) {
78-
std::string tmp(s, 'z');
79-
LogInfo("%s", tmp.c_str());
80-
}
81-
82-
std::string tmp(4096, 'x');
83-
LogInfo("%s", tmp.c_str());
84-
85-
ch.cleanup();
86-
}
87-
8869
TEST(AsyncFileSink, FileDivide)
8970
{
9071
AsyncFileSink ch;
@@ -116,28 +97,34 @@ TEST(AsyncFileSink, ParamNormalize)
11697
ch.cleanup();
11798
}
11899

119-
TEST(AsyncFileSink, CreateFileInInit)
100+
TEST(AsyncFileSink, RemoveLogFileDuringWriting)
120101
{
121102
AsyncFileSink ch;
122103
ch.setFilePath("/tmp/tbox");
123-
ch.setFilePrefix("create_file_init");
104+
ch.setFilePrefix("remove_log_file_during_writing");
124105
ch.enable();
125-
std::string name = ch.currentFilename();
126-
EXPECT_TRUE(util::fs::IsFileExist(name));
106+
util::fs::RemoveFile(ch.currentFilename());
107+
LogInfo("Hello");
108+
std::this_thread::sleep_for(std::chrono::seconds(1));
109+
EXPECT_TRUE(util::fs::IsFileExist(ch.currentFilename()));
127110
ch.cleanup();
128111
}
129112

130-
TEST(AsyncFileSink, RemoveLogFileDuringWriting)
113+
TEST(AsyncFileSink, Truncate)
131114
{
115+
auto origin_len = LogSetMaxLength(100);
116+
132117
AsyncFileSink ch;
133118
ch.setFilePath("/tmp/tbox");
134-
ch.setFilePrefix("remove_log_file_during_writing");
119+
ch.setFilePrefix("truncate");
135120
ch.enable();
136121
util::fs::RemoveFile(ch.currentFilename());
137-
LogInfo("Hello");
138-
std::this_thread::sleep_for(std::chrono::seconds(1));
139-
EXPECT_TRUE(util::fs::IsFileExist(ch.currentFilename()));
122+
123+
std::string tmp(200, 'x');
124+
LogInfo("%s", tmp.c_str());
125+
140126
ch.cleanup();
127+
LogSetMaxLength(origin_len);
141128
}
142129

143130
#include <tbox/event/loop.h>
@@ -157,10 +144,10 @@ TEST(AsyncFileSink, Benchmark)
157144
function<void()> func = [&] {
158145
for (int i = 0; i < 100; ++i)
159146
LogInfo("%d %s", i, tmp.c_str());
160-
sp_loop->run(func);
147+
sp_loop->runNext(func);
161148
counter += 100;
162149
};
163-
sp_loop->run(func);
150+
sp_loop->runNext(func);
164151

165152
sp_loop->exitLoop(chrono::seconds(10));
166153
sp_loop->runLoop();

0 commit comments

Comments
 (0)