hamnet70/impl/src/jsonlogger.c

134 lines
2.3 KiB
C
Raw Normal View History

#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include "jsonlogger.h"
#define LOG_OR_RETURN(...) \
if(dprintf(m_fifo_fd, __VA_ARGS__) < 0) { \
return false; \
}
static int m_fifo_fd = -1;
static char m_fifo_path[1024];
static bool start_message(void)
{
if(m_fifo_fd < 0) {
// FIFO was not opened yet. Try to open it now.
m_fifo_fd = open(m_fifo_path, O_WRONLY | O_NONBLOCK);
if(m_fifo_fd < 0) {
if(errno != ENXIO) {
perror("open");
}
return false;
}
}
ssize_t ret = write(m_fifo_fd, "{", 1);
if(ret < 0) {
// FIFO is not writable or other error
switch(errno) {
case EAGAIN: // FIFO not ready for writing -> drop message
break;
case EPIPE: // FIFO was closed on the other side
close(m_fifo_fd);
m_fifo_fd = -1;
break;
default: // other errors are logged to stderr
perror("write");
break;
}
return false;
}
return true;
}
static bool end_message(void)
{
ssize_t ret = write(m_fifo_fd, "}\n", 2);
if(ret < 0) {
// FIFO is not writable or other error
if(errno != EAGAIN) {
perror("write");
}
return false;
}
return true;
}
bool jsonlogger_init(const char *fifoname)
{
// try to create the named FIFO
int ret = mkfifo(fifoname, 0666);
if(ret < 0) {
if(errno != EEXIST) {
perror("mkfifo");
return false;
}
}
strncpy(m_fifo_path, fifoname, sizeof(m_fifo_path));
m_fifo_fd = -1; // open on demand
return true;
}
void jsonlogger_shutdown(void)
{
close(m_fifo_fd);
}
bool jsonlogger_log_simple_integer(const char *msg_type, int64_t value)
{
if(!start_message()) {
return false;
}
LOG_OR_RETURN("\"%s\": %ld", msg_type, value);
return end_message();
}
bool jsonlogger_log_simple_double(const char *msg_type, double value)
{
if(!start_message()) {
return false;
}
LOG_OR_RETURN("\"%s\": %g", msg_type, value);
return end_message();
}
bool jsonlogger_log_rx_stats(const rx_stats_t *rx_stats)
{
if(!start_message()) {
return false;
}
LOG_OR_RETURN("\"preambles_found\": %zd, ", rx_stats->preambles_found);
LOG_OR_RETURN("\"successful_decodes\": %zd, ", rx_stats->successful_decodes);
LOG_OR_RETURN("\"failed_decodes\": %zd, ", rx_stats->failed_decodes);
LOG_OR_RETURN("\"header_errors\": %zd", rx_stats->header_errors);
return end_message();
}