Remove old logger
We don't need the old queue logger and log reader.
Change-Id: I108fbd3e3e6fdf3a87083ca42cb2deeedd2b5761
diff --git a/aos/logging/BUILD b/aos/logging/BUILD
index 68a493b..0ba9931 100644
--- a/aos/logging/BUILD
+++ b/aos/logging/BUILD
@@ -34,69 +34,6 @@
],
)
-cc_binary(
- name = "binary_log_writer",
- srcs = [
- "binary_log_writer.cc",
- ],
- visibility = ["//visibility:public"],
- deps = [
- ":binary_log_file",
- ":implementations",
- ":log_namer",
- ":logging",
- "//aos:configuration",
- "//aos:die",
- "//aos:init",
- "//aos/ipc_lib:queue",
- "//aos/time",
- ],
-)
-
-cc_binary(
- name = "log_streamer",
- srcs = [
- "log_streamer.cc",
- ],
- visibility = ["//visibility:public"],
- deps = [
- ":implementations",
- ":logging",
- "//aos:init",
- "//aos/ipc_lib:queue",
- "//aos/time",
- ],
-)
-
-cc_binary(
- name = "log_displayer",
- srcs = [
- "log_displayer.cc",
- ],
- visibility = ["//visibility:public"],
- deps = [
- ":binary_log_file",
- ":implementations",
- ":logging",
- "//aos:configuration",
- "//aos:init",
- "//aos/util:string_to_num",
- ],
-)
-
-cc_library(
- name = "binary_log_file",
- srcs = [
- "binary_log_file.cc",
- ],
- hdrs = [
- "binary_log_file.h",
- ],
- deps = [
- ":implementations",
- ],
-)
-
cc_library(
name = "sizes",
hdrs = [
diff --git a/aos/logging/binary_log_file.cc b/aos/logging/binary_log_file.cc
deleted file mode 100644
index 9ea5c82..0000000
--- a/aos/logging/binary_log_file.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-#include "aos/logging/binary_log_file.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <signal.h>
-#include <setjmp.h>
-
-namespace aos {
-namespace logging {
-namespace linux_code {
-namespace {
-
-unsigned long SystemPageSize() {
- static unsigned long r = sysconf(_SC_PAGESIZE);
- return r;
-}
-
-} // namespace
-
-LogFileAccessor::LogFileAccessor(int fd, bool writable)
- : fd_(fd), writable_(writable), offset_(0), current_(0), position_(0) {
- // Check to make sure that mmap will allow mmaping in chunks of kPageSize.
- if (SystemPageSize() > kPageSize || (kPageSize % SystemPageSize()) != 0) {
- AOS_LOG(FATAL, "system page size (%lu) not factor of kPageSize (%zd).\n",
- SystemPageSize(), kPageSize);
- }
-
- MapNextPage();
-}
-
-void LogFileAccessor::Sync() const {
- msync(current_, kPageSize, MS_ASYNC | MS_INVALIDATE);
-}
-
-void LogFileAccessor::SkipToLastSeekablePage() {
- AOS_CHECK(definitely_use_mmap());
-
- struct stat info;
- if (fstat(fd_, &info) == -1) {
- AOS_PLOG(FATAL, "fstat(%d, %p) failed", fd_, &info);
- }
-
- AOS_CHECK((info.st_size % kPageSize) == 0);
- const auto last_readable_page_number = (info.st_size / kPageSize) - 1;
- const auto last_seekable_page_number =
- last_readable_page_number / kSeekPages * kSeekPages;
- const off_t new_offset = last_seekable_page_number * kPageSize;
- // We don't want to go backwards...
- if (new_offset > offset_) {
- Unmap(current_);
- offset_ = new_offset;
- MapNextPage();
- }
-}
-
-// The only way to tell is using fstat, but we don't really want to be making a
-// syscall every single time somebody wants to know the answer, so it gets
-// cached in is_last_page_.
-bool LogFileAccessor::IsLastPage() {
- if (is_last_page_ != Maybe::kUnknown) {
- return is_last_page_ == Maybe::kYes;
- }
-
- struct stat info;
- if (fstat(fd_, &info) == -1) {
- AOS_PLOG(FATAL, "fstat(%d, %p) failed", fd_, &info);
- }
- bool r = offset_ == static_cast<off_t>(info.st_size - kPageSize);
- is_last_page_ = r ? Maybe::kYes : Maybe::kNo;
- return r;
-}
-
-void LogFileAccessor::MapNextPage() {
- if (writable_) {
- if (ftruncate(fd_, offset_ + kPageSize) == -1) {
- AOS_PLOG(FATAL, "ftruncate(%d, %zd) failed", fd_, kPageSize);
- }
- }
-
- if (use_read_ == Maybe::kYes) {
- ssize_t todo = kPageSize;
- while (todo > 0) {
- ssize_t result = read(fd_, current_ + (kPageSize - todo), todo);
- if (result == -1) {
- AOS_PLOG(FATAL, "read(%d, %p, %zu) failed", fd_,
- current_ + (kPageSize - todo), todo);
- } else if (result == 0) {
- memset(current_, 0, todo);
- result = todo;
- }
- todo -= result;
- }
- AOS_CHECK_EQ(0, todo);
- } else {
- current_ = static_cast<char *>(
- mmap(NULL, kPageSize, PROT_READ | (writable_ ? PROT_WRITE : 0),
- MAP_SHARED, fd_, offset_));
- if (current_ == MAP_FAILED) {
- if (!writable_ && use_read_ == Maybe::kUnknown && errno == ENODEV) {
- AOS_LOG(INFO, "Falling back to reading the file using read(2).\n");
- use_read_ = Maybe::kYes;
- current_ = new char[kPageSize];
- MapNextPage();
- return;
- } else {
- AOS_PLOG(
- FATAL,
- "mmap(NULL, %zd, PROT_READ [ | PROT_WRITE], MAP_SHARED, %d, %jd)"
- " failed",
- kPageSize, fd_, static_cast<intmax_t>(offset_));
- }
- } else {
- use_read_ = Maybe::kNo;
- }
- if (madvise(current_, kPageSize, MADV_SEQUENTIAL | MADV_WILLNEED) == -1) {
- AOS_PLOG(WARNING,
- "madvise(%p, %zd, MADV_SEQUENTIAL | MADV_WILLNEED) failed",
- current_, kPageSize);
- }
- }
- offset_ += kPageSize;
-}
-
-void LogFileAccessor::Unmap(void *location) {
- AOS_CHECK_NE(Maybe::kUnknown, use_read_);
-
- if (use_read_ == Maybe::kNo) {
- if (munmap(location, kPageSize) == -1) {
- AOS_PLOG(FATAL, "munmap(%p, %zd) failed", location, kPageSize);
- }
- }
- is_last_page_ = Maybe::kUnknown;
- position_ = 0;
-}
-
-const LogFileMessageHeader *LogFileReader::ReadNextMessage(bool wait) {
- LogFileMessageHeader *r;
- do {
- r = static_cast<LogFileMessageHeader *>(
- static_cast<void *>(¤t()[position()]));
- if (wait) {
- AOS_CHECK(definitely_use_mmap());
- if (futex_wait(&r->marker) != 0) continue;
- }
- if (r->marker == 2) {
- Unmap(current());
- MapNextPage();
- CheckCurrentPageReadable();
- r = static_cast<LogFileMessageHeader *>(static_cast<void *>(current()));
- }
- } while (wait && r->marker == 0);
- if (r->marker == 0) {
- return NULL;
- }
- IncrementPosition(sizeof(LogFileMessageHeader) + r->name_size +
- r->message_size);
- if (position() >= kPageSize) {
- // It's a lot better to blow up here rather than getting SIGBUS errors the
- // next time we try to read...
- AOS_LOG(FATAL, "corrupt log file running over page size\n");
- }
- return r;
-}
-
-// This mess is because the only not completely hackish way to do this is to set
-// up a handler for SIGBUS/SIGSEGV that siglongjmps out to avoid either the
-// instruction being repeated infinitely (and more signals being delivered) or
-// (with SA_RESETHAND) the signal killing the process.
-namespace {
-
-void *volatile fault_address;
-sigjmp_buf jump_context;
-
-void CheckCurrentPageReadableHandler(int /*signal*/, siginfo_t *info, void *) {
- fault_address = info->si_addr;
-
- siglongjmp(jump_context, 1);
-}
-
-} // namespace
-void LogFileReader::CheckCurrentPageReadable() {
- if (definitely_use_read()) return;
-
- if (sigsetjmp(jump_context, 1) == 0) {
- struct sigaction action;
- action.sa_sigaction = CheckCurrentPageReadableHandler;
- sigemptyset(&action.sa_mask);
- action.sa_flags = SA_RESETHAND | SA_SIGINFO;
- struct sigaction previous_bus, previous_segv;
- if (sigaction(SIGBUS, &action, &previous_bus) == -1) {
- AOS_PLOG(FATAL, "sigaction(SIGBUS(=%d), %p, %p) failed", SIGBUS, &action,
- &previous_bus);
- }
- if (sigaction(SIGSEGV, &action, &previous_segv) == -1) {
- AOS_PLOG(FATAL, "sigaction(SIGSEGV(=%d), %p, %p) failed", SIGSEGV,
- &action, &previous_segv);
- }
-
- char __attribute__((unused)) c = current()[0];
-
- if (sigaction(SIGBUS, &previous_bus, NULL) == -1) {
- AOS_PLOG(FATAL, "sigaction(SIGBUS(=%d), %p, NULL) failed", SIGBUS,
- &previous_bus);
- }
- if (sigaction(SIGSEGV, &previous_segv, NULL) == -1) {
- AOS_PLOG(FATAL, "sigaction(SIGSEGV(=%d), %p, NULL) failed", SIGSEGV,
- &previous_segv);
- }
- } else {
- if (fault_address == current()) {
- AOS_LOG(FATAL, "could not read 1 byte at offset 0x%jx into log file\n",
- static_cast<uintmax_t>(offset()));
- } else {
- AOS_LOG(FATAL, "faulted at %p, not %p like we were (maybe) supposed to\n",
- fault_address, current());
- }
- }
-}
-
-LogFileMessageHeader *LogFileWriter::GetWritePosition(size_t message_size) {
- if (NeedNewPageFor(message_size)) ForceNewPage();
- LogFileMessageHeader *const r = static_cast<LogFileMessageHeader *>(
- static_cast<void *>(¤t()[position()]));
- IncrementPosition(message_size);
- return r;
-}
-
-// A number of seekable pages, not the actual file offset, is stored in *cookie.
-bool LogFileWriter::ShouldClearSeekableData(off_t *cookie,
- size_t next_message_size) const {
- off_t next_message_page = (offset() / kPageSize) - 1;
- if (NeedNewPageFor(next_message_size)) {
- ++next_message_page;
- }
- const off_t current_seekable_page = next_message_page / kSeekPages;
- AOS_CHECK_LE(*cookie, current_seekable_page);
- const bool r = *cookie != current_seekable_page;
- *cookie = current_seekable_page;
- return r;
-}
-
-bool LogFileWriter::NeedNewPageFor(size_t bytes) const {
- return position() + bytes + (kAlignment - (bytes % kAlignment)) +
- sizeof(aos_futex) >
- kPageSize;
-}
-
-void LogFileWriter::ForceNewPage() {
- char *const temp = current();
- MapNextPage();
- if (futex_set_value(
- static_cast<aos_futex *>(static_cast<void *>(&temp[position()])),
- 2) == -1) {
- AOS_PLOG(WARNING, "readers will hang because futex_set_value(%p, 2) failed",
- &temp[position()]);
- }
- Unmap(temp);
-}
-
-} // namespace linux_code
-} // namespace logging
-} // namespace aos
diff --git a/aos/logging/binary_log_file.h b/aos/logging/binary_log_file.h
deleted file mode 100644
index 79b580d..0000000
--- a/aos/logging/binary_log_file.h
+++ /dev/null
@@ -1,207 +0,0 @@
-#ifndef AOS_LOGGING_BINARY_LOG_FILE_H_
-#define AOS_LOGGING_BINARY_LOG_FILE_H_
-
-#include <sys/types.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "aos/logging/implementations.h"
-
-namespace aos {
-namespace logging {
-namespace linux_code {
-
-// What to align messages to. A macro because it gets used in attributes.
-// This definition gets #undefed later. Use LogFileAccessor::kAlignment instead.
-#define MESSAGE_ALIGNMENT 8
-
-// File format: {
-// LogFileMessageHeader header;
-// char *name; // of the process that wrote the message
-// void *message;
-// } not crossing kPageSize boundaries into the file and aligned to
-// MESSAGE_ALIGNMENT.
-//
-// Field sizes designed to fit the various values from LogMessage even on
-// other machines (hopefully) because they're baked into the files. They are
-// layed out so that all of the fields are aligned even though the whole thing
-// is packed.
-//
-// A lot of the fields don't have comments because they're the same as the
-// identically named fields in LogMessage.
-struct __attribute__((aligned(MESSAGE_ALIGNMENT))) __attribute__((packed))
- LogFileMessageHeader {
- // Represents the type of an individual message.
- enum class MessageType : uint16_t {
- // char[] (no '\0' on the end).
- kString,
- kStructType,
- kStruct,
- kMatrix,
- };
-
- // Gets futex_set once this one has been written
- // for readers keeping up with a live writer.
- //
- // Gets initialized to 0 by ftruncate.
- //
- // There will be something here after the last message on a "page" set to 2
- // (by the futex_set) to indicate that the next message is on the next page.
- aos_futex marker;
- static_assert(sizeof(marker) == 4, "mutex changed size!");
- static_assert(MESSAGE_ALIGNMENT >= alignof(aos_futex),
- "MESSAGE_ALIGNMENT is too small");
-
- uint32_t time_sec;
- static_assert(sizeof(time_sec) >= sizeof(LogMessage::seconds),
- "tv_sec won't fit");
- uint32_t time_nsec;
- static_assert(sizeof(time_nsec) >= sizeof(LogMessage::nseconds),
- "tv_nsec won't fit");
-
- int32_t source;
- static_assert(sizeof(source) >= sizeof(LogMessage::source), "PIDs won't fit");
-
- // Both including all of the bytes in that part of the message.
- uint32_t name_size, message_size;
-
- uint16_t sequence;
- static_assert(sizeof(sequence) == sizeof(LogMessage::sequence),
- "something changed");
-
- MessageType type;
-
- log_level level;
- static_assert(sizeof(level) == 1, "log_level changed size!");
-};
-static_assert(std::is_pod<LogFileMessageHeader>::value,
- "LogFileMessageHeader will to get dumped to a file");
-static_assert(offsetof(LogFileMessageHeader, marker) == 0,
- "marker has to be at the start so readers can find it");
-
-// Handles the mmapping and munmapping for reading and writing log files.
-class LogFileAccessor {
- public:
- LogFileAccessor(int fd, bool writable);
- ~LogFileAccessor() {
- if (use_read_ == Maybe::kYes) {
- delete[] current_;
- }
- }
-
- // Asynchronously syncs all open mappings.
- void Sync() const;
-
- // Returns true iff we currently have the last page in the file mapped.
- // This is fundamentally a racy question, so the return value may not be
- // accurate by the time this method returns.
- bool IsLastPage();
-
- // Skips to the last page which is an even multiple of kSeekPages.
- // This is fundamentally racy, so it may not actually be on the very last
- // possible multiple of kSeekPages when it returns, but it should be close.
- // This will never move backwards.
- void SkipToLastSeekablePage();
-
- size_t file_offset(const void *msg) {
- return offset() + (static_cast<const char *>(msg) - current());
- }
-
- protected:
- // The size of the chunks that get mmaped/munmapped together. Large enough so
- // that not too much space is wasted and it's hopefully bigger than and a
- // multiple of the system page size but small enough so that really large
- // chunks of memory don't have to get mapped at the same time.
- static const size_t kPageSize = 16384;
- // What to align messages to, copied into an actual constant.
- static const size_t kAlignment = MESSAGE_ALIGNMENT;
-#undef MESSAGE_ALIGNMENT
- // Pages which are multiples of this from the beginning of a file start with
- // no saved state (ie struct types). This allows seeking immediately to the
- // largest currently written interval of this number when following.
- static const size_t kSeekPages = 256;
-
- char *current() const { return current_; }
- size_t position() const { return position_; }
- off_t offset() const { return offset_; }
-
- void IncrementPosition(size_t size) {
- position_ += size;
- AlignPosition();
- }
-
- void MapNextPage();
- void Unmap(void *location);
-
- // Advances position to the next (aligned) location.
- void AlignPosition() {
- position_ += kAlignment - (position_ % kAlignment);
- }
-
- protected:
- bool definitely_use_read() const { return use_read_ == Maybe::kYes; }
- bool definitely_use_mmap() const { return use_read_ == Maybe::kNo; }
-
- private:
- // Used for representing things that we might know to be true/false or we
- // might not know (yet).
- enum class Maybe { kUnknown, kYes, kNo };
-
- const int fd_;
- const bool writable_;
-
- // Into the file. Always a multiple of kPageSize.
- off_t offset_;
- char *current_;
- size_t position_;
-
- Maybe is_last_page_ = Maybe::kUnknown;
-
- // Use read instead of mmap (necessary for fds that don't support mmap).
- Maybe use_read_ = Maybe::kUnknown;
-};
-
-class LogFileReader : public LogFileAccessor {
- public:
- LogFileReader(int fd) : LogFileAccessor(fd, false) {}
-
- // May return NULL iff wait is false.
- const LogFileMessageHeader *ReadNextMessage(bool wait);
-
- private:
- // Tries reading from the current page to see if it fails because the file
- // isn't big enough.
- void CheckCurrentPageReadable();
-};
-
-class LogFileWriter : public LogFileAccessor {
- public:
- LogFileWriter(int fd) : LogFileAccessor(fd, true) {}
-
- // message_size should be the total number of bytes needed for the message.
- LogFileMessageHeader *GetWritePosition(size_t message_size);
-
- // Returns true exactly once for each unique cookie on each page where cached
- // data should be cleared.
- // Call with a non-zero next_message_size to determine if cached data should
- // be forgotten before writing a next_message_size-sized message.
- // cookie should be initialized to 0.
- bool ShouldClearSeekableData(off_t *cookie, size_t next_message_size) const;
-
- // Forces a move to a new page for the next message.
- // This is important when there is cacheable data that needs to be re-written
- // before a message which will spill over onto the next page but the cacheable
- // message being refreshed is smaller and won't get to a new page by itself.
- void ForceNewPage();
-
- private:
- bool NeedNewPageFor(size_t bytes) const;
-};
-
-} // namespace linux_code
-} // namespace logging
-} // namespace aos
-
-#endif // AOS_LOGGING_BINARY_LOG_FILE_H_
diff --git a/aos/logging/binary_log_writer.cc b/aos/logging/binary_log_writer.cc
deleted file mode 100644
index d4dea64..0000000
--- a/aos/logging/binary_log_writer.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <mntent.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-#include <string>
-
-#include <chrono>
-#include <map>
-#include <unordered_set>
-
-#include "aos/die.h"
-#include "aos/logging/binary_log_file.h"
-#include "aos/logging/implementations.h"
-#include "aos/logging/log_namer.h"
-#include "aos/time/time.h"
-#include "aos/configuration.h"
-#include "aos/init.h"
-#include "aos/ipc_lib/queue.h"
-
-namespace aos {
-namespace logging {
-namespace linux_code {
-namespace {
-
-int BinaryLogReaderMain() {
- InitNRT();
-
- const std::string file_name = GetLogName("aos_log");
- int fd = open(file_name.c_str(), O_SYNC | O_APPEND | O_RDWR | O_CREAT,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
- if (fd == -1) {
- AOS_PLOG(FATAL, "opening file '%s' failed", file_name.c_str());
- }
- LogFileWriter writer(fd);
-
- RawQueue *queue = GetLoggingQueue();
-
- ::std::unordered_set<uint32_t> written_type_ids;
-
- while (true) {
- const LogMessage *const msg =
- static_cast<const LogMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
- if (msg == NULL) {
- // If we've emptied the queue, then wait for a bit before starting to read
- // again so the queue can buffer up some logs. This avoids lots of context
- // switches and mutex contention which happens if we're constantly reading
- // new messages as they come in.
- ::std::this_thread::sleep_for(::std::chrono::milliseconds(100));
- continue;
- }
-
- const size_t raw_output_length =
- sizeof(LogFileMessageHeader) + msg->name_length + msg->message_length;
- size_t output_length = raw_output_length;
- LogFileMessageHeader *const output = writer.GetWritePosition(output_length);
- char *output_strings = reinterpret_cast<char *>(output) + sizeof(*output);
- output->name_size = msg->name_length;
- output->message_size = msg->message_length;
- output->source = msg->source;
- output->level = msg->level;
- output->time_sec = msg->seconds;
- output->time_nsec = msg->nseconds;
- output->sequence = msg->sequence;
- memcpy(output_strings, msg->name, msg->name_length);
-
- switch (msg->type) {
- case LogMessage::Type::kString:
- memcpy(output_strings + msg->name_length, msg->message,
- msg->message_length);
- output->type = LogFileMessageHeader::MessageType::kString;
- break;
- }
-
- if (output->message_size - msg->message_length !=
- output_length - raw_output_length) {
- AOS_LOG(FATAL, "%zu != %zu\n", output->message_size - msg->message_length,
- output_length - raw_output_length);
- }
-
- futex_set(&output->marker);
-
- queue->FreeMessage(msg);
- }
-
- Cleanup();
- return 0;
-}
-
-} // namespace
-} // namespace linux_code
-} // namespace logging
-} // namespace aos
-
-int main() {
- return ::aos::logging::linux_code::BinaryLogReaderMain();
-}
diff --git a/aos/logging/log_displayer.cc b/aos/logging/log_displayer.cc
deleted file mode 100644
index fa8fe6b..0000000
--- a/aos/logging/log_displayer.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <inttypes.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-
-#include "aos/configuration.h"
-#include "aos/logging/binary_log_file.h"
-#include "aos/logging/logging.h"
-#include "aos/logging/implementations.h"
-#include "aos/logging/printf_formats.h"
-#include "aos/util/string_to_num.h"
-
-using ::aos::logging::linux_code::LogFileMessageHeader;
-
-namespace {
-
-const char *kArgsHelp = "[OPTION]... [FILE]\n"
- "Display log file FILE (created by BinaryLogReader) to stdout.\n"
- "FILE is \"aos_log-current\" by default.\n"
- "FILE can also be \"-\" to read from standard input.\n"
- "\n"
- " -n, --name-prefix NAME "
- "only display entries from processes which share NAME as a prefix\n"
- " -N, --name NAME only display entries from processes named NAME\n"
- " -l, --level LEVEL "
- "only display log entries at least as important as LEVEL\n"
- " -p, --pid PID only display log entries from process PID\n"
- " -f, --follow "
- "wait when the end of the file is reached (implies --end)\n"
- " -t, --terminate stop when the end of file is reached (default)\n"
- " -b, --beginning start at the beginning of the file (default)\n"
- " -e, --end start at the end of the file\n"
- " -s, --skip NUMBER skip NUMBER matching logs\n"
- " -m, --max NUMBER only display up to NUMBER logs\n"
- " // -o, --format FORMAT use FORMAT to display log entries\n"
- " -h, --help display this help and exit\n"
- "\n"
- "LEVEL must be DEBUG, INFO, WARNING, ERROR, or FATAL.\n"
- " It defaults to INFO.\n"
- "\n"
- "TODO(brians) implement the commented out ones.\n";
-
-const char *kExampleUsages = "To view logs from the shooter:\n"
- "\t`log_displayer -n shooter`\n"
- "To view debug logs from the shooter:\n"
- "\t`log_displayer -n shooter -l DEBUG`\n"
- "To view what the shooter is logging in realtime:\n"
- "\t`log_displayer -f -n shooter`\n"
- "To view shooter logs from an old log file:\n"
- "\t`log_displayer aos_log-<number> -n shooter`\n"
- "To view the statuses of the shooter hall effects in realtime:\n"
- "\t`log_displayer -f -n shooter -l DEBUG | grep .Position`\n";
-
-std::string GetRootDirectory() {
- ssize_t size = 0;
- std::unique_ptr<char[]> retu;
- while (true) {
- size += 256;
- retu.reset(new char[size]);
-
- ssize_t ret = readlink("/proc/self/exe", retu.get(), size);
- if (ret < 0) {
- if (ret != -1) {
- LOG(WARNING) << "it returned " << ret << ", not -1";
- }
-
- PLOG(FATAL) << "readlink(\"/proc/self/exe\", " << retu.get() << ", " << size
- << ") failed";
- }
- if (ret < size) {
- void *last_slash = memrchr(retu.get(), '/', ret);
- if (last_slash == NULL) {
- retu.get()[ret] = '\0';
- LOG(FATAL) << "couldn't find a '/' in \"" << retu.get() << "\"";
- }
- *static_cast<char *>(last_slash) = '\0';
- LOG(INFO) << "got a root dir of \"" << retu.get() << "\"";
- return std::string(retu.get());
- }
- }
-}
-
-
-void PrintHelpAndExit() {
- fprintf(stderr, "Usage: %s %s", program_invocation_name, kArgsHelp);
- fprintf(stderr, "\nExample usages:\n\n%s", kExampleUsages);
-
- // Get the possible executables from start_list.txt.
- FILE *start_list = fopen("start_list.txt", "r");
- if (!start_list) {
- ::std::string path(GetRootDirectory());
- path += "/start_list.txt";
- start_list = fopen(path.c_str(), "r");
- if (!start_list) {
- printf(
- "\nCannot open start_list.txt. This means that the\npossible "
- "arguments for the -n option cannot be shown. log_displayer\nlooks "
- "for start_list.txt in the current working directory and in\n%s.\n\n",
- path.c_str());
- AOS_PLOG(FATAL, "Unable to open start_list.txt");
- }
- }
-
- // Get file size.
- if (fseek(start_list, 0, SEEK_END)) {
- AOS_PLOG(FATAL, "fseek() failed while reading start_list.txt");
- }
- int size = ftell(start_list);
- if (size < 0) {
- AOS_PLOG(FATAL, "ftell() failed while reading start_list.txt");
- }
- rewind(start_list);
-
- ::std::unique_ptr<char[]> contents(new char[size + 1]);
- if (contents == NULL) {
- AOS_LOG(FATAL, "malloc() failed while reading start_list.txt.\n");
- }
- size_t bytes_read = fread(contents.get(), 1, size, start_list);
- if (bytes_read < static_cast<size_t>(size)) {
- AOS_LOG(FATAL, "Read %zu bytes from start_list.txt, expected %d.\n",
- bytes_read, size);
- }
-
- // printf doesn't like strings without the \0.
- contents[size] = '\0';
- fprintf(stderr, "\nPossible arguments for the -n option:\n%s", contents.get());
-
- if (fclose(start_list)) {
- AOS_LOG(FATAL, "fclose() failed.\n");
- }
-
- exit(EXIT_SUCCESS);
-}
-
-} // namespace
-
-int main(int argc, char **argv) {
- const char *filter_name = nullptr, *filter_exact_name = nullptr;
- size_t filter_length = 0;
- log_level filter_level = INFO;
- bool follow = false;
- // Whether we need to skip everything until we get to the end of the file.
- bool skip_to_end = false;
- const char *filename = "aos_log-current";
- int display_max = 0;
- int32_t source_pid = -1;
-
- ::aos::logging::Init();
- ::aos::logging::SetImplementation(
- new ::aos::logging::StreamLogImplementation(stdout));
-
- while (true) {
- static struct option long_options[] = {
- {"name-prefix", required_argument, NULL, 'n'},
- {"name", required_argument, NULL, 'N'},
- {"level", required_argument, NULL, 'l'},
- {"pid", required_argument, NULL, 'p'},
-
- {"follow", no_argument, NULL, 'f'},
- {"terminate", no_argument, NULL, 't'},
- {"beginning", no_argument, NULL, 'b'},
- {"end", no_argument, NULL, 'e'},
- {"skip", required_argument, NULL, 's'},
- {"max", required_argument, NULL, 'm'},
-
- {"format", required_argument, NULL, 'o'},
-
- {"help", no_argument, NULL, 'h'},
- {0, 0, 0, 0}
- };
- int option_index = 0;
-
- const int c = getopt_long(argc, argv, "N:n:l:p:fts:m:o:h",
- long_options, &option_index);
- if (c == -1) { // if we're at the end
- break;
- }
- switch (c) {
- case 0:
- fputs("LogDisplayer: got a 0 option but didn't set up any\n", stderr);
- abort();
- case 'n':
- filter_name = optarg;
- filter_exact_name = nullptr;
- filter_length = strlen(filter_name);
- break;
- case 'N':
- filter_exact_name = optarg;
- filter_name = nullptr;
- filter_length = strlen(filter_exact_name);
- break;
- case 'l':
- filter_level = ::aos::logging::str_log(optarg);
- if (filter_level == LOG_UNKNOWN) {
- fprintf(stderr, "LogDisplayer: unknown log level '%s'\n", optarg);
- exit(EXIT_FAILURE);
- }
- break;
- case 'p':
- if (!::aos::util::StringToNumber(::std::string(optarg), &source_pid)) {
- fprintf(stderr, "ERROR: -p expects a number, not '%s'.\n", optarg);
- exit(EXIT_FAILURE);
- }
- if (source_pid < 0) {
- fprintf(stderr, "LogDisplayer: invalid pid '%s'\n", optarg);
- exit(EXIT_FAILURE);
- }
- break;
- case 'f':
- follow = true;
- skip_to_end = true;
- break;
- case 't':
- follow = false;
- break;
- case 'b':
- skip_to_end = false;
- break;
- case 'e':
- skip_to_end = true;
- break;
- case 'm':
- if (!::aos::util::StringToNumber(::std::string(optarg), &display_max)) {
- fprintf(stderr, "ERROR: -m expects a number, not '%s'.\n", optarg);
- exit(EXIT_FAILURE);
- }
- if (display_max <= 0) {
- fprintf(stderr, "LogDisplayer: invalid max log number '%s'\n",
- optarg);
- exit(EXIT_FAILURE);
- }
- break;
- case 'o':
- abort();
- break;
- case 'h':
- PrintHelpAndExit();
- break;
- case '?':
- break;
- default:
- fprintf(stderr, "LogDisplayer: in a bad spot (%s: %d)\n",
- __FILE__, __LINE__);
- abort();
- }
- }
-
- if (optind < argc) {
- // We got a filename.
- filename = argv[optind++];
- }
- if (optind < argc) {
- fputs("non-option ARGV-elements: ", stderr);
- while (optind < argc) {
- fprintf(stderr, "%s\n", argv[optind++]);
- }
- }
-
- int fd;
- if (strcmp(filename, "-") == 0) {
- if (skip_to_end) {
- fputs("Can't skip to end of stdin!\n", stderr);
- return EXIT_FAILURE;
- }
- fd = STDIN_FILENO;
- } else {
- fd = open(filename, O_RDONLY);
- }
-
- fprintf(stderr, "displaying down to level %s from file '%s'\n",
- ::aos::logging::log_str(filter_level), filename);
-
- if (fd == -1) {
- AOS_PLOG(FATAL, "couldn't open file '%s' for reading", filename);
- }
- ::aos::logging::linux_code::LogFileReader reader(fd);
-
- if (skip_to_end) {
- fputs("skipping old logs...\n", stderr);
- reader.SkipToLastSeekablePage();
- }
-
- const LogFileMessageHeader *msg;
- int displayed = 0;
- do {
- msg = reader.ReadNextMessage(follow);
- if (msg == NULL) {
- fputs("reached end of file\n", stderr);
- return 0;
- }
-
- if (source_pid >= 0 && msg->source != source_pid) {
- // Message is from the wrong process.
- continue;
- }
-
- if (skip_to_end) {
- if (reader.IsLastPage()) {
- fputs("done skipping old logs\n", stderr);
- skip_to_end = false;
- } else {
- continue;
- }
- }
-
- if (::aos::logging::log_gt_important(filter_level, msg->level)) continue;
-
- const char *position =
- reinterpret_cast<const char *>(msg + 1);
-
- if (filter_name != nullptr) {
- const size_t compare_length =
- ::std::min<size_t>(filter_length, msg->name_size);
- if (memcmp(filter_name, position, compare_length) != 0) {
- continue;
- }
- if (compare_length < msg->name_size) {
- if (position[compare_length] != '.') continue;
- }
- }
-
- if (filter_exact_name != nullptr) {
- if (filter_length != msg->name_size) continue;
- if (memcmp(filter_exact_name, position, filter_length) != 0) {
- continue;
- }
- }
-
- if (display_max && displayed++ >= display_max) {
- fputs("Not displaying the rest of the messages.\n", stderr);
- return 0;
- }
-
- position += msg->name_size;
-
-#define BASE_ARGS \
- AOS_LOGGING_BASE_ARGS( \
- msg->name_size, reinterpret_cast<const char *>(msg + 1), msg->source, \
- msg->sequence, msg->level, msg->time_sec, msg->time_nsec)
- switch (msg->type) {
- case LogFileMessageHeader::MessageType::kString:
- fprintf(stdout, AOS_LOGGING_BASE_FORMAT "%.*s", BASE_ARGS,
- static_cast<int>(msg->message_size), position);
- break;
- case LogFileMessageHeader::MessageType::kStruct:
- case LogFileMessageHeader::MessageType::kMatrix:
- AOS_LOG(FATAL, "Unsupported matrix or struct\n");
- break;
- case LogFileMessageHeader::MessageType::kStructType:
- AOS_LOG(FATAL, "shouldn't get here\n");
- break;
- }
-#undef BASE_ARGS
- } while (msg != NULL);
-}
diff --git a/aos/logging/log_streamer.cc b/aos/logging/log_streamer.cc
deleted file mode 100644
index 4477868..0000000
--- a/aos/logging/log_streamer.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-#include <chrono>
-#include <string>
-
-#include "aos/logging/implementations.h"
-#include "aos/logging/logging.h"
-#include "aos/time/time.h"
-#include "aos/init.h"
-#include "aos/ipc_lib/queue.h"
-
-namespace aos {
-namespace logging {
-namespace linux_code {
-namespace {
-
-namespace chrono = ::std::chrono;
-
-int LogStreamerMain() {
- InitNRT();
-
- RawQueue *queue = GetLoggingQueue();
-
- const monotonic_clock::time_point now = monotonic_clock::now();
- chrono::seconds sec =
- chrono::duration_cast<chrono::seconds>(now.time_since_epoch());
- chrono::nanoseconds nsec =
- chrono::duration_cast<chrono::nanoseconds>(now.time_since_epoch() - sec);
- printf("starting at %" PRId32 "s%" PRId32 "ns-----------------------------\n",
- static_cast<int32_t>(sec.count()), static_cast<int32_t>(nsec.count()));
-
- while (true) {
- const LogMessage *const msg = static_cast<const LogMessage *>(
- queue->ReadMessage(RawQueue::kNonBlock));
- if (msg == NULL) {
- ::std::this_thread::sleep_for(::std::chrono::milliseconds(100));
- } else {
- internal::PrintMessage(stdout, *msg);
-
- queue->FreeMessage(msg);
- }
- }
-
- Cleanup();
- return 0;
-}
-
-} // namespace
-} // namespace linux_code
-} // namespace logging
-} // namespace aos
-
-int main() {
- return ::aos::logging::linux_code::LogStreamerMain();
-}