Skip to content

Commit 1bef33f

Browse files
Merge pull request #12452 from ClickHouse/system-log-dont-log-under-mutex
SystemLog: do not log under mutex
2 parents 000b197 + dac5e1c commit 1bef33f

1 file changed

Lines changed: 40 additions & 30 deletions

File tree

src/Interpreters/SystemLog.h

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -233,46 +233,56 @@ void SystemLog<LogElement>::add(const LogElement & element)
233233
/// Otherwise the tests like 01017_uniqCombined_memory_usage.sql will be flacky.
234234
auto temporarily_disable_memory_tracker = getCurrentMemoryTrackerActionLock();
235235

236-
std::lock_guard lock(mutex);
236+
/// Should not log messages under mutex.
237+
bool queue_is_half_full = false;
237238

238-
if (is_shutdown)
239-
return;
240-
241-
if (queue.size() == DBMS_SYSTEM_LOG_QUEUE_SIZE / 2)
242239
{
243-
// The queue more than half full, time to flush.
244-
// We only check for strict equality, because messages are added one
245-
// by one, under exclusive lock, so we will see each message count.
246-
// It is enough to only wake the flushing thread once, after the message
247-
// count increases past half available size.
248-
const uint64_t queue_end = queue_front_index + queue.size();
249-
if (requested_flush_before < queue_end)
250-
requested_flush_before = queue_end;
240+
std::unique_lock lock(mutex);
251241

252-
flush_event.notify_all();
253-
LOG_INFO(log, "Queue is half full for system log '{}'.", demangle(typeid(*this).name()));
254-
}
242+
if (is_shutdown)
243+
return;
255244

256-
if (queue.size() >= DBMS_SYSTEM_LOG_QUEUE_SIZE)
257-
{
258-
// Ignore all further entries until the queue is flushed.
259-
// Log a message about that. Don't spam it -- this might be especially
260-
// problematic in case of trace log. Remember what the front index of the
261-
// queue was when we last logged the message. If it changed, it means the
262-
// queue was flushed, and we can log again.
263-
if (queue_front_index != logged_queue_full_at_index)
245+
if (queue.size() == DBMS_SYSTEM_LOG_QUEUE_SIZE / 2)
264246
{
265-
logged_queue_full_at_index = queue_front_index;
247+
queue_is_half_full = true;
248+
249+
// The queue more than half full, time to flush.
250+
// We only check for strict equality, because messages are added one
251+
// by one, under exclusive lock, so we will see each message count.
252+
// It is enough to only wake the flushing thread once, after the message
253+
// count increases past half available size.
254+
const uint64_t queue_end = queue_front_index + queue.size();
255+
if (requested_flush_before < queue_end)
256+
requested_flush_before = queue_end;
257+
258+
flush_event.notify_all();
259+
}
266260

267-
// TextLog sets its logger level to 0, so this log is a noop and
268-
// there is no recursive logging.
269-
LOG_ERROR(log, "Queue is full for system log '{}' at {}", demangle(typeid(*this).name()), queue_front_index);
261+
if (queue.size() >= DBMS_SYSTEM_LOG_QUEUE_SIZE)
262+
{
263+
// Ignore all further entries until the queue is flushed.
264+
// Log a message about that. Don't spam it -- this might be especially
265+
// problematic in case of trace log. Remember what the front index of the
266+
// queue was when we last logged the message. If it changed, it means the
267+
// queue was flushed, and we can log again.
268+
if (queue_front_index != logged_queue_full_at_index)
269+
{
270+
logged_queue_full_at_index = queue_front_index;
271+
272+
// TextLog sets its logger level to 0, so this log is a noop and
273+
// there is no recursive logging.
274+
lock.unlock();
275+
LOG_ERROR(log, "Queue is full for system log '{}' at {}", demangle(typeid(*this).name()), queue_front_index);
276+
}
277+
278+
return;
270279
}
271280

272-
return;
281+
queue.push_back(element);
273282
}
274283

275-
queue.push_back(element);
284+
if (queue_is_half_full)
285+
LOG_INFO(log, "Queue is half full for system log '{}'.", demangle(typeid(*this).name()));
276286
}
277287

278288

0 commit comments

Comments
 (0)