// // Copyright (C) 2022 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "host/commands/cvd/logger.h" #include #include #include #include #include #include "common/libs/fs/shared_buf.h" #include "common/libs/utils/tee_logging.h" #include "host/commands/cvd/server_client.h" namespace cuttlefish { ServerLogger::ServerLogger() { auto log_callback = [this](android::base::LogId log_buffer_id, android::base::LogSeverity severity, const char* tag, const char* file, unsigned int line, const char* message) { auto thread_id = std::this_thread::get_id(); std::shared_lock lock(thread_loggers_lock_); auto logger_it = thread_loggers_.find(thread_id); if (logger_it == thread_loggers_.end()) { return; } logger_it->second->LogMessage(log_buffer_id, severity, tag, file, line, message); }; android::base::SetLogger(log_callback); } ServerLogger::~ServerLogger() { android::base::SetLogger(android::base::StderrLogger); } ServerLogger::ScopedLogger ServerLogger::LogThreadToFd(SharedFD target) { return ScopedLogger(*this, std::move(target)); } ServerLogger::ScopedLogger::ScopedLogger(ServerLogger& server_logger, SharedFD target) : server_logger_(server_logger), target_(std::move(target)) { auto thread_id = std::this_thread::get_id(); std::unique_lock lock(server_logger_.thread_loggers_lock_); server_logger_.thread_loggers_[thread_id] = this; } ServerLogger::ScopedLogger::ScopedLogger( ServerLogger::ScopedLogger&& other) noexcept : server_logger_(other.server_logger_), target_(std::move(other.target_)) { auto thread_id = std::this_thread::get_id(); std::unique_lock lock(server_logger_.thread_loggers_lock_); server_logger_.thread_loggers_[thread_id] = this; } ServerLogger::ScopedLogger::~ScopedLogger() { auto thread_id = std::this_thread::get_id(); std::unique_lock lock(server_logger_.thread_loggers_lock_); auto logger_it = server_logger_.thread_loggers_.find(thread_id); if (logger_it == server_logger_.thread_loggers_.end()) { return; } if (logger_it->second == this) { server_logger_.thread_loggers_.erase(logger_it); } } void ServerLogger::ScopedLogger::LogMessage( android::base::LogId /* log_buffer_id */, android::base::LogSeverity severity, const char* tag, const char* file, unsigned int line, const char* message) { time_t t = time(nullptr); struct tm now; localtime_r(&t, &now); auto output_string = StderrOutputGenerator(now, getpid(), android::base::GetThreadId(), severity, tag, file, line, message); WriteAll(target_, output_string); } } // namespace cuttlefish