diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 7526f60d..0ac6c903 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1881,6 +1881,44 @@ ngx_escape_json(u_char *dst, u_char *src, size_t size)
 }
 
 
+uintptr_t
+ngx_escape_rfc5424sd(u_char *dst, u_char *src, size_t size)
+{
+    u_char      ch;
+    ngx_uint_t  len;
+
+    if (dst == NULL) {
+        len = 0;
+
+        while (size) {
+            ch = *src++;
+
+            if (ch == '\\' || ch == '"' || ch == ']') {
+                len++;
+            }
+
+            size--;
+        }
+
+        return (uintptr_t) len;
+    }
+
+    while (size) {
+        ch = *src++;
+
+        if (ch == '\\' || ch == '"' || ch == ']') {
+            *dst++ = '\\';
+        }
+
+        *dst++ = ch;
+
+        size--;
+    }
+
+    return (uintptr_t) dst;
+}
+
+
 void
 ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,
     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index 7363bd24..ebe07926 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -208,6 +208,7 @@ uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size,
 void ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type);
 uintptr_t ngx_escape_html(u_char *dst, u_char *src, size_t size);
 uintptr_t ngx_escape_json(u_char *dst, u_char *src, size_t size);
+uintptr_t ngx_escape_rfc5424sd(u_char *dst, u_char *src, size_t size);
 
 
 typedef struct {
diff --git a/src/core/ngx_syslog.c b/src/core/ngx_syslog.c
index 0a67928e..6c631a66 100644
--- a/src/core/ngx_syslog.c
+++ b/src/core/ngx_syslog.c
@@ -197,6 +197,9 @@ ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
         } else if (len == 10 && ngx_strncmp(p, "nohostname", 10) == 0) {
             peer->nohostname = 1;
 
+        } else if (len == 7 && ngx_strncmp(p, "rfc5424", 7) == 0) {
+            peer->rfc5424 = 1;
+
         } else {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "unknown syslog parameter \"%s\"", p);
@@ -223,6 +226,20 @@ ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf)
 
     pri = peer->facility * 8 + peer->severity;
 
+    if (peer->rfc5424) {
+        /*
+         * MSGID and PROCID are NILVALUEs.
+         */
+        if (peer->nohostname) {
+            return ngx_sprintf(buf, "<%ui>1 %V - %V - - ", pri,
+                               &ngx_cached_http_log_iso8601, &peer->tag);
+        }
+
+        return ngx_sprintf(buf, "<%ui>1 %V %V %V - - ", pri,
+                           &ngx_cached_http_log_iso8601, &ngx_cycle->hostname,
+                           &peer->tag);
+    }
+
     if (peer->nohostname) {
         return ngx_sprintf(buf, "<%ui>%V %V: ", pri, &ngx_cached_syslog_time,
                            &peer->tag);
diff --git a/src/core/ngx_syslog.h b/src/core/ngx_syslog.h
index cc4c842c..98daf611 100644
--- a/src/core/ngx_syslog.h
+++ b/src/core/ngx_syslog.h
@@ -18,6 +18,7 @@ typedef struct {
     ngx_connection_t  conn;
     unsigned          busy:1;
     unsigned          nohostname:1;
+    unsigned          rfc5424:1;
 } ngx_syslog_peer_t;
 
 
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index 917ed55f..02813b9a 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -14,6 +14,11 @@
 #endif
 
 
+#define NGX_FMT_ESCAPE_DEFAULT          0
+#define NGX_FMT_ESCAPE_JSON             1
+#define NGX_FMT_ESCAPE_RFC5424SD        2
+
+
 typedef struct ngx_http_log_op_s  ngx_http_log_op_t;
 
 typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
@@ -126,7 +131,7 @@ static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
 
 static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
-    ngx_http_log_op_t *op, ngx_str_t *value, ngx_uint_t json);
+    ngx_http_log_op_t *op, ngx_str_t *value, ngx_uint_t escape);
 static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
     uintptr_t data);
 static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
