From 606b10f9597ffadc1e665f8f6f69e71d524d5eed Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 2 Dec 2006 00:42:54 +0000
Subject: [PATCH] Add some documentation for DTrace support.  Simon Riggs

---
 doc/src/sgml/monitoring.sgml | 279 ++++++++++++++++++++++++++++++++++-
 1 file changed, 278 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index adffbec1870..f949bfda350 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.39 2006/11/24 21:18:42 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.40 2006/12/02 00:42:54 tgl Exp $ -->
 
 <chapter id="monitoring">
  <title>Monitoring Database Activity</title>
@@ -791,4 +791,281 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
    <productname>PostgreSQL</productname>, refer to <xref linkend="mvcc">.
   </para>
  </sect1>
+
+ <sect1 id="dynamic-trace">
+  <title>Dynamic Tracing</title>
+
+ <indexterm zone="dynamic-trace">
+  <primary>DTrace</primary>
+ </indexterm>
+
+  <para>
+   <productname>PostgreSQL</productname> provides facilities to support
+   dynamic tracing of the database server. This allows an external
+   utility to be called at specific points in the code and thereby trace
+   execution.  Currently, this facility is primarily intended for use by
+   database developers, as it requires substantial familiarity with the code.
+  </para>
+
+  <para>
+   A number of trace points, often called probes, are already inserted
+   into the source code.  By default these probes are disabled, and
+   the user needs to explicitly tell the configure script to make the
+   probes available in <productname>PostgreSQL</productname>.
+  </para>
+
+  <para> 
+   Currently, only the DTrace utility is supported, which is only available
+   on Solaris Express and Solaris 10+. It is expected that DTrace will
+   be available in the future on FreeBSD and Mac OS X.
+   Supporting other dynamic tracing utilities is theoretically possible by
+   changing the definitions for the <literal>PG_TRACE</> macros in
+   <filename>src/include/pg_trace.h</>.
+  </para>
+
+  <sect2 id="compiling-for-trace">
+   <title>Compiling for Dynamic Trace</title>
+
+  <para>
+   By default, trace points are disabled, so you will need to
+   explicitly tell the configure script to make the probes available
+   in <productname>PostgreSQL</productname>. To include DTrace support
+   in a 32-bit binary, specify <option>--enable-dtrace</> to configure.
+   For example:
+<programlisting>
+      $ ./configure --enable-dtrace ...
+</programlisting>
+   To include DTrace support in a 64-bit binary, specify 
+   <option>--enable-dtrace</>
+   and <literal>DTRACEFLAGS="-64"</> to configure. For example,
+   using the gcc compiler:
+<programlisting>
+      $ ./configure CC='gcc -m64' --enable-dtrace DTRACEFLAGS='-64' ...
+</programlisting>            
+   Using Sun's compiler:
+<programlisting>            
+      $ ./configure CC='/path_to_sun_compiler/cc -xtarget=native64' --enable-dtrace DTRACEFLAGS='-64' ...
+</programlisting>
+  </para>
+  </sect2>
+
+  <sect2 id="trace-points">
+   <title>Built-in Trace Points</title>
+
+  <para>
+   A few standard trace points are provided in the source code
+   (of course, more can be added as needed for a particular problem).
+   These are:
+  </para>
+
+ <table id="trace-point-table">
+  <title>Built-in Trace Points</title>
+  <tgroup cols="3">
+   <thead>
+    <row>
+     <entry>Name</entry>
+     <entry>Parameters</entry>
+     <entry>Overview</entry>
+    </row>
+   </thead>
+
+   <tbody>
+    <row>
+     <entry>transaction__start</entry>
+     <entry>(int transactionId)</entry>
+     <entry>The start of a new transaction.</entry>
+    </row>
+    <row>
+     <entry>transaction__commit</entry>
+     <entry>(int transactionId)</entry>
+     <entry>The successful completion of a transaction.</entry>
+    </row>
+    <row>
+     <entry>transaction__abort</entry>
+     <entry>(int transactionId)</entry>
+     <entry>The unsuccessful completion of a transaction.</entry>
+    </row>
+             
+    <row>
+     <entry>lwlock__acquire</entry>
+     <entry>(int lockid, int mode)</entry>
+     <entry>An LWLock has been acquired.</entry>
+    </row>
+    <row>
+     <entry>lwlock__release</entry>
+     <entry>(int lockid, int mode)</entry>
+     <entry>An LWLock has been released.</entry>
+    </row>
+    <row>
+     <entry>lwlock__startwait</entry>
+     <entry>(int lockid, int mode)</entry>
+     <entry>An LWLock was not immediately available and a backend
+       has begun to wait for the lock to become available.
+     </entry>
+    </row>    
+    <row>
+     <entry>lwlock__endwait</entry>
+     <entry>(int lockid, int mode)</entry>
+     <entry>A backend has been released from its wait for an LWLock.
+     </entry>
+    </row>
+    <row>
+     <entry>lwlock__condacquire</entry>
+     <entry>(int lockid, int mode)</entry>
+     <entry>An LWLock was successfully acquired when the caller specified no
+      waiting.
+     </entry>
+    </row> 
+    <row>
+     <entry>lwlock__condacquire__fail</entry>
+     <entry>(int lockid, int mode)</entry>
+     <entry>An LWLock was not successfully acquired when the caller specified
+      no waiting.
+     </entry>
+    </row>
+    <row>
+     <entry>lock__startwait</entry>
+     <entry>(int locktag_field2, int lockmode)</entry>
+     <entry>A request for a heavyweight lock (lmgr lock) has begun to wait
+      because the lock is not available.
+     </entry>
+    </row>
+    <row>
+     <entry>lock__endwait</entry>
+     <entry>(int locktag_field2, int lockmode)</entry>
+     <entry>A request for a heavyweight lock (lmgr lock) has finished waiting
+      (i.e., has acquired the lock).
+     </entry>
+    </row>
+   </tbody>
+   </tgroup>
+  </table>
+  </sect2>
+
+  <sect2 id="using-trace-points">
+   <title>Using Trace Points</title>
+
+  <para>
+   The example below shows a DTrace script for analyzing transaction
+   counts on the system, as an alternative to snapshotting 
+   <structname>pg_stat_database</> before and after a performance test.
+<programlisting>
+#!/usr/sbin/dtrace -qs 
+
+postgresql$1:::transaction-start
+{
+      @start["Start"] = count();
+      self->ts  = timestamp;
+}
+
+postgresql$1:::transaction-abort
+{
+      @abort["Abort"] = count();
+}
+
+postgresql$1:::transaction-commit
+/self->ts/
+{
+      @commit["Commit"] = count();
+      @time["Total time (ns)"] = sum(timestamp - self->ts);
+      self->ts=0;
+}
+</programlisting>
+   Note how the double underline in trace point names needs to
+   be replaced by a hyphen when using D script.
+   When executed, the example D script gives output such as:
+<programlisting>
+# ./txn_count.d `pgrep -n postgres`
+^C
+
+Start                                          71
+Commit                                         70
+Abort                                           1
+Total time (ns)                        2312105013
+</programlisting>
+  </para>
+  <para>
+   You should remember that trace programs need to be carefully written and
+   debugged prior to their use, otherwise the trace information collected may
+   be meaningless. In most cases where problems are found it is the 
+   instrumentation that is at fault, not the underlying system. When 
+   discussing information found using dynamic tracing, be sure to enclose
+   the script used to allow that too to be checked and discussed.
+  </para>
+  </sect2>
+
+  <sect2 id="defining-trace-points">
+   <title>Defining Trace Points</title>
+
+  <para>
+   New trace points can be defined within the code wherever the developer
+   desires, though this will require a re-compile.
+  </para>
+
+  <para>
+   A trace point can be inserted by using one of the
+   trace macros. These are chosen according to how many variables will
+   be made available for inspection at that trace point. Tracing the
+   occurrence of an event can be achieved with a single line, using
+   just the trace point name, e.g.
+<programlisting>
+      PG_TRACE (my__new__trace__point);
+</programlisting>
+   More complex trace points can be provided with one or more variables
+   for inspection by the dynamic tracing utility by using the
+   <literal>PG_TRACE</><replaceable>n</> macro that corresponds to the number
+   of parameters after the trace point name:
+<programlisting>
+      PG_TRACE3 (my__complex__event, varX, varY, varZ);
+</programlisting>
+   The definition of the transaction__start trace point is shown below:
+<programlisting>
+static void
+StartTransaction(void)
+{
+    ...
+
+    /*
+     * generate a new transaction id
+     */
+    s->transactionId = GetNewTransactionId(false);
+
+    XactLockTableInsert(s->transactionId);
+
+    PG_TRACE1(transaction__start, s->transactionId);
+
+    ...
+}    
+</programlisting>
+   Note how the transaction ID is made available to the dynamic tracing
+   utility.
+  </para>
+
+  <para>
+   The dynamic tracing utility may require you to further define these trace
+   points.  For example, DTrace requires you to add new probes to the file
+   <filename>src/backend/utils/probes.d</> as shown here:
+<programlisting>
+provider postgresql {
+      ...
+      probe transaction__start(int);
+      ...
+ };
+</programlisting>
+  </para>
+
+  <para>
+   You should take care that the datatypes specified for the probe arguments
+   match the datatypes of the variables used in the <literal>PG_TRACE</>
+   macro. This is not checked at compile time. You can check that your newly
+   added trace point is available by recompiling, then running the new binary,
+   and as root, executing a DTrace command such as:
+<programlisting>
+dtrace -l -n transaction-start
+</programlisting>
+  </para>
+  </sect2>
+
+ </sect1>
+
 </chapter>
-- 
GitLab