Implement logging
This commit is contained in:
@ -10,6 +10,6 @@ git_override(
|
|||||||
commit = "4f28899228fb3ad0126897876f147ca15026151e",
|
commit = "4f28899228fb3ad0126897876f147ca15026151e",
|
||||||
)
|
)
|
||||||
|
|
||||||
bazel_dep(name = "rules_python", version = "1.1.0", dev_dependency = True)
|
bazel_dep(name = "rules_python", version = "1.1.0")
|
||||||
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
|
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
|
||||||
python.toolchain(python_version = "3.13", is_default = True)
|
python.toolchain(python_version = "3.13", is_default = True)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
void report_assert_failure( const char* msg, const source_location& sl = source_location{});
|
void report_assert_failure(const char* msg, const source_location& sl = source_location{});
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
|
||||||
|
@ -90,6 +90,9 @@ public:
|
|||||||
{
|
{
|
||||||
return H::combine(ASL_MOVE(h), *b);
|
return H::combine(ASL_MOVE(h), *b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<is_object U, allocator A>
|
||||||
|
friend constexpr U* leak(box<U, A>&&);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
|
template<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
|
||||||
@ -111,5 +114,11 @@ constexpr box<T, Allocator> make_box(Args&&... args)
|
|||||||
return box<T>(ptr, ASL_MOVE(allocator));
|
return box<T>(ptr, ASL_MOVE(allocator));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<is_object T, allocator A>
|
||||||
|
constexpr T* leak(box<T, A>&& b)
|
||||||
|
{
|
||||||
|
return exchange(b.m_ptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
cc_library(
|
cc_library(
|
||||||
name = "log",
|
name = "log",
|
||||||
srcs = [
|
srcs = [
|
||||||
"log.hpp",
|
"log.cpp",
|
||||||
],
|
],
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"log.cpp",
|
"log.hpp",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//asl",
|
"//asl",
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
#include "asl/log/log.hpp"
|
||||||
|
#include "asl/print.hpp"
|
||||||
|
#include "asl/string_builder.hpp"
|
||||||
|
|
||||||
|
// @Todo Don't use internal get_stdout_writer, make console module
|
||||||
|
|
||||||
|
static asl::log::DefaultLogger g_default_logger{asl::print_internals::get_stdout_writer()};
|
||||||
|
static asl::log::Logger* g_head = &g_default_logger;
|
||||||
|
|
||||||
|
static constexpr asl::string_view kLevelName[] = {
|
||||||
|
" DEBUG ",
|
||||||
|
" INFO ",
|
||||||
|
" WARNING ",
|
||||||
|
" ERROR ",
|
||||||
|
};
|
||||||
|
|
||||||
|
void asl::log::register_logger(box<Logger> logger_box)
|
||||||
|
{
|
||||||
|
auto* logger = leak(ASL_MOVE(logger_box));
|
||||||
|
logger->m_next = exchange(g_head, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
void asl::log::DefaultLogger::log(const message& msg)
|
||||||
|
{
|
||||||
|
asl::format(m_writer, "[{}] {}:{}: {}\n",
|
||||||
|
kLevelName[msg.level], // NOLINT
|
||||||
|
msg.location.file,
|
||||||
|
msg.location.line,
|
||||||
|
msg.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void asl::log::log_inner(
|
||||||
|
level l,
|
||||||
|
string_view fmt, span<const format_internals::type_erased_arg> args,
|
||||||
|
const source_location& sl)
|
||||||
|
{
|
||||||
|
// @Todo Use temporary allocator
|
||||||
|
StringWriter msg_writer{};
|
||||||
|
asl::format_internals::format(&msg_writer, fmt, args);
|
||||||
|
|
||||||
|
message m{
|
||||||
|
.level = l,
|
||||||
|
.message = msg_writer.as_string_view(),
|
||||||
|
.location = sl,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto* it = g_head; it != nullptr; it = it->next_logger())
|
||||||
|
{
|
||||||
|
it->log(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <asl/format.hpp>
|
||||||
|
#include <asl/utility.hpp>
|
||||||
|
#include <asl/box.hpp>
|
||||||
|
|
||||||
|
namespace asl::log
|
||||||
|
{
|
||||||
|
|
||||||
|
enum level : uint8_t
|
||||||
|
{
|
||||||
|
kDebug = 0,
|
||||||
|
kInfo,
|
||||||
|
kWarning,
|
||||||
|
kError,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct message
|
||||||
|
{
|
||||||
|
level level;
|
||||||
|
string_view message;
|
||||||
|
source_location location;
|
||||||
|
};
|
||||||
|
|
||||||
|
// @Todo Write and use an intrusive doubly-linked list
|
||||||
|
class Logger
|
||||||
|
{
|
||||||
|
Logger* m_next{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Logger() = default;
|
||||||
|
ASL_DEFAULT_COPY_MOVE(Logger);
|
||||||
|
virtual ~Logger() = default;
|
||||||
|
|
||||||
|
virtual void log(const message&) = 0;
|
||||||
|
|
||||||
|
friend void register_logger(box<Logger>);
|
||||||
|
|
||||||
|
constexpr Logger* next_logger() const { return m_next; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// @Todo Make a deref_as trait & deref utility
|
||||||
|
// @Todo Accept writer as box, pointer, reference, or value
|
||||||
|
class DefaultLogger : public Logger
|
||||||
|
{
|
||||||
|
Writer* m_writer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit constexpr DefaultLogger(Writer* writer) : m_writer{writer} {}
|
||||||
|
|
||||||
|
void log(const message&) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
void register_logger(box<Logger>);
|
||||||
|
|
||||||
|
// @Todo Add a way to remove loggers (including all)
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
requires constructible_from<T, Args&&...> && convertible_from<Logger*, T*>
|
||||||
|
void register_logger(Args&&... args)
|
||||||
|
{
|
||||||
|
register_logger(make_box<T>(ASL_FWD(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_inner(level l, string_view fmt, span<const format_internals::type_erased_arg> args, const source_location& sl);
|
||||||
|
|
||||||
|
template<formattable... Args>
|
||||||
|
void log(level l, const source_location& sl, string_view fmt, const Args&... args)
|
||||||
|
{
|
||||||
|
format_internals::type_erased_arg type_erased_args[] = {
|
||||||
|
format_internals::type_erased_arg(args)...
|
||||||
|
};
|
||||||
|
log_inner(l, fmt, type_erased_args, sl);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace asl::log
|
||||||
|
|
||||||
|
// @Todo Compile-time configuration of logging
|
||||||
|
|
||||||
|
#define ASL_LOG_DEBUG(...) ::asl::log::log(::asl::log::kDebug, ::asl::source_location{}, __VA_ARGS__)
|
||||||
|
#define ASL_LOG_INFO(...) ::asl::log::log(::asl::log::kInfo, ::asl::source_location{}, __VA_ARGS__)
|
||||||
|
#define ASL_LOG_WARNING(...) ::asl::log::log(::asl::log::kWarning, ::asl::source_location{}, __VA_ARGS__)
|
||||||
|
#define ASL_LOG_ERROR(...) ::asl::log::log(::asl::log::kError, ::asl::source_location{}, __VA_ARGS__)
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
#include <asl/log/log.hpp>
|
||||||
|
#include <asl/testing/testing.hpp>
|
||||||
|
|
||||||
|
ASL_TEST(log)
|
||||||
|
{
|
||||||
|
asl::log::log(asl::log::kInfo, asl::source_location{}, "Hello, {}!", "world"_sv);
|
||||||
|
|
||||||
|
ASL_LOG_ERROR("Oh no! {}", 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -81,4 +81,16 @@ constexpr bool is_pow2(isize_t v)
|
|||||||
ASL_DELETE_COPY(T) \
|
ASL_DELETE_COPY(T) \
|
||||||
ASL_DELETE_MOVE(T)
|
ASL_DELETE_MOVE(T)
|
||||||
|
|
||||||
|
#define ASL_DEFAULT_COPY(T) \
|
||||||
|
T(const T&) = default; \
|
||||||
|
T& operator=(const T&) = default;
|
||||||
|
|
||||||
|
#define ASL_DEFAULT_MOVE(T) \
|
||||||
|
T(T&&) = default; \
|
||||||
|
T& operator=(T&&) = default;
|
||||||
|
|
||||||
|
#define ASL_DEFAULT_COPY_MOVE(T) \
|
||||||
|
ASL_DEFAULT_COPY(T) \
|
||||||
|
ASL_DEFAULT_MOVE(T)
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
3
todo.txt
3
todo.txt
@ -1,4 +1 @@
|
|||||||
logging
|
|
||||||
dynlib
|
|
||||||
|
|
||||||
warning compare with 0 in format_float.cpp
|
warning compare with 0 in format_float.cpp
|
||||||
|
@ -5,4 +5,5 @@ py_binary(
|
|||||||
srcs = [
|
srcs = [
|
||||||
"fix_line_endings.py",
|
"fix_line_endings.py",
|
||||||
],
|
],
|
||||||
|
visibility = ["//:__subpackages__"],
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user