#include "latencylog.h" static void latencylog_fill_event(latency_event_t *event, const char *node_role, const char *node_id, const char *event_name, int64_t ts_unix_nano, const message_t *msg) { memset(event, 0, sizeof(*event)); event->ts_unix_nano = ts_unix_nano; snprintf(event->node_role, sizeof(event->node_role), "%s", node_role == NULL ? "" : node_role); snprintf(event->node_id, sizeof(event->node_id), "%s", node_id == NULL ? "" : node_id); snprintf(event->event, sizeof(event->event), "%s", event_name == NULL ? "" : event_name); event->message_type = msg->type; event->message_id = msg->id; snprintf(event->from, sizeof(event->from), "%s", msg->from); snprintf(event->to, sizeof(event->to), "%s", msg->to); snprintf(event->file_name, sizeof(event->file_name), "%s", msg->file_name); event->body_size = (int) msg->body_len; } latency_logger_t *latencylog_open_jsonl(const char *path) { latency_logger_t *logger; FILE *file; if (path == NULL || path[0] == '\0') { return NULL; } if (omni_ensure_parent_dir(path) != 0) { return NULL; } file = fopen(path, "ab"); if (file == NULL) { return NULL; } logger = (latency_logger_t *) calloc(1, sizeof(*logger)); if (logger == NULL) { fclose(file); return NULL; } omni_file_logger_init(&logger->file_logger, file); logger->enabled = 1; return logger; } void latencylog_close(latency_logger_t *logger) { if (logger == NULL) { return; } if (logger->file_logger.file != NULL) { fclose(logger->file_logger.file); } omni_file_logger_destroy(&logger->file_logger); free(logger); } int latencylog_log_event(latency_logger_t *logger, const latency_event_t *event) { char *node_role = NULL; char *node_id = NULL; char *event_name = NULL; char *from = NULL; char *to = NULL; char *file_name = NULL; char *line = NULL; if (logger == NULL || event == NULL || !logger->enabled) { return 0; } node_role = omni_json_escape(event->node_role); node_id = omni_json_escape(event->node_id); event_name = omni_json_escape(event->event); from = omni_json_escape(event->from); to = omni_json_escape(event->to); file_name = omni_json_escape(event->file_name); if (node_role == NULL || node_id == NULL || event_name == NULL || from == NULL || to == NULL || file_name == NULL) { free(node_role); free(node_id); free(event_name); free(from); free(to); free(file_name); return -1; } line = omni_strdup_printf( "{\"ts_unix_nano\":%" PRId64 ",\"node_role\":\"%s\",\"node_id\":\"%s\",\"event\":\"%s\",\"message_type\":\"%s\",\"message_id\":%" PRIu64 ",\"from\":\"%s\",\"to\":\"%s\",\"file_name\":\"%s\",\"body_size\":%d}", event->ts_unix_nano, node_role, node_id, event_name, protocol_message_type_name(event->message_type), event->message_id, from, to, file_name, event->body_size ); free(node_role); free(node_id); free(event_name); free(from); free(to); free(file_name); if (line == NULL) { return -1; } if (omni_file_logger_write_line(&logger->file_logger, line) != 0) { free(line); return -1; } free(line); return 0; } int latencylog_is_business_message(const message_t *msg) { if (msg == NULL) { return 0; } return msg->type == MSG_TYPE_TEXT || msg->type == MSG_TYPE_FILE || msg->type == MSG_TYPE_BINARY; } void latencylog_log_message_event(latency_logger_t *logger, const char *node_role, const char *node_id, const char *event_name, const message_t *msg) { latencylog_log_message_event_at(logger, node_role, node_id, event_name, omni_now_unix_nano(), msg); } void latencylog_log_message_event_at(latency_logger_t *logger, const char *node_role, const char *node_id, const char *event_name, int64_t ts_unix_nano, const message_t *msg) { latency_event_t event; if (!latencylog_is_business_message(msg)) { return; } latencylog_fill_event(&event, node_role, node_id, event_name, ts_unix_nano, msg); (void) latencylog_log_event(logger, &event); }