From 004ceffaf43974a79b18ca0c514301f661c43050 Mon Sep 17 00:00:00 2001
From: Dmitry Ivanov <ivadmi5@gmail.com>
Date: Wed, 15 Nov 2023 23:33:40 +0300
Subject: [PATCH] feat(say): add method for setting log format by name

This patch adds a new method `log_set_format_by_name` which helps
FFI users set arbitrary logger's output format using its name
encoded as nul-terminated cstring.

NO_DOC=internal
NO_TEST=internal
NO_CHANGELOG=internal
---
 extra/exports      |  1 +
 src/lib/core/say.c | 31 ++++++++++++++++++++-----------
 src/lib/core/say.h | 10 ++++++++++
 3 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/extra/exports b/extra/exports
index d5256d90f7..94f6d66cdc 100644
--- a/extra/exports
+++ b/extra/exports
@@ -670,3 +670,4 @@ log_create
 log_destroy
 log_new
 log_say
+log_set_format_by_name
diff --git a/src/lib/core/say.c b/src/lib/core/say.c
index 26274ca622..a808807243 100644
--- a/src/lib/core/say.c
+++ b/src/lib/core/say.c
@@ -70,6 +70,7 @@ void
 (*log_write_flightrec)(int level, const char *filename, int line,
 		       const char *error, const char *format, va_list ap);
 
+static const log_format_func_t say_format_funcs[];
 enum say_format log_format = SF_PLAIN;
 enum { SAY_SYSLOG_DEFAULT_PORT = 512 };
 
@@ -230,6 +231,17 @@ log_set_format(struct log *log, log_format_func_t format_func)
 	log->format_func = format_func;
 }
 
+int
+log_set_format_by_name(struct log *log, const char *format)
+{
+	enum say_format say_format = say_format_by_name(format);
+	log_format_func_t format_func = say_format_funcs[say_format];
+	if (format_func == NULL)
+		return -1;
+	log_set_format(log, format_func);
+	return 0;
+}
+
 struct log *
 log_default_logger()
 {
@@ -252,18 +264,9 @@ say_get_log_level(void)
 void
 say_set_log_format(enum say_format format)
 {
-	log_format_func_t format_func;
-
-	switch (format) {
-	case SF_JSON:
-		format_func = say_format_json;
-		break;
-	case SF_PLAIN:
-		format_func = say_format_plain;
-		break;
-	default:
+	log_format_func_t format_func = say_format_funcs[format];
+	if (format_func == NULL)
 		unreachable();
-	}
 
 	log_set_format(log_default, format_func);
 	log_format = format;
@@ -276,6 +279,12 @@ say_set_flightrec_log_level(int new_level)
 	log_level_flightrec = new_level;
 }
 
+static const log_format_func_t say_format_funcs[] = {
+	[SF_PLAIN] = say_format_plain,
+	[SF_JSON] = say_format_json,
+	[say_format_MAX] = NULL,
+};
+
 static const char *say_format_strs[] = {
 	[SF_PLAIN] = "plain",
 	[SF_JSON] = "json",
diff --git a/src/lib/core/say.h b/src/lib/core/say.h
index dd1719998d..9e11ecac2e 100644
--- a/src/lib/core/say.h
+++ b/src/lib/core/say.h
@@ -260,6 +260,16 @@ log_set_level(struct log *log, enum say_level level);
 void
 log_set_format(struct log *log, log_format_func_t format_func);
 
+/**
+ * Set log format by name. Can be used dynamically.
+ *
+ * @param log		log object
+ * @param format_name	format name.
+ * @retval 0 in case of success, -1 otherwise
+ */
+int
+log_set_format_by_name(struct log *log, const char *format);
+
 /**
  * @return a default log object.
  */
-- 
GitLab