#ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "selfdrive/common/swaglog.h" #include #include #include #include #include #include "json11.hpp" #include "selfdrive/common/util.h" #include "selfdrive/common/version.h" #include "selfdrive/hardware/hw.h" class LogState { public: LogState() = default; ~LogState(); std::mutex lock; bool inited; json11::Json::object ctx_j; void *zctx; void *sock; int print_level; }; LogState::~LogState() { zmq_close(sock); zmq_ctx_destroy(zctx); } static LogState s = {}; static void cloudlog_init() { if (s.inited) return; s.ctx_j = json11::Json::object {}; s.zctx = zmq_ctx_new(); s.sock = zmq_socket(s.zctx, ZMQ_PUSH); int timeout = 100; // 100 ms timeout on shutdown for messages to be received by logmessaged zmq_setsockopt(s.sock, ZMQ_LINGER, &timeout, sizeof(timeout)); zmq_connect(s.sock, "ipc:///tmp/logmessage"); s.print_level = CLOUDLOG_WARNING; const char* print_level = getenv("LOGPRINT"); if (print_level) { if (strcmp(print_level, "debug") == 0) { s.print_level = CLOUDLOG_DEBUG; } else if (strcmp(print_level, "info") == 0) { s.print_level = CLOUDLOG_INFO; } else if (strcmp(print_level, "warning") == 0) { s.print_level = CLOUDLOG_WARNING; } } // openpilot bindings char* dongle_id = getenv("DONGLE_ID"); if (dongle_id) { s.ctx_j["dongle_id"] = dongle_id; } char* daemon_name = getenv("MANAGER_DAEMON"); if (daemon_name) { s.ctx_j["daemon"] = daemon_name; } s.ctx_j["version"] = COMMA_VERSION; s.ctx_j["dirty"] = !getenv("CLEAN"); // device type if (Hardware::EON()) { s.ctx_j["device"] = "eon"; } else if (Hardware::TICI()) { s.ctx_j["device"] = "tici"; } else { s.ctx_j["device"] = "pc"; } s.inited = true; } static void log(int levelnum, const char* filename, int lineno, const char* func, const char* msg, const std::string& log_s) { if (levelnum >= s.print_level) { printf("%s: %s\n", filename, msg); } char levelnum_c = levelnum; zmq_send(s.sock, (levelnum_c + log_s).c_str(), log_s.length() + 1, ZMQ_NOBLOCK); } void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func, const char* fmt, ...) { char* msg_buf = nullptr; va_list args; va_start(args, fmt); int ret = vasprintf(&msg_buf, fmt, args); va_end(args); if (ret <= 0 || !msg_buf) return; std::lock_guard lk(s.lock); cloudlog_init(); json11::Json log_j = json11::Json::object { {"msg", msg_buf}, {"ctx", s.ctx_j}, {"levelnum", levelnum}, {"filename", filename}, {"lineno", lineno}, {"funcname", func}, {"created", seconds_since_epoch()} }; std::string log_s = log_j.dump(); log(levelnum, filename, lineno, func, msg_buf, log_s); free(msg_buf); }