/** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ #include #include #include #include using namespace Aws::Utils; using namespace Aws::Utils::Logging; static const char* AllocationTag = "DefaultLogSystem"; static const int BUFFERED_MSG_COUNT = 100; static std::shared_ptr MakeDefaultLogFile(const Aws::String& filenamePrefix) { Aws::String newFileName = filenamePrefix + DateTime::CalculateGmtTimestampAsString("%Y-%m-%d-%H") + ".log"; return Aws::MakeShared(AllocationTag, newFileName.c_str(), Aws::OFStream::out | Aws::OFStream::app); } static void LogThread(DefaultLogSystem::LogSynchronizationData* syncData, std::shared_ptr logFile, const Aws::String& filenamePrefix, bool rollLog) { // localtime requires access to env. variables to get Timezone, which is not thread-safe int32_t lastRolledHour = DateTime::Now().GetHour(false /*localtime*/); for(;;) { std::unique_lock locker(syncData->m_logQueueMutex); syncData->m_queueSignal.wait(locker, [&](){ return syncData->m_stopLogging == true || syncData->m_queuedLogMessages.size() > 0; } ); if (syncData->m_stopLogging && syncData->m_queuedLogMessages.size() == 0) { break; } Aws::Vector messages(std::move(syncData->m_queuedLogMessages)); syncData->m_queuedLogMessages.reserve(BUFFERED_MSG_COUNT); locker.unlock(); if (messages.size() > 0) { if (rollLog) { // localtime requires access to env. variables to get Timezone, which is not thread-safe int32_t currentHour = DateTime::Now().GetHour(false /*localtime*/); if (currentHour != lastRolledHour) { logFile = MakeDefaultLogFile(filenamePrefix); lastRolledHour = currentHour; } } for (const auto& msg : messages) { (*logFile) << msg; } logFile->flush(); } } } DefaultLogSystem::DefaultLogSystem(LogLevel logLevel, const std::shared_ptr& logFile) : Base(logLevel), m_syncData(), m_loggingThread() { m_loggingThread = std::thread(LogThread, &m_syncData, logFile, "", false); } DefaultLogSystem::DefaultLogSystem(LogLevel logLevel, const Aws::String& filenamePrefix) : Base(logLevel), m_syncData(), m_loggingThread() { m_loggingThread = std::thread(LogThread, &m_syncData, MakeDefaultLogFile(filenamePrefix), filenamePrefix, true); } DefaultLogSystem::~DefaultLogSystem() { { std::lock_guard locker(m_syncData.m_logQueueMutex); m_syncData.m_stopLogging = true; m_syncData.m_queueSignal.notify_one(); } m_loggingThread.join(); } void DefaultLogSystem::ProcessFormattedStatement(Aws::String&& statement) { std::lock_guard locker(m_syncData.m_logQueueMutex); m_syncData.m_queuedLogMessages.emplace_back(std::move(statement)); if(m_syncData.m_queuedLogMessages.size() >= BUFFERED_MSG_COUNT) { m_syncData.m_queueSignal.notify_one(); } } void DefaultLogSystem::Flush() { std::lock_guard locker(m_syncData.m_logQueueMutex); m_syncData.m_queueSignal.notify_one(); }