diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index d2e5b08..0d46d38 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1589,6 +1589,28 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
       </para>
       </listitem>
     </varlistentry>
+
+     <varlistentry id="libpq-connect-log-dir" xreflabel="logdir">
+      <term><literal>logdir</literal></term>
+      <listitem>
+       <para>
+        Path of directory where log file written. When both <literal>logdir</literal>
+        and <literal>logsize</literal> is set, logging is enabled.
+      </para>
+     </listitem>
+    </varlistentry>
+
+     <varlistentry id="libpq-connect-log-size" xreflabel="logsize">
+      <term><literal>logsize</literal></term>
+      <listitem>
+       <para>
+        Maximum log size. The unit is megabyte. When the log file size exceeds 
+        to <literal>logsize</literal>, the log is output to another file. 
+        When both <literal>logdir</literal> and <literal>logsize</literal> is set, 
+        logging is enabled.
+      </para>
+     </listitem>
+    </varlistentry>
     </variablelist>
    </para>
   </sect2>
@@ -7472,6 +7494,26 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
       linkend="libpq-connect-target-session-attrs"/> connection parameter.
      </para>
     </listitem>
+
+    <listitem>
+     <para>
+      <indexterm>
+       <primary><envar>PGLOGDIR</envar></primary>
+      </indexterm>
+      <envar>PGLOGDIR</envar> behaves the same as the <xref
+      linkend="libpq-connect-log-dir"/> connection parameter.
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      <indexterm>
+       <primary><envar>PGLOGSIZE</envar></primary>
+      </indexterm>
+      <envar>PGLOGSIZE</envar> behaves the same as the <xref
+      linkend="libpq-connect-log-size"/> connection parameter.
+     </para>
+    </listitem>
    </itemizedlist>
   </para>
 
@@ -8300,6 +8342,35 @@ int PQisthreadsafe();
   </para>
  </sect1>
 
+ <sect1 id="libpq-logging">
+  <title>Logging</title>
+
+  <indexterm zone="libpq-logging">
+   <primary>trace log</primary>
+  </indexterm>
+  <indexterm zone="libpq-logging">
+   <primary>logging</primary>
+  </indexterm>
+
+  <para>
+   Libpq trace log can trace information about SQL queries which issued by 
+   the libpq application. This output help determine whether the couse is 
+   on backend side or application side and solve issues with the libpq Driver 
+   when it use. The log without requiring recompile of the libpq application.
+  </para>
+
+  <para>
+   You can activate this log by setting both <parameter>logdir</parameter> and 
+   <parameter>logsize</parameter> of the connection string, or by setting both 
+   the environment variables <envar>PGLOGDIR</envar> and <envar>PGLOGSIZE</envar>.
+   The log trace file is written in a directory setting by <envar>PGLOGDIR</envar> 
+   or <parameter>logdir</parameter>.
+   The file name is determined as <filename>libpq-%ProcessID-%Y-%m-%d_%H%M%S.log</filename>.
+   If the setting of the file path by the connection string or the environment variable is 
+   incorrect, the log file is not created in the intended location. 
+   The maximum log file size you set is output to the beginning of the file, so you can check it.
+  </para>
+ </sect1>
 
  <sect1 id="libpq-build">
   <title>Building <application>libpq</application> Programs</title>
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index bc456fe..67c1f12 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -325,6 +325,15 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
 		"Target-Session-Attrs", "", 11, /* sizeof("read-write") = 11 */
 	offsetof(struct pg_conn, target_session_attrs)},
 
+	/* libpq trace log options */
+	{"logdir", "PGLOGDIR", NULL, NULL,
+		"Logdir", "", MAXPGPATH - 4,
+	offsetof(struct pg_conn, logdir)},
+
+	{"logsize", "PGLOGSIZE", NULL, NULL,
+		"Logsize", "", 5,
+	offsetof(struct pg_conn, logsize_str)},
+
 	/* Terminating entry --- MUST BE LAST */
 	{NULL, NULL, NULL, NULL,
 	NULL, NULL, 0}
