#include "logger.h" #include #include #include #include #include namespace NYT::NLogging { //////////////////////////////////////////////////////////////////////////////// namespace NDetail { void OnCriticalLogEvent( const TLogger& logger, const TLogEvent& event) { if (event.Level == ELogLevel::Fatal || event.Level == ELogLevel::Alert && logger.GetAbortOnAlert()) { fprintf(stderr, "*** Aborting on critical log event\n"); fwrite(event.MessageRef.begin(), 1, event.MessageRef.size(), stderr); fprintf(stderr, "\n"); YT_ABORT(); } } TSharedRef TMessageStringBuilder::Flush() { return Buffer_.Slice(0, GetLength()); } void TMessageStringBuilder::DisablePerThreadCache() { Cache_ = nullptr; CacheDestroyed_ = true; } void TMessageStringBuilder::DoReset() { Buffer_.Reset(); } void TMessageStringBuilder::DoReserve(size_t newCapacity) { auto oldLength = GetLength(); newCapacity = FastClp2(newCapacity); auto newChunkSize = std::max(ChunkSize, newCapacity); // Hold the old buffer until the data is copied. auto oldBuffer = std::move(Buffer_); auto* cache = GetCache(); if (Y_LIKELY(cache)) { auto oldCapacity = End_ - Begin_; auto deltaCapacity = newCapacity - oldCapacity; if (End_ == cache->Chunk.Begin() + cache->ChunkOffset && cache->ChunkOffset + deltaCapacity <= cache->Chunk.Size()) { // Resize inplace. Buffer_ = cache->Chunk.Slice(cache->ChunkOffset - oldCapacity, cache->ChunkOffset + deltaCapacity); cache->ChunkOffset += deltaCapacity; End_ = Begin_ + newCapacity; return; } if (Y_UNLIKELY(cache->ChunkOffset + newCapacity > cache->Chunk.Size())) { cache->Chunk = TSharedMutableRef::Allocate(newChunkSize, {.InitializeStorage = false}); cache->ChunkOffset = 0; } Buffer_ = cache->Chunk.Slice(cache->ChunkOffset, cache->ChunkOffset + newCapacity); cache->ChunkOffset += newCapacity; } else { Buffer_ = TSharedMutableRef::Allocate(newChunkSize, {.InitializeStorage = false}); newCapacity = newChunkSize; } if (oldLength > 0) { ::memcpy(Buffer_.Begin(), Begin_, oldLength); } Begin_ = Buffer_.Begin(); End_ = Begin_ + newCapacity; } TMessageStringBuilder::TPerThreadCache* TMessageStringBuilder::GetCache() { if (Y_LIKELY(Cache_)) { return Cache_; } if (CacheDestroyed_) { return nullptr; } static YT_THREAD_LOCAL(TPerThreadCache) Cache; Cache_ = &GetTlsRef(Cache); return Cache_; } TMessageStringBuilder::TPerThreadCache::~TPerThreadCache() { TMessageStringBuilder::DisablePerThreadCache(); } YT_THREAD_LOCAL(TMessageStringBuilder::TPerThreadCache*) TMessageStringBuilder::Cache_; YT_THREAD_LOCAL(bool) TMessageStringBuilder::CacheDestroyed_; } // namespace NDetail //////////////////////////////////////////////////////////////////////////////// Y_WEAK TLoggingContext GetLoggingContext() { return { .Instant = GetCpuInstant(), .ThreadId = TThread::CurrentThreadId(), .ThreadName = GetCurrentThreadName(), }; } Y_WEAK ILogManager* GetDefaultLogManager() { return nullptr; } //////////////////////////////////////////////////////////////////////////////// YT_THREAD_LOCAL(ELogLevel) ThreadMinLogLevel = ELogLevel::Minimum; void SetThreadMinLogLevel(ELogLevel minLogLevel) { ThreadMinLogLevel = minLogLevel; } ELogLevel GetThreadMinLogLevel() { return ThreadMinLogLevel; } //////////////////////////////////////////////////////////////////////////////// TLogger::TLogger(ILogManager* logManager, TStringBuf categoryName) : LogManager_(logManager) , Category_(LogManager_ ? LogManager_->GetCategory(categoryName) : nullptr) , MinLevel_(LogManager_ ? LoggerDefaultMinLevel : NullLoggerMinLevel) { } TLogger::TLogger(TStringBuf categoryName) : TLogger(GetDefaultLogManager(), categoryName) { } TLogger::operator bool() const { return LogManager_; } const TLoggingCategory* TLogger::GetCategory() const { return Category_; } bool TLogger::IsLevelEnabledHeavy(ELogLevel level) const { // Note that we managed to reach this point, i.e. level >= MinLevel_, // which implies that MinLevel_ != ELogLevel::Maximum, so this logger was not // default constructed, thus it has non-trivial category. YT_ASSERT(Category_); if (Category_->CurrentVersion != Category_->ActualVersion->load(std::memory_order::relaxed)) { LogManager_->UpdateCategory(const_cast(Category_)); } return level >= Category_->MinPlainTextLevel && level >= ThreadMinLogLevel; } bool TLogger::GetAbortOnAlert() const { return LogManager_->GetAbortOnAlert(); } bool TLogger::IsEssential() const { return Essential_; } void TLogger::UpdateAnchor(TLoggingAnchor* anchor) const { LogManager_->UpdateAnchor(anchor); } void TLogger::RegisterStaticAnchor(TLoggingAnchor* anchor, ::TSourceLocation sourceLocation, TStringBuf message) const { LogManager_->RegisterStaticAnchor(anchor, sourceLocation, message); } void TLogger::Write(TLogEvent&& event) const { LogManager_->Enqueue(std::move(event)); } void TLogger::AddRawTag(const TString& tag) { if (!Tag_.empty()) { Tag_ += ", "; } Tag_ += tag; } TLogger TLogger::WithRawTag(const TString& tag) const { auto result = *this; result.AddRawTag(tag); return result; } TLogger TLogger::WithEssential(bool essential) const { auto result = *this; result.Essential_ = essential; return result; } TLogger TLogger::WithStructuredValidator(TStructuredValidator validator) const { auto result = *this; result.StructuredValidators_.push_back(std::move(validator)); return result; } TLogger TLogger::WithMinLevel(ELogLevel minLevel) const { auto result = *this; if (result) { result.MinLevel_ = minLevel; } return result; } const TString& TLogger::GetTag() const { return Tag_; } const TLogger::TStructuredTags& TLogger::GetStructuredTags() const { return StructuredTags_; } const TLogger::TStructuredValidators& TLogger::GetStructuredValidators() const { return StructuredValidators_; } //////////////////////////////////////////////////////////////////////////////// void LogStructuredEvent( const TLogger& logger, NYson::TYsonString message, ELogLevel level) { YT_VERIFY(message.GetType() == NYson::EYsonType::MapFragment); if (!logger.GetStructuredValidators().empty()) { auto samplingRate = logger.GetCategory()->StructuredValidationSamplingRate.load(); auto p = RandomNumber(); if (p < samplingRate) { for (const auto& validator : logger.GetStructuredValidators()) { validator(message); } } } auto loggingContext = GetLoggingContext(); auto event = NDetail::CreateLogEvent( loggingContext, logger, level); event.MessageKind = ELogMessageKind::Structured; event.MessageRef = message.ToSharedRef(); event.Family = ELogFamily::Structured; logger.Write(std::move(event)); } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT::NLogging