parent
d2f8e1d4e0
commit
749bb591fb
|
@ -6,6 +6,7 @@
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
|
@ -135,6 +136,101 @@ char* tr_logGetTimeStr(char* buf, size_t buflen)
|
||||||
****
|
****
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
void logAddImpl(
|
||||||
|
[[maybe_unused]] char const* file,
|
||||||
|
[[maybe_unused]] int line,
|
||||||
|
tr_log_level level,
|
||||||
|
[[maybe_unused]] std::string_view name,
|
||||||
|
std::string_view msg)
|
||||||
|
{
|
||||||
|
if (std::empty(msg))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const lock = std::lock_guard(message_mutex_);
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
OutputDebugStringA(tr_strvJoin(msg, "\r\n").c_str());
|
||||||
|
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
|
||||||
|
int prio;
|
||||||
|
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case TR_LOG_CRITICAL:
|
||||||
|
prio = ANDROID_LOG_FATAL;
|
||||||
|
break;
|
||||||
|
case TR_LOG_ERROR:
|
||||||
|
prio = ANDROID_LOG_ERROR;
|
||||||
|
break;
|
||||||
|
case TR_LOG_WARN:
|
||||||
|
prio = ANDROID_LOG_WARN;
|
||||||
|
break;
|
||||||
|
case TR_LOG_INFO:
|
||||||
|
prio = ANDROID_LOG_INFO;
|
||||||
|
break;
|
||||||
|
case TR_LOG_DEBUG:
|
||||||
|
prio = ANDROID_LOG_DEBUG;
|
||||||
|
break;
|
||||||
|
case TR_LOG_TRACE:
|
||||||
|
prio = ANDROID_LOG_VERBOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
__android_log_print(prio, "transmission", "%" TR_PRIsv, TR_PRIsv_ARG(msg));
|
||||||
|
#else
|
||||||
|
__android_log_print(prio, "transmission", "[%s:%d] %" TR_PRIsv, file, line, TR_PRIsv_ARG(msg));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
if (tr_logGetQueueEnabled())
|
||||||
|
{
|
||||||
|
auto* const newmsg = tr_new0(tr_log_message, 1);
|
||||||
|
newmsg->level = level;
|
||||||
|
newmsg->when = tr_time();
|
||||||
|
newmsg->message = tr_strvDup(msg);
|
||||||
|
newmsg->file = file;
|
||||||
|
newmsg->line = line;
|
||||||
|
newmsg->name = tr_strvDup(name);
|
||||||
|
|
||||||
|
*myQueueTail = newmsg;
|
||||||
|
myQueueTail = &newmsg->next;
|
||||||
|
++myQueueLength;
|
||||||
|
|
||||||
|
if (myQueueLength > TR_LOG_MAX_QUEUE_LENGTH)
|
||||||
|
{
|
||||||
|
tr_log_message* old = myQueue;
|
||||||
|
myQueue = old->next;
|
||||||
|
old->next = nullptr;
|
||||||
|
tr_logFreeQueue(old);
|
||||||
|
--myQueueLength;
|
||||||
|
TR_ASSERT(myQueueLength == TR_LOG_MAX_QUEUE_LENGTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char timestr[64];
|
||||||
|
|
||||||
|
tr_sys_file_t fp = tr_logGetFile();
|
||||||
|
|
||||||
|
if (fp == TR_BAD_SYS_FILE)
|
||||||
|
{
|
||||||
|
fp = tr_sys_file_get_std(TR_STD_SYS_FILE_ERR, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_logGetTimeStr(timestr, sizeof(timestr));
|
||||||
|
|
||||||
|
auto const out = !std::empty(name) ? tr_strvJoin("["sv, timestr, "] "sv, name, ": "sv, msg) :
|
||||||
|
tr_strvJoin("["sv, timestr, "] "sv, msg);
|
||||||
|
tr_sys_file_write_line(fp, out, nullptr);
|
||||||
|
tr_sys_file_flush(fp, nullptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void tr_logAddMessage(
|
void tr_logAddMessage(
|
||||||
[[maybe_unused]] char const* file,
|
[[maybe_unused]] char const* file,
|
||||||
[[maybe_unused]] int line,
|
[[maybe_unused]] int line,
|
||||||
|
@ -143,117 +239,54 @@ void tr_logAddMessage(
|
||||||
char const* fmt,
|
char const* fmt,
|
||||||
...)
|
...)
|
||||||
{
|
{
|
||||||
|
// message logging shouldn't affect errno
|
||||||
|
int const err = errno;
|
||||||
|
|
||||||
|
// skip unwanted messages
|
||||||
if (!tr_logLevelIsActive(level))
|
if (!tr_logLevelIsActive(level))
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int const err = errno; /* message logging shouldn't affect errno */
|
|
||||||
char buf[1024];
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
auto const lock = std::lock_guard(message_mutex_);
|
|
||||||
|
|
||||||
/* build the text message */
|
|
||||||
*buf = '\0';
|
|
||||||
va_start(ap, fmt);
|
|
||||||
int const buf_len = evutil_vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (buf_len < 0)
|
|
||||||
{
|
{
|
||||||
errno = err;
|
errno = err;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
auto const lock = std::lock_guard(message_mutex_);
|
||||||
|
|
||||||
if ((size_t)buf_len < sizeof(buf) - 3)
|
// don't log the same warning ad infinitum.
|
||||||
|
// it's not useful after some point.
|
||||||
|
bool last_one = false;
|
||||||
|
if (level == TR_LOG_CRITICAL || level == TR_LOG_ERROR || level == TR_LOG_WARN)
|
||||||
{
|
{
|
||||||
buf[buf_len + 0] = '\r';
|
static auto constexpr MaxRepeat = size_t{ 30 };
|
||||||
buf[buf_len + 1] = '\n';
|
static auto counts = new std::map<std::pair<char const*, int>, size_t>{};
|
||||||
buf[buf_len + 2] = '\0';
|
|
||||||
OutputDebugStringA(buf);
|
|
||||||
buf[buf_len + 0] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OutputDebugStringA(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__ANDROID__)
|
auto& count = (*counts)[std::make_pair(file, line)];
|
||||||
|
++count;
|
||||||
int prio;
|
last_one = count == MaxRepeat;
|
||||||
|
if (count > MaxRepeat)
|
||||||
switch (level)
|
|
||||||
{
|
|
||||||
case TR_LOG_ERROR:
|
|
||||||
prio = ANDROID_LOG_ERROR;
|
|
||||||
break;
|
|
||||||
case TR_LOG_INFO:
|
|
||||||
prio = ANDROID_LOG_INFO;
|
|
||||||
break;
|
|
||||||
case TR_LOG_DEBUG:
|
|
||||||
prio = ANDROID_LOG_DEBUG;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
prio = ANDROID_LOG_VERBOSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NDEBUG
|
|
||||||
__android_log_print(prio, "transmission", "%s", buf);
|
|
||||||
#else
|
|
||||||
__android_log_print(prio, "transmission", "[%s:%d] %s", file, line, buf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
if (!tr_str_is_empty(buf))
|
|
||||||
{
|
|
||||||
if (tr_logGetQueueEnabled())
|
|
||||||
{
|
{
|
||||||
auto* const newmsg = tr_new0(tr_log_message, 1);
|
errno = err;
|
||||||
newmsg->level = level;
|
return;
|
||||||
newmsg->when = tr_time();
|
|
||||||
newmsg->message = tr_strndup(buf, buf_len);
|
|
||||||
newmsg->file = file;
|
|
||||||
newmsg->line = line;
|
|
||||||
newmsg->name = tr_strvDup(name);
|
|
||||||
|
|
||||||
*myQueueTail = newmsg;
|
|
||||||
myQueueTail = &newmsg->next;
|
|
||||||
++myQueueLength;
|
|
||||||
|
|
||||||
if (myQueueLength > TR_LOG_MAX_QUEUE_LENGTH)
|
|
||||||
{
|
|
||||||
tr_log_message* old = myQueue;
|
|
||||||
myQueue = old->next;
|
|
||||||
old->next = nullptr;
|
|
||||||
tr_logFreeQueue(old);
|
|
||||||
--myQueueLength;
|
|
||||||
TR_ASSERT(myQueueLength == TR_LOG_MAX_QUEUE_LENGTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char timestr[64];
|
|
||||||
|
|
||||||
tr_sys_file_t fp = tr_logGetFile();
|
|
||||||
|
|
||||||
if (fp == TR_BAD_SYS_FILE)
|
|
||||||
{
|
|
||||||
fp = tr_sys_file_get_std(TR_STD_SYS_FILE_ERR, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
tr_logGetTimeStr(timestr, sizeof(timestr));
|
|
||||||
|
|
||||||
auto const out = !std::empty(name) ? tr_strvJoin("["sv, timestr, "] "sv, name, ": "sv, buf) :
|
|
||||||
tr_strvJoin("["sv, timestr, "] "sv, buf);
|
|
||||||
tr_sys_file_write_line(fp, out, nullptr);
|
|
||||||
tr_sys_file_flush(fp, nullptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
// build the message
|
||||||
|
auto buf = std::array<char, 2048>{};
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int const buf_len = evutil_vsnprintf(std::data(buf), std::size(buf), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (buf_len <= 0)
|
||||||
|
{
|
||||||
|
errno = err;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// log the messages
|
||||||
|
logAddImpl(file, line, level, name, std::data(buf));
|
||||||
|
if (last_one)
|
||||||
|
{
|
||||||
|
logAddImpl(file, line, level, "", _("Too many messages like this! I won't log this message anymore this session."));
|
||||||
|
}
|
||||||
|
|
||||||
errno = err;
|
errno = err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue