123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- #include "logger.h"
- #include <library/cpp/yt/assert/assert.h>
- #include <library/cpp/yt/cpu_clock/clock.h>
- #include <library/cpp/yt/misc/thread_name.h>
- #include <util/system/compiler.h>
- #include <util/system/thread.h>
- 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::DoReset()
- {
- Buffer_.Reset();
- }
- struct TPerThreadCache;
- YT_DEFINE_THREAD_LOCAL(TPerThreadCache*, Cache);
- YT_DEFINE_THREAD_LOCAL(bool, CacheDestroyed);
- struct TPerThreadCache
- {
- TSharedMutableRef Chunk;
- size_t ChunkOffset = 0;
- ~TPerThreadCache()
- {
- TMessageStringBuilder::DisablePerThreadCache();
- }
- static YT_PREVENT_TLS_CACHING TPerThreadCache* GetCache()
- {
- auto& cache = Cache();
- if (Y_LIKELY(cache)) {
- return cache;
- }
- if (CacheDestroyed()) {
- return nullptr;
- }
- static thread_local TPerThreadCache CacheData;
- cache = &CacheData;
- return cache;
- }
- };
- void TMessageStringBuilder::DisablePerThreadCache()
- {
- Cache() = nullptr;
- CacheDestroyed() = true;
- }
- 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 = TPerThreadCache::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<TMessageBufferTag>(newChunkSize, {.InitializeStorage = false});
- cache->ChunkOffset = 0;
- }
- Buffer_ = cache->Chunk.Slice(cache->ChunkOffset, cache->ChunkOffset + newCapacity);
- cache->ChunkOffset += newCapacity;
- } else {
- Buffer_ = TSharedMutableRef::Allocate<TMessageBufferTag>(newChunkSize, {.InitializeStorage = false});
- newCapacity = newChunkSize;
- }
- if (oldLength > 0) {
- ::memcpy(Buffer_.Begin(), Begin_, oldLength);
- }
- Begin_ = Buffer_.Begin();
- End_ = Begin_ + newCapacity;
- }
- } // namespace NDetail
- ////////////////////////////////////////////////////////////////////////////////
- Y_WEAK TLoggingContext GetLoggingContext()
- {
- return {
- .Instant = GetCpuInstant(),
- .ThreadId = TThread::CurrentThreadId(),
- .ThreadName = GetCurrentThreadName(),
- };
- }
- Y_WEAK ILogManager* GetDefaultLogManager()
- {
- return nullptr;
- }
- ////////////////////////////////////////////////////////////////////////////////
- YT_DEFINE_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<TLoggingCategory*>(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<double>();
- 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
|