调整类重载,修复部分BUG,增加请求头检查
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <fmt/args.h>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <array>
|
||||
|
||||
// 格式化用的辅助函数
|
||||
|
||||
@@ -168,14 +169,174 @@ std::string uns::toBinary(unsigned long number, int bits)
|
||||
return "0b" + res;
|
||||
}
|
||||
|
||||
bool StartsWith(std::string_view str, std::string_view prefix)
|
||||
{
|
||||
if (str.size() < prefix.size())
|
||||
return false;
|
||||
return str.compare(0, prefix.size(), prefix) == 0;
|
||||
}
|
||||
|
||||
bool IsSizeUnit(std::string_view str)
|
||||
{
|
||||
if (str == "bit")
|
||||
return true;
|
||||
if (str.empty())
|
||||
return false;
|
||||
char last = str.back();
|
||||
return last == 'b' || last == 'B';
|
||||
}
|
||||
|
||||
bool IsNonNegativeInteger(std::string_view str, int& value)
|
||||
{
|
||||
if (str.empty())
|
||||
return false;
|
||||
int result = 0;
|
||||
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result);
|
||||
if (ec != std::errc() || ptr != str.data() + str.size())
|
||||
return false;
|
||||
if (result < 0)
|
||||
return false;
|
||||
value = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<std::string, int> ParseSizeFormat(std::string_view input)
|
||||
{
|
||||
constexpr std::pair<std::string_view, int> default_value = { "B", 2 };
|
||||
if (!StartsWith(input, "siz"))
|
||||
return { std::string(default_value.first), default_value.second };
|
||||
|
||||
std::string_view body = input.substr(3);
|
||||
if (body.empty() || body.front() != '-')
|
||||
return { std::string(default_value.first), default_value.second };
|
||||
|
||||
body.remove_prefix(1);
|
||||
size_t first_dash = body.find('-');
|
||||
if (first_dash == std::string_view::npos)
|
||||
{
|
||||
// siz-xx 或 siz-x
|
||||
if (IsSizeUnit(body))
|
||||
return { std::string(body), 2 };
|
||||
int precision = 0;
|
||||
if (IsNonNegativeInteger(body, precision))
|
||||
return { "B", precision };
|
||||
return { std::string(default_value.first), default_value.second };
|
||||
}
|
||||
|
||||
// siz-xx-y
|
||||
std::string_view unit = body.substr(0, first_dash);
|
||||
std::string_view precision_str = body.substr(first_dash + 1);
|
||||
if (!IsSizeUnit(unit))
|
||||
return { std::string(default_value.first), default_value.second };
|
||||
int precision = 0;
|
||||
if (!IsNonNegativeInteger(precision_str, precision))
|
||||
return { std::string(default_value.first), default_value.second };
|
||||
return { std::string(unit), precision };
|
||||
}
|
||||
|
||||
std::string FormatFileSize(size_t size, const std::string& unit, int precision)
|
||||
{
|
||||
static constexpr double K = 1024.0;
|
||||
static constexpr std::array<const char*, 9> units =
|
||||
{
|
||||
"B",
|
||||
"KB",
|
||||
"MB",
|
||||
"GB",
|
||||
"TB",
|
||||
"PB",
|
||||
"EB",
|
||||
"ZB",
|
||||
"YB"
|
||||
};
|
||||
|
||||
static constexpr std::array<const char*, 9> iec_units =
|
||||
{
|
||||
"B",
|
||||
"KIB",
|
||||
"MIB",
|
||||
"GIB",
|
||||
"TIB",
|
||||
"PIB",
|
||||
"EIB",
|
||||
"ZIB",
|
||||
"YIB"
|
||||
};
|
||||
|
||||
std::string input_unit = unit;
|
||||
std::transform(input_unit.begin(), input_unit.end(), input_unit.begin(), [] (unsigned char c)
|
||||
{
|
||||
return static_cast<char>(std::toupper(c));
|
||||
});
|
||||
|
||||
double bytes = static_cast<double>(size);
|
||||
if ((input_unit == "BIT") || (input_unit == "BITS"))
|
||||
bytes /= 8.0;
|
||||
else
|
||||
{
|
||||
size_t unit_index = 0;
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < units.size(); ++i)
|
||||
{
|
||||
if ((input_unit == units[i]) || (input_unit == iec_units[i]))
|
||||
{
|
||||
unit_index = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return std::format("{} {}", size, input_unit);
|
||||
for (size_t i = 0; i < unit_index; ++i)
|
||||
bytes *= K;
|
||||
}
|
||||
|
||||
size_t output_index = 0;
|
||||
while ((bytes >= K) && (output_index < (units.size() - 1)))
|
||||
{
|
||||
bytes /= K;
|
||||
++output_index;
|
||||
}
|
||||
if (precision < 0)
|
||||
precision = 0;
|
||||
|
||||
if (std::fabs(bytes - std::round(bytes)) < std::numeric_limits<double>::epsilon())
|
||||
return fmt::format("{} {}", static_cast<size_t>(std::round(bytes)), units[output_index]);
|
||||
|
||||
std::string value = fmt::format("{:.{}f}", bytes, precision);
|
||||
return fmt::format("{} {}", value, units[output_index]);
|
||||
}
|
||||
|
||||
std::string ServerLogger::GenerateLogHeader(uns::ServerLogLevel LogLevel)
|
||||
{
|
||||
std::string hstr;
|
||||
// 在日志行最开头添加对应日志级别的颜色控制码
|
||||
switch (LogLevel)
|
||||
{
|
||||
case uns::llDebug:
|
||||
hstr += "\033[36m"; // 青色
|
||||
break;
|
||||
case uns::llInfo:
|
||||
hstr += "\033[32m"; // 绿色
|
||||
break;
|
||||
case uns::llWarning:
|
||||
hstr += "\033[33m"; // 黄色
|
||||
break;
|
||||
case uns::llError:
|
||||
hstr += "\033[31m"; // 红色
|
||||
break;
|
||||
case uns::llFatal:
|
||||
hstr += "\033[1;37;41m"; // 亮白字 + 红底 (极度醒目)
|
||||
break;
|
||||
case uns::llTrace:
|
||||
default:
|
||||
break; // TRACE 与未知级别保持默认颜色,不追加转义码
|
||||
}
|
||||
time_t lt = time(NULL);
|
||||
tm* loctim = localtime(<);
|
||||
char timestr[250] = {};
|
||||
sprintf(timestr, "{%04d-%02d-%02d %02d:%02d:%02d} ", loctim->tm_year + 1900, loctim->tm_mon + 1, loctim->tm_mday, loctim->tm_hour, loctim->tm_min, loctim->tm_sec);
|
||||
hstr = timestr;
|
||||
hstr += timestr;
|
||||
switch (LogLevel)
|
||||
{
|
||||
case uns::llTrace:
|
||||
@@ -211,6 +372,40 @@ std::string ServerLogger::GenerateFileInfo(std::string filename, int line_num)
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// 高性能、100% 异常安全的 ANSI 颜色码剥离函数
|
||||
inline std::string StripAnsiCodes(const std::string& input) noexcept
|
||||
{
|
||||
std::string result;
|
||||
// 预分配内存,避免多次 Realloc(即使底层内存极度匮乏,noexcept 也会兜底)
|
||||
try
|
||||
{
|
||||
result.reserve(input.size());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// 极罕见的内存耗尽情况,直接降级返回原串或空串,绝不崩溃
|
||||
return input;
|
||||
}
|
||||
bool in_escape = false;
|
||||
for (char c : input)
|
||||
{
|
||||
if (c == '\033') // 遇到转义字符 '\033' (ESC)
|
||||
{
|
||||
in_escape = true;
|
||||
continue;
|
||||
}
|
||||
if (in_escape)
|
||||
{
|
||||
// ANSI 颜色控制码以 'm' 结尾(例如 \033[31m 或 \033[0m)
|
||||
if (c == 'm')
|
||||
in_escape = false;
|
||||
continue; // 跳过转义序列内的所有字符
|
||||
}
|
||||
result.push_back(c);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ServerLogger::WriteBatchToOutputs(const std::deque<std::string>& batch)
|
||||
{
|
||||
if (batch.empty())
|
||||
@@ -222,7 +417,7 @@ void ServerLogger::WriteBatchToOutputs(const std::deque<std::string>& batch)
|
||||
continue;
|
||||
std::fwrite(item.c_str(), 1, item.size(), stdout);
|
||||
if (LogStream.is_open())
|
||||
LogStream << item;
|
||||
LogStream << StripAnsiCodes(item);
|
||||
RotateIfNeeded(now, true);
|
||||
}
|
||||
std::fflush(stdout);
|
||||
@@ -355,6 +550,18 @@ void ServerLogger::RotateIfNeeded(std::time_t now, bool check_size_after_write)
|
||||
}
|
||||
}
|
||||
|
||||
size_t GetUnsignedInteger(const uns::LogVariant& value)
|
||||
{
|
||||
return std::visit([] (const auto& v) -> size_t
|
||||
{
|
||||
using T = std::decay_t<decltype(v)>;
|
||||
if constexpr (std::is_integral_v<T> && !std::is_same_v<T, char> && !std::is_same_v<T, bool>)
|
||||
return static_cast<size_t>(v);
|
||||
else
|
||||
return 0;
|
||||
}, value);
|
||||
}
|
||||
|
||||
inline std::string RewriteFormatString(const std::string& real_format, const uns::LogArg* args, size_t count, fmt::dynamic_format_arg_store<fmt::format_context>& store)
|
||||
{
|
||||
std::string out;
|
||||
@@ -366,14 +573,14 @@ inline std::string RewriteFormatString(const std::string& real_format, const uns
|
||||
// escaped {{
|
||||
if ((c == '{') && ((i + 1) < real_format.size()) && (real_format[i + 1] == '{'))
|
||||
{
|
||||
out += '{';
|
||||
out += "{{";
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
// escaped }}
|
||||
if ((c == '}') && ((i + 1) < real_format.size()) && (real_format[i + 1] == '}'))
|
||||
{
|
||||
out += '}';
|
||||
out += "}}";
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
@@ -407,6 +614,11 @@ inline std::string RewriteFormatString(const std::string& real_format, const uns
|
||||
else
|
||||
store.push_back(args[arg_index]);
|
||||
}
|
||||
else if (StartsWith(inside, "siz"))
|
||||
{
|
||||
auto [u, p] = ParseSizeFormat(inside);
|
||||
store.push_back(FormatFileSize(GetUnsignedInteger(arg.value), u, p));
|
||||
}
|
||||
else
|
||||
store.push_back(args[arg_index]);
|
||||
}
|
||||
@@ -421,6 +633,9 @@ inline std::string RewriteFormatString(const std::string& real_format, const uns
|
||||
++i;
|
||||
}
|
||||
|
||||
// debug
|
||||
// std::string debug = "[RewriteFormatString] RAW=|" + real_format + "|, OUT=|" + out + "|\n";
|
||||
// std::fwrite(debug.c_str(), 1, debug.size(), stdout);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -456,7 +671,7 @@ void ServerLogger::LogImpl(uns::ServerLogLevel level, const std::string& format,
|
||||
|
||||
std::string logstr = GenerateLogHeader(level);
|
||||
logstr += formatted;
|
||||
logstr += "\n";
|
||||
logstr += "\033[0m\n";
|
||||
|
||||
std::unique_lock<std::mutex> lock(QueueMutex);
|
||||
LogQueue.push_back(logstr);
|
||||
@@ -497,7 +712,7 @@ void ServerLogger::LogFImpl(uns::ServerLogLevel level, const std::string& filena
|
||||
|
||||
std::string logstr = GenerateLogHeader(level);
|
||||
logstr += formatted;
|
||||
logstr += "\n";
|
||||
logstr += "\033[0m\n";
|
||||
|
||||
std::unique_lock<std::mutex> lock(QueueMutex);
|
||||
LogQueue.push_back(logstr);
|
||||
@@ -527,7 +742,7 @@ void ServerLogger::LogFMTImpl(uns::ServerLogLevel level, const std::string& form
|
||||
|
||||
std::string logstr = GenerateLogHeader(level);
|
||||
logstr += formatted;
|
||||
logstr += "\n";
|
||||
logstr += "\033[0m\n";
|
||||
|
||||
std::unique_lock<std::mutex> lock(QueueMutex);
|
||||
LogQueue.push_back(logstr);
|
||||
@@ -557,7 +772,7 @@ void ServerLogger::LogFMT_FImpl(uns::ServerLogLevel level, const std::string& fi
|
||||
|
||||
std::string logstr = GenerateLogHeader(level);
|
||||
logstr += formatted;
|
||||
logstr += "\n";
|
||||
logstr += "\033[0m\n";
|
||||
|
||||
std::unique_lock<std::mutex> lock(QueueMutex);
|
||||
LogQueue.push_back(logstr);
|
||||
|
||||
Reference in New Issue
Block a user