diff --git a/src/knot/common/log.c b/src/knot/common/log.c
index 80bec72b969b705debc91a020d496ce87388be0a..7e9eecf153bcdc0c9878cf0e2b8e9fe110a4c1b6 100644
--- a/src/knot/common/log.c
+++ b/src/knot/common/log.c
@@ -207,10 +207,10 @@ void log_levels_add(log_target_t target, log_source_t src, int levels)
 	}
 }
 
-static void emit_log_msg(int level, const char *zone, size_t zone_len, const char *msg)
+static void emit_log_msg(int level, log_source_t src, const char *zone,
+                         size_t zone_len, const char *msg)
 {
 	log_t *log = s_log;
-	log_source_t src = zone ? LOG_SOURCE_ZONE : LOG_SOURCE_SERVER;
 
 	// Syslog target.
 	if (*src_levels(log, LOG_TARGET_SYSLOG, src) & LOG_MASK(level)) {
@@ -289,7 +289,8 @@ static int log_msg_add(char **write, size_t *capacity, const char *fmt, ...)
 	return KNOT_EOK;
 }
 
-static void log_msg_text(int level, const char *zone, const char *fmt, va_list args)
+static void log_msg_text(int level, log_source_t src, const char *zone,
+                         const char *fmt, va_list args)
 {
 	if (!log_isopen()) {
 		return;
@@ -328,36 +329,45 @@ static void log_msg_text(int level, const char *zone, const char *fmt, va_list a
 	int ret = vsnprintf(write, capacity, fmt, args);
 	if (ret >= 0) {
 		// Send to logging targets.
-		emit_log_msg(level, zone, zone_len, buff);
+		emit_log_msg(level, src, zone, zone_len, buff);
 	}
 
 	rcu_read_unlock();
 }
 
-void log_msg(int priority, const char *fmt, ...)
+void log_fmt(int priority, log_source_t src, const char *fmt, ...)
 {
 	va_list args;
 	va_start(args, fmt);
-	log_msg_text(priority, NULL, fmt, args);
+	log_msg_text(priority, src, NULL, fmt, args);
 	va_end(args);
 }
 
-void log_msg_zone(int priority, const knot_dname_t *zone, const char *fmt, ...)
+void log_fmt_zone(int priority, log_source_t src, const knot_dname_t *zone,
+                  const char *fmt, ...)
 {
 	char buff[KNOT_DNAME_TXT_MAXLEN + 1];
 	char *zone_str = knot_dname_to_str(buff, zone, sizeof(buff));
+	if (zone_str == NULL) {
+		zone_str = NULL_ZONE_STR;
+	}
 
 	va_list args;
 	va_start(args, fmt);
-	log_msg_text(priority, zone_str ? zone_str : NULL_ZONE_STR, fmt, args);
+	log_msg_text(priority, src, zone_str, fmt, args);
 	va_end(args);
 }
 
-void log_msg_zone_str(int priority, const char *zone, const char *fmt, ...)
+void log_fmt_zone_str(int priority, log_source_t src, const char *zone,
+                      const char *fmt, ...)
 {
+	if (zone == NULL) {
+		zone = NULL_ZONE_STR;
+	}
+
 	va_list args;
 	va_start(args, fmt);
-	log_msg_text(priority, zone ? zone : NULL_ZONE_STR, fmt, args);
+	log_msg_text(priority, src, zone, fmt, args);
 	va_end(args);
 }
 
diff --git a/src/knot/common/log.h b/src/knot/common/log.h
index 6d84b73fcce47989473d4589d7b2aaf269be41fa..3fb3d0cc5ca9389decc5541480b194756283e223 100644
--- a/src/knot/common/log.h
+++ b/src/knot/common/log.h
@@ -104,54 +104,71 @@ void log_levels_add(log_target_t target, log_source_t src, int levels);
  * Function follows printf() format.
  *
  * \param priority  Message priority.
+ * \param src       Message source.
  * \param fmt       Content of the logged message.
  */
-void log_msg(int priority, const char *fmt, ...)
-	__attribute__((format(printf, 2, 3)));
+void log_fmt(int priority, log_source_t src, const char *fmt, ...)
+__attribute__((format(printf, 3, 4)));
 
 /*!
  * \brief Log message into zone category.
  *
- * \see log_msg
+ * \see log_fmt
  *
  * \param zone  Zone name in wire format.
  */
-void log_msg_zone(int priority, const knot_dname_t *zone, const char *fmt, ...)
-	__attribute__((format(printf, 3, 4)));
+void log_fmt_zone(int priority, log_source_t src, const knot_dname_t *zone, const char *fmt, ...)
+__attribute__((format(printf, 4, 5)));
 
 /*!
  * \brief Log message into zone category.
  *
- * \see log_msg
+ * \see log_fmt
  *
  * \param zone  Zone name as an ASCII string.
  */
-void log_msg_zone_str(int priority, const char *zone, const char *fmt, ...)
-	__attribute__((format(printf, 3, 4)));
+void log_fmt_zone_str(int priority, log_source_t src, const char *zone, const char *fmt, ...)
+__attribute__((format(printf, 4, 5)));
+
+/* Compatibility wrappers. */
+#define log_msg(priority, fmt, ...) log_fmt(priority, LOG_SOURCE_SERVER, fmt, ##__VA_ARGS__)
+#define log_msg_zone(priority, zone, fmt, ...) log_fmt_zone(priority, LOG_SOURCE_ZONE, zone, fmt, ##__VA_ARGS__)
+#define log_msg_zone_str(priority, zone, fmt, ...) log_fmt_zone_str(priority, LOG_SOURCE_ZONE, zone, fmt, ##__VA_ARGS__)
 
 /*!
  * \brief Convenient logging macros.
  */
-#define log_fatal(msg, ...)   log_msg(LOG_CRIT,    msg, ##__VA_ARGS__)
-#define log_error(msg, ...)   log_msg(LOG_ERR,     msg, ##__VA_ARGS__)
-#define log_warning(msg, ...) log_msg(LOG_WARNING, msg, ##__VA_ARGS__)
-#define log_notice(msg, ...)  log_msg(LOG_NOTICE,  msg, ##__VA_ARGS__)
-#define log_info(msg, ...)    log_msg(LOG_INFO,    msg, ##__VA_ARGS__)
-#define log_debug(msg, ...)   log_msg(LOG_DEBUG,   msg, ##__VA_ARGS__)
-
-#define log_zone_fatal(zone, msg, ...)   log_msg_zone(LOG_CRIT,    zone, msg, ##__VA_ARGS__)
-#define log_zone_error(zone, msg, ...)   log_msg_zone(LOG_ERR,     zone, msg, ##__VA_ARGS__)
-#define log_zone_warning(zone, msg, ...) log_msg_zone(LOG_WARNING, zone, msg, ##__VA_ARGS__)
-#define log_zone_notice(zone, msg, ...)  log_msg_zone(LOG_NOTICE,  zone, msg, ##__VA_ARGS__)
-#define log_zone_info(zone, msg, ...)    log_msg_zone(LOG_INFO,    zone, msg, ##__VA_ARGS__)
-#define log_zone_debug(zone, msg, ...)   log_msg_zone(LOG_DEBUG,   zone, msg, ##__VA_ARGS__)
-
-#define log_zone_str_fatal(zone, msg, ...)   log_msg_zone_str(LOG_CRIT,    zone, msg, ##__VA_ARGS__)
-#define log_zone_str_error(zone, msg, ...)   log_msg_zone_str(LOG_ERR,     zone, msg, ##__VA_ARGS__)
-#define log_zone_str_warning(zone, msg, ...) log_msg_zone_str(LOG_WARNING, zone, msg, ##__VA_ARGS__)
-#define log_zone_str_notice(zone, msg, ...)  log_msg_zone_str(LOG_NOTICE,  zone, msg, ##__VA_ARGS__)
-#define log_zone_str_info(zone, msg, ...)    log_msg_zone_str(LOG_INFO,    zone, msg, ##__VA_ARGS__)
-#define log_zone_str_debug(zone, msg, ...)   log_msg_zone_str(LOG_DEBUG,   zone, msg, ##__VA_ARGS__)
+#define log_fatal(msg, ...)   log_fmt(LOG_CRIT,    LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
+#define log_error(msg, ...)   log_fmt(LOG_ERR,     LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
+#define log_warning(msg, ...) log_fmt(LOG_WARNING, LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
+#define log_notice(msg, ...)  log_fmt(LOG_NOTICE,  LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
+#define log_info(msg, ...)    log_fmt(LOG_INFO,    LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
+#define log_debug(msg, ...)   log_fmt(LOG_DEBUG,   LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
+
+#define log_ctl_fatal(msg, ...)   log_fmt(LOG_CRIT,    LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
+#define log_ctl_error(msg, ...)   log_fmt(LOG_ERR,     LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
+#define log_ctl_warning(msg, ...) log_fmt(LOG_WARNING, LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
+#define log_ctl_notice(msg, ...)  log_fmt(LOG_NOTICE,  LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
+#define log_ctl_info(msg, ...)    log_fmt(LOG_INFO,    LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
+#define log_ctl_debug(msg, ...)   log_fmt(LOG_DEBUG,   LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
+
+#define log_ctl_zone_str_error(zone, msg, ...) log_fmt_zone_str(LOG_ERR,   LOG_SOURCE_CONTROL, zone, msg, ##__VA_ARGS__)
+#define log_ctl_zone_str_info(zone, msg, ...)  log_fmt_zone_str(LOG_INFO,  LOG_SOURCE_CONTROL, zone, msg, ##__VA_ARGS__)
+#define log_ctl_zone_str_debug(zone, msg, ...) log_fmt_zone_str(LOG_DEBUG, LOG_SOURCE_CONTROL, zone, msg, ##__VA_ARGS__)
+
+#define log_zone_fatal(zone, msg, ...)   log_fmt_zone(LOG_CRIT,    LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_error(zone, msg, ...)   log_fmt_zone(LOG_ERR,     LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_warning(zone, msg, ...) log_fmt_zone(LOG_WARNING, LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_notice(zone, msg, ...)  log_fmt_zone(LOG_NOTICE,  LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_info(zone, msg, ...)    log_fmt_zone(LOG_INFO,    LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_debug(zone, msg, ...)   log_fmt_zone(LOG_DEBUG,   LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+
+#define log_zone_str_fatal(zone, msg, ...)   log_fmt_zone_str(LOG_CRIT,    LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_str_error(zone, msg, ...)   log_fmt_zone_str(LOG_ERR,     LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_str_warning(zone, msg, ...) log_fmt_zone_str(LOG_WARNING, LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_str_notice(zone, msg, ...)  log_fmt_zone_str(LOG_NOTICE,  LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_str_info(zone, msg, ...)    log_fmt_zone_str(LOG_INFO,    LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
+#define log_zone_str_debug(zone, msg, ...)   log_fmt_zone_str(LOG_DEBUG,   LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
 
 /*!
  * \brief Update open files ownership.