0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
logging.h
Go to the documentation of this file.
1/**
2 * @file src/util/logging.h
3 *
4 * Copyright (c) 2021-2025 Bartek Kryza <bkryza@gmail.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18#pragma once
19
20#include "fmt_formatters.h"
21
22#include <inja/inja.hpp>
23#include <spdlog/sinks/stdout_color_sinks.h>
24#include <spdlog/spdlog.h>
25
26// For release builds, use only file names in the log paths, for debug use
27// full paths to make it easier to navigate to specific file:line in the code
28// from logs
29#if defined(NDEBUG)
30#define FILENAME_ \
31 (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
32#else
33#define FILENAME_ __FILE__
34#endif
35
36#define LOG_ERROR(fmt__, ...) \
37 ::clanguml::logging::log_impl( \
38 spdlog::level::err, fmt__, FILENAME_, __LINE__, ##__VA_ARGS__)
39
40#define LOG_WARN(fmt__, ...) \
41 ::clanguml::logging::log_impl( \
42 spdlog::level::warn, fmt__, FILENAME_, __LINE__, ##__VA_ARGS__)
43
44#define LOG_INFO(fmt__, ...) \
45 ::clanguml::logging::log_impl( \
46 spdlog::level::info, fmt__, FILENAME_, __LINE__, ##__VA_ARGS__)
47
48#define LOG_DBG(fmt__, ...) \
49 ::clanguml::logging::log_impl( \
50 spdlog::level::debug, fmt__, FILENAME_, __LINE__, ##__VA_ARGS__)
51
52#define LOG_TRACE(fmt__, ...) \
53 ::clanguml::logging::log_impl( \
54 spdlog::level::trace, fmt__, FILENAME_, __LINE__, ##__VA_ARGS__)
55
56namespace fmt {
57template <> struct formatter<inja::json> : formatter<std::string> {
58 auto format(const inja::json &json,
59 format_context &ctx) const -> decltype(ctx.out())
60 {
61 return fmt::format_to(ctx.out(), "{}", json.dump());
62 }
63};
64} // namespace fmt
65
66namespace clanguml::logging {
67
68enum class logger_type_t {
69 text,
70 json,
71 get /*!< This key is used to get the global logger type value */
72};
73
74logger_type_t logger_type(logger_type_t type = logger_type_t::get);
75
76std::string to_string(logger_type_t type);
77
78std::string to_string(spdlog::level::level_enum level);
79
80void escape_json_string(std::string &s);
81
82template <typename T> decltype(auto) escape_json(T &&val)
83{
84 using DecayedT = std::decay_t<T>;
85 if constexpr (std::is_same_v<DecayedT, inja::json>) {
86 std::string result{val.dump()};
87 return result;
88 }
89 else if constexpr (std::is_convertible_v<DecayedT, std::string>) {
90 std::string result{val};
91 escape_json_string(result);
92 return result;
93 }
94 else
95 return std::forward<T>(val);
96}
97
98template <typename FilenameT, typename LineT, typename... Args>
99void log_impl(spdlog::level::level_enum level, logger_type_t type,
100 std::string_view fmt_, FilenameT f, LineT l, Args &&...args)
101{
102 if (type == logger_type_t::text) {
103 spdlog::get("clanguml-logger")
104 ->log(level, fmt::runtime("[{}:{}] " + std::string{fmt_}), f, l,
105 std::forward<Args>(args)...);
106 }
107 else {
108 spdlog::get("clanguml-logger")
109 ->log(level,
110 fmt::runtime(R"("file": "{}", "line": {}, "message": ")" +
111 std::string{fmt_} + "\""),
112 f, l, escape_json(std::forward<Args>(args))...);
113 }
114}
115
116template <typename FilenameT, typename LineT, typename... Args>
117void log_impl(spdlog::level::level_enum level, std::string_view fmt_,
118 FilenameT f, LineT t, Args &&...args)
119{
120 log_impl(level, logger_type(), fmt_, f, t, std::forward<Args>(args)...);
121}
122
123} // namespace clanguml::logging