Skip to content

Commit bfe489e

Browse files
committed
log: cache recent threads up to a day
In general, a pthread implementation reuses thread ids routinely so the circular_buffer is there to help us see what the thread name was historically (capped at 4 entries). However, to guard against this map from growing without bound, discard entries that are more than a day old. This would happen if a thread logged an Entry and has since disappeared for more than a day. Signed-off-by: Patrick Donnelly <[email protected]>
1 parent 7de5af5 commit bfe489e

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

src/log/Log.cc

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ void Log::_flush_logbuf()
373373

374374
void Log::_flush(EntryVector& t, bool crash)
375375
{
376+
auto now = mono_clock::now();
376377
long len = 0;
377378
if (t.empty()) {
378379
assert(m_log_buf.empty());
@@ -444,10 +445,29 @@ void Log::_flush(EntryVector& t, bool crash)
444445
m_journald->log_entry(e);
445446
}
446447

448+
{
449+
auto [it, _] = m_recent_thread_names.try_emplace(e.m_thread, now, DEFAULT_MAX_THREAD_NAMES);
450+
auto& [t, names] = it->second;
451+
if (names.size() == 0 || names.front() != e.m_thread_name.data()) {
452+
names.push_front(e.m_thread_name.data());
453+
}
454+
t = now;
455+
}
456+
447457
m_recent.push_back(std::move(e));
448458
}
449459
t.clear();
450460

461+
for (auto it = m_recent_thread_names.begin(); it != m_recent_thread_names.end(); ) {
462+
auto t = it->second.first;
463+
auto since = now - t;
464+
if (since > std::chrono::seconds(60*60*24)) {
465+
it = m_recent_thread_names.erase(it);
466+
} else {
467+
++it;
468+
}
469+
}
470+
451471
_flush_logbuf();
452472
}
453473

@@ -494,15 +514,10 @@ void Log::dump_recent()
494514
_flush(m_flush, false);
495515

496516
_log_message("--- begin dump of recent events ---", true);
497-
std::map<pthread_t, std::set<std::string> > recent_pthread_ids;
498517
{
499518
EntryVector t;
500519
t.insert(t.end(), std::make_move_iterator(m_recent.begin()), std::make_move_iterator(m_recent.end()));
501520
m_recent.clear();
502-
for (const auto& e : t) {
503-
auto& set = recent_pthread_ids[e.m_thread];
504-
set.insert(e.m_thread_name.data());
505-
}
506521
_flush(t, true);
507522
}
508523

@@ -517,13 +532,14 @@ void Log::dump_recent()
517532
m_stderr_log, m_stderr_crash), true);
518533

519534
_log_message("--- pthread ID / name mapping for recent threads ---", true);
520-
for (const auto& [pthread_id, pthread_names] : recent_pthread_ids)
535+
for (const auto& [tid, t_names] : m_recent_thread_names)
521536
{
537+
[[maybe_unused]] auto [t, names] = t_names;
522538
// we want the ID to be printed in the same format as we use for a log entry.
523539
// The reason is easier grepping.
524540
auto msg = fmt::format(" {:x} / {}",
525-
tid_to_int(pthread_id),
526-
fmt::join(pthread_names, ", "));
541+
tid_to_int(tid),
542+
fmt::join(names, ", "));
527543
_log_message(msg, true);
528544
}
529545

src/log/Log.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
#include <boost/circular_buffer.hpp>
88

99
#include <condition_variable>
10+
#include <map>
1011
#include <memory>
1112
#include <mutex>
1213
#include <queue>
1314
#include <string>
1415
#include <string_view>
1516

1617
#include "common/Thread.h"
18+
#include "common/ceph_time.h"
1719
#include "common/likely.h"
1820

1921
#include "log/Entry.h"
@@ -86,9 +88,14 @@ class Log : private Thread
8688

8789
private:
8890
using EntryRing = boost::circular_buffer<ConcreteEntry>;
91+
using mono_clock = ceph::coarse_mono_clock;
92+
using mono_time = ceph::coarse_mono_time;
93+
94+
using RecentThreadNames = std::map<pthread_t, std::pair<mono_time, boost::circular_buffer<std::string> > >;
8995

9096
static const std::size_t DEFAULT_MAX_NEW = 100;
9197
static const std::size_t DEFAULT_MAX_RECENT = 10000;
98+
static constexpr std::size_t DEFAULT_MAX_THREAD_NAMES = 4;
9299

93100
Log **m_indirect_this;
94101

@@ -102,6 +109,7 @@ class Log : private Thread
102109
pthread_t m_queue_mutex_holder;
103110
pthread_t m_flush_mutex_holder;
104111

112+
RecentThreadNames m_recent_thread_names; // protected by m_flush_mutex
105113
EntryVector m_new; ///< new entries
106114
EntryRing m_recent; ///< recent (less new) entries we've already written at low detail
107115
EntryVector m_flush; ///< entries to be flushed (here to optimize heap allocations)

0 commit comments

Comments
 (0)