Compare commits
No commits in common. "55210a7e30af724e9ae1a69008d9f14deb506571" and "811a5f122fee1a1badc1ced4d530aa8c19788040" have entirely different histories.
55210a7e30
...
811a5f122f
8
log.cpp
8
log.cpp
|
@ -6,10 +6,9 @@
|
||||||
|
|
||||||
std::vector<LogEntry> log_entries;
|
std::vector<LogEntry> log_entries;
|
||||||
|
|
||||||
LogEntry::LogEntry(time_t time, std::string message_) : message(std::move(message_)) {
|
LogEntry::LogEntry(time_t time_, std::string message_) : time(time_), message(std::move(message_)) {
|
||||||
size_t pos;
|
size_t pos;
|
||||||
|
|
||||||
localtime_r(&time, &this->time);
|
|
||||||
while ((pos = this->message.find('\n')) != std::string::npos) {
|
while ((pos = this->message.find('\n')) != std::string::npos) {
|
||||||
this->message.replace(pos, 1, 1, ' ');
|
this->message.replace(pos, 1, 1, ' ');
|
||||||
}
|
}
|
||||||
|
@ -17,14 +16,15 @@ LogEntry::LogEntry(time_t time, std::string message_) : message(std::move(messag
|
||||||
|
|
||||||
|
|
||||||
std::string to_string(const LogEntry& entry) {
|
std::string to_string(const LogEntry& entry) {
|
||||||
|
struct tm tm;
|
||||||
char time_as_str[128] = {0};
|
char time_as_str[128] = {0};
|
||||||
strftime(time_as_str, 127 * sizeof(char), "%c", &entry.time);
|
strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&entry.time, &tm));
|
||||||
return std::string(1, '[') + time_as_str + "] " + entry.message;
|
return std::string(1, '[') + time_as_str + "] " + entry.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_log(const LogEntry& entry) {
|
void print_log(const LogEntry& entry) {
|
||||||
char time_as_str[128] = {0};
|
char time_as_str[128] = {0};
|
||||||
strftime(time_as_str, 127 * sizeof(char), "%c", &entry.time);
|
strftime(time_as_str, 127 * sizeof(char), "%c", localtime(&entry.time));
|
||||||
fprintf(stderr, "[%s] %s\n", time_as_str, entry.message.c_str());
|
fprintf(stderr, "[%s] %s\n", time_as_str, entry.message.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
log.h
5
log.h
|
@ -1,15 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct LogEntry {
|
struct LogEntry {
|
||||||
struct tm time;
|
time_t time;
|
||||||
std::string message;
|
std::string message;
|
||||||
|
|
||||||
LogEntry() = default;
|
LogEntry() = default;
|
||||||
LogEntry(time_t time, std::string message_);
|
LogEntry(time_t time_, std::string message_);
|
||||||
};
|
};
|
||||||
extern std::vector<LogEntry> log_entries;
|
extern std::vector<LogEntry> log_entries;
|
||||||
|
|
||||||
|
|
178
logcat_entry.cpp
178
logcat_entry.cpp
|
@ -7,24 +7,9 @@
|
||||||
#include "logcat_entry.h"
|
#include "logcat_entry.h"
|
||||||
#include "pcre2_wrapper.h"
|
#include "pcre2_wrapper.h"
|
||||||
|
|
||||||
static const Pcre2Regex LogcatEntryRegex(
|
static const Pcre2Regex LogcatEntryRegex("^\\s*(\\d+)(?:\\.\\d+)?(?:\\s+([\\w\\d._-]+))?\\s+(\\d+)\\s+(\\d+)\\s+([A-Z])\\s+(.+?)\\s*:\\s(.*)$");
|
||||||
"^ *(\\d+)(?:\\.\\d+)?" // time
|
|
||||||
"(?: +([\\w\\d._-]+))?" // optional user
|
|
||||||
" +(\\d+)" // pid
|
|
||||||
" +(\\d+)" // tid
|
|
||||||
" +([A-Z])" // priority
|
|
||||||
" +(.+?) *: (.*)$" // tag and message
|
|
||||||
);
|
|
||||||
static const Pcre2Regex BufferRegex("^--------- (?:beginning of|switch to) (\\w+)$");
|
static const Pcre2Regex BufferRegex("^--------- (?:beginning of|switch to) (\\w+)$");
|
||||||
|
|
||||||
static std::string leftpad(const std::string& str, size_t characters);
|
|
||||||
static inline char to_char(Priority priority);
|
|
||||||
static inline std::string rightpad(const std::string& str, size_t characters);
|
|
||||||
|
|
||||||
static inline Priority priority_from(char c);
|
|
||||||
static inline long to_long(const char* str, const char* expected_end);
|
|
||||||
static unsigned long long to_ull(const char* str, const char* expected_end);
|
|
||||||
|
|
||||||
const char* to_string(Priority priority) {
|
const char* to_string(Priority priority) {
|
||||||
switch (priority) {
|
switch (priority) {
|
||||||
case Priority::Verbose: return "Verbose";
|
case Priority::Verbose: return "Verbose";
|
||||||
|
@ -59,9 +44,34 @@ const char* to_string_lower(Buffer buffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string leftpad(const std::string& str, size_t characters) {
|
||||||
|
return str.size() >= characters
|
||||||
|
? str
|
||||||
|
: std::string(characters - str.size(), ' ') + str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char to_char(Priority priority) {
|
||||||
|
switch (priority) {
|
||||||
|
case Priority::Verbose: return 'V';
|
||||||
|
case Priority::Debug: return 'D';
|
||||||
|
case Priority::Info: return 'I';
|
||||||
|
case Priority::Warn: return 'W';
|
||||||
|
case Priority::Error: return 'E';
|
||||||
|
case Priority::Fatal: return 'F';
|
||||||
|
case Priority::Unknown: return 'U';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string rightpad(const std::string& str, size_t characters) {
|
||||||
|
return str.size() >= characters
|
||||||
|
? str
|
||||||
|
: str + std::string(characters - str.size(), ' ');
|
||||||
|
}
|
||||||
|
|
||||||
std::string to_string(const LogcatEntry& logcat_entry) {
|
std::string to_string(const LogcatEntry& logcat_entry) {
|
||||||
char logcat_style_time_as_str[32] = {0};
|
char logcat_style_time_as_str[32] = {0};
|
||||||
strftime(logcat_style_time_as_str, 31 * sizeof(char), "%Y-%m-%d %H:%M:%S", &logcat_entry.time);
|
struct tm tm;
|
||||||
|
strftime(logcat_style_time_as_str, 31 * sizeof(char), "%Y-%m-%d %H:%M:%S", localtime_r(&logcat_entry.time, &tm));
|
||||||
|
|
||||||
return std::string(logcat_style_time_as_str)
|
return std::string(logcat_style_time_as_str)
|
||||||
+ ' ' + leftpad(logcat_entry.user.value_or(" "), 5)
|
+ ' ' + leftpad(logcat_entry.user.value_or(" "), 5)
|
||||||
|
@ -72,6 +82,45 @@ std::string to_string(const LogcatEntry& logcat_entry) {
|
||||||
+ ": " + logcat_entry.message;
|
+ ": " + logcat_entry.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline Priority priority_from(char c) {
|
||||||
|
switch (c) {
|
||||||
|
case 'V': return Priority::Verbose;
|
||||||
|
case 'D': return Priority::Debug;
|
||||||
|
case 'I': return Priority::Info;
|
||||||
|
case 'W': return Priority::Warn;
|
||||||
|
case 'E': return Priority::Error;
|
||||||
|
case 'F': return Priority::Fatal;
|
||||||
|
default: return Priority::Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long to_long(const char* str, const char* expected_end) {
|
||||||
|
char* endptr;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
long res = strtol(str, &endptr, 10);
|
||||||
|
if (endptr != expected_end) {
|
||||||
|
throw std::invalid_argument(std::string(str) + " has trailing text");
|
||||||
|
} else if (res == LONG_MAX && errno == ERANGE) {
|
||||||
|
throw std::overflow_error(std::string(str) + " is too big");
|
||||||
|
} else if (res == LONG_MIN && errno == ERANGE) {
|
||||||
|
throw std::underflow_error(std::string(str) + " is too small");
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long long to_unsigned_long_long(const char* str, const char* expected_end) {
|
||||||
|
char* endptr;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
unsigned long long res = strtoull(str, &endptr, 10);
|
||||||
|
if (endptr != expected_end) {
|
||||||
|
throw std::invalid_argument(std::string(str) + " has trailing text");
|
||||||
|
} else if (res == ULLONG_MAX && errno == ERANGE) {
|
||||||
|
throw std::overflow_error(std::string(str) + " is too big");
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<LogcatEntry> try_parse_logcat_entry(char* buf, size_t length, Buffer buffer) {
|
std::optional<LogcatEntry> try_parse_logcat_entry(char* buf, size_t length, Buffer buffer) {
|
||||||
regmatch_t matches[8];
|
regmatch_t matches[8];
|
||||||
|
@ -85,26 +134,21 @@ std::optional<LogcatEntry> try_parse_logcat_entry(char* buf, size_t length, Buff
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto group_exists = [](const regmatch_t& match) { return match.rm_so > -1 && match.rm_eo > -1; };
|
std::optional<std::string> user;
|
||||||
auto group_long = [&](const regmatch_t& match) { return to_long(&buf[match.rm_so], &buf[match.rm_eo]); };
|
if (matches[2].rm_so > -1 && matches[2].rm_eo > -1) {
|
||||||
auto group_ull = [&](const regmatch_t& match) { return to_ull(&buf[match.rm_so], &buf[match.rm_eo]); };
|
user = std::string(&buf[matches[2].rm_so], static_cast<size_t>(matches[2].rm_eo - matches[2].rm_so));
|
||||||
auto group_string = [&](const regmatch_t& match) { return std::string(&buf[match.rm_so], static_cast<size_t>(match.rm_eo - match.rm_so)); };
|
}
|
||||||
auto group_priority = [&](const regmatch_t& match) { return priority_from(buf[match.rm_so]); };
|
|
||||||
|
|
||||||
// if pcre2 gives us negative offsets then i'll die
|
// if pcre2 gives us negative offsets then i'll die
|
||||||
LogcatEntry logcat_entry = {
|
LogcatEntry logcat_entry = {
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
// time to be set at the end
|
.time = to_long(&buf[matches[1].rm_so], &buf[matches[1].rm_eo]),
|
||||||
.user = group_exists(matches[2]) ? std::optional(group_string(matches[2])) : std::nullopt,
|
.user = std::move(user),
|
||||||
.pid = group_ull(matches[3]),
|
.pid = to_unsigned_long_long(&buf[matches[3].rm_so], &buf[matches[3].rm_eo]),
|
||||||
.tid = group_ull(matches[4]),
|
.tid = to_unsigned_long_long(&buf[matches[4].rm_so], &buf[matches[4].rm_eo]),
|
||||||
.priority = group_priority(matches[5]),
|
.priority = priority_from(buf[matches[5].rm_so]),
|
||||||
.tag = group_string(matches[6]),
|
.tag = std::string(&buf[matches[6].rm_so], static_cast<size_t>(matches[6].rm_eo - matches[6].rm_so)),
|
||||||
.message = group_string(matches[7]),
|
.message = std::string(&buf[matches[7].rm_so], static_cast<size_t>(matches[7].rm_eo - matches[7].rm_so)),
|
||||||
};
|
};
|
||||||
|
|
||||||
time_t time = group_long(matches[1]);
|
|
||||||
localtime_r(&time, &logcat_entry.time);
|
|
||||||
return std::move(logcat_entry);
|
return std::move(logcat_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,69 +238,3 @@ void to_json(nlohmann::json& j, const Priority& priority) {
|
||||||
case Priority::Fatal: j = "FATAL"; break;
|
case Priority::Fatal: j = "FATAL"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static std::string leftpad(const std::string& str, size_t characters) {
|
|
||||||
return str.size() >= characters
|
|
||||||
? str
|
|
||||||
: std::string(characters - str.size(), ' ') + str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline char to_char(Priority priority) {
|
|
||||||
switch (priority) {
|
|
||||||
case Priority::Verbose: return 'V';
|
|
||||||
case Priority::Debug: return 'D';
|
|
||||||
case Priority::Info: return 'I';
|
|
||||||
case Priority::Warn: return 'W';
|
|
||||||
case Priority::Error: return 'E';
|
|
||||||
case Priority::Fatal: return 'F';
|
|
||||||
case Priority::Unknown: return 'U';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline std::string rightpad(const std::string& str, size_t characters) {
|
|
||||||
return str.size() >= characters
|
|
||||||
? str
|
|
||||||
: str + std::string(characters - str.size(), ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline Priority priority_from(char c) {
|
|
||||||
switch (c) {
|
|
||||||
case 'V': return Priority::Verbose;
|
|
||||||
case 'D': return Priority::Debug;
|
|
||||||
case 'I': return Priority::Info;
|
|
||||||
case 'W': return Priority::Warn;
|
|
||||||
case 'E': return Priority::Error;
|
|
||||||
case 'F': return Priority::Fatal;
|
|
||||||
default: return Priority::Unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long to_long(const char* str, const char* expected_end) {
|
|
||||||
char* endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
long res = strtol(str, &endptr, 10);
|
|
||||||
if (endptr != expected_end) {
|
|
||||||
throw std::invalid_argument(std::string(str) + " has trailing text");
|
|
||||||
} else if (res == LONG_MAX && errno == ERANGE) {
|
|
||||||
throw std::overflow_error(std::string(str) + " is too big");
|
|
||||||
} else if (res == LONG_MIN && errno == ERANGE) {
|
|
||||||
throw std::underflow_error(std::string(str) + " is too small");
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long long to_ull(const char* str, const char* expected_end) {
|
|
||||||
char* endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
unsigned long long res = strtoull(str, &endptr, 10);
|
|
||||||
if (endptr != expected_end) {
|
|
||||||
throw std::invalid_argument(std::string(str) + " has trailing text");
|
|
||||||
} else if (res == ULLONG_MAX && errno == ERANGE) {
|
|
||||||
throw std::overflow_error(std::string(str) + " is too big");
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
@ -28,7 +27,7 @@ enum class Priority {
|
||||||
|
|
||||||
struct LogcatEntry {
|
struct LogcatEntry {
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
struct tm time;
|
time_t time;
|
||||||
std::optional<std::string> user;
|
std::optional<std::string> user;
|
||||||
size_t pid;
|
size_t pid;
|
||||||
size_t tid;
|
size_t tid;
|
||||||
|
|
|
@ -52,33 +52,27 @@ void debug_window(LogcatThread& logcat_thread, LogcatEntries& logcat_entries) {
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::Button("Add test entry (w/ user)")) {
|
if (ImGui::Button("Add test entry (w/ user)")) {
|
||||||
LogcatEntry entry = {
|
logcat_entries.push_back({
|
||||||
.buffer = Buffer::Main,
|
.buffer = Buffer::Main,
|
||||||
// time to be set later
|
.time = time(nullptr),
|
||||||
.user = "blankie",
|
.user = "blankie",
|
||||||
.pid = 69,
|
.pid = 69,
|
||||||
.tid = 420,
|
.tid = 420,
|
||||||
.priority = Priority::Error,
|
.priority = Priority::Error,
|
||||||
.tag = "blanket, inc.",
|
.tag = "blanket, inc.",
|
||||||
.message = "Failed to make blanket",
|
.message = "Failed to make blanket",
|
||||||
};
|
});
|
||||||
time_t entry_time = time(nullptr);
|
|
||||||
localtime_r(&entry_time, &entry.time);
|
|
||||||
logcat_entries.push_back(std::move(entry));
|
|
||||||
}
|
}
|
||||||
if (ImGui::Button("Add test entry (w/o user)")) {
|
if (ImGui::Button("Add test entry (w/o user)")) {
|
||||||
LogcatEntry entry = {
|
logcat_entries.push_back({
|
||||||
.buffer = Buffer::Crash,
|
.buffer = Buffer::Crash,
|
||||||
// time to be set later
|
.time = time(nullptr),
|
||||||
.pid = 420,
|
.pid = 420,
|
||||||
.tid = 69,
|
.tid = 69,
|
||||||
.priority = Priority::Fatal,
|
.priority = Priority::Fatal,
|
||||||
.tag = "blanket, inc.",
|
.tag = "blanket, inc.",
|
||||||
.message = "Failed to invent blankets",
|
.message = "Failed to invent blankets",
|
||||||
};
|
});
|
||||||
time_t entry_time = time(nullptr);
|
|
||||||
localtime_r(&entry_time, &entry.time);
|
|
||||||
logcat_entries.push_back(std::move(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
|
|
||||||
static inline void render_table_item_context_menu(const LogEntry& log_entry) {
|
static inline void render_table_item_context_menu(const LogEntry& log_entry) {
|
||||||
|
struct tm tm;
|
||||||
char time_as_str[128] = {0};
|
char time_as_str[128] = {0};
|
||||||
strftime(time_as_str, 127 * sizeof(char), "%c", &log_entry.time);
|
strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&log_entry.time, &tm));
|
||||||
|
|
||||||
ImGui::TextDisabled("[%s] %s", time_as_str, log_entry.message.c_str());
|
ImGui::TextDisabled("[%s] %s", time_as_str, log_entry.message.c_str());
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
@ -31,8 +32,9 @@ static inline void render_table_item(const LogEntry& log_entry, size_t log_entry
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
if (ImGui::TableSetColumnIndex(0)) {
|
if (ImGui::TableSetColumnIndex(0)) {
|
||||||
|
struct tm tm;
|
||||||
char time_as_str[128] = {0};
|
char time_as_str[128] = {0};
|
||||||
strftime(time_as_str, 127 * sizeof(char), "%c", &log_entry.time);
|
strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&log_entry.time, &tm));
|
||||||
|
|
||||||
ImGui::TextUnformatted(time_as_str);
|
ImGui::TextUnformatted(time_as_str);
|
||||||
table_item_popup();
|
table_item_popup();
|
||||||
|
|
|
@ -19,8 +19,9 @@ static inline void render_table_item_context_menu(const LogcatEntry& logcat_entr
|
||||||
|
|
||||||
if (ImGui::Selectable("Copy")) ImGui::SetClipboardText(text.c_str());
|
if (ImGui::Selectable("Copy")) ImGui::SetClipboardText(text.c_str());
|
||||||
if (ImGui::Selectable("Copy Time")) {
|
if (ImGui::Selectable("Copy Time")) {
|
||||||
|
struct tm tm;
|
||||||
char time_as_str[128] = {0};
|
char time_as_str[128] = {0};
|
||||||
strftime(time_as_str, 127 * sizeof(char), "%c", &logcat_entry.time);
|
strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&logcat_entry.time, &tm));
|
||||||
ImGui::SetClipboardText(time_as_str);
|
ImGui::SetClipboardText(time_as_str);
|
||||||
}
|
}
|
||||||
if (ImGui::Selectable("Copy User", false, logcat_entry.user ? 0 : ImGuiSelectableFlags_Disabled)) {
|
if (ImGui::Selectable("Copy User", false, logcat_entry.user ? 0 : ImGuiSelectableFlags_Disabled)) {
|
||||||
|
@ -47,8 +48,9 @@ static inline void render_table_item(const LogcatEntry& logcat_entry, size_t log
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
if (ImGui::TableSetColumnIndex(0)) {
|
if (ImGui::TableSetColumnIndex(0)) {
|
||||||
|
struct tm tm;
|
||||||
char time_as_str[128] = {0};
|
char time_as_str[128] = {0};
|
||||||
strftime(time_as_str, 127 * sizeof(char), "%c", &logcat_entry.time);
|
strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&logcat_entry.time, &tm));
|
||||||
|
|
||||||
ImGui::TextUnformatted(time_as_str);
|
ImGui::TextUnformatted(time_as_str);
|
||||||
table_item_popup();
|
table_item_popup();
|
||||||
|
|
Loading…
Reference in New Issue