@@ -1128,6 +1137,19 @@ connectOptions2(PGconn *conn)
 	}
 
 	/*
+	 * If both size and directory of trace log was given,
+	 * initialize a trace log.
+	 */
+	if (conn->logsize_str && conn->logsize_str[0] != '\0')
+		conn->logsize = atoi(conn->logsize_str);
+
+	if (conn->logdir != NULL && conn->logsize > 0 && conn->logsize < 2048)
+	{
+		conn->logsize = conn->logsize * 1024 * 1024;
+		initTraceLog(conn);
+	}
+
+	/*
 	 * If password was not given, try to look it up in password file.  Note
 	 * that the result might be different for each host/port pair.
 	 */
@@ -3716,6 +3738,14 @@ freePGconn(PGconn *conn)
 	termPQExpBuffer(&conn->errorMessage);
 	termPQExpBuffer(&conn->workBuffer);
 
+	/* clean up libpq trace log structures */
+	if (conn->logsize_str)
+		free(conn->logsize_str);
+	if (conn->logdir)
+		free(conn->logdir);
+	if (conn->traceDebug)
+		fclose(conn->traceDebug);
+
 	free(conn);
 
 #ifdef WIN32
@@ -3751,6 +3781,8 @@ sendTerminateConn(PGconn *conn)
 	 */
 	if (conn->sock != PGINVALID_SOCKET && conn->status == CONNECTION_OK)
 	{
+		if (conn->Pfdebug || conn->traceDebug)
+			traceLog_fprintf(conn, true, "Send connection terminate message to backend: ");
 		/*
 		 * Try to send "close connection" message to backend. Ignore any
 		 * error.
@@ -4153,6 +4185,9 @@ int
 pqPacketSend(PGconn *conn, char pack_type,
 			 const void *buf, size_t buf_len)
 {
+	if (conn->Pfdebug || conn->traceDebug)
+		traceLog_fprintf(conn, true, "Send connection start message to backend: ");
+
 	/* Start the message. */
 	if (pqPutMsgStart(pack_type, true, conn))
 		return STATUS_ERROR;
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 6aed8c8..675d1bd 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -879,7 +879,7 @@ pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
 	res->errMsg = (char *) pqResultAlloc(res, strlen(msgBuf) + 2, false);
 	if (res->errMsg)
 	{
-		sprintf(res->errMsg, "%s\n", msgBuf);
+		sprintf(res->errMsg, "NOTICE: %s\n", msgBuf);
 
 		/*
 		 * Pass to receiver, then free it.
@@ -991,9 +991,9 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
 	pgParameterStatus *pstatus;
 	pgParameterStatus *prev;
 
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "pqSaveParameterStatus: '%s' = '%s'\n",
-				name, value);
+	if (conn->Pfdebug || conn->traceDebug)
+		traceLog_fprintf(conn, false, "pqSaveParameterStatus: '%s' = '%s'\n",
+						 name, value);
 
 	/*
 	 * Forget any old information about the parameter
@@ -1208,6 +1208,9 @@ fail:
 int
 PQsendQuery(PGconn *conn, const char *query)
 {
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendQuery start :");
+
 	if (!PQsendQueryStart(conn))
 		return 0;
 
@@ -1219,6 +1222,9 @@ PQsendQuery(PGconn *conn, const char *query)
 		return 0;
 	}
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, false, "Query: %s \n",query);
+
 	/* construct the outgoing Query message */
 	if (pqPutMsgStart('Q', false, conn) < 0 ||
 		pqPuts(query, conn) < 0 ||
@@ -1249,6 +1255,10 @@ PQsendQuery(PGconn *conn, const char *query)
 
 	/* OK, it's launched! */
 	conn->asyncStatus = PGASYNC_BUSY;
+
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendQuery end :");
+
 	return 1;
 }
 
@@ -1266,6 +1276,9 @@ PQsendQueryParams(PGconn *conn,
 				  const int *paramFormats,
 				  int resultFormat)
 {
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendQueryParams start :");
+
 	if (!PQsendQueryStart(conn))
 		return 0;
 
@@ -1283,6 +1296,9 @@ PQsendQueryParams(PGconn *conn,
 		return 0;
 	}
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendQueryParams end :");
+
 	return PQsendQueryGuts(conn,
 						   command,
 						   "",	/* use unnamed statement */
@@ -1306,6 +1322,9 @@ PQsendPrepare(PGconn *conn,
 			  const char *stmtName, const char *query,
 			  int nParams, const Oid *paramTypes)
 {
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendPrepare start :");
+
 	if (!PQsendQueryStart(conn))
 		return 0;
 
@@ -1337,6 +1356,9 @@ PQsendPrepare(PGconn *conn,
 		return 0;
 	}
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, false, "Statement name: %s, Query: %s \n",stmtName, query);
+
 	/* construct the Parse message */
 	if (pqPutMsgStart('P', false, conn) < 0 ||
 		pqPuts(stmtName, conn) < 0 ||
@@ -1386,6 +1408,10 @@ PQsendPrepare(PGconn *conn,
 
 	/* OK, it's launched! */
 	conn->asyncStatus = PGASYNC_BUSY;
+
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendPrepare end :");
+
 	return 1;
 
 sendFailed:
@@ -1492,6 +1518,9 @@ PQsendQueryGuts(PGconn *conn,
 {
 	int			i;
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendQueryGuts start :");
+
 	/* This isn't gonna work on a 2.0 server */
 	if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
 	{
@@ -1507,6 +1536,9 @@ PQsendQueryGuts(PGconn *conn,
 
 	if (command)
 	{
+		if (conn->traceDebug)
+			traceLog_fprintf(conn, false, "Statement name: %s, Command: %s \n",stmtName, command);
+
 		/* construct the Parse message */
 		if (pqPutMsgStart('P', false, conn) < 0 ||
 			pqPuts(stmtName, conn) < 0 ||
@@ -1638,6 +1670,10 @@ PQsendQueryGuts(PGconn *conn,
 
 	/* OK, it's launched! */
 	conn->asyncStatus = PGASYNC_BUSY;
+
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendQueryGuts end :");
+
 	return 1;
 
 sendFailed:
@@ -1820,6 +1856,7 @@ PQgetResult(PGconn *conn)
 
 		/* Parse it. */
 		parseInput(conn);
+
 	}
 
 	/* Return the appropriate thing. */
@@ -2081,6 +2118,9 @@ PQexecFinish(PGconn *conn)
 	PGresult   *result;
 	PGresult   *lastResult;
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQexecFinish start :");
+
 	/*
 	 * For backwards compatibility, return the last result if there are more
 	 * than one --- but merge error messages if we get more than one error
@@ -2120,6 +2160,9 @@ PQexecFinish(PGconn *conn)
 			break;
 	}
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQexecFinish end :");
+
 	return lastResult;
 }
 
@@ -2203,6 +2246,9 @@ PQsendDescribePortal(PGconn *conn, const char *portal)
 static int
 PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
 {
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendDescribe start :");
+
 	/* Treat null desc_target as empty string */
 	if (!desc_target)
 		desc_target = "";
@@ -2218,6 +2264,9 @@ PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
 		return 0;
 	}
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, false, "Describe type: %c, target: %s \n",desc_type, desc_target);
+
 	/* construct the Describe message */
 	if (pqPutMsgStart('D', false, conn) < 0 ||
 		pqPutc(desc_type, conn) < 0 ||
@@ -2249,6 +2298,10 @@ PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
 
 	/* OK, it's launched! */
 	conn->asyncStatus = PGASYNC_BUSY;
+
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "PQsendDescribe end :");
+
 	return 1;
 
 sendFailed:
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index 46ece1a..ba60acb 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -35,6 +35,7 @@
 
 #ifdef WIN32
 #include "win32.h"
+#include <windows.h>
 #else
 #include <unistd.h>
 #include <sys/time.h>
@@ -45,6 +46,7 @@
 #endif
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
+#include <sys/timeb.h>
 #endif
 
 #include "libpq-fe.h"
@@ -60,6 +62,169 @@ static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
 			  time_t end_time);
 static int	pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time);
 
+static void getTraceLogFilename(PGconn *conn,char* filename);
+static void traceLog_fputnbytes(PGconn *conn, const char *head, const char *str, size_t n);
+static void fputnbytes(FILE *f, const char *str, size_t n);
+static void getCurrentTime(char* currenttime,int type);
+#define	TRACELOG_TIME_SIZE	28
+
+/*
+ * getCurrentTime: get current time for trace log output
+ *
+ * type=0 currenttime formate %Y-%m-%d_%H%M%S
+ * type=1 currenttime formate %Y/%m/%d %H:%M:%S.%Milliseconds
+ */
+static void
+getCurrentTime(char* currenttime,int type)
+{
+#ifdef WIN32
+	SYSTEMTIME localTime;
+	GetLocalTime(&localTime);
+	if(type==0)
+		snprintf(currenttime,TRACELOG_TIME_SIZE,"%4d-%02d-%02d_%02d%02d%02d",
+				localTime.wYear,localTime.wMonth,localTime.wDay,
+				localTime.wHour,localTime.wMinute,localTime.wSecond);
+	else if(type==1)
+		snprintf(currenttime,TRACELOG_TIME_SIZE,"%4d/%02d/%02d %02d:%02d:%02d.%03d",
+				localTime.wYear,localTime.wMonth,localTime.wDay,
+				localTime.wHour,localTime.wMinute,localTime.wSecond,
+				localTime.wMilliseconds);
+#else
+	struct timeb localTime;
+	struct tm *tm;
+	ftime(&localTime);
+	tm = localtime(&localTime.time);
+	if(type == 0)
+		snprintf(currenttime, TRACELOG_TIME_SIZE,"%4d-%02d-%02d_%02d%02d%02d",
+				1900+ tm->tm_year,1 + tm->tm_mon, tm->tm_mday,
+				tm->tm_hour, tm->tm_min, tm->tm_sec);
+	else if(type==1)
+		snprintf(currenttime, TRACELOG_TIME_SIZE,"%4d/%02d/%02d %02d:%02d:%02d.%03d",
+				1900+ tm->tm_year,1 + tm->tm_mon, tm->tm_mday,
+				tm->tm_hour, tm->tm_min, tm->tm_sec, localTime.millitm);
+#endif
+}
+
+/*
+ * getTraceLogFilename: build trace log file name
+ * The name is libpq-%ProcessID-%Y-%m-%d_%H%M%S.log.
+ */
+static void
+getTraceLogFilename(PGconn *conn,char* filename)
+{
+	char		currenttime[TRACELOG_TIME_SIZE];    /* %Y-%m-%d_%H%M%S */
+	getCurrentTime(currenttime,0);
+
+#ifdef WIN32
+	snprintf(filename, MAXPGPATH, "%s\\libpq-%d-%s.log", conn->logdir,getpid(),currenttime);
+#else
+	snprintf(filename, MAXPGPATH, "%s/libpq-%d-%s.log", conn->logdir,getpid(),currenttime);
+#endif
+}
+
+/* 
+ * initTraceLog: initialize a trace log file
+ */
+void
+initTraceLog(PGconn *conn)
+{
+	char		logfilename[MAXPGPATH];
+	getTraceLogFilename(conn,logfilename);
+	conn->traceDebug=fopen(logfilename,"w");
+	fprintf(conn->traceDebug, "Maximum log size is %d B.\n", conn->logsize);
+}
+
+/*
+ * traceLog_fprintf: output trace log to file
+ * If PQtrace() is called, PQtrace() is output followed by libpq trace log.
+ */
+void
+traceLog_fprintf(PGconn *conn, bool addTime, const char *fmt,...)
+{
+	char		logfilename[MAXPGPATH];
+	char		msgBuf[MAXPGPATH];
+	va_list		args;
+	int			ret;
+	char		currenttime[TRACELOG_TIME_SIZE];
+
+	va_start(args, fmt);
+	vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
+	msgBuf[sizeof(msgBuf) - 1] = '\0';
+	va_end(args);
+
+	if(conn->Pfdebug)
+	{
+		fprintf(conn->Pfdebug, "%s", msgBuf);
+	}
+	else if(conn->traceDebug)
+	{
+		if((int)ftell(conn->traceDebug) >= conn->logsize)
+		{
+			fclose(conn->traceDebug);
+			getTraceLogFilename(conn,logfilename);
+			conn->traceDebug = fopen(logfilename,"w");
+			if(conn->traceDebug == NULL)
+				return;
+		}
+
+		/* Select trace log message style */
+		if(addTime)
+		{
+			getCurrentTime(currenttime,1);
+			ret = fprintf(conn->traceDebug, "%s  %s\n", msgBuf, currenttime);
+		}
+		else
+		{
+			ret = fprintf(conn->traceDebug, "%s",msgBuf);
+		}
+
+		if(ret < 0)
+		{
+			fclose(conn->traceDebug);
+			conn->traceDebug = NULL;
+			return;
+		}
+		fflush(conn->traceDebug);
+	}
+}
+/*
+ * traceLog_fputnbytes: output trace log to file using fputnbytes()
+ */
+static void
+traceLog_fputnbytes(PGconn *conn,const char *head, const char *str, size_t n)
+{
+	char		logfilename[MAXPGPATH];
+	int			ret;
+
+	if (conn->Pfdebug)
+	{
+		fprintf(conn->Pfdebug, "%s", head);
+		fputnbytes(conn->Pfdebug,str, n);
+		fprintf(conn->Pfdebug, "\n");
+	}
+	else if(conn->traceDebug)
+	{
+		if((int)ftell(conn->traceDebug) >= conn->logsize)
+		{
+			fclose(conn->traceDebug);
+			getTraceLogFilename(conn,logfilename);
+			conn->traceDebug = fopen(logfilename,"w");
+			if(conn->traceDebug == NULL)
+				return;
+		}
+		ret = fprintf(conn->traceDebug, "%s", head);
+		if(ret < 0)
+		{
+			fclose(conn->traceDebug);
+			conn->traceDebug = NULL;
+			return;
+		}
+		fputnbytes(conn->traceDebug,str,n);
+		fprintf(conn->traceDebug,"\n");
+		fflush(conn->traceDebug);
+	}
+}
+
 /*
  * PQlibVersion: return the libpq version number
  */
@@ -98,8 +263,8 @@ pqGetc(char *result, PGconn *conn)
 
 	*result = conn->inBuffer[conn->inCursor++];
 
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "From backend> %c\n", *result);
+	if(conn->Pfdebug||conn->traceDebug)
+		traceLog_fprintf(conn, false, "From backend> %c\n", *result);
 
 	return 0;
 }
@@ -114,8 +279,8 @@ pqPutc(char c, PGconn *conn)
 	if (pqPutMsgBytes(&c, 1, conn))
 		return EOF;
 
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "To backend> %c\n", c);
+	if(conn->Pfdebug||conn->traceDebug)
+		traceLog_fprintf(conn, false, "To backend> %c\n", c);
 
 	return 0;
 }
@@ -152,9 +317,9 @@ pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
 
 	conn->inCursor = ++inCursor;
 
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "From backend> \"%s\"\n",
-				buf->data);
+	if(conn->Pfdebug||conn->traceDebug)
+		traceLog_fprintf(conn, false, "From backend> \"%s\"\n",
+						buf->data);
 
 	return 0;
 }
@@ -181,8 +346,8 @@ pqPuts(const char *s, PGconn *conn)
 	if (pqPutMsgBytes(s, strlen(s) + 1, conn))
 		return EOF;
 
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
+	if(conn->Pfdebug||conn->traceDebug)
+		traceLog_fprintf(conn, false, "To backend> \"%s\"\n", s);
 
 	return 0;
 }
@@ -194,6 +359,7 @@ pqPuts(const char *s, PGconn *conn)
 int
 pqGetnchar(char *s, size_t len, PGconn *conn)
 {
+	char		buf[100];
 	if (len > (size_t) (conn->inEnd - conn->inCursor))
 		return EOF;
 
@@ -202,11 +368,10 @@ pqGetnchar(char *s, size_t len, PGconn *conn)
 
 	conn->inCursor += len;
 
-	if (conn->Pfdebug)
+	if(conn->Pfdebug||conn->traceDebug)
 	{
-		fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
-		fputnbytes(conn->Pfdebug, s, len);
-		fprintf(conn->Pfdebug, "\n");
+		sprintf(buf, "From backend (%lu)> ", (unsigned long) len);
+		traceLog_fputnbytes(conn,buf,s, len);
 	}
 
 	return 0;
@@ -228,7 +393,7 @@ pqSkipnchar(size_t len, PGconn *conn)
 
 	if (conn->Pfdebug)
 	{
-		fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
+		fprintf(conn->Pfdebug, "(pqSkipnchar)From backend (%lu)> ", (unsigned long) len);
 		fputnbytes(conn->Pfdebug, conn->inBuffer + conn->inCursor, len);
 		fprintf(conn->Pfdebug, "\n");
 	}
@@ -245,14 +410,14 @@ pqSkipnchar(size_t len, PGconn *conn)
 int
 pqPutnchar(const char *s, size_t len, PGconn *conn)
 {
+	char		buf[100];
 	if (pqPutMsgBytes(s, len, conn))
 		return EOF;
 
-	if (conn->Pfdebug)
+	if(conn->Pfdebug||conn->traceDebug)
 	{
-		fprintf(conn->Pfdebug, "To backend> ");
-		fputnbytes(conn->Pfdebug, s, len);
-		fprintf(conn->Pfdebug, "\n");
+		sprintf(buf,"To backend (%lu)> ", (unsigned long) len);
+		traceLog_fputnbytes(conn,buf,s,len);
 	}
 
 	return 0;
@@ -292,8 +457,8 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
 			return EOF;
 	}
 
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
+	if(conn->Pfdebug||conn->traceDebug)
+		traceLog_fprintf(conn, false, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
 
 	return 0;
 }
@@ -328,8 +493,8 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
 			return EOF;
 	}
 
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
+	if(conn->Pfdebug||conn->traceDebug)
+		traceLog_fprintf(conn, false, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
 
 	return 0;
 }
@@ -548,9 +713,9 @@ pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
 	conn->outMsgEnd = endPos;
 	/* length word, if needed, will be filled in by pqPutMsgEnd */
 
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "To backend> Msg %c\n",
-				msg_type ? msg_type : ' ');
+	if(conn->Pfdebug||conn->traceDebug)
+		traceLog_fprintf(conn, false, "To backend> Msg %c\n",
+						msg_type ? msg_type : ' ');
 
 	return 0;
 }
