diff --git a/src/module.c b/src/module.c
index 3bff4779..a71d442c 100644
--- a/src/module.c
+++ b/src/module.c
@@ -2768,6 +2768,30 @@ void RM_EmitAOF(RedisModuleIO *io, const char *cmdname, const char *fmt, ...) {
     return;
 }
 
+/* --------------------------------------------------------------------------
+ * Logging
+ * -------------------------------------------------------------------------- */
+
+/* Produces a log message to the standard Redis log. */
+void RM_Log(RedisModuleCtx *ctx, int level, const char *fmt, ...)
+{
+    va_list ap;
+    char msg[LOG_MAX_LEN];
+    size_t name_len;
+
+    if ((level&0xff) < server.verbosity) return;
+    if (!ctx->module) return;   /* Can only log if module is initialized */
+
+    name_len = snprintf(msg, sizeof(msg),"%s: ", ctx->module->name);
+
+    va_start(ap, fmt);
+    vsnprintf(msg + name_len, sizeof(msg) - name_len, fmt, ap);
+    va_end(ap);
+
+    serverLogRaw(level,msg);
+}
+
+
 /* --------------------------------------------------------------------------
  * Modules API internals
  * -------------------------------------------------------------------------- */
@@ -2886,6 +2910,7 @@ void moduleRegisterCoreAPI(void) {
     REGISTER_API(SaveDouble);
     REGISTER_API(LoadDouble);
     REGISTER_API(EmitAOF);
+    REGISTER_API(Log);
 }
 
 /* Global initialization at Redis startup. */
diff --git a/src/modules/API.md b/src/modules/API.md
index e03edf6a..24768c5b 100644
--- a/src/modules/API.md
+++ b/src/modules/API.md
@@ -1115,3 +1115,11 @@ by a module. The command works exactly like `RedisModule_Call()` in the way
 the parameters are passed, but it does not return anything as the error
 handling is performed by Redis itself.
 
+## `RM_Log`
+
+    void RM_Log(RedisModuleCtx *ctx, int level, const char *fmt, ...);
+
+Produce a log message into the standard Redis log. All standard Redis logging
+configuration applies here. Messages can only be logged after a module has
+initialized, and are prefixed by the name of the module.  Log level is
+specified using the REDISMODULE_LOG_* macros.
diff --git a/src/redismodule.h b/src/redismodule.h
index 618b39e4..aa43a736 100644
--- a/src/redismodule.h
+++ b/src/redismodule.h
@@ -68,6 +68,13 @@
 #define REDISMODULE_POSITIVE_INFINITE (1.0/0.0)
 #define REDISMODULE_NEGATIVE_INFINITE (-1.0/0.0)
 
+/* Logging levels */
+#define REDISMODULE_LOG_DEBUG 0
+#define REDISMODULE_LOG_VERBOSE 1
+#define REDISMODULE_LOG_NOTICE 2
+#define REDISMODULE_LOG_WARNING 3
+
+
 /* ------------------------- End of common defines ------------------------ */
 
 #ifndef REDISMODULE_CORE
@@ -180,6 +187,7 @@ RedisModuleString *REDISMODULE_API_FUNC(RedisModule_LoadString)(RedisModuleIO *i
 char *REDISMODULE_API_FUNC(RedisModule_LoadStringBuffer)(RedisModuleIO *io, size_t *lenptr);
 void REDISMODULE_API_FUNC(RedisModule_SaveDouble)(RedisModuleIO *io, double value);
 double REDISMODULE_API_FUNC(RedisModule_LoadDouble)(RedisModuleIO *io);
+void REDISMODULE_API_FUNC(RedisModule_Log)(RedisModuleCtx *ctx, int level, const char *fmt, ...);
 
 /* This is included inline inside each Redis module. */
 static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int apiver) __attribute__((unused));
@@ -270,6 +278,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
     REDISMODULE_GET_API(SaveDouble);
     REDISMODULE_GET_API(LoadDouble);
     REDISMODULE_GET_API(EmitAOF);
+    REDISMODULE_GET_API(Log);
 
     RedisModule_SetModuleAttribs(ctx,name,ver,apiver);
     return REDISMODULE_OK;