diff --git a/include/spdlog/common.h b/include/spdlog/common.h
index a7d2a7de2ba2b122113ddb1d0e6d3281ee1495c3..31a1eb812750058707197b13f16d66048d96c2a9 100644
--- a/include/spdlog/common.h
+++ b/include/spdlog/common.h
@@ -52,8 +52,8 @@
 #endif
 
 
-// Get the basename of __FILE__ (at compile time if possible) 
-#if FMT_HAS_FEATURE(__builtin_strrchr) 
+// Get the basename of __FILE__ (at compile time if possible)
+#if FMT_HAS_FEATURE(__builtin_strrchr)
 #define SPDLOG_STRRCHR(str, sep) __builtin_strrchr(str, sep)
 #else
 #define SPDLOG_STRRCHR(str, sep) strrchr(str, sep)
@@ -204,11 +204,13 @@ struct source_loc
     SPDLOG_CONSTEXPR source_loc()
         : filename{""}
         , line{0}
+        , funcname{""}
     {
     }
-    SPDLOG_CONSTEXPR source_loc(const char *filename, int line)
+    SPDLOG_CONSTEXPR source_loc(const char *filename, int line, const char *funcname)
         : filename{filename}
         , line{static_cast<uint32_t>(line)}
+        , funcname{funcname}
     {
     }
 
@@ -218,6 +220,7 @@ struct source_loc
     }
     const char *filename;
     uint32_t line;
+    const char *funcname;
 };
 
 namespace details {
diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h
index e049f78bd0082ca73fe6a51e80de32395536e6fa..b63857a3a865c625a324b42e4c3487b4c38bb3bc 100644
--- a/include/spdlog/details/pattern_formatter.h
+++ b/include/spdlog/details/pattern_formatter.h
@@ -895,6 +895,26 @@ public:
         }
     }
 };
+// print source funcname
+class source_funcname_formatter final : public flag_formatter
+{
+public:
+    explicit source_funcname_formatter(padding_info padinfo)
+        : flag_formatter(padinfo){};
+
+    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
+    {
+        if (msg.source.empty())
+        {
+            return;
+        }
+        scoped_pad p(msg.source.funcname, padinfo_, dest);
+        fmt_helper::append_string_view(msg.source.funcname, dest);
+#ifdef SPDLOG_FUNCTION_SUFFIX
+        fmt_helper::append_string_view(SPDLOG_FUNCTION_SUFFIX, dest);
+#endif
+    }
+};
 
 // Full info formatter
 // pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
@@ -1216,6 +1236,10 @@ private:
             formatters_.push_back(details::make_unique<details::source_linenum_formatter>(padding));
             break;
 
+        case ('!'): // source funcname
+            formatters_.push_back(details::make_unique<details::source_funcname_formatter>(padding));
+            break;
+
         case ('%'): // % char
             formatters_.push_back(details::make_unique<details::ch_formatter>('%'));
             break;
diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h
index 408c86e2a279454b33a4847377bd1f76b5b44217..8e33fef02f5e198704506d392aea60eadbae8598 100644
--- a/include/spdlog/spdlog.h
+++ b/include/spdlog/spdlog.h
@@ -313,10 +313,20 @@ inline void critical(const wchar_t *fmt, const Args &... args)
 // SPDLOG_LEVEL_OFF
 //
 
+#ifndef SPDLOG_FUNCTION
+    #define SPDLOG_FUNCTION __FUNCTION__
+#endif
+
+#ifdef SPDLOG_SOURCE_MACROS_ON
+    #define SPDLOG_LOG_MACRO(...) log(spdlog::source_loc{SPDLOG_FILE_BASENAME(__FILE__), __LINE__, SPDLOG_FUNCTION}, __VA_ARGS__)
+#else
+    #define SPDLOG_LOG_MACRO(...) log(__VA_ARGS__)
+#endif
+
 #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE
 #define SPDLOG_LOGGER_TRACE(logger, ...)\
     if(logger->should_log(spdlog::level::trace))\
-        logger->log(spdlog::source_loc{SPDLOG_FILE_BASENAME(__FILE__), __LINE__}, spdlog::level::trace, __VA_ARGS__)
+        logger->SPDLOG_LOG_MACRO(spdlog::level::trace, __VA_ARGS__)
 #define SPDLOG_TRACE(...) SPDLOG_LOGGER_TRACE(spdlog::default_logger_raw(), __VA_ARGS__)
 #else
 #define SPDLOG_LOGGER_TRACE(logger, ...) (void)0
