diff --git a/mongoose.c b/mongoose.c
index 0f291723ba25e87044af3265b804560485b293f6..fe7bb00edbfeeceed93c83b24112a938df0f4cac 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -428,6 +428,9 @@ int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len) {
 extern "C" {
 #endif /* __cplusplus */
 
+/*
+ * Log level; `LL_INFO` is the default. Use `cs_log_set_level()` to change it.
+ */
 enum cs_log_level {
   LL_NONE = -1,
   LL_ERROR = 0,
@@ -440,12 +443,54 @@ enum cs_log_level {
   _LL_MAX = 5,
 };
 
-/* Set log level. */
+/*
+ * Set max log level to print; messages with the level above the given one will
+ * not be printed.
+ */
 void cs_log_set_level(enum cs_log_level level);
 
-/* Set log filter. NULL (a default) logs everything. */
-void cs_log_set_filter(const char *source_file_name);
+/*
+ * Set log filter. NULL (a default) logs everything.
+ * Otherwise, function name and file name will be tested against the given
+ * pattern, and only matching messages will be printed.
+ *
+ * For the pattern syntax, refer to `mg_match_prefix()` in `str_util.h`.
+ *
+ * Example:
+ * ```c
+ * void foo(void) {
+ *   LOG(LL_INFO, ("hello from foo"));
+ * }
+ *
+ * void bar(void) {
+ *   LOG(LL_INFO, ("hello from bar"));
+ * }
+ *
+ * void test(void) {
+ *   cs_log_set_filter(NULL);
+ *   foo();
+ *   bar();
+ *
+ *   cs_log_set_filter("f*");
+ *   foo();
+ *   bar(); // Will NOT print anything
+ *
+ *   cs_log_set_filter("bar");
+ *   foo(); // Will NOT print anything
+ *   bar();
+ * }
+ * ```
+ */
+void cs_log_set_filter(const char *pattern);
 
+/*
+ * Helper function which prints message prefix with the given `level`, function
+ * name `func` and `filename`. If message should be printed (accordingly to the
+ * current log level and filter), prints the prefix and returns 1, otherwise
+ * returns 0.
+ *
+ * Clients should typically just use `LOG()` macro.
+ */
 int cs_log_print_prefix(enum cs_log_level level, const char *func,
                         const char *filename);
 
@@ -453,13 +498,29 @@ extern enum cs_log_level cs_log_threshold;
 
 #if CS_ENABLE_STDIO
 
+/*
+ * Set file to write logs into. If `NULL`, logs go to `stderr`.
+ */
 void cs_log_set_file(FILE *file);
+
+/*
+ * Prints log to the current log file, appends "\n" in the end and flushes the
+ * stream.
+ */
 void cs_log_printf(const char *fmt, ...)
 #ifdef __GNUC__
     __attribute__((format(printf, 1, 2)))
 #endif
     ;
 
+/*
+ * Format and print message `x` with the given level `l`. Example:
+ *
+ * ```c
+ * LOG(LL_INFO, ("my info message: %d", 123));
+ * LOG(LL_DEBUG, ("my debug message: %d", 123));
+ * ```
+ */
 #define LOG(l, x)                                                    \
   do {                                                               \
     if (cs_log_print_prefix(l, __func__, __FILE__)) cs_log_printf x; \
@@ -467,6 +528,9 @@ void cs_log_printf(const char *fmt, ...)
 
 #ifndef CS_NDEBUG
 
+/*
+ * Shortcut for `LOG(LL_VERBOSE_DEBUG, (...))`
+ */
 #define DBG(x) LOG(LL_VERBOSE_DEBUG, x)
 
 #else /* NDEBUG */
@@ -524,12 +588,12 @@ double cs_log_ts WEAK;
 
 enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
 
-void cs_log_set_filter(const char *str) WEAK;
-void cs_log_set_filter(const char *str) {
+void cs_log_set_filter(const char *pattern) WEAK;
+void cs_log_set_filter(const char *pattern) {
   free(s_filter_pattern);
-  if (str != NULL) {
-    s_filter_pattern = strdup(str);
-    s_filter_pattern_len = strlen(str);
+  if (pattern != NULL) {
+    s_filter_pattern = strdup(pattern);
+    s_filter_pattern_len = strlen(pattern);
   } else {
     s_filter_pattern = NULL;
     s_filter_pattern_len = 0;