1 #ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
3 #ifndef SIMDJSON_CONDITIONAL_INCLUDE
4 #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
5 #include "simdjson/generic/ondemand/base.h"
6 #include "simdjson/generic/ondemand/logger.h"
7 #include "simdjson/generic/ondemand/json_iterator.h"
8 #include "simdjson/generic/ondemand/value_iterator.h"
15 namespace SIMDJSON_IMPLEMENTATION {
19 static constexpr
const char * DASHES =
"----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
20 static constexpr
const int LOG_EVENT_LEN = 20;
21 static constexpr
const int LOG_BUFFER_LEN = 30;
22 static constexpr
const int LOG_SMALL_BUFFER_LEN = 10;
23 static int log_depth = 0;
26 static inline char printable_char(
char c) {
34 template<
typename... Args>
35 static inline std::string string_format(
const std::string& format,
const Args&... args)
37 SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
38 int size_s = std::snprintf(
nullptr, 0, format.c_str(), args...) + 1;
39 auto size =
static_cast<size_t>(size_s);
40 if (size <= 0)
return std::string();
41 std::unique_ptr<char[]> buf(
new char[size]);
42 std::snprintf(buf.get(), size, format.c_str(), args...);
43 SIMDJSON_POP_DISABLE_WARNINGS
44 return std::string(buf.get(), buf.get() + size - 1);
47 static inline log_level get_log_level_from_env()
49 SIMDJSON_PUSH_DISABLE_WARNINGS
50 SIMDJSON_DISABLE_DEPRECATED_WARNING
51 char *lvl = getenv(
"SIMDJSON_LOG_LEVEL");
52 SIMDJSON_POP_DISABLE_WARNINGS
53 if (lvl && simdjson_strcasecmp(lvl,
"ERROR") == 0) {
return log_level::error; }
54 return log_level::info;
57 static inline log_level log_threshold()
59 static log_level threshold = get_log_level_from_env();
63 static inline bool should_log(log_level level)
65 return level >= log_threshold();
68 inline void log_event(
const json_iterator &iter,
const char *type, std::string_view detail,
int delta,
int depth_delta) noexcept {
69 log_line(iter,
"", type, detail, delta, depth_delta, log_level::info);
72 inline void log_value(
const json_iterator &iter, token_position index,
depth_t depth,
const char *type, std::string_view detail) noexcept {
73 log_line(iter, index, depth,
"", type, detail, log_level::info);
75 inline void log_value(
const json_iterator &iter,
const char *type, std::string_view detail,
int delta,
int depth_delta) noexcept {
76 log_line(iter,
"", type, detail, delta, depth_delta, log_level::info);
79 inline void log_start_value(
const json_iterator &iter, token_position index,
depth_t depth,
const char *type, std::string_view detail) noexcept {
80 log_line(iter, index, depth,
"+", type, detail, log_level::info);
81 if (LOG_ENABLED) { log_depth++; }
83 inline void log_start_value(
const json_iterator &iter,
const char *type,
int delta,
int depth_delta) noexcept {
84 log_line(iter,
"+", type,
"", delta, depth_delta, log_level::info);
85 if (LOG_ENABLED) { log_depth++; }
88 inline void log_end_value(
const json_iterator &iter,
const char *type,
int delta,
int depth_delta) noexcept {
89 if (LOG_ENABLED) { log_depth--; }
90 log_line(iter,
"-", type,
"", delta, depth_delta, log_level::info);
93 inline void log_error(
const json_iterator &iter,
const char *error,
const char *detail,
int delta,
int depth_delta) noexcept {
94 log_line(iter,
"ERROR: ", error, detail, delta, depth_delta, log_level::error);
96 inline void log_error(
const json_iterator &iter, token_position index,
depth_t depth,
const char *error,
const char *detail) noexcept {
97 log_line(iter, index, depth,
"ERROR: ", error, detail, log_level::error);
100 inline void log_event(
const value_iterator &iter,
const char *type, std::string_view detail,
int delta,
int depth_delta) noexcept {
101 log_event(iter.json_iter(), type, detail, delta, depth_delta);
104 inline void log_value(
const value_iterator &iter,
const char *type, std::string_view detail,
int delta,
int depth_delta) noexcept {
105 log_value(iter.json_iter(), type, detail, delta, depth_delta);
108 inline void log_start_value(
const value_iterator &iter,
const char *type,
int delta,
int depth_delta) noexcept {
109 log_start_value(iter.json_iter(), type, delta, depth_delta);
112 inline void log_end_value(
const value_iterator &iter,
const char *type,
int delta,
int depth_delta) noexcept {
113 log_end_value(iter.json_iter(), type, delta, depth_delta);
116 inline void log_error(
const value_iterator &iter,
const char *error,
const char *detail,
int delta,
int depth_delta) noexcept {
117 log_error(iter.json_iter(), error, detail, delta, depth_delta);
120 inline void log_headers() noexcept {
122 if (simdjson_unlikely(should_log(log_level::info))) {
124 static bool displayed_hint{
false};
127 if (!displayed_hint) {
129 printf(
"# Logging provides the depth and position of the iterator user-visible steps:\n");
130 printf(
"# +array says 'this is where we were when we discovered the start array'\n");
132 "# -array says 'this is where we were when we ended the array'\n");
133 printf(
"# skip says 'this is a structural or value I am skipping'\n");
134 printf(
"# +/-skip says 'this is a start/end array or object I am skipping'\n");
136 printf(
"# The indentation of the terms (array, string,...) indicates the depth,\n");
137 printf(
"# in addition to the depth being displayed.\n");
139 printf(
"# Every token in the document has a single depth determined by the tokens before it,\n");
140 printf(
"# and is not affected by what the token actually is.\n");
142 printf(
"# Not all structural elements are presented as tokens in the logs.\n");
144 printf(
"# We never give control to the user within an empty array or an empty object.\n");
146 printf(
"# Inside an array, having a depth greater than the array's depth means that\n");
147 printf(
"# we are pointing inside a value.\n");
148 printf(
"# Having a depth equal to the array means that we are pointing right before a value.\n");
149 printf(
"# Having a depth smaller than the array means that we have moved beyond the array.\n");
150 displayed_hint =
true;
153 printf(
"| %-*s ", LOG_EVENT_LEN,
"Event");
154 printf(
"| %-*s ", LOG_BUFFER_LEN,
"Buffer");
155 printf(
"| %-*s ", LOG_SMALL_BUFFER_LEN,
"Next");
157 printf(
"| %-*s ", 5,
"Depth");
161 printf(
"|%.*s", LOG_EVENT_LEN + 2, DASHES);
162 printf(
"|%.*s", LOG_BUFFER_LEN + 2, DASHES);
163 printf(
"|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES);
165 printf(
"|%.*s", 5 + 2, DASHES);
173 template <
typename... Args>
174 inline void log_line(
const json_iterator &iter,
const char *title_prefix,
const char *title, std::string_view detail,
int delta,
int depth_delta, log_level level, Args&&... args) noexcept {
175 log_line(iter, iter.position()+delta,
depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward<Args>(args)...);
178 template <
typename... Args>
179 inline void log_line(
const json_iterator &iter, token_position index,
depth_t depth,
const char *title_prefix,
const char *title, std::string_view detail, log_level level, Args&&... args) noexcept {
181 if (simdjson_unlikely(should_log(level))) {
182 const int indent = depth * 2;
183 const auto buf = iter.token.buf;
184 auto msg = string_format(title, std::forward<Args>(args)...);
185 printf(
"| %*s%s%-*s ", indent,
"", title_prefix,
186 LOG_EVENT_LEN - indent -
int(strlen(title_prefix)), msg.c_str());
192 if (index < iter._root) {
193 printf(
"%*s", LOG_BUFFER_LEN,
"");
195 auto current_structural = &buf[*index];
196 for (
int i = 0; i < LOG_BUFFER_LEN; i++) {
197 printf(
"%c", printable_char(current_structural[i]));
205 auto next_structural = &buf[*(index + 1)];
206 for (
int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) {
207 printf(
"%c", printable_char(next_structural[i]));
212 printf(
"| %5i ", depth);
213 printf(
"| %6.*s ",
int(detail.size()), detail.data());
int32_t depth_t
Represents the depth of a JSON value (number of nested arrays/objects).
The top level simdjson namespace, containing everything the library provides.