Index: /pjproject/trunk/pjlib/include/pj/config.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/config.h	(revision 3751)
+++ /pjproject/trunk/pjlib/include/pj/config.h	(revision 3752)
@@ -409,4 +409,31 @@
 #endif
 
+/**
+ * Enable log indentation feature.
+ *
+ * Default: 1
+ */
+#ifndef PJ_LOG_ENABLE_INDENT
+#   define PJ_LOG_ENABLE_INDENT        1
+#endif
+
+/**
+ * Number of PJ_LOG_INDENT_CHAR to put every time pj_log_push_indent()
+ * is called.
+ *
+ * Default: 1
+ */
+#ifndef PJ_LOG_INDENT_SIZE
+#   define PJ_LOG_INDENT_SIZE        1
+#endif
+
+/**
+ * Log indentation character.
+ *
+ * Default: space
+ */
+#ifndef PJ_LOG_INDENT_CHAR
+#   define PJ_LOG_INDENT_CHAR	    '.'
+#endif
 
 /**
Index: /pjproject/trunk/pjlib/include/pj/log.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/log.h	(revision 3751)
+++ /pjproject/trunk/pjlib/include/pj/log.h	(revision 3752)
@@ -82,5 +82,7 @@
     PJ_LOG_HAS_COLOR	  = 1024, /**< Colorize logs [yes on win32]	      */
     PJ_LOG_HAS_LEVEL_TEXT = 2048, /**< Include level text string [no]	      */
-    PJ_LOG_HAS_THREAD_ID  = 4096  /**< Include thread identification [no]     */
+    PJ_LOG_HAS_THREAD_ID  = 4096, /**< Include thread identification [no]     */
+    PJ_LOG_HAS_THREAD_SWC = 8192, /**< Add mark when thread has switched [yes]*/
+    PJ_LOG_HAS_INDENT     =16384  /**< Indentation. Say yes! [yes]            */
 };
 
@@ -204,4 +206,23 @@
 PJ_DECL(unsigned) pj_log_get_decor(void);
 
+/**
+ * Add indentation to log message. Indentation will add PJ_LOG_INDENT_CHAR
+ * before the message, and is useful to show the depth of function calls.
+ *
+ * @param indent    The indentation to add or substract. Positive value
+ * 		    adds current indent, negative value subtracts current
+ * 		    indent.
+ */
+PJ_DECL(void) pj_log_add_indent(int indent);
+
+/**
+ * Push indentation to the right by default value (PJ_LOG_INDENT).
+ */
+PJ_DECL(void) pj_log_push_indent(void);
+
+/**
+ * Pop indentation (to the left) by default value (PJ_LOG_INDENT).
+ */
+PJ_DECL(void) pj_log_pop_indent(void);
 
 /**
Index: /pjproject/trunk/pjlib/src/pj/log.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/log.c	(revision 3751)
+++ /pjproject/trunk/pjlib/src/pj/log.c	(revision 3752)
@@ -32,6 +32,15 @@
 #endif
 
+static void *g_last_thread;
+
 #if PJ_HAS_THREADS
 static long thread_suspended_tls_id = -1;
+#  if PJ_LOG_ENABLE_INDENT
+static long thread_indent_tls_id = -1;
+#  endif
+#endif
+
+#if !PJ_LOG_ENABLE_INDENT || !PJ_HAS_THREADS
+static int log_indent;
 #endif
 
@@ -39,5 +48,6 @@
 static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
 			    PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE |
-			    PJ_LOG_HAS_SPACE
+			    PJ_LOG_HAS_SPACE | PJ_LOG_HAS_THREAD_SWC |
+			    PJ_LOG_HAS_INDENT
 #if defined(PJ_WIN32) && PJ_WIN32!=0
 			    | PJ_LOG_HAS_COLOR
@@ -72,4 +82,6 @@
 #endif
 
+#define LOG_MAX_INDENT		80
+
 #if PJ_HAS_THREADS
 static void logging_shutdown(void)
@@ -79,6 +91,58 @@
 	thread_suspended_tls_id = -1;
     }
-}
-#endif
+#  if PJ_LOG_ENABLE_INDENT
+    if (thread_indent_tls_id != -1) {
+	pj_thread_local_free(thread_indent_tls_id);
+	thread_indent_tls_id = -1;
+    }
+#  endif
+}
+#endif	/* PJ_HAS_THREADS */
+
+#if PJ_LOG_ENABLE_INDENT && PJ_HAS_THREADS
+static void log_set_indent(int indent)
+{
+    if (indent < 0) indent = 0;
+    pj_thread_local_set(thread_indent_tls_id, (void*)(long)indent);
+}
+
+static int log_get_raw_indent()
+{
+    return (long)pj_thread_local_get(thread_indent_tls_id);
+}
+
+#else
+static void log_set_indent(int indent)
+{
+    log_indent = indent;
+    if (log_indent < 0) log_indent = 0;
+}
+
+static int log_get_raw_indent()
+{
+    return log_indent;
+}
+#endif	/* PJ_LOG_ENABLE_INDENT && PJ_HAS_THREADS */
+
+static int log_get_indent()
+{
+    int indent = log_get_raw_indent();
+    return indent > LOG_MAX_INDENT ? LOG_MAX_INDENT : indent;
+}
+
+PJ_DEF(void) pj_log_add_indent(int indent)
+{
+    log_set_indent(log_get_raw_indent() + indent);
+}
+
+PJ_DEF(void) pj_log_push_indent(void)
+{
+    pj_log_add_indent(PJ_LOG_INDENT_SIZE);
+}
+
+PJ_DEF(void) pj_log_pop_indent(void)
+{
+    pj_log_add_indent(-PJ_LOG_INDENT_SIZE);
+}
 
 pj_status_t pj_log_init(void)
@@ -86,8 +150,21 @@
 #if PJ_HAS_THREADS
     if (thread_suspended_tls_id == -1) {
-	pj_thread_local_alloc(&thread_suspended_tls_id);
+	pj_status_t status;
+	status = pj_thread_local_alloc(&thread_suspended_tls_id);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+#  if PJ_LOG_ENABLE_INDENT
+	status = pj_thread_local_alloc(&thread_indent_tls_id);
+	if (status != PJ_SUCCESS) {
+	    pj_thread_local_free(thread_suspended_tls_id);
+	    thread_suspended_tls_id = -1;
+	    return status;
+	}
+#  endif
 	pj_atexit(&logging_shutdown);
     }
 #endif
+    g_last_thread = NULL;
     return PJ_SUCCESS;
 }
@@ -243,5 +320,5 @@
     char log_buffer[PJ_LOG_MAX_SIZE];
 #endif
-    int saved_level, len, print_len;
+    int saved_level, len, print_len, indent;
 
     PJ_CHECK_STACK();
@@ -277,5 +354,5 @@
     }
     if (log_decor & PJ_LOG_HAS_YEAR) {
-	*pre++ = ' ';
+	if (pre!=log_buffer) *pre++ = ' ';
 	pre += pj_utoa(ptime.year, pre);
     }
@@ -289,5 +366,5 @@
     }
     if (log_decor & PJ_LOG_HAS_TIME) {
-	*pre++ = ' ';
+	if (pre!=log_buffer) *pre++ = ' ';
 	pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
 	*pre++ = ':';
@@ -303,5 +380,5 @@
 	enum { SENDER_WIDTH = 14 };
 	int sender_len = strlen(sender);
-	*pre++ = ' ';
+	if (pre!=log_buffer) *pre++ = ' ';
 	if (sender_len <= SENDER_WIDTH) {
 	    while (sender_len < SENDER_WIDTH)
@@ -335,7 +412,25 @@
 	*pre++ = ' ';
 
-    if (log_decor & PJ_LOG_HAS_SPACE) {
+    if (log_decor & PJ_LOG_HAS_THREAD_SWC) {
+	void *current_thread = (void*)pj_thread_this();
+	if (current_thread != g_last_thread) {
+	    *pre++ = '!';
+	    g_last_thread = current_thread;
+	} else {
+	    *pre++ = ' ';
+	}
+    } else if (log_decor & PJ_LOG_HAS_SPACE) {
 	*pre++ = ' ';
     }
+
+#if PJ_LOG_ENABLE_INDENT
+    if (log_decor & PJ_LOG_HAS_INDENT) {
+	indent = log_get_indent();
+	if (indent > 0) {
+	    pj_memset(pre, PJ_LOG_INDENT_CHAR, indent);
+	    pre += indent;
+	}
+    }
+#endif
 
     len = pre - log_buffer;
