Skip to content

Commit

Permalink
YT-23050: Make logger tolerant to logging during its own initialization
Browse files Browse the repository at this point in the history
commit_hash:e40178974c2ab0b3d9d3c40f4f80cd0d80f4681e
  • Loading branch information
E1pp committed Oct 14, 2024
1 parent 5efb84f commit c1640e3
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 23 deletions.
121 changes: 100 additions & 21 deletions yt/yt/core/logging/log_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,26 +348,52 @@ class TLogManager::TImpl
RegisterWriterFactory(TString(TStderrLogWriterConfig::WriterType), GetStderrLogWriterFactory());
}

bool IsInitialized() const
{
return InitializationFinished_.Test();
}

void Initialize()
{
std::call_once(Initialized_, [&] {
// NB: Cannot place this logic inside ctor since it may boot up Compression threads unexpected
// and these will try to access TLogManager instance causing a deadlock.
try {
if (auto config = TLogManagerConfig::TryCreateFromEnv()) {
DoUpdateConfig(config, /*fromEnv*/ true);
}
} catch (const std::exception& ex) {
fprintf(stderr, "Error configuring logging from environment variables\n%s\n",
ex.what());
[[likely]] if (InitializationFinished_.Test()) {
// Don't bother doing syscalls on a hot path.
return;
}

// Sync is done via event so there is no need for stronger memory orders.
// Case of recursive call is alright, because there sync is done via sequenced-before ordering.
[[likely]] if (InitializationStarted_.exchange(true, std::memory_order::relaxed)) {
NThreading::TThreadId initializerThreadId = NThreading::InvalidThreadId;
while (initializerThreadId == NThreading::InvalidThreadId) {
initializerThreadId = InitializerThreadId_.load(std::memory_order::relaxed);
}
if (GetCurrentThreadId() == initializerThreadId) {
// Recursive call -- bail out.
return;
}
// Another thread -- now wait for real.
InitializationFinished_.Wait();
return;
}
InitializerThreadId_.store(GetCurrentThreadId(), std::memory_order::relaxed);

if (!IsConfiguredFromEnv()) {
DoUpdateConfig(TLogManagerConfig::CreateDefault(), /*fromEnv*/ false);
// NB: Cannot place this logic inside ctor since it may boot up Compression threads unexpected
// and these will try to access TLogManager instance causing a deadlock.
try {
if (auto config = TLogManagerConfig::TryCreateFromEnv()) {
DoUpdateConfig(config, /*fromEnv*/ true);
}
} catch (const std::exception& ex) {
fprintf(stderr, "Error configuring logging from environment variables\n%s\n",
ex.what());
}

SystemCategory_ = GetCategory(SystemLoggingCategoryName);
});
if (!IsConfiguredFromEnv()) {
DoUpdateConfig(TLogManagerConfig::CreateDefault(), /*fromEnv*/ false);
}

SystemCategory_ = GetCategory(SystemLoggingCategoryName);
InitializationFinished_.NotifyAll();
}

void Configure(INodePtr node)
Expand Down Expand Up @@ -1347,7 +1373,10 @@ class TLogManager::TImpl
std::atomic<ui64> HighBacklogWatermark_ = Max<ui64>();
std::atomic<ui64> LowBacklogWatermark_ = Max<ui64>();

std::once_flag Initialized_;
std::atomic<bool> InitializationStarted_ = false;
std::atomic<NThreading::TThreadId> InitializerThreadId_ = NThreading::InvalidThreadId;
NThreading::TEvent InitializationFinished_;

std::once_flag Started_;
std::atomic<bool> Suspended_ = false;
std::atomic<bool> ScheduledOutOfBand_ = false;
Expand Down Expand Up @@ -1431,105 +1460,155 @@ TLogManager::~TLogManager() = default;
TLogManager* TLogManager::Get()
{
auto* logManager = LeakySingleton<TLogManager>();
logManager->Initialize();
logManager->Impl_->Initialize();
return logManager;
}

void TLogManager::Configure(TLogManagerConfigPtr config, bool sync)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->Configure(std::move(config), /*fromEnv*/ false, sync);
}

void TLogManager::ConfigureFromEnv()
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->ConfigureFromEnv();
}

bool TLogManager::IsConfiguredFromEnv()
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return false;
}
return Impl_->IsConfiguredFromEnv();
}

void TLogManager::Shutdown()
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->Shutdown();
}

int TLogManager::GetVersion() const
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return 0;
}
return Impl_->GetVersion();
}

bool TLogManager::GetAbortOnAlert() const
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return false;
}
return Impl_->GetAbortOnAlert();
}

const TLoggingCategory* TLogManager::GetCategory(TStringBuf categoryName)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return nullptr;
}
return Impl_->GetCategory(categoryName);
}

void TLogManager::UpdateCategory(TLoggingCategory* category)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->UpdateCategory(category);
}

void TLogManager::UpdateAnchor(TLoggingAnchor* anchor)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->UpdateAnchor(anchor);
}

void TLogManager::RegisterStaticAnchor(TLoggingAnchor* anchor, ::TSourceLocation sourceLocation, TStringBuf anchorMessage)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->RegisterStaticAnchor(anchor, sourceLocation, anchorMessage);
}

TLoggingAnchor* TLogManager::RegisterDynamicAnchor(TString anchorMessage)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return nullptr;
}
return Impl_->RegisterDynamicAnchor(std::move(anchorMessage));
}

void TLogManager::RegisterWriterFactory(const TString& typeName, const ILogWriterFactoryPtr& factory)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->RegisterWriterFactory(typeName, factory);
}

void TLogManager::UnregisterWriterFactory(const TString& typeName)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->UnregisterWriterFactory(typeName);
}

void TLogManager::Enqueue(TLogEvent&& event)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
Cerr << NYT::Format("Trying to log event during logger initialization -- skipping") << Endl;
return;
}
Impl_->Enqueue(std::move(event));
}

void TLogManager::Reopen()
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->Reopen();
}

void TLogManager::EnableReopenOnSighup()
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->EnableReopenOnSighup();
}

void TLogManager::SuppressRequest(TRequestId requestId)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->SuppressRequest(requestId);
}

void TLogManager::Synchronize(TInstant deadline)
{
[[unlikely]] if (!Impl_->IsInitialized()) {
return;
}
Impl_->Synchronize(deadline);
}

void TLogManager::Initialize()
{
Impl_->Initialize();
}

////////////////////////////////////////////////////////////////////////////////

TFiberMinLogLevelGuard::TFiberMinLogLevelGuard(ELogLevel minLogLevel)
Expand Down
2 changes: 0 additions & 2 deletions yt/yt/core/logging/log_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ class TLogManager

DECLARE_LEAKY_SINGLETON_FRIEND()

void Initialize();

class TImpl;
const TIntrusivePtr<TImpl> Impl_;
};
Expand Down

0 comments on commit c1640e3

Please sign in to comment.