@@ -136,6 +141,10 @@ static size_t ngx_http_log_json_variable_getlen(ngx_http_request_t *r,
     uintptr_t data);
 static u_char *ngx_http_log_json_variable(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
+static size_t ngx_http_log_rfc5424sd_variable_getlen(ngx_http_request_t *r,
+    uintptr_t data);
+static u_char *ngx_http_log_rfc5424sd_variable(ngx_http_request_t *r,
+    u_char *buf, ngx_http_log_op_t *op);
 
 
 static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
@@ -905,7 +914,7 @@ ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
 
 static ngx_int_t
 ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
-    ngx_str_t *value, ngx_uint_t json)
+    ngx_str_t *value, ngx_uint_t escape)
 {
     ngx_int_t  index;
 
@@ -916,13 +925,21 @@ ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
 
     op->len = 0;
 
-    if (json) {
+    switch (escape) {
+    case NGX_FMT_ESCAPE_JSON:
         op->getlen = ngx_http_log_json_variable_getlen;
         op->run = ngx_http_log_json_variable;
+        break;
 
-    } else {
+    case NGX_FMT_ESCAPE_RFC5424SD:
+        op->getlen = ngx_http_log_rfc5424sd_variable_getlen;
+        op->run = ngx_http_log_rfc5424sd_variable;
+        break;
+
+    default:
         op->getlen = ngx_http_log_variable_getlen;
         op->run = ngx_http_log_variable;
+        break;
     }
 
     op->data = index;
@@ -1033,6 +1050,47 @@ ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
 
 
 static size_t
+ngx_http_log_rfc5424sd_variable_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+    uintptr_t                   len;
+    ngx_http_variable_value_t  *value;
+
+    value = ngx_http_get_indexed_variable(r, data);
+
+    if (value == NULL || value->not_found) {
+        return 0;
+    }
+
+    len = ngx_escape_rfc5424sd(NULL, value->data, value->len);
+
+    value->escape = len ? 1 : 0;
+
+    return value->len + len;
+}
+
+
+static u_char *
+ngx_http_log_rfc5424sd_variable(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    ngx_http_variable_value_t  *value;
+
+    value = ngx_http_get_indexed_variable(r, op->data);
+
+    if (value == NULL || value->not_found) {
+        return buf;
+    }
+
+    if (value->escape == 0) {
+        return ngx_cpymem(buf, value->data, value->len);
+
+    } else {
+        return (u_char *) ngx_escape_rfc5424sd(buf, value->data, value->len);
+    }
+}
+
+
+static size_t
 ngx_http_log_json_variable_getlen(ngx_http_request_t *r, uintptr_t data)
 {
     uintptr_t                   len;
@@ -1536,18 +1594,21 @@ ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
     size_t               i, len;
     ngx_str_t           *value, var;
     ngx_int_t           *flush;
-    ngx_uint_t           bracket, json;
+    ngx_uint_t           bracket, escape;
     ngx_http_log_op_t   *op;
     ngx_http_log_var_t  *v;
 
-    json = 0;
+    escape = NGX_FMT_ESCAPE_DEFAULT;
     value = args->elts;
 
     if (s < args->nelts && ngx_strncmp(value[s].data, "escape=", 7) == 0) {
         data = value[s].data + 7;
 
         if (ngx_strcmp(data, "json") == 0) {
-            json = 1;
+            escape = NGX_FMT_ESCAPE_JSON;
+
+        } else if (ngx_strcmp(data, "rfc5424sd") == 0) {
+            escape = NGX_FMT_ESCAPE_RFC5424SD;
 
         } else if (ngx_strcmp(data, "default") != 0) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -1636,7 +1697,7 @@ ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
                     }
                 }
 
-                if (ngx_http_log_variable_compile(cf, op, &var, json)
+                if (ngx_http_log_variable_compile(cf, op, &var, escape)
                     != NGX_OK)
                 {
                     return NGX_CONF_ERROR;
diff --git a/src/stream/ngx_stream_log_module.c b/src/stream/ngx_stream_log_module.c
index 466bdda5..ad28397e 100644
--- a/src/stream/ngx_stream_log_module.c
+++ b/src/stream/ngx_stream_log_module.c
@@ -14,6 +14,11 @@
 #endif
 
 
+#define NGX_FMT_ESCAPE_DEFAULT          0
+#define NGX_FMT_ESCAPE_JSON             1
+#define NGX_FMT_ESCAPE_RFC5424SD        2
+
+
 typedef struct ngx_stream_log_op_s  ngx_stream_log_op_t;
 
 typedef u_char *(*ngx_stream_log_op_run_pt) (ngx_stream_session_t *s,
@@ -106,7 +111,7 @@ static void ngx_stream_log_flush(ngx_open_file_t *file, ngx_log_t *log);
 static void ngx_stream_log_flush_handler(ngx_event_t *ev);
 
 static ngx_int_t ngx_stream_log_variable_compile(ngx_conf_t *cf,
-    ngx_stream_log_op_t *op, ngx_str_t *value, ngx_uint_t json);
+    ngx_stream_log_op_t *op, ngx_str_t *value, ngx_uint_t escape);
 static size_t ngx_stream_log_variable_getlen(ngx_stream_session_t *s,
     uintptr_t data);
 static u_char *ngx_stream_log_variable(ngx_stream_session_t *s, u_char *buf,
@@ -116,6 +121,10 @@ static size_t ngx_stream_log_json_variable_getlen(ngx_stream_session_t *s,
     uintptr_t data);
 static u_char *ngx_stream_log_json_variable(ngx_stream_session_t *s,
     u_char *buf, ngx_stream_log_op_t *op);
+static size_t ngx_stream_log_rfc5424sd_variable_getlen(ngx_stream_session_t *s,
+    uintptr_t data);
+static u_char *ngx_stream_log_rfc5424sd_variable(ngx_stream_session_t *s,
+    u_char *buf, ngx_stream_log_op_t *op);
 
 
 static void *ngx_stream_log_create_main_conf(ngx_conf_t *cf);
@@ -682,7 +691,7 @@ ngx_stream_log_copy_long(ngx_stream_session_t *s, u_char *buf,
 
 static ngx_int_t
 ngx_stream_log_variable_compile(ngx_conf_t *cf, ngx_stream_log_op_t *op,
-    ngx_str_t *value, ngx_uint_t json)
+    ngx_str_t *value, ngx_uint_t escape)
 {
     ngx_int_t  index;
 
@@ -693,11 +702,18 @@ ngx_stream_log_variable_compile(ngx_conf_t *cf, ngx_stream_log_op_t *op,
 
     op->len = 0;
 
-    if (json) {
+    switch (escape) {
+    case NGX_FMT_ESCAPE_JSON:
         op->getlen = ngx_stream_log_json_variable_getlen;
         op->run = ngx_stream_log_json_variable;
+        break;
 
-    } else {
+    case NGX_FMT_ESCAPE_RFC5424SD:
+        op->getlen = ngx_stream_log_rfc5424sd_variable_getlen;
+        op->run = ngx_stream_log_rfc5424sd_variable;
+        break;
+
+    default:
         op->getlen = ngx_stream_log_variable_getlen;
         op->run = ngx_stream_log_variable;
     }
@@ -811,6 +827,47 @@ ngx_stream_log_escape(u_char *dst, u_char *src, size_t size)
 
 
 static size_t
+ngx_stream_log_rfc5424sd_variable_getlen(ngx_stream_session_t *s, uintptr_t data)
+{
+    uintptr_t                     len;
+    ngx_stream_variable_value_t  *value;
+
+    value = ngx_stream_get_indexed_variable(s, data);
+
+    if (value == NULL || value->not_found) {
+        return 0;
+    }
+
+    len = ngx_escape_rfc5424sd(NULL, value->data, value->len);
+
+    value->escape = len ? 1 : 0;
+
+    return value->len + len;
+}
+
+
+static u_char *
+ngx_stream_log_rfc5424sd_variable(ngx_stream_session_t *s, u_char *buf,
+    ngx_stream_log_op_t *op)
+{
+    ngx_stream_variable_value_t  *value;
+
+    value = ngx_stream_get_indexed_variable(s, op->data);
+
+    if (value == NULL || value->not_found) {
+        return buf;
+    }
+
+    if (value->escape == 0) {
+        return ngx_cpymem(buf, value->data, value->len);
+
+    } else {
+        return (u_char *) ngx_escape_rfc5424sd(buf, value->data, value->len);
+    }
+}
+
+
+static size_t
 ngx_stream_log_json_variable_getlen(ngx_stream_session_t *s, uintptr_t data)
 {
     uintptr_t                     len;
@@ -1265,17 +1322,20 @@ ngx_stream_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
     size_t                 i, len;
     ngx_str_t             *value, var;
     ngx_int_t             *flush;
-    ngx_uint_t             bracket, json;
+    ngx_uint_t             bracket, escape;
     ngx_stream_log_op_t   *op;
 
-    json = 0;
+    escape = NGX_FMT_ESCAPE_DEFAULT;
     value = args->elts;
 
     if (s < args->nelts && ngx_strncmp(value[s].data, "escape=", 7) == 0) {
         data = value[s].data + 7;
 
         if (ngx_strcmp(data, "json") == 0) {
-            json = 1;
+            escape = NGX_FMT_ESCAPE_JSON;
+
+        } else if (ngx_strcmp(data, "rfc5424sd") == 0) {
+            escape = NGX_FMT_ESCAPE_RFC5424SD;
 
         } else if (ngx_strcmp(data, "default") != 0) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -1350,7 +1410,7 @@ ngx_stream_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
                     goto invalid;
                 }
 
-                if (ngx_stream_log_variable_compile(cf, op, &var, json)
+                if (ngx_stream_log_variable_compile(cf, op, &var, escape)
                     != NGX_OK)
                 {
                     return NGX_CONF_ERROR;
