diff --git a/mongoose.c b/mongoose.c
index 10d3924d0ef6a7b6fce923cbde2e6c8645796cc8..66563fcf14d92ab4aab9f56d2b2b8d87df33faaa 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -223,36 +223,34 @@ enum cs_log_level {
   _LL_MAX = 5,
 };
 
+/* Set log level. */
 void cs_log_set_level(enum cs_log_level level);
 
+/* Set log filter. NULL (a default) logs everything. */
+void cs_log_set_filter(char *source_file_name);
+
+int cs_log_print_prefix(enum cs_log_level level, const char *func,
+                        const char *filename);
+
+extern enum cs_log_level cs_log_threshold;
+
 #if CS_ENABLE_STDIO
 
 void cs_log_set_file(FILE *file);
-extern enum cs_log_level cs_log_threshold;
-void cs_log_print_prefix(enum cs_log_level level, const char *func);
 void cs_log_printf(const char *fmt, ...)
 #ifdef __GNUC__
     __attribute__((format(printf, 1, 2)))
 #endif
     ;
 
-#define LOG(l, x)                       \
-  do {                                  \
-    if (cs_log_threshold >= l) {        \
-      cs_log_print_prefix(l, __func__); \
-      cs_log_printf x;                  \
-    }                                   \
+#define LOG(l, x)                                                    \
+  do {                                                               \
+    if (cs_log_print_prefix(l, __func__, __FILE__)) cs_log_printf x; \
   } while (0)
 
 #ifndef CS_NDEBUG
 
-#define DBG(x)                                         \
-  do {                                                 \
-    if (cs_log_threshold >= LL_VERBOSE_DEBUG) {        \
-      cs_log_print_prefix(LL_VERBOSE_DEBUG, __func__); \
-      cs_log_printf x;                                 \
-    }                                                  \
-  } while (0)
+#define DBG(x) LOG(LL_VERBOSE_DEBUG, x)
 
 #else /* NDEBUG */
 
@@ -287,6 +285,7 @@ void cs_log_printf(const char *fmt, ...)
 #include <string.h>
 
 /* Amalgamated: #include "common/cs_time.h" */
+/* Amalgamated: #include "common/str_util.h" */
 
 enum cs_log_level cs_log_threshold WEAK =
 #if CS_ENABLE_DEBUG
@@ -295,6 +294,9 @@ enum cs_log_level cs_log_threshold WEAK =
     LL_ERROR;
 #endif
 
+static char *s_filter_pattern = NULL;
+static size_t s_filter_pattern_len;
+
 #if CS_ENABLE_STDIO
 
 FILE *cs_log_file WEAK = NULL;
@@ -305,9 +307,30 @@ double cs_log_ts WEAK;
 
 enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
 
-void cs_log_print_prefix(enum cs_log_level level, const char *func) WEAK;
-void cs_log_print_prefix(enum cs_log_level level, const char *func) {
+void cs_log_set_filter(char *str) WEAK;
+void cs_log_set_filter(char *str) {
+  free(s_filter_pattern);
+  if (str != NULL) {
+    s_filter_pattern = strdup(str);
+    s_filter_pattern_len = strlen(str);
+  } else {
+    s_filter_pattern = NULL;
+    s_filter_pattern_len = 0;
+  }
+};
+
+int cs_log_print_prefix(enum cs_log_level, const char *, const char *) WEAK;
+int cs_log_print_prefix(enum cs_log_level level, const char *func,
+                        const char *filename) {
   char prefix[21];
+
+  if (level > cs_log_threshold) return 0;
+  if (s_filter_pattern != NULL &&
+      mg_match_prefix(s_filter_pattern, s_filter_pattern_len, func) < 0 &&
+      mg_match_prefix(s_filter_pattern, s_filter_pattern_len, filename) < 0) {
+    return 0;
+  }
+
   strncpy(prefix, func, 20);
   prefix[20] = '\0';
   if (cs_log_file == NULL) cs_log_file = stderr;
@@ -320,6 +343,7 @@ void cs_log_print_prefix(enum cs_log_level level, const char *func) {
     cs_log_ts = now;
   }
 #endif
+  return 1;
 }
 
 void cs_log_printf(const char *fmt, ...) WEAK;