@@ -324,7 +334,7 @@ inline void critical(const wchar_t *fmt, const Args &... args)
 #endif
 
 #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG
-#define SPDLOG_LOGGER_DEBUG(logger, ...) logger->log(spdlog::level::debug, __VA_ARGS__)
+#define SPDLOG_LOGGER_DEBUG(logger, ...) logger->SPDLOG_LOG_MACRO(spdlog::level::debug, __VA_ARGS__)
 #define SPDLOG_DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__)
 #else
 #define SPDLOG_LOGGER_DEBUG(logger, ...) (void)0
@@ -332,7 +342,7 @@ inline void critical(const wchar_t *fmt, const Args &... args)
 #endif
 
 #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_INFO
-#define SPDLOG_LOGGER_INFO(logger, ...) logger->log(spdlog::level::info, __VA_ARGS__)
+#define SPDLOG_LOGGER_INFO(logger, ...) logger->SPDLOG_LOG_MACRO(spdlog::level::info, __VA_ARGS__)
 #define SPDLOG_INFO(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__)
 #else
 #define SPDLOG_LOGGER_INFO(logger, ...) (void)0
@@ -340,7 +350,7 @@ inline void critical(const wchar_t *fmt, const Args &... args)
 #endif
 
 #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_WARN
-#define SPDLOG_LOGGER_WARN(logger, ...) logger->log(spdlog::level::warn, __VA_ARGS__)
+#define SPDLOG_LOGGER_WARN(logger, ...) logger->SPDLOG_LOG_MACRO(spdlog::level::warn, __VA_ARGS__)
 #define SPDLOG_WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__)
 #else
 #define SPDLOG_LOGGER_WARN(logger, ...) (void)0
@@ -348,7 +358,7 @@ inline void critical(const wchar_t *fmt, const Args &... args)
 #endif
 
 #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_ERROR
-#define SPDLOG_LOGGER_ERROR(logger, ...) logger->log(spdlog::level::err, __VA_ARGS__)
+#define SPDLOG_LOGGER_ERROR(logger, ...) logger->SPDLOG_LOG_MACRO(spdlog::level::err, __VA_ARGS__)
 #define SPDLOG_ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__)
 #else
 #define SPDLOG_LOGGER_ERROR(logger, ...) (void)0
@@ -356,7 +366,7 @@ inline void critical(const wchar_t *fmt, const Args &... args)
 #endif
 
 #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_CRITICAL
-#define SPDLOG_LOGGER_CRITICAL(logger, ...) logger->log(spdlog::level::critical, __VA_ARGS__)
+#define SPDLOG_LOGGER_CRITICAL(logger, ...) logger->SPDLOG_LOG_MACRO(spdlog::level::critical, __VA_ARGS__)
 #define SPDLOG_CRITICAL(...) SPDLOG_LOGGER_CRITICAL(spdlog::default_logger_raw(), __VA_ARGS__)
 #else
 #define SPDLOG_LOGGER_CRITICAL(logger, ...) (void)0
diff --git a/include/spdlog/tweakme.h b/include/spdlog/tweakme.h
index f76cd0c4a63811a4fe6e0dcc8b28f6df10543e3b..82ee90ef2c74b958cdbe1a95ae16f22535723e19 100644
--- a/include/spdlog/tweakme.h
+++ b/include/spdlog/tweakme.h
@@ -133,4 +133,27 @@
 // Macros like SPDLOG_DEBUG(..), SPDLOG_INFO(..)  will expand to empty statements if not enabled
 //
 // #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment to enable file name, file number and function name macros.
+// Used in macros like SPDLOG_DEBUG(..), SPDLOG_INFO(..) etc
+//
+// #define SPDLOG_SOURCE_MACROS_ON
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment (and change if desired) macro to use for function names.
+// This is compiler dependent.
+// __PRETTY_FUNCTION__ might be nicer in clang/gcc, and __FUNCTION__ in msvc.
+// Defaults to __FUNCTION__ (should work on all compilers) if not defined.
+//
+// #define SPDLOG_FUNCTION __PRETTY_FUNCTION__
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment (and change if desired) string to add to the end of functions names.
+// Used in macros like SPDLOG_DEBUG(..), SPDLOG_INFO(..) etc
+//
+// #define SPDLOG_FUNCTION_SUFFIX "()"
 ///////////////////////////////////////////////////////////////////////////////
\ No newline at end of file