@@ -586,9 +751,9 @@ pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
 int
 pqPutMsgEnd(PGconn *conn)
 {
-	if (conn->Pfdebug)
-		fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
-				conn->outMsgEnd - conn->outCount);
+	if(conn->Pfdebug||conn->traceDebug)
+		traceLog_fprintf(conn, false, "To backend> Msg complete, length %u\n",
+						conn->outMsgEnd - conn->outCount);
 
 	/* Fill in length word if needed */
 	if (conn->outMsgStart >= 0)
@@ -677,9 +842,17 @@ pqReadData(PGconn *conn)
 	}
 
 	/* OK, try to read some data */
+
 retry3:
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "Start receiving message from backend:");
+
 	nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
 						  conn->inBufSize - conn->inEnd);
+
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "End receiving message from backend:");
+
 	if (nread < 0)
 	{
 		if (SOCK_ERRNO == EINTR)
@@ -767,9 +940,16 @@ retry3:
 	 * Still not sure that it's EOF, because some data could have just
 	 * arrived.
 	 */
+
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "Start receiving message from backend:");
 retry4:
 	nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
 						  conn->inBufSize - conn->inEnd);
+
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "End receiving message from backend:");
+
 	if (nread < 0)
 	{
 		if (SOCK_ERRNO == EINTR)
@@ -846,6 +1026,9 @@ pqSendSome(PGconn *conn, int len)
 	{
 		int			sent;
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "Start sending message to backend:");
+
 #ifndef WIN32
 		sent = pqsecure_write(conn, ptr, len);
 #else
@@ -858,6 +1041,9 @@ pqSendSome(PGconn *conn, int len)
 		sent = pqsecure_write(conn, ptr, Min(len, 65536));
 #endif
 
+	if (conn->traceDebug)
+		traceLog_fprintf(conn, true, "End sending message to backend:");
+
 		if (sent < 0)
 		{
 			/* Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble */
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 66fd317..71d4329 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -500,6 +500,11 @@ struct pg_conn
 
 	/* Buffer for receiving various parts of messages */
 	PQExpBufferData workBuffer; /* expansible string */
+
+	char	   *logsize_str;		/* Trace log maximum size (string) */
+	int			logsize;		/* Trace log maximum size */
+	char	   *logdir;			/* Trace log directory to save log */
+	FILE	   *traceDebug;			/* Trace log file to write trace info */
 };
 
 /* PGcancel stores all data necessary to cancel a connection. A copy of this
@@ -666,6 +671,10 @@ extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
 				 bool got_epipe);
 #endif
 
+/* libpq trace log  */
+extern void initTraceLog(PGconn *conn);
+extern void traceLog_fprintf(PGconn *conn, bool addTime, const char *fmt,...) pg_attribute_printf(3, 4);
+
 /* === SSL === */
 
 /*
