ap

An audio player suited to my tastes
Log | Files | Refs | README | LICENSE

commit 4c47068a62d6f958a868e5ecf5fe8fbe188c26af
parent 640b43ae702e7057b7d5a69ea78a1fd4b2aeeb62
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date:   Sat, 25 Mar 2023 10:07:41 -0700

Update server logging functions

Separate log levels and subjects, allowing for much more flexibility
and replace the aps_log() function with aps_logfmt().

The log entry format is also changed, and while it takes a lot more
printf(3) statements, it's more readable.

Diffstat:
Maps/aps.c | 14+++++++-------
Maps/buf.c | 20+++++++++++++++++++-
Maps/log.c | 61++++++++++++++++++++++++++++++++++---------------------------
Maps/log.h | 32++++++++++++++++++++++----------
Maps/main.c | 6+++---
Maps/queue.c | 10+++++-----
6 files changed, 90 insertions(+), 53 deletions(-)

diff --git a/aps/aps.c b/aps/aps.c @@ -1,5 +1,5 @@ /* - * Copyright 2021, 2022 Jacob R. Edwards + * Copyright 2021-2023 Jacob R. Edwards * * ap -- audio player * @@ -95,7 +95,7 @@ aps_close(struct aps *aps) int aps_drop(struct aps *aps, int fd) { - aps_log(aps, INFO, fd, "dropping client"); + aps_log(aps, fd, INFO, logsubjects[LogConn], "dropping client"); --aps->nfds; aps->pfds[fd].fd = -1; buffree(aps->clients[fd].response); @@ -128,9 +128,9 @@ aps_accept(struct aps *aps) while ((s = accept4(aps->con->sock, NULL, NULL, 0)) >= 0) { if (aps_addfd(aps, s)) - aps_log(aps, ERROR, s, "unable to add client"); + aps_log(aps, s, ERROR, logsubjects[LogConn], "unable to add client"); else - aps_log(aps, INFO, s, "client added"); + aps_log(aps, s, INFO, logsubjects[LogConn], "client added"); } return errno != EWOULDBLOCK; @@ -242,7 +242,7 @@ aps_command(struct aps *aps, int fd) if (buf == NULL) return 0; - aps_logfmt(aps, COMMAND, fd, "input '%s'", buf); + aps_log(aps, fd, DEBUG, logsubjects[LogCommand], "raw '%s'", buf); argv = split(buf, NULL); if (argv == NULL) { @@ -273,7 +273,7 @@ void aps_errordrop(struct aps *aps, int fd, char *why) { /* One could send(2) the error aswell. */ - aps_log(aps, ERROR, fd, why); + aps_log(aps, fd, ERROR, logsubjects[LogConn], why); aps_drop(aps, fd); } @@ -313,6 +313,6 @@ aps_unname(struct aps *aps) { if (unlink(aps->con->path) == 0) return 0; - aps_logfmt(aps, WARN, 0, "%s: unable to remove socket", aps->con->path); + aps_log(aps, 0, WARN, NULL, "%s: unable to remove socket", aps->con->path); return 1; } diff --git a/aps/buf.c b/aps/buf.c @@ -1,3 +1,21 @@ +/* Copyright 2021-2023 Jacob R. Edwards + * + * ap -- audio player + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + #include <sys/socket.h> #include <ctype.h> @@ -47,6 +65,6 @@ aps_bufstatus(struct aps *aps, int fd, char *error) bufappend(buf, "\n", 1); aps->pfds[fd].events = POLLOUT; - aps_logfmt(aps, COMMAND, fd, "error: %s", error); + aps_log(aps, fd, INFO, logsubjects[LogCommand], "error: %s", error); return 0; } diff --git a/aps/log.c b/aps/log.c @@ -1,5 +1,5 @@ /* - * Copyright 2021, 2022 Jacob R. Edwards + * Copyright 2021-2023 Jacob R. Edwards * * ap -- audio player * @@ -26,60 +26,67 @@ #include <string.h> #include "aps.h" +#include "bug.h" #include "log.h" #include "util.h" static struct { - char *str; - int level; -} binds[] = { + char *s; + int i; +} levels[] = { + { "debug", DEBUG }, { "info", INFO }, { "warn", WARN }, { "error", ERROR }, - { "fatal", FATAL }, - { "command", COMMAND }, - { "queue", QUEUE } + { "fatal", FATAL } }; -char * -levelstr(int level) +int +strlevel(char *s) { int i; - for (i = 0; i < LEN(binds); ++i) - if (level == binds[i].level) - return binds[i].str; - return NULL; + for (i = 0; i < LEN(levels); ++i) + if (strcmp(levels[i].s, s) == 0) + return levels[i].i; + return -1; } -int -strlevel(char *str) +char * +levelstr(int level) { int i; - for (i = 0; i < LEN(binds); ++i) - if (strcmp(str, binds[i].str) == 0) - return binds[i].level; - return -1; + for (i = 0; i < LEN(levels); ++i) + if (levels[i].i == level) + return levels[i].s; + return NULL; } void -aps_logfmt(struct aps *aps, int level, int fd, char *fmt, ...) +aps_log(struct aps *aps, int fd, int level, char *subject, char *fmt, ...) { va_list ap; + char *p; if (fmt == NULL || (aps && !(level & aps->loglevel))) return; - fprintf(stderr, "aps(%d) %s: ", fd, levelstr(level)); + fprintf(stderr, "aps: "); + + if (fd) + fprintf(stderr, "client %d ", fd); + + if (subject) + fprintf(stderr, "%s ", subject); + + if (!(p = levelstr(level))) + bug("invalid log level"); + fprintf(stderr, "%s", p); + + fprintf(stderr, ": "); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fputs("\n", stderr); } - -void -aps_log(struct aps *aps, int level, int fd, char *msg) -{ - aps_logfmt(aps, level, fd, "%s", msg); -} diff --git a/aps/log.h b/aps/log.h @@ -1,13 +1,25 @@ -enum { - INFO = 1 << 0, - WARN = 1 << 1, - ERROR = 1 << 2, - FATAL = 1 << 3, - COMMAND = 1 << 4, - QUEUE = 1 << 5 +enum loglevel { + DEBUG = 1 << 0, + INFO = DEBUG << 1, + WARN = INFO << 1, + ERROR = WARN << 1, + FATAL = ERROR << 1 +}; + +enum logsubject { + LogGeneral, + LogCommand, + LogConn, + LogQueue, + LogLast, +}; + +static char *logsubjects[LogLast] = { + [LogCommand] = "command", + [LogConn] = "connection", + [LogQueue] = "queue" }; -char *levelstr(int); int strlevel(char *); -void aps_logfmt(struct aps *, int, int, char *, ...); -void aps_log(struct aps *, int, int, char *); +char *levelstr(int); +void aps_log(struct aps *, int, int, char *, char *, ...); diff --git a/aps/main.c b/aps/main.c @@ -1,5 +1,5 @@ /* - * Copyright 2021, 2022 Jacob R. Edwards + * Copyright 2021-2023 Jacob R. Edwards * * ap -- audio player * @@ -44,14 +44,14 @@ static struct aps *aps; void die(char *s) { - aps_logfmt(NULL, FATAL, 0, "%s: %s", s, errstr); + aps_log(NULL, 0, FATAL, NULL, "%s: %s", s, errstr); exit(1); } void sigclose(int sig) { - aps_log(aps, FATAL, 0, "close signal"); + aps_log(aps, 0, FATAL, NULL, "close signal"); aps->close = 1; } diff --git a/aps/queue.c b/aps/queue.c @@ -1,5 +1,5 @@ /* - * Copyright 2021, 2022 Jacob R. Edwards + * Copyright 2021-2023 Jacob R. Edwards * * ap -- audio player * @@ -30,7 +30,7 @@ void queue_set(struct aps *aps, struct item *item) { aps->queue = item; - aps_logfmt(aps, QUEUE, 0, "set '%s'", item ? item->path : ""); + aps_log(aps, 0, INFO, logsubjects[LogQueue], "set '%s'", item ? item->path : ""); if (aps->player->state != OFF && aps->player->state != STOPPED) { pstop(aps->player); @@ -43,11 +43,11 @@ queue_add(struct aps *aps, struct item *at, char *s) { struct item *item; - aps_logfmt(aps, QUEUE, 0, "add '%s'", s); + aps_log(aps, 0, INFO, logsubjects[LogQueue], "add '%s'", s); item = item_new(s); if (item == NULL) { - aps_log(aps, ERROR, 0, "unable to create queue item"); + aps_log(aps, 0, ERROR, logsubjects[LogQueue], "unable to create queue item"); return NULL; } @@ -66,7 +66,7 @@ queue_remove(struct aps *aps, struct item *item) if (item == NULL) return NULL; - aps_logfmt(aps, QUEUE, 0, "remove '%s'", item->path); + aps_log(aps, 0, INFO, logsubjects[LogQueue], "remove '%s'", item->path); next = item->next; if (next == item)