Thread: fix log_min_duration_statement logic error

fix log_min_duration_statement logic error

From
Neil Conway
Date:
This patch fixes an obvious bug in the "should I print the duration of
this query?" logic in postgres.c

I also don't particularly like the format of the log message (for one
thing, the "duration_statement" prefix in the log message shouldn't
include an underscore, it's not a variable or anything -- and the case
can be made that if we printed the duration because log_duration is set,
we don't need to print it again if the duration of the query exceeded
log_min_duration_statement), but I haven't changed it.

-Neil


Attachment

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Neil Conway <neilc@samurai.com> writes:
> I also don't particularly like the format of the log message (for one
> thing, the "duration_statement" prefix in the log message shouldn't
> include an underscore, it's not a variable or anything -- and the case
> can be made that if we printed the duration because log_duration is set,
> we don't need to print it again if the duration of the query exceeded
> log_min_duration_statement), but I haven't changed it.

I think there should be just one "duration: nnn" log entry, printed if
either condition holds.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Andrew Dunstan
Date:
Tom Lane wrote:

>Neil Conway <neilc@samurai.com> writes:
>
>
>>I also don't particularly like the format of the log message (for one
>>thing, the "duration_statement" prefix in the log message shouldn't
>>include an underscore, it's not a variable or anything -- and the case
>>can be made that if we printed the duration because log_duration is set,
>>we don't need to print it again if the duration of the query exceeded
>>log_min_duration_statement), but I haven't changed it.
>>
>>
>
>I think there should be just one "duration: nnn" log entry, printed if
>either condition holds.
>
>
>
I think that would be consistent with my session-end log patch.

cheers

andrew


Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Tom Lane writes:

> Neil Conway <neilc@samurai.com> writes:
> > I also don't particularly like the format of the log message (for one
> > thing, the "duration_statement" prefix in the log message shouldn't
> > include an underscore, it's not a variable or anything -- and the case
> > can be made that if we printed the duration because log_duration is set,
> > we don't need to print it again if the duration of the query exceeded
> > log_min_duration_statement), but I haven't changed it.
>
> I think there should be just one "duration: nnn" log entry, printed if
> either condition holds.

Is anyone going to take care of this?

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Yes, I will.

---------------------------------------------------------------------------

Peter Eisentraut wrote:
> Tom Lane writes:
>
> > Neil Conway <neilc@samurai.com> writes:
> > > I also don't particularly like the format of the log message (for one
> > > thing, the "duration_statement" prefix in the log message shouldn't
> > > include an underscore, it's not a variable or anything -- and the case
> > > can be made that if we printed the duration because log_duration is set,
> > > we don't need to print it again if the duration of the query exceeded
> > > log_min_duration_statement), but I haven't changed it.
> >
> > I think there should be just one "duration: nnn" log entry, printed if
> > either condition holds.
>
> Is anyone going to take care of this?
>
> --
> Peter Eisentraut   peter_e@gmx.net
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Your patch has been added to the PostgreSQL unapplied patches list at:

    http://momjian.postgresql.org/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------


Neil Conway wrote:
> This patch fixes an obvious bug in the "should I print the duration of
> this query?" logic in postgres.c
>
> I also don't particularly like the format of the log message (for one
> thing, the "duration_statement" prefix in the log message shouldn't
> include an underscore, it's not a variable or anything -- and the case
> can be made that if we printed the duration because log_duration is set,
> we don't need to print it again if the duration of the query exceeded
> log_min_duration_statement), but I haven't changed it.
>
> -Neil
>

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
> I think there should be just one "duration: nnn" log entry, printed if
> either condition holds.

Your patch has been added to the PostgreSQL unapplied patches list at:

    http://momjian.postgresql.org/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------


Tom Lane wrote:
> Neil Conway <neilc@samurai.com> writes:
> > I also don't particularly like the format of the log message (for one
> > thing, the "duration_statement" prefix in the log message shouldn't
> > include an underscore, it's not a variable or anything -- and the case
> > can be made that if we printed the duration because log_duration is set,
> > we don't need to print it again if the duration of the query exceeded
> > log_min_duration_statement), but I haven't changed it.
>
> I think there should be just one "duration: nnn" log entry, printed if
> either condition holds.
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
>       subscribe-nomail command to majordomo@postgresql.org so that your
>       message can get through to the mailing list cleanly
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Patch applied.  Thanks.

I also marged this test into log_duration and use the same log tag for
both, as suggested.

---------------------------------------------------------------------------


Neil Conway wrote:
> This patch fixes an obvious bug in the "should I print the duration of
> this query?" logic in postgres.c
>
> I also don't particularly like the format of the log message (for one
> thing, the "duration_statement" prefix in the log message shouldn't
> include an underscore, it's not a variable or anything -- and the case
> can be made that if we printed the duration because log_duration is set,
> we don't need to print it again if the duration of the query exceeded
> log_min_duration_statement), but I haven't changed it.
>
> -Neil
>

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.367
diff -c -c -r1.367 postgres.c
*** src/backend/tcop/postgres.c    29 Sep 2003 00:05:25 -0000    1.367
--- src/backend/tcop/postgres.c    29 Sep 2003 18:28:27 -0000
***************
*** 955,979 ****
          usecs = (long) (stop_t.tv_sec - start_t.tv_sec) * 1000000 + (long) (stop_t.tv_usec - start_t.tv_usec);

          /*
!          * Output a duration_query to the log if the query has exceeded
!          * the min duration.
           */
!         if (usecs >= save_log_min_duration_statement * 1000)
              ereport(LOG,
!                     (errmsg("duration_statement: %ld.%06ld %s",
                              (long) (stop_t.tv_sec - start_t.tv_sec),
                              (long) (stop_t.tv_usec - start_t.tv_usec),
                              query_string)));
-
-         /*
-          * If the user is requesting logging of all durations, then log
-          * that as well.
-          */
-         if (save_log_duration)
-             ereport(LOG,
-                     (errmsg("duration: %ld.%06ld sec",
-                             (long) (stop_t.tv_sec - start_t.tv_sec),
-                             (long) (stop_t.tv_usec - start_t.tv_usec))));
      }

      if (save_log_statement_stats)
--- 955,971 ----
          usecs = (long) (stop_t.tv_sec - start_t.tv_sec) * 1000000 + (long) (stop_t.tv_usec - start_t.tv_usec);

          /*
!          * Output a duration_statement to the log if the query has exceeded
!          * the min duration, or if we are to print all durations.
           */
!         if (save_log_duration ||
!             (save_log_min_duration_statement > 0 &&
!              usecs >= save_log_min_duration_statement * 1000))
              ereport(LOG,
!                     (errmsg("duration: %ld.%06ld %s",
                              (long) (stop_t.tv_sec - start_t.tv_sec),
                              (long) (stop_t.tv_usec - start_t.tv_usec),
                              query_string)));
      }

      if (save_log_statement_stats)

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Neil Conway <neilc@samurai.com> writes:
> > I also don't particularly like the format of the log message (for one
> > thing, the "duration_statement" prefix in the log message shouldn't
> > include an underscore, it's not a variable or anything -- and the case
> > can be made that if we printed the duration because log_duration is set,
> > we don't need to print it again if the duration of the query exceeded
> > log_min_duration_statement), but I haven't changed it.
>
> I think there should be just one "duration: nnn" log entry, printed if
> either condition holds.

Done.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Bruce Momjian writes:

> > I think there should be just one "duration: nnn" log entry, printed if
> > either condition holds.
>
> Done.

Now, if I have log_statement and log_duration on, it logs each statement
twice.  The documentation says this:

log_duration (boolean)

  Causes the duration of every completed statement to be logged. To use
  this option, enable log_statement and log_pid so you can link the
  statement to the duration using the process ID.

This needs more thought.

Also, please put units on all numbers.

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Thanks Peter.  Patch attached.  I added "(secs)" to the ouput:

    LOG:  duration(secs): 0.000257
    LOG:  duration(secs): 0.000754
    LOG:  duration(secs): 0.008115 select * from pg_class;


---------------------------------------------------------------------------

Peter Eisentraut wrote:
> Bruce Momjian writes:
>
> > > I think there should be just one "duration: nnn" log entry, printed if
> > > either condition holds.
> >
> > Done.
>
> Now, if I have log_statement and log_duration on, it logs each statement
> twice.  The documentation says this:
>
> log_duration (boolean)
>
>   Causes the duration of every completed statement to be logged. To use
>   this option, enable log_statement and log_pid so you can link the
>   statement to the duration using the process ID.
>
> This needs more thought.
>
> Also, please put units on all numbers.
>
> --
> Peter Eisentraut   peter_e@gmx.net
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.369
diff -c -c -r1.369 postgres.c
*** src/backend/tcop/postgres.c    2 Oct 2003 06:34:04 -0000    1.369
--- src/backend/tcop/postgres.c    4 Oct 2003 02:45:50 -0000
***************
*** 943,948 ****
--- 943,949 ----
      if (save_log_duration || save_log_min_duration_statement > 0)
      {
          long        usecs;
+         bool        print_statement;

          gettimeofday(&stop_t, NULL);
          if (stop_t.tv_usec < start_t.tv_usec)
***************
*** 956,969 ****
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         if (save_log_duration ||
!             (save_log_min_duration_statement > 0 &&
!              usecs >= save_log_min_duration_statement * 1000))
              ereport(LOG,
!                     (errmsg("duration: %ld.%06ld %s",
                              (long) (stop_t.tv_sec - start_t.tv_sec),
                              (long) (stop_t.tv_usec - start_t.tv_usec),
!                             query_string)));
      }

      if (save_log_statement_stats)
--- 957,972 ----
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement > 0 &&
!                            usecs >= save_log_min_duration_statement * 1000);
!
!         if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration(secs): %ld.%06ld%s%s",
                              (long) (stop_t.tv_sec - start_t.tv_sec),
                              (long) (stop_t.tv_usec - start_t.tv_usec),
!                             print_statement ? " " : "",
!                             print_statement ? query_string : "")));
      }

      if (save_log_statement_stats)

Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Bruce Momjian writes:

> Thanks Peter.  Patch attached.  I added "(secs)" to the ouput:
>
>     LOG:  duration(secs): 0.000257
>     LOG:  duration(secs): 0.000754
>     LOG:  duration(secs): 0.008115 select * from pg_class;

I think the units typically go after the number.

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Bruce Momjian writes:
>> LOG:  duration(secs): 0.000257
>> LOG:  duration(secs): 0.000754
>> LOG:  duration(secs): 0.008115 select * from pg_class;

> I think the units typically go after the number.

In any case, this is unnecessarily incompatible with everything else.
EXPLAIN and psql's \timing show query durations in milliseconds.  And
isn't log_min_duration_statement itself measured in milliseconds?

I would prefer to see the log entries look like

    LOG: query: select * from pg_class;
    LOG: duration: nn.nnn msec

in all cases, rather than moving information around depending on which
combination of switches happens to have caused the log entries to be
generated.  Am willing to fix the code to make this happen.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
> > Bruce Momjian writes:
> >> LOG:  duration(secs): 0.000257
> >> LOG:  duration(secs): 0.000754
> >> LOG:  duration(secs): 0.008115 select * from pg_class;
>
> > I think the units typically go after the number.
>
> In any case, this is unnecessarily incompatible with everything else.
> EXPLAIN and psql's \timing show query durations in milliseconds.  And
> isn't log_min_duration_statement itself measured in milliseconds?
>
> I would prefer to see the log entries look like
>
>     LOG: query: select * from pg_class;
>     LOG: duration: nn.nnn msec
>
> in all cases, rather than moving information around depending on which
> combination of switches happens to have caused the log entries to be
> generated.  Am willing to fix the code to make this happen.

The problem with two lines is that another log message could get between
them.  I agree milliseconds makes more sense for output.

Maybe:

    LOG: duration: nn.nnn msec, select * from pg_class;

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Tom Lane wrote:
>> I would prefer to see the log entries look like
>>
>> LOG: query: select * from pg_class;
>> LOG: duration: nn.nnn msec

> The problem with two lines is that another log message could get between
> them.

That was true already with log_statement and log_duration as separate
operations.  People use log_pid to deal with it.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Tom Lane wrote:
> >> I would prefer to see the log entries look like
> >>
> >> LOG: query: select * from pg_class;
> >> LOG: duration: nn.nnn msec
>
> > The problem with two lines is that another log message could get between
> > them.
>
> That was true already with log_statement and log_duration as separate
> operations.  People use log_pid to deal with it.

Attached are some emails I sent while we were discussing this feature in
March.

The idea was for the parameter to show query and duration --- a
combination that is asked for frequently and easily grep'ed, unlike
joining on pid, which because of pid wrap-around, isn't even fool-proof.

One thing that isn't implemented in current CVS is to allow 0 to always
print the duration and query (-1 disables it and is the default).  I can
see that being _very_ valuable, and used enough to warrant the fact that
it isn't orthoginal (we already have log_statement).  The reason we
needed to do it this way was so we could print the statement _after_ it
completes so we could include the duration.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
OK, here is a patch that uses the zero value to print all queries:

 LOG:  duration: 0.310 msecs,  select 1;
 LOG:  duration: 8.108 msecs,  select * from pg_class;
 LOG:  duration: 1.992 msecs,  select * from pg_class, pg_proc limit 1;
 LOG:  duration: 2.797 msecs,  select * from pg_class, pg_proc order by pg_proc.oid limit 1;
 LOG:  duration: 16190.962 msecs,  select * from pg_class, pg_proc order by pg_proc.oid;

Comments?

---------------------------------------------------------------------------

Bruce Momjian wrote:
> Tom Lane wrote:
> > Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > > Tom Lane wrote:
> > >> I would prefer to see the log entries look like
> > >>
> > >> LOG: query: select * from pg_class;
> > >> LOG: duration: nn.nnn msec
> >
> > > The problem with two lines is that another log message could get between
> > > them.
> >
> > That was true already with log_statement and log_duration as separate
> > operations.  People use log_pid to deal with it.
>
> Attached are some emails I sent while we were discussing this feature in
> March.
>
> The idea was for the parameter to show query and duration --- a
> combination that is asked for frequently and easily grep'ed, unlike
> joining on pid, which because of pid wrap-around, isn't even fool-proof.
>
> One thing that isn't implemented in current CVS is to allow 0 to always
> print the duration and query (-1 disables it and is the default).  I can
> see that being _very_ valuable, and used enough to warrant the fact that
> it isn't orthoginal (we already have log_statement).  The reason we
> needed to do it this way was so we could print the statement _after_ it
> completes so we could include the duration.
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

> >From pgman Wed Feb 12 15:03:03 2003
> Subject: Re: [HACKERS] log_duration
> In-Reply-To: <87smuurif6.fsf@stark.dyndns.tv>
> To: Greg Stark <gsstark@mit.edu>
> Date: Wed, 12 Feb 2003 16:49:58 -0500 (EST)
> cc: pgsql-hackers@postgresql.org
> X-Mailer: ELM [version 2.4ME+ PL99 (25)]
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Type: text/plain; charset=US-ASCII
> Content-Length:  3288
> Status: OR
>
> Greg Stark wrote:
> > Tom Lane <tgl@sss.pgh.pa.us> writes:
> >
> > > "Christopher Kings-Lynne" <chriskl@familyhealth.com.au> writes:
> > > > Looking at the log_duration postgresql.conf option.  How about adding an
> > > > option log_duration_min which is a value in milliseconds that is the minimum
> > > > time a query must run for before being logged.
> > >
> > > Fine with me --- but you'll need to add more logic than that.  Right
> > > now, log_duration *only* causes the query duration to be printed out;
> > > if you ain't got log_statement on, you're in the dark as to what the
> > > query itself was.  You'll need to add some code to print the query
> > > (the log_min_error_statement logic might be a useful source of
> > > inspiration).  Not sure how this should interact with the case where
> > > log_duration is set and the min-duration isn't.  But maybe that case
> > > is silly, and we should just redefine log_duration as a minimum runtime
> > > that causes the query *and* its runtime to be printed to the log.
>
> Tom is right here.  log_duration _just_ prints the duration, so we would
> need to basically create a merged param that does log_duration and
> log_statement and have it activate only if the statement takes more than
> X milliseconds, something like log_long_statement, or something like
> that.
>
> Here are the log_* params we have:
>
>     log_connections = false
>     log_hostname = false
>     log_source_port = false
>     log_pid = false
>     log_statement = false
>     log_duration = false
>     log_timestamp = false
>
> Basically, log_pid pulls them all together.  Without that, you don't
> have any way to pull together individual lines in the log, and with pid
> wraparound, you can't even do that 100%.  I wonder if we should put a
> number before the pid and increment it on every pid wraparound.
>
> One nice thing is that each element is orthoginal.  But, for the
> functionality desired, we have to merge log_statement and log_duration
> and have it print for statements taking over X milliseconds.  I have no
> problem adding it, but it has to be clear it isn't orthoginal but is a
> conditional combination of two other parameters.
>
> > Is it even guaranteed to be properly ordered on a busy server with multiple
> > processors anyways?
> >
> > One option is to have log_query output an identifier with the query such as a
> > hash of the query or the pointer value for the plan, suppressing duplicates.
> > Then log_duration prints the identifier with the duration.
> >
> > This means on a busy server running lots of prepared queries you would see a
> > whole bunch of queries on startup, then hopefully no durations. Any durations
> > printed could cause alarms to go off. To find the query you grep the logs for
> > the identifier in the duration message.
>
> Actually, log_pid is the proper way to do this.  You can then add log
> connections, and get a full snapshot of what is happening for that
> session.
>
> > This only really works if you're using prepared queries everywhere. But in the
> > long run that will be the case for OLTP systems, which is where log_duration
> > is really useful.
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
>
> >From pgman Wed Feb 12 15:03:03 2003
> Subject: Re: [HACKERS] log_duration
> In-Reply-To: <GNELIHDDFBOCMGBFGEFOMEIGCFAA.chriskl@familyhealth.com.au>
> To: Christopher Kings-Lynne <chriskl@familyhealth.com.au>
> Date: Wed, 12 Feb 2003 21:32:05 -0500 (EST)
> cc: Greg Stark <gsstark@mit.edu>, pgsql-hackers@postgresql.org
> X-Mailer: ELM [version 2.4ME+ PL99 (25)]
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Type: text/plain; charset=US-ASCII
> Content-Length:  1245
> Status: OR
>
> Christopher Kings-Lynne wrote:
> > > Tom is right here.  log_duration _just_ prints the duration, so we would
> > > need to basically create a merged param that does log_duration and
> > > log_statement and have it activate only if the statement takes more than
> > > X milliseconds, something like log_long_statement, or something like
> > > that.
> > >
> > > Here are the log_* params we have:
> > >
> > >     log_connections = false
> > >     log_hostname = false
> > >     log_source_port = false
> > >     log_pid = false
> > >     log_statement = false
> > >     log_duration = false
> > >     log_timestamp = false
> >
> > OK, while I'm doing all this benchmarking and stuff - is there any sort of
> > option where I can see it logged when a sort doesn't have enought sort
> > memory and hence hits the disk?  eg. an elog(LOG) is emitted?
>
> Someone asked about this at FOSDEM. The only way I know to do it is look
> in the pgsql_temp directory, but they disappear pretty quickly.  Folks,
> do we need something to report sort file usage?
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
>
> >From pgman Wed Feb 12 15:03:03 2003
> Subject: Re: [HACKERS] log_duration
> In-Reply-To: <GNELIHDDFBOCMGBFGEFOGEIHCFAA.chriskl@familyhealth.com.au>
> To: Christopher Kings-Lynne <chriskl@familyhealth.com.au>
> Date: Wed, 12 Feb 2003 22:07:04 -0500 (EST)
> cc: Greg Stark <gsstark@mit.edu>, pgsql-hackers@postgresql.org
> X-Mailer: ELM [version 2.4ME+ PL99 (25)]
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Type: text/plain; charset=US-ASCII
> Content-Length:  1366
> Status: OR
>
>
> Well, part of the issue here is that it isn't always bad to use sort
> file;  certainly it is better to use them than to swap.
>
> We have a checkpoint_warning in 7.4 that will warn about excessive
> checkpointing.  What would our criteria be for warning about sort_mem?
> Seems we would have to know how much free memory there is available, and
> in fact, if there is lots of free memory, the sort files will just sit
> in the kernel disk cache anyway.
>
> I am not saying this is a bad idea --- we just need to define it clearer.
>
> ---------------------------------------------------------------------------
>
> Christopher Kings-Lynne wrote:
> > > Someone asked about this at FOSDEM. The only way I know to do it is look
> > > in the pgsql_temp directory, but they disappear pretty quickly.  Folks,
> > > do we need something to report sort file usage?
> >
> > How about a new GUC variable: log_sort_tempfiles
> >
> > And in the code that creates the temp file, if the GUC variable is true,
> > then do:
> >
> > elog(LOG, "Sort needed temp file.  Sort required 2456K.  Try increasing
> > sort_mem.");
> >
> > Or something?
> >
> > Chris
> >
> >
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
>
> >From pgman Wed Feb 12 15:03:03 2003
> Subject: Re: [HACKERS] log_duration
> In-Reply-To: <10231.1045109729@sss.pgh.pa.us>
> To: Tom Lane <tgl@sss.pgh.pa.us>
> Date: Wed, 12 Feb 2003 23:46:11 -0500 (EST)
> cc: Greg Stark <gsstark@mit.edu>, pgsql-hackers@postgresql.org
> X-Mailer: ELM [version 2.4ME+ PL99 (25)]
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Type: text/plain; charset=US-ASCII
> Content-Length:  1792
> Status: OR
>
> Tom Lane wrote:
> > Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > > One nice thing is that each element is orthoginal.  But, for the
> > > functionality desired, we have to merge log_statement and log_duration
> > > and have it print for statements taking over X milliseconds.  I have no
> > > problem adding it, but it has to be clear it isn't orthoginal but is a
> > > conditional combination of two other parameters.
> >
> > Actually, I was wondering if we shouldn't *replace* the current
> > log_duration with a combined form (that specifies a minimum interesting
> > duration).  I can't quite see the need for orthogonality here.  The
> > only reason you'd care about query duration is that you're looking for
> > the slow ones, no?  So why bother logging the fast ones?  Besides, you
> > can specify min-duration zero if you really want 'em all.
>
> We did talk about this a while ago, and folks wanted the query printed
> _before_ it was executed, so they could see the query in the logs at the
> time it was issued, both for monitoring and for showing the time the
> query started when log_timestamp is enabled.
>
> Seems the clearest option would be for log_duration to print the query
> string too, and convert it to an integer field.  I can see zero meaning
> print all queries and durations.  What value do we use to turn it off?
> -1?
>
> This would give us log_statement that prints at query start, and
> log_duration that prints query and duration at query end.  How is that?
>
> Maybe we should rename them as log_statement_start and
> log_statement_duration.
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
>
> >From pgman Fri Mar 14 09:01:29 2003
> Subject: Re: [HACKERS] log_duration
> In-Reply-To: <200302130446.h1D4kBF29082@candle.pha.pa.us>
> To: Bruce Momjian <pgman@candle.pha.pa.us>
> Date: Fri, 14 Mar 2003 14:27:38 -0500 (EST)
> cc: Tom Lane <tgl@sss.pgh.pa.us>, Greg Stark <gsstark@mit.edu>,
>     pgsql-hackers@postgresql.org
> X-Mailer: ELM [version 2.4ME+ PL99 (25)]
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Type: text/plain; charset=US-ASCII
> Content-Length:  2472
> Status: OR
>
>
> Added to TODO:
>
>     * Add GUC log_statement_duration to print statement and >= min duration
>
> ---------------------------------------------------------------------------
>
> Bruce Momjian wrote:
> > Tom Lane wrote:
> > > Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > > > One nice thing is that each element is orthoginal.  But, for the
> > > > functionality desired, we have to merge log_statement and log_duration
> > > > and have it print for statements taking over X milliseconds.  I have no
> > > > problem adding it, but it has to be clear it isn't orthoginal but is a
> > > > conditional combination of two other parameters.
> > >
> > > Actually, I was wondering if we shouldn't *replace* the current
> > > log_duration with a combined form (that specifies a minimum interesting
> > > duration).  I can't quite see the need for orthogonality here.  The
> > > only reason you'd care about query duration is that you're looking for
> > > the slow ones, no?  So why bother logging the fast ones?  Besides, you
> > > can specify min-duration zero if you really want 'em all.
> >
> > We did talk about this a while ago, and folks wanted the query printed
> > _before_ it was executed, so they could see the query in the logs at the
> > time it was issued, both for monitoring and for showing the time the
> > query started when log_timestamp is enabled.
> >
> > Seems the clearest option would be for log_duration to print the query
> > string too, and convert it to an integer field.  I can see zero meaning
> > print all queries and durations.  What value do we use to turn it off?
> > -1?
> >
> > This would give us log_statement that prints at query start, and
> > log_duration that prints query and duration at query end.  How is that?
> >
> > Maybe we should rename them as log_statement_start and
> > log_statement_duration.
> >
> > --
> >   Bruce Momjian                        |  http://candle.pha.pa.us
> >   pgman@candle.pha.pa.us               |  (610) 359-1001
> >   +  If your life is a hard drive,     |  13 Roberts Road
> >   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
> >
> > ---------------------------(end of broadcast)---------------------------
> > TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
> >
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.210
diff -c -c -r1.210 runtime.sgml
*** doc/src/sgml/runtime.sgml    3 Oct 2003 19:26:49 -0000    1.210
--- doc/src/sgml/runtime.sgml    5 Oct 2003 03:10:51 -0000
***************
*** 1691,1702 ****
           Sets a minimum statement execution time (in milliseconds)
           above which a statement will be logged.  All SQL statements
           that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero (the default)
!      disables time-based logging.  For example, if you set it
           to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this
!          option can be useful in tracking down unoptimized queries in
!          your applications.
           Only superusers can increase this or set it to zero if this option
           is set to non-zero by the administrator.
          </para>
--- 1691,1702 ----
           Sets a minimum statement execution time (in milliseconds)
           above which a statement will be logged.  All SQL statements
           that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero will print
!          all queries with their durations.  Minus-one (the default)
!          disables time-based logging.  For example, if you set it
           to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this option can be useful
!          in tracking down unoptimized queries in your applications.
           Only superusers can increase this or set it to zero if this option
           is set to non-zero by the administrator.
          </para>
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.370
diff -c -c -r1.370 postgres.c
*** src/backend/tcop/postgres.c    4 Oct 2003 02:47:04 -0000    1.370
--- src/backend/tcop/postgres.c    5 Oct 2003 03:10:54 -0000
***************
*** 694,700 ****
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
--- 694,700 ----
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
***************
*** 940,946 ****
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
      {
          long        usecs;
          bool        print_statement;
--- 940,946 ----
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
      {
          long        usecs;
          bool        print_statement;
***************
*** 957,970 ****
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement > 0 &&
!                            usecs >= save_log_min_duration_statement * 1000);

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration(secs): %ld.%06ld%s%s",
!                             (long) (stop_t.tv_sec - start_t.tv_sec),
!                             (long) (stop_t.tv_usec - start_t.tv_usec),
                              print_statement ? " " : "",
                              print_statement ? query_string : "")));
      }
--- 957,972 ----
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement == 0 ||
!                            (save_log_min_duration_statement > 0 &&
!                             usecs >= save_log_min_duration_statement * 1000));

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration: %ld.%03ld msecs, %s%s",
!                             (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
!                             (stop_t.tv_usec - start_t.tv_usec) / 1000),
!                             (long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
                              print_statement ? " " : "",
                              print_statement ? query_string : "")));
      }
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.162
diff -c -c -r1.162 guc.c
*** src/backend/utils/misc/guc.c    3 Oct 2003 19:26:49 -0000    1.162
--- src/backend/utils/misc/guc.c    5 Oct 2003 03:10:58 -0000
***************
*** 128,134 ****
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = 0;


  /*
--- 128,134 ----
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = -1;


  /*
***************
*** 1185,1194 ****
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("The default is 0 (turning this feature off).")
          },
          &log_min_duration_statement,
!         0, 0, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
--- 1185,1194 ----
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("Zero prints all queries.  The default is -1 (turning this feature off).")
          },
          &log_min_duration_statement,
!         -1, -1, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.91
diff -c -c -r1.91 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample    3 Oct 2003 19:26:49 -0000    1.91
--- src/backend/utils/misc/postgresql.conf.sample    5 Oct 2003 03:10:58 -0000
***************
*** 157,165 ****
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = 0  # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero disables.

  #silent_mode = false         # DO NOT USE without Syslog!

--- 157,166 ----
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = -1 # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero prints all queries.
!                  # Minus-one disables.

  #silent_mode = false         # DO NOT USE without Syslog!


Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> The reason we
> needed to do it this way was so we could print the statement _after_ it
> completes so we could include the duration.

The behavior I had in mind was to dump the statement at the end of the
query if (a) the duration needs to be printed and (b) the statement
wasn't already dumped at the start --- ie, log_statement was not on
at the start.

The historical behavior of log_min_error_statement has been to make two
separate log entries: the failing query and the error.  This has worked
well enough AFAIK; why not keep that behavior for log_min_duration?

BTW, there's a separate set of problems that have yet to be addressed,
which is how any of these logging options apply for V3-protocol query
operations.  The existing code only seems to work for the old-style
query path.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > The reason we
> > needed to do it this way was so we could print the statement _after_ it
> > completes so we could include the duration.
>
> The behavior I had in mind was to dump the statement at the end of the
> query if (a) the duration needs to be printed and (b) the statement
> wasn't already dumped at the start --- ie, log_statement was not on
> at the start.
>
> The historical behavior of log_min_error_statement has been to make two
> separate log entries: the failing query and the error.  This has worked
> well enough AFAIK; why not keep that behavior for log_min_duration?

I think separate entries work for log_min_error_statement because the
error string and query are both long, and you can pretty much guess
which error goes with which query, and you are looking at errors, which
are pretty rare events, hopefully.

I think they fit pretty nicely on one line, and lot of folks want that
information.  I realize it looks like bloatware because it duplicates
some existing functionality, but I think it is a combination of duration
and statement output that can't be done easily separately.

Also, I don't see us combining any other log_* operations:

    #log_connections = false
    #log_duration = false
    #log_pid = false
    #log_statement = false
    #log_timestamp = false
    #log_hostname = false
    #log_source_port = false

> BTW, there's a separate set of problems that have yet to be addressed,
> which is how any of these logging options apply for V3-protocol query
> operations.  The existing code only seems to work for the old-style
> query path.

You mean how are they passed to the client?  I assumed that would work
for pre-V3 clients.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> I think they fit pretty nicely on one line, and lot of folks want that
> information.  I realize it looks like bloatware because it duplicates
> some existing functionality, but I think it is a combination of duration
> and statement output that can't be done easily separately.

Sure it can.  You're essentially arguing that DBAs are too dumb to match
up matching query and duration log outputs.  I don't buy that.  I think
they'll be analyzing their logs with little Perl scripts anyway, and
that consistency of log output format will be worth more to those
scripts than sometimes having related items all on one log line.

>> BTW, there's a separate set of problems that have yet to be addressed,
>> which is how any of these logging options apply for V3-protocol query
>> operations.  The existing code only seems to work for the old-style
>> query path.

> You mean how are they passed to the client?  I assumed that would work
> for pre-V3 clients.

No, I mean the functionality isn't in the extended-query code path at
all, and it's not immediately clear where to insert it (eg, which steps
of parse/bind/execute do what logging, or where you measure duration).

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > I think they fit pretty nicely on one line, and lot of folks want that
> > information.  I realize it looks like bloatware because it duplicates
> > some existing functionality, but I think it is a combination of duration
> > and statement output that can't be done easily separately.
>
> Sure it can.  You're essentially arguing that DBAs are too dumb to match
> up matching query and duration log outputs.  I don't buy that.  I think
> they'll be analyzing their logs with little Perl scripts anyway, and
> that consistency of log output format will be worth more to those
> scripts than sometimes having related items all on one log line.

Yes, I am arguing that we shouldn't make people jump through Perl hoops
to get a statement/duration line in their log files.  I think it is
asked for enough that a nice printed line will help them.

If we already have the parameter, why not make it easy.  If they are
using Perl, they can already use log_statement and log_duration to print
only queries taking over a certain amount of time.

> >> BTW, there's a separate set of problems that have yet to be addressed,
> >> which is how any of these logging options apply for V3-protocol query
> >> operations.  The existing code only seems to work for the old-style
> >> query path.
>
> > You mean how are they passed to the client?  I assumed that would work
> > for pre-V3 clients.
>
> No, I mean the functionality isn't in the extended-query code path at
> all, and it's not immediately clear where to insert it (eg, which steps
> of parse/bind/execute do what logging, or where you measure duration).

I assume it would be all executor stuff, but I see what you mean that
the perpare isn't going through the normal query path.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Tom Lane writes:

> Sure it can.  You're essentially arguing that DBAs are too dumb to match
> up matching query and duration log outputs.  I don't buy that.  I think
> they'll be analyzing their logs with little Perl scripts anyway, and
> that consistency of log output format will be worth more to those
> scripts than sometimes having related items all on one log line.

When you're dealing with a large installation, these little Perl scripts
become difficult.  I've just had to deal with a similar issue with a
popular MTA which spreads the relevant log information over several lines.
If you're generating 500 MB of log output a day, it becomes a problem.

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Tom Lane writes:

> I would prefer to see the log entries look like
>
>     LOG: query: select * from pg_class;
>     LOG: duration: nn.nnn msec

I'm not fond of the abbrevation "msec" or even "msecs".  The official
abbreviation is "ms".

Btw., I was wondering, are we kidding ourselves when we display
microsecond precision to the user?  What accuracy do these measurements
have in respect to what they are actually supposed to measure?

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Tom Lane writes:
>
> > Sure it can.  You're essentially arguing that DBAs are too dumb to match
> > up matching query and duration log outputs.  I don't buy that.  I think
> > they'll be analyzing their logs with little Perl scripts anyway, and
> > that consistency of log output format will be worth more to those
> > scripts than sometimes having related items all on one log line.
>
> When you're dealing with a large installation, these little Perl scripts
> become difficult.  I've just had to deal with a similar issue with a
> popular MTA which spreads the relevant log information over several lines.
> If you're generating 500 MB of log output a day, it becomes a problem.

I can imagine.  I wasn't sure how I would write Perl code to join things
via pid.  I am sure it can be done (load into hash), but it wasn't
trivial like grep.

Peter, any problems with pid wrap-around?  I am thinking we need to
prepend a "wrap count" on the front of the pid output for 7.5.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Tom Lane writes:
>
> > I would prefer to see the log entries look like
> >
> >     LOG: query: select * from pg_class;
> >     LOG: duration: nn.nnn msec
>
> I'm not fond of the abbrevation "msec" or even "msecs".  The official
> abbreviation is "ms".

Yep.  Someone suggested "msec" in their example, so I used that, but I
like "ms" better too:

    LOG:  duration: 0.950 ms; select 1;
    LOG:  duration: 0.269 ms; set log_min_duration_statement = 1;

Patch attached.

> Btw., I was wondering, are we kidding ourselves when we display
> microsecond precision to the user?  What accuracy do these measurements
> have in respect to what they are actually supposed to measure?

Not sure.  I think the microsecond stuff is accurate to some degree, but
not sure how much.  I think the tick is 10ms, but I thought the timing
was much more accurate than that.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.210
diff -c -c -r1.210 runtime.sgml
*** doc/src/sgml/runtime.sgml    3 Oct 2003 19:26:49 -0000    1.210
--- doc/src/sgml/runtime.sgml    5 Oct 2003 14:12:20 -0000
***************
*** 1691,1702 ****
           Sets a minimum statement execution time (in milliseconds)
           above which a statement will be logged.  All SQL statements
           that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero (the default)
!      disables time-based logging.  For example, if you set it
           to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this
!          option can be useful in tracking down unoptimized queries in
!          your applications.
           Only superusers can increase this or set it to zero if this option
           is set to non-zero by the administrator.
          </para>
--- 1691,1702 ----
           Sets a minimum statement execution time (in milliseconds)
           above which a statement will be logged.  All SQL statements
           that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero will print
!          all queries with their durations.  Minus-one (the default)
!          disables time-based logging.  For example, if you set it
           to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this option can be useful
!          in tracking down unoptimized queries in your applications.
           Only superusers can increase this or set it to zero if this option
           is set to non-zero by the administrator.
          </para>
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.370
diff -c -c -r1.370 postgres.c
*** src/backend/tcop/postgres.c    4 Oct 2003 02:47:04 -0000    1.370
--- src/backend/tcop/postgres.c    5 Oct 2003 14:12:23 -0000
***************
*** 694,700 ****
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
--- 694,700 ----
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
***************
*** 940,946 ****
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
      {
          long        usecs;
          bool        print_statement;
--- 940,946 ----
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
      {
          long        usecs;
          bool        print_statement;
***************
*** 957,971 ****
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement > 0 &&
!                            usecs >= save_log_min_duration_statement * 1000);

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration(secs): %ld.%06ld%s%s",
!                             (long) (stop_t.tv_sec - start_t.tv_sec),
!                             (long) (stop_t.tv_usec - start_t.tv_usec),
!                             print_statement ? " " : "",
                              print_statement ? query_string : "")));
      }

--- 957,973 ----
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement == 0 ||
!                            (save_log_min_duration_statement > 0 &&
!                             usecs >= save_log_min_duration_statement * 1000));

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration: %ld.%03ld ms%s%s",
!                             (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
!                             (stop_t.tv_usec - start_t.tv_usec) / 1000),
!                             (long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
!                             print_statement ? "; " : "",
                              print_statement ? query_string : "")));
      }

Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.162
diff -c -c -r1.162 guc.c
*** src/backend/utils/misc/guc.c    3 Oct 2003 19:26:49 -0000    1.162
--- src/backend/utils/misc/guc.c    5 Oct 2003 14:12:28 -0000
***************
*** 128,134 ****
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = 0;


  /*
--- 128,134 ----
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = -1;


  /*
***************
*** 1185,1194 ****
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("The default is 0 (turning this feature off).")
          },
          &log_min_duration_statement,
!         0, 0, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
--- 1185,1194 ----
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("Zero prints all queries.  The default is -1 (turning this feature off).")
          },
          &log_min_duration_statement,
!         -1, -1, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.91
diff -c -c -r1.91 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample    3 Oct 2003 19:26:49 -0000    1.91
--- src/backend/utils/misc/postgresql.conf.sample    5 Oct 2003 14:12:29 -0000
***************
*** 157,165 ****
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = 0  # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero disables.

  #silent_mode = false         # DO NOT USE without Syslog!

--- 157,166 ----
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = -1 # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero prints all queries.
!                  # Minus-one disables.

  #silent_mode = false         # DO NOT USE without Syslog!


Re: fix log_min_duration_statement logic error

From
Andrew Dunstan
Date:

Bruce Momjian wrote:

>
>
>>Btw., I was wondering, are we kidding ourselves when we display
>>microsecond precision to the user?  What accuracy do these measurements
>>have in respect to what they are actually supposed to measure?
>>
>>
>
>Not sure.  I think the microsecond stuff is accurate to some degree, but
>not sure how much.  I think the tick is 10ms, but I thought the timing
>was much more accurate than that.
>
>
>
On my (slow) linux box the apparent time delay between 2 immediately
successive calls to gettimeofday() is 3 or 4 microsecs.

Presumably the clock tick is something much larger than that - I forget
where to look to find that out.

I think the real question is what granularity of reporting will be most
useful. For the session duration patch I restricted it to 1/100th of a
second, and didn't bother rounding the last place there because it
wasn't worth it (I thought). For query duration presumably something
smaller seems appropriate,  but I'm not sure how small. I suspect
anything much below a millisec (or at most 100 microsecs) is of
comparatively little value. OTOH truncating it is also probably of
little value - if you can read 3 or 4 decimal places you can read 6 just
as easily - just be aware that the low values have little information value.

cheers

andrew


Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> When you're dealing with a large installation, these little Perl scripts
> become difficult.  I've just had to deal with a similar issue with a
> popular MTA which spreads the relevant log information over several lines.
> If you're generating 500 MB of log output a day, it becomes a problem.

True, but it would take really serious revisions of our log output
formatting to fix things so that a naive "grep" will be useful for much
of anything.

To take just the most obvious limitation in what Bruce is proposing: a
grep for "duration" will yield the duration and the first line of the
SQL command.  If an installation is in the habit of breaking their SQL
into multiple lines, this will be less than useful.  Some people like
to format their code like this:

    SELECT
        a, b, c
    FROM
        ...

in which case showing just the first line will be quite content-free.

There are already similar problems with extracting error information
from the logs (and the 7.4 redesign of error formatting has made 'em
worse).

If we are going to try to design the log output so that you don't need
reassembly scripts to link related lines together, then we have got lots
bigger problems to fix than log_duration.  I'm not convinced it's an
appropriate goal at all, though.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Btw., I was wondering, are we kidding ourselves when we display
> microsecond precision to the user?  What accuracy do these measurements
> have in respect to what they are actually supposed to measure?

<shrug>  The operating system API we are using is spec'd at microsecond
precision.  It's likely on any given hardware that some of the low order
digits might be bogus, but it is not our business to guess how many.
If we throw away low-order digits we may be losing useful information.
(This becomes more and more likely as machines get faster.)

We have EXPLAIN ANALYZE output showing two fractional digits of msec,
so it is discarding one potentially significant digit.  I did that for
consistency with the historical behavior of showing two fractional
digits of cost estimates, but could probably be talked into the idea
that three digits should be shown instead.

BTW, EXPLAIN ANALYZE puts out

 Total runtime: 406.53 msec

Do you want to make an exception to the string freeze to change this
to "ms"?

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Peter, any problems with pid wrap-around?  I am thinking we need to
> prepend a "wrap count" on the front of the pid output for 7.5.

Why?  And how would you know when the PIDs have wrapped anyway?

The OS already guarantees that no two concurrently running procs have
the same PID.  That seems sufficient to me.  It's conceivable that a PID
could be recycled quickly enough that it wasn't obvious from the logs
that this was a new backend process and not the same old one, but do you
care?  (And if you did care, wouldn't you be monitoring log_connections,
which would tip you off?)

I think this is a red herring.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Tom Lane writes:

> BTW, EXPLAIN ANALYZE puts out
>  Total runtime: 406.53 msec
> Do you want to make an exception to the string freeze to change this
> to "ms"?

I just realized, all the things that are sent as a query result instead of
an error or notice are not gettext-enabled.  I guess we'll have to do
without that in this release.  So, making the above change does not pose a
problem.

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
ohp@pyrenet.fr
Date:
On Sat, 4 Oct 2003, Tom Lane wrote:

> Date: Sat, 04 Oct 2003 15:43:34 -0400
> From: Tom Lane <tgl@sss.pgh.pa.us>
> To: Bruce Momjian <pgman@candle.pha.pa.us>
> Cc: Peter Eisentraut <peter_e@gmx.net>, Neil Conway <neilc@samurai.com>,
>      PostgreSQL Patches <pgsql-patches@postgresql.org>
> Subject: Re: [PATCHES] fix log_min_duration_statement logic error
>
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Tom Lane wrote:
> >> I would prefer to see the log entries look like
> >>
> >> LOG: query: select * from pg_class;
> >> LOG: duration: nn.nnn msec
>
> > The problem with two lines is that another log message could get between
> > them.
>
> That was true already with log_statement and log_duration as separate
> operations.  People use log_pid to deal with it.
Sorry to jump in... the log_pid is NOT ENOUGH where you have more than
30000 connections a day (witch is my case)

There has been discussion as to have 1 Log file/database where are we on
that? Is it dead?
Thanks
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: the planner will ignore your desire to choose an index scan if your
>       joining column's datatypes do not match
>

--
Olivier PRENANT                    Tel: +33-5-61-50-97-00 (Work)
6, Chemin d'Harraud Turrou           +33-5-61-50-97-01 (Fax)
31190 AUTERIVE                       +33-6-07-63-80-64 (GSM)
FRANCE                          Email: ohp@pyrenet.fr
------------------------------------------------------------------------------
Make your life a dream, make your dream a reality. (St Exupery)

Re: fix log_min_duration_statement logic error

From
Rod Taylor
Date:
> > That was true already with log_statement and log_duration as separate
> > operations.  People use log_pid to deal with it.
> Sorry to jump in... the log_pid is NOT ENOUGH where you have more than
> 30000 connections a day (witch is my case)

log_pid isn't enough, but log_pid + log_connections certainly is.

log_connections tells you when a new connection was made, so guessing
isn't required.

> There has been discussion as to have 1 Log file/database where are we on
> that? Is it dead?

Well, this wouldn't help either unless you happen to have several not so
active databases that makes for a busy system.

Attachment

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
> > When you're dealing with a large installation, these little Perl scripts
> > become difficult.  I've just had to deal with a similar issue with a
> > popular MTA which spreads the relevant log information over several lines.
> > If you're generating 500 MB of log output a day, it becomes a problem.
>
> True, but it would take really serious revisions of our log output
> formatting to fix things so that a naive "grep" will be useful for much
> of anything.
>
> To take just the most obvious limitation in what Bruce is proposing: a
> grep for "duration" will yield the duration and the first line of the
> SQL command.  If an installation is in the habit of breaking their SQL
> into multiple lines, this will be less than useful.  Some people like
> to format their code like this:
>
>     SELECT
>         a, b, c
>     FROM
>         ...
>
> in which case showing just the first line will be quite content-free.
>

It is pretty easy to continue pulling lines after the 'duration' hit to
see the full query, perhap using awk, or even grep with a + arg.  I just
don't see why we should make it harder for folks by splitting it over
several lines.  For folks that want to use perl, they can use the
existing log_* outputs to join by pid and get whatever they want.  If
you want to call this option an option for dummies that don't want to
deal with Perl (and Peter has expressed that it isn't easy), that's
fine.

Does someone want to show us a Perl script do join lines for this
must-requested output?  I don't feel like sending it to everyone who
needs to find the slow queries in their application.  Do you?

If you want, we can have vote on it.  Frankly, the code was designed and
submitted as one line output, and I think a vote will show one-line
output as the winner.

> There are already similar problems with extracting error information
> from the logs (and the 7.4 redesign of error formatting has made 'em
> worse).
>
> If we are going to try to design the log output so that you don't need
> reassembly scripts to link related lines together, then we have got lots
> bigger problems to fix than log_duration.  I'm not convinced it's an
> appropriate goal at all, though.

Again, it is cost/benefit --- how many people want easy reporting of
queries and their durations.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> It is pretty easy to continue pulling lines after the 'duration' hit to
> see the full query, perhap using awk, or even grep with a + arg.  I just
> don't see why we should make it harder for folks by splitting it over
> several lines.

Somehow I fail to see how that's a consistent position.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
ohp@pyrenet.fr
Date:
On Sun, 5 Oct 2003, Rod Taylor wrote:

> Date: Sun, 05 Oct 2003 13:05:32 -0400
> From: Rod Taylor <rbt@rbt.ca>
> To: ohp@pyrenet.fr
> Cc: Tom Lane <tgl@sss.pgh.pa.us>, Bruce Momjian <pgman@candle.pha.pa.us>,
>      Peter Eisentraut <peter_e@gmx.net>, Neil Conway <neilc@samurai.com>,
>      PostgreSQL Patches <pgsql-patches@postgresql.org>
> Subject: Re: [PATCHES] fix log_min_duration_statement logic error
>
> > > That was true already with log_statement and log_duration as separate
> > > operations.  People use log_pid to deal with it.
> > Sorry to jump in... the log_pid is NOT ENOUGH where you have more than
> > 30000 connections a day (witch is my case)
>
> log_pid isn't enough, but log_pid + log_connections certainly is.
>
> log_connections tells you when a new connection was made, so guessing
> isn't required.
>
> > There has been discussion as to have 1 Log file/database where are we on
> > that? Is it dead?
>
> Well, this wouldn't help either unless you happen to have several not so
> active databases that makes for a busy system.
>
Only that I could give the log file to the customer owning the database(s)
that would make my job esier.

Also I'd love to see the log_query being settable per database...

--
Olivier PRENANT                    Tel: +33-5-61-50-97-00 (Work)
6, Chemin d'Harraud Turrou           +33-5-61-50-97-01 (Fax)
31190 AUTERIVE                       +33-6-07-63-80-64 (GSM)
FRANCE                          Email: ohp@pyrenet.fr
------------------------------------------------------------------------------
Make your life a dream, make your dream a reality. (St Exupery)

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Tom Lane writes:
>> BTW, EXPLAIN ANALYZE puts out
>> Total runtime: 406.53 msec
>> Do you want to make an exception to the string freeze to change this
>> to "ms"?

> I just realized, all the things that are sent as a query result instead of
> an error or notice are not gettext-enabled.  I guess we'll have to do
> without that in this release.  So, making the above change does not pose a
> problem.

Okay, I'll make that change.  Any opinions about the 2-vs-3-digit issue?

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > It is pretty easy to continue pulling lines after the 'duration' hit to
> > see the full query, perhap using awk, or even grep with a + arg.  I just
> > don't see why we should make it harder for folks by splitting it over
> > several lines.
>
> Somehow I fail to see how that's a consistent position.

It is easier than making things split across lines.  It is a common
request so I want to make it as easy as possible --- that seems
consistent.  If you can think of a way to make it even easier, please
let me know.

I have not heard from you why we should make it harder (split across two
lines), except for consistency with log_statement and log_duration
outputs.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
> > Tom Lane writes:
> >> BTW, EXPLAIN ANALYZE puts out
> >> Total runtime: 406.53 msec
> >> Do you want to make an exception to the string freeze to change this
> >> to "ms"?
>
> > I just realized, all the things that are sent as a query result instead of
> > an error or notice are not gettext-enabled.  I guess we'll have to do
> > without that in this release.  So, making the above change does not pose a
> > problem.
>
> Okay, I'll make that change.  Any opinions about the 2-vs-3-digit issue?

I think three is the only reasonable number --- when you are in digits
to the right of the decimal, it should be grouped by three.  To group
by two makes it look like a US dollar amount, and I can't see a rational
for two digits.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
ohp@pyrenet.fr writes:
> Also I'd love to see the log_query being settable per database...

AFAIK you can do that now.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Bruce Momjian wrote:
> Tom Lane wrote:
> > Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > > It is pretty easy to continue pulling lines after the 'duration' hit to
> > > see the full query, perhap using awk, or even grep with a + arg.  I just
> > > don't see why we should make it harder for folks by splitting it over
> > > several lines.
> >
> > Somehow I fail to see how that's a consistent position.
>
> It is easier than making things split across lines.  It is a common
> request so I want to make it as easy as possible --- that seems
> consistent.  If you can think of a way to make it even easier, please
> let me know.
>
> I have not heard from you why we should make it harder (split across two
> lines), except for consistency with log_statement and log_duration
> outputs.

Also, now that you mention queries output as multiple lines:

    LOG:  duration: 3.938 ms; select *
    from pg_language;

Should we instead convert newlines to "\n" and output the query as a
single line?  Do we have lots of other multi-line outputs in the log
files?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> I have not heard from you why we should make it harder (split across two
> lines), except for consistency with log_statement and log_duration
> outputs.

That is exactly my argument.  I'll freely admit that it's not a strong
point, but I find the claim that the inconsistent formats will be easier
to parse to be a much weaker argument, in the absence of any attempt to
make them *actually* easier to parse (like really truly one line).

[ later ]
> Should we instead convert newlines to "\n" and output the query as a
> single line?

That would shore up your position considerably.  It needs a little
thought as to whether this would induce any confusion, and whether we
really care if so.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > I have not heard from you why we should make it harder (split across two
> > lines), except for consistency with log_statement and log_duration
> > outputs.
>
> That is exactly my argument.  I'll freely admit that it's not a strong
> point, but I find the claim that the inconsistent formats will be easier
> to parse to be a much weaker argument, in the absence of any attempt to
> make them *actually* easier to parse (like really truly one line).
>
> [ later ]
> > Should we instead convert newlines to "\n" and output the query as a
> > single line?
>
> That would shore up your position considerably.  It needs a little
> thought as to whether this would induce any confusion, and whether we
> really care if so.

Good, we are moving forward with something we both like.  Let me work up
a patch and post it.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Rod Taylor
Date:
> > I have not heard from you why we should make it harder (split across two
> > lines), except for consistency with log_statement and log_duration
> > outputs.

I think this is a perfectly good argument. Don't make writing the tools
to parse the log more difficult than necessary.

Rather than making the log files look nice, lets add a module to PgAdmin
that can read it and display it in a user friendly manner (with
abilities like sorting queries by execution time!).

> Should we instead convert newlines to "\n" and output the query as a
> single line?  Do we have lots of other multi-line outputs in the log
> files?

Please don't. Or if you do, don't data unless you intend to escape
special characters (in this case \) at the same time so we can convert
it back to the original state.

Attachment

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Rod Taylor wrote:
-- Start of PGP signed section.
> > > I have not heard from you why we should make it harder (split across two
> > > lines), except for consistency with log_statement and log_duration
> > > outputs.
>
> I think this is a perfectly good argument. Don't make writing the tools
> to parse the log more difficult than necessary.
>
> Rather than making the log files look nice, lets add a module to PgAdmin
> that can read it and display it in a user friendly manner (with
> abilities like sorting queries by execution time!).
>
> > Should we instead convert newlines to "\n" and output the query as a
> > single line?  Do we have lots of other multi-line outputs in the log
> > files?
>
> Please don't. Or if you do, don't data unless you intend to escape
> special characters (in this case \) at the same time so we can convert
> it back to the original state.

OK, I coded to convert newline to "\n", carriage return to "\r", and
backslash to "\\".  This might cause confusion if you are doing:

    INSERT INTO tab VALUES ('\b');

which outputs as:

    INSERT INTO tab VALUES ('\\b');

but I see your point that we should be accurate.  Actual output is:

    LOG:  duration: 1.762 ms; insert into ii values ('\\b');

Another example:

    LOG:  duration: 4.228 ms; select *\nfrom pg_language;

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > I have not heard from you why we should make it harder (split across two
> > lines), except for consistency with log_statement and log_duration
> > outputs.
>
> That is exactly my argument.  I'll freely admit that it's not a strong
> point, but I find the claim that the inconsistent formats will be easier
> to parse to be a much weaker argument, in the absence of any attempt to
> make them *actually* easier to parse (like really truly one line).
>
> [ later ]
> > Should we instead convert newlines to "\n" and output the query as a
> > single line?
>
> That would shore up your position considerably.  It needs a little
> thought as to whether this would induce any confusion, and whether we
> really care if so.

OK, patch attached.  It does the single-line log_min_duration_statement,
and adds a zero value to always print the duration and statement.  I
have also added code to convert end-of-line characters to \n and \r, and
doubles backslashes.  It also makes log_statement print as one line, and
shows pg_stat_activity as one line.  Without this fix, you get:

    test=> select *  from pg_stat_activity;
     datid | datname | procpid | usesysid | usename  |           current_query           |          query_start

-------+---------+---------+----------+----------+-----------------------------------+-------------------------------
     17139 | test    |   19167 |        1 | postgres |                                   |
     17139 | test    |   19131 |        1 | postgres | select *
    from pg_class, pg_proc; | 2003-10-05 15:14:05.338268-04

New output is:

    test=> select * from pg_stat_activity;
     datid | datname | procpid | usesysid | usename  |           current_query           |          query_start

-------+---------+---------+----------+----------+-----------------------------------+-------------------------------
     17139 | test    |   20391 |        1 | postgres |                                   |
     17139 | test    |   20344 |        1 | postgres | select *\nfrom pg_proc, pg_class; | 2003-10-05
16:25:07.610427-04
    (2 rows)

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.210
diff -c -c -r1.210 runtime.sgml
*** doc/src/sgml/runtime.sgml    3 Oct 2003 19:26:49 -0000    1.210
--- doc/src/sgml/runtime.sgml    5 Oct 2003 20:26:09 -0000
***************
*** 1691,1702 ****
           Sets a minimum statement execution time (in milliseconds)
           above which a statement will be logged.  All SQL statements
           that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero (the default)
!      disables time-based logging.  For example, if you set it
           to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this
!          option can be useful in tracking down unoptimized queries in
!          your applications.
           Only superusers can increase this or set it to zero if this option
           is set to non-zero by the administrator.
          </para>
--- 1691,1702 ----
           Sets a minimum statement execution time (in milliseconds)
           above which a statement will be logged.  All SQL statements
           that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero will print
!          all queries with their durations.  Minus-one (the default)
!          disables time-based logging.  For example, if you set it
           to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this option can be useful
!          in tracking down unoptimized queries in your applications.
           Only superusers can increase this or set it to zero if this option
           is set to non-zero by the administrator.
          </para>
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.370
diff -c -c -r1.370 postgres.c
*** src/backend/tcop/postgres.c    4 Oct 2003 02:47:04 -0000    1.370
--- src/backend/tcop/postgres.c    5 Oct 2003 20:26:12 -0000
***************
*** 150,156 ****
  static void finish_xact_command(void);
  static void SigHupHandler(SIGNAL_ARGS);
  static void FloatExceptionHandler(SIGNAL_ARGS);
!

  /* ----------------------------------------------------------------
   *        routines to obtain user input
--- 150,156 ----
  static void finish_xact_command(void);
  static void SigHupHandler(SIGNAL_ARGS);
  static void FloatExceptionHandler(SIGNAL_ARGS);
! static char *str_add_symbolic_eol(const char *str);

  /* ----------------------------------------------------------------
   *        routines to obtain user input
***************
*** 461,467 ****

      if (log_statement)
          ereport(LOG,
!                 (errmsg("query: %s", query_string)));

      if (log_parser_stats)
          ResetUsage();
--- 461,467 ----

      if (log_statement)
          ereport(LOG,
!                 (errmsg("query: %s", str_add_symbolic_eol(query_string))));

      if (log_parser_stats)
          ResetUsage();
***************
*** 686,692 ****
       */
      debug_query_string = query_string;

!     pgstat_report_activity(query_string);

      /*
       * We use save_log_* so "SET log_duration = true"  and "SET
--- 686,692 ----
       */
      debug_query_string = query_string;

!     pgstat_report_activity(str_add_symbolic_eol(query_string));

      /*
       * We use save_log_* so "SET log_duration = true"  and "SET
***************
*** 694,700 ****
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
--- 694,700 ----
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
***************
*** 940,946 ****
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
      {
          long        usecs;
          bool        print_statement;
--- 940,946 ----
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
      {
          long        usecs;
          bool        print_statement;
***************
*** 957,972 ****
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement > 0 &&
!                            usecs >= save_log_min_duration_statement * 1000);

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration(secs): %ld.%06ld%s%s",
!                             (long) (stop_t.tv_sec - start_t.tv_sec),
!                             (long) (stop_t.tv_usec - start_t.tv_usec),
!                             print_statement ? " " : "",
!                             print_statement ? query_string : "")));
      }

      if (save_log_statement_stats)
--- 957,974 ----
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement == 0 ||
!                            (save_log_min_duration_statement > 0 &&
!                             usecs >= save_log_min_duration_statement * 1000));

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration: %ld.%03ld ms%s%s",
!                             (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
!                             (stop_t.tv_usec - start_t.tv_usec) / 1000),
!                             (long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
!                             print_statement ? "; " : "",
!                             print_statement ? str_add_symbolic_eol(query_string) : "")));
      }

      if (save_log_statement_stats)
***************
*** 1000,1006 ****
       */
      debug_query_string = query_string;

!     pgstat_report_activity(query_string);

      set_ps_display("PARSE");

--- 1002,1008 ----
       */
      debug_query_string = query_string;

!     pgstat_report_activity(str_add_symbolic_eol(query_string));

      set_ps_display("PARSE");

***************
*** 3196,3198 ****
--- 3198,3236 ----

      pfree(str.data);
  }
+
+ /*
+  *    str_add_symbolic_eol
+  *
+  *    This string coverts literal newlines to "\n" for log output.
+  */
+ static char *str_add_symbolic_eol(const char *str)
+ {
+     char *outstr = palloc(strlen(str) * 2 + 1);
+     int    len = strlen(str);
+     int i, outlen = 0;
+
+     for (i = 0; i < len; i++)
+     {
+         if (str[i] == '\n')
+         {
+             outstr[outlen++] = '\\';
+             outstr[outlen++] = 'n';
+         }
+         else if (str[i] == '\r')
+         {
+             outstr[outlen++] = '\\';
+             outstr[outlen++] = 'r';
+         }
+         else if (str[i] == '\\')
+         {
+             outstr[outlen++] = '\\';
+             outstr[outlen++] = '\\';
+         }
+         else
+             outstr[outlen++] = str[i];
+     }
+     outstr[outlen++]    = '\0';
+     return outstr;
+ }
+
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.162
diff -c -c -r1.162 guc.c
*** src/backend/utils/misc/guc.c    3 Oct 2003 19:26:49 -0000    1.162
--- src/backend/utils/misc/guc.c    5 Oct 2003 20:26:19 -0000
***************
*** 128,134 ****
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = 0;


  /*
--- 128,134 ----
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = -1;


  /*
***************
*** 1185,1194 ****
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("The default is 0 (turning this feature off).")
          },
          &log_min_duration_statement,
!         0, 0, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
--- 1185,1194 ----
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("Zero prints all queries.  The default is -1 (turning this feature off).")
          },
          &log_min_duration_statement,
!         -1, -1, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.91
diff -c -c -r1.91 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample    3 Oct 2003 19:26:49 -0000    1.91
--- src/backend/utils/misc/postgresql.conf.sample    5 Oct 2003 20:26:20 -0000
***************
*** 157,165 ****
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = 0  # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero disables.

  #silent_mode = false         # DO NOT USE without Syslog!

--- 157,166 ----
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = -1 # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero prints all queries.
!                  # Minus-one disables.

  #silent_mode = false         # DO NOT USE without Syslog!


Re: fix log_min_duration_statement logic error

From
Rod Taylor
Date:
> have also added code to convert end-of-line characters to \n and \r, and
> doubles backslashes.  It also makes log_statement print as one line, and
> shows pg_stat_activity as one line.  Without this fix, you get:

And how does it look with what was originally a fairly readable 30 or 40
line query?

Attachment

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Rod Taylor wrote:
-- Start of PGP signed section.
> > have also added code to convert end-of-line characters to \n and \r, and
> > doubles backslashes.  It also makes log_statement print as one line, and
> > shows pg_stat_activity as one line.  Without this fix, you get:
>
> And how does it look with what was originally a fairly readable 30 or 40
> line query?

Probably pretty long.  I think the pg_stat_activity case really needs
the "\n" because if not the query breaks the table output format.  Not
sure about log_statement or log_min_duration_statement.  Having it be
one line makes grep easy, and is probably easier for processing via
tools, but reading the log could be harder:

  LOG:  duration: 7.466 ms; select *\nfrom pg_class\nwhere oid = 3 and\nrelname = 'abcd' and\nrelkind = 'r'\norder by
relname;

The old format output was:

  LOG:  duration: 7.466 ms; select *
  from pg_class
  where oid = 3 and
  relname = 'abcd' and
  relkind = 'r'
  order by relname;

It is hard to understand how a tool would grab the query from the above
log except to look for another TAG: entry and stop there.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Another example:
>     LOG:  duration: 4.228 ms; select *\nfrom pg_language;

Minor quibble: would it read better as

    LOG:  duration n.nnn ms: query
or
    LOG:  duration n.nnn ms for query

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Another example:
> >     LOG:  duration: 4.228 ms; select *\nfrom pg_language;
>
> Minor quibble: would it read better as
>
>     LOG:  duration n.nnn ms: query
> or
>     LOG:  duration n.nnn ms for query

I like it:

    LOG:  duration: 4.056 ms for select * \nfrom pg_language;

Another idea if you like consistency would be:

    LOG:  duration: 4.056 ms  query: select * \nfrom pg_language;

Patch for "query:" version attached.

Do I need to pfree the memory returned by str_make_symbolic_eol() or is
that cleaned up automatically?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.210
diff -c -c -r1.210 runtime.sgml
*** doc/src/sgml/runtime.sgml    3 Oct 2003 19:26:49 -0000    1.210
--- doc/src/sgml/runtime.sgml    5 Oct 2003 21:17:30 -0000
***************
*** 1691,1702 ****
           Sets a minimum statement execution time (in milliseconds)
           above which a statement will be logged.  All SQL statements
           that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero (the default)
!      disables time-based logging.  For example, if you set it
           to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this
!          option can be useful in tracking down unoptimized queries in
!          your applications.
           Only superusers can increase this or set it to zero if this option
           is set to non-zero by the administrator.
          </para>
--- 1691,1702 ----
           Sets a minimum statement execution time (in milliseconds)
           above which a statement will be logged.  All SQL statements
           that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero will print
!          all queries with their durations.  Minus-one (the default)
!          disables time-based logging.  For example, if you set it
           to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this option can be useful
!          in tracking down unoptimized queries in your applications.
           Only superusers can increase this or set it to zero if this option
           is set to non-zero by the administrator.
          </para>
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.370
diff -c -c -r1.370 postgres.c
*** src/backend/tcop/postgres.c    4 Oct 2003 02:47:04 -0000    1.370
--- src/backend/tcop/postgres.c    5 Oct 2003 21:17:33 -0000
***************
*** 150,156 ****
  static void finish_xact_command(void);
  static void SigHupHandler(SIGNAL_ARGS);
  static void FloatExceptionHandler(SIGNAL_ARGS);
!

  /* ----------------------------------------------------------------
   *        routines to obtain user input
--- 150,156 ----
  static void finish_xact_command(void);
  static void SigHupHandler(SIGNAL_ARGS);
  static void FloatExceptionHandler(SIGNAL_ARGS);
! static char *str_make_symbolic_eol(const char *str);

  /* ----------------------------------------------------------------
   *        routines to obtain user input
***************
*** 461,467 ****

      if (log_statement)
          ereport(LOG,
!                 (errmsg("query: %s", query_string)));

      if (log_parser_stats)
          ResetUsage();
--- 461,467 ----

      if (log_statement)
          ereport(LOG,
!                 (errmsg("query: %s", str_make_symbolic_eol(query_string))));

      if (log_parser_stats)
          ResetUsage();
***************
*** 686,692 ****
       */
      debug_query_string = query_string;

!     pgstat_report_activity(query_string);

      /*
       * We use save_log_* so "SET log_duration = true"  and "SET
--- 686,692 ----
       */
      debug_query_string = query_string;

!     pgstat_report_activity(str_make_symbolic_eol(query_string));

      /*
       * We use save_log_* so "SET log_duration = true"  and "SET
***************
*** 694,700 ****
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
--- 694,700 ----
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
***************
*** 940,946 ****
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
      {
          long        usecs;
          bool        print_statement;
--- 940,946 ----
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
      {
          long        usecs;
          bool        print_statement;
***************
*** 957,972 ****
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement > 0 &&
!                            usecs >= save_log_min_duration_statement * 1000);

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration(secs): %ld.%06ld%s%s",
!                             (long) (stop_t.tv_sec - start_t.tv_sec),
!                             (long) (stop_t.tv_usec - start_t.tv_usec),
!                             print_statement ? " " : "",
!                             print_statement ? query_string : "")));
      }

      if (save_log_statement_stats)
--- 957,974 ----
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement == 0 ||
!                            (save_log_min_duration_statement > 0 &&
!                             usecs >= save_log_min_duration_statement * 1000));

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration: %ld.%03ld ms%s%s",
!                             (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
!                             (stop_t.tv_usec - start_t.tv_usec) / 1000),
!                             (long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
!                             print_statement ? "  query: " : "",
!                             print_statement ? str_make_symbolic_eol(query_string) : "")));
      }

      if (save_log_statement_stats)
***************
*** 1000,1006 ****
       */
      debug_query_string = query_string;

!     pgstat_report_activity(query_string);

      set_ps_display("PARSE");

--- 1002,1008 ----
       */
      debug_query_string = query_string;

!     pgstat_report_activity(str_make_symbolic_eol(query_string));

      set_ps_display("PARSE");

***************
*** 3196,3198 ****
--- 3198,3236 ----

      pfree(str.data);
  }
+
+ /*
+  *    str_make_symbolic_eol
+  *
+  *    This string coverts literal newlines to "\n" for log output.
+  */
+ static char *str_make_symbolic_eol(const char *str)
+ {
+     char *outstr = palloc(strlen(str) * 2 + 1);
+     int    len = strlen(str);
+     int i, outlen = 0;
+
+     for (i = 0; i < len; i++)
+     {
+         if (str[i] == '\n')
+         {
+             outstr[outlen++] = '\\';
+             outstr[outlen++] = 'n';
+         }
+         else if (str[i] == '\r')
+         {
+             outstr[outlen++] = '\\';
+             outstr[outlen++] = 'r';
+         }
+         else if (str[i] == '\\')
+         {
+             outstr[outlen++] = '\\';
+             outstr[outlen++] = '\\';
+         }
+         else
+             outstr[outlen++] = str[i];
+     }
+     outstr[outlen++]    = '\0';
+     return outstr;
+ }
+
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.162
diff -c -c -r1.162 guc.c
*** src/backend/utils/misc/guc.c    3 Oct 2003 19:26:49 -0000    1.162
--- src/backend/utils/misc/guc.c    5 Oct 2003 21:17:37 -0000
***************
*** 128,134 ****
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = 0;


  /*
--- 128,134 ----
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = -1;


  /*
***************
*** 1185,1194 ****
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("The default is 0 (turning this feature off).")
          },
          &log_min_duration_statement,
!         0, 0, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
--- 1185,1194 ----
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("Zero prints all queries.  The default is -1 (turning this feature off).")
          },
          &log_min_duration_statement,
!         -1, -1, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.91
diff -c -c -r1.91 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample    3 Oct 2003 19:26:49 -0000    1.91
--- src/backend/utils/misc/postgresql.conf.sample    5 Oct 2003 21:17:37 -0000
***************
*** 157,165 ****
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = 0  # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero disables.

  #silent_mode = false         # DO NOT USE without Syslog!

--- 157,166 ----
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = -1 # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero prints all queries.
!                  # Minus-one disables.

  #silent_mode = false         # DO NOT USE without Syslog!


Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> It is hard to understand how a tool would grab the query from the above
> log except to look for another TAG: entry and stop there.

That was pretty much the centerpiece of my complaint --- up to now it's
been tremendously difficult to parse the PG logs automatically, and I
think something along this line would make it much easier.

I am inclined to think though that Bruce has done this in the wrong
place.  If we are going to try to enforce "no real newlines inserted as
part of logged strings", then it ought to be done at a low level in
elog.c where it will apply to *everything* that goes into the log, not
just log_statement/log_duration.  For example, we presently allow
embedded newlines in DETAIL/HINT messages, which is fine for frontend
messages but helps to render the log unparsable.  Those should be
\n-ified too if we are really interested in making the log easy to
process.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
>            Sets a minimum statement execution time (in milliseconds)
>            above which a statement will be logged.  All SQL statements
>            that run longer than the time specified will be logged together
> !          with their actual duration.  Setting this to zero will print
> !          all queries with their durations.  Minus-one (the default)
> !          disables time-based logging.  For example, if you set it
>            to <literal>250</literal> then all SQL statements that run longer
> !          than 250ms will be logged.

You're being very unclear, not to say self-contradictory, as to whether
the condition is "> value" or ">= value".  I suspect it is really the
latter but this description sure doesn't convey the fact.

>            Only superusers can increase this or set it to zero if this option
>            is set to non-zero by the administrator.

If you're changing the "off" state to -1 then this last sentence is now
wrong, no?  Also, do the non-superuser adjustment constraints in guc.c
still work correctly with this meaning (probably so, but it needs to be
checked)?

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Rod Taylor
Date:
> Probably pretty long.  I think the pg_stat_activity case really needs
> the "\n" because if not the query breaks the table output format.  Not

I was actually thinking exactly the opposite. pg_stat_activity viewed in
pgadmin GUI is going to format the table perfectly fine, but with
everthing on one line it will be next to impossible to understand
anything complex.

I would imagine psql will also be easier to read using human placed \n's
rather than random ones at the terminal width.

Perhaps the environment I work in isn't the normal case, but usually if
I'm trying to track something down, it's the complex 10 table join,
multi-subselect report style query that someone in account management
just happens to be running but poorly formed.

> It is hard to understand how a tool would grab the query from the above
> log except to look for another TAG: entry and stop there.

Yup.. Same way you group entries by PID, then reset the PID the next
time you see a new connection formed with it.

Attachment

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Rod Taylor wrote:
-- Start of PGP signed section.
> > Probably pretty long.  I think the pg_stat_activity case really needs
> > the "\n" because if not the query breaks the table output format.  Not
>
> I was actually thinking exactly the opposite. pg_stat_activity viewed in
> pgadmin GUI is going to format the table perfectly fine, but with
> everthing on one line it will be next to impossible to understand
> anything complex.

You are right.  It is psql that is at fault for causing the \n value to
start at the beginning of the next line and not at the proper column on
the next line.  I will not change the pg_stat_activity values.

Tom's idea of doing it in elog is better, of course.

> I would imagine psql will also be easier to read using human placed \n's
> rather than random ones at the terminal width.

Right.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> >            Sets a minimum statement execution time (in milliseconds)
> >            above which a statement will be logged.  All SQL statements
> >            that run longer than the time specified will be logged together
> > !          with their actual duration.  Setting this to zero will print
> > !          all queries with their durations.  Minus-one (the default)
> > !          disables time-based logging.  For example, if you set it
> >            to <literal>250</literal> then all SQL statements that run longer
> > !          than 250ms will be logged.
>
> You're being very unclear, not to say self-contradictory, as to whether
> the condition is "> value" or ">= value".  I suspect it is really the
> latter but this description sure doesn't convey the fact.
>
> >            Only superusers can increase this or set it to zero if this option
> >            is set to non-zero by the administrator.
>
> If you're changing the "off" state to -1 then this last sentence is now
> wrong, no?  Also, do the non-superuser adjustment constraints in guc.c
> still work correctly with this meaning (probably so, but it needs to be
> checked)?

OK, new text:

     <varlistentry>
      <term><varname>log_min_duration_statement</varname> (<type>integer</type>)</term>
       <listitem>
        <para>
         Sets a minimum statement execution time (in milliseconds)
         for statement to be logged.  All SQL statements
         that run in the time specified or longer will be logged with
         their duration.  Setting this to zero will print
         all queries and their durations.  Minus-one (the default)
         disables this.  For example, if you set it to
         <literal>250</literal> then all SQL statements that run 250ms
         or longer will be logged.  Enabling this option can be
         useful in tracking down unoptimized queries in your applications.
         Only superusers can increase this or set it to minus-one if this
         option is set by the administrator.
        </para>
       </listitem>
      </varlistentry>


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > It is hard to understand how a tool would grab the query from the above
> > log except to look for another TAG: entry and stop there.
>
> That was pretty much the centerpiece of my complaint --- up to now it's
> been tremendously difficult to parse the PG logs automatically, and I
> think something along this line would make it much easier.
>
> I am inclined to think though that Bruce has done this in the wrong
> place.  If we are going to try to enforce "no real newlines inserted as
> part of logged strings", then it ought to be done at a low level in
> elog.c where it will apply to *everything* that goes into the log, not
> just log_statement/log_duration.  For example, we presently allow
> embedded newlines in DETAIL/HINT messages, which is fine for frontend
> messages but helps to render the log unparsable.  Those should be
> \n-ified too if we are really interested in making the log easy to
> process.

Agreed.  elog is the proper place, because then you guarantee that it is
all on one line.  Is that OK?  Do we have elogs that we want over
several lines?  Is this something we can do at this stage in beta?

Also, my change to pg_stat_activity was wrong, as Rod pointed out --- it
is psql that should handle \n properly, because pgadmin already does.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
> > Tom Lane writes:
> >> BTW, EXPLAIN ANALYZE puts out
> >> Total runtime: 406.53 msec
> >> Do you want to make an exception to the string freeze to change this
> >> to "ms"?
>
> > I just realized, all the things that are sent as a query result instead of
> > an error or notice are not gettext-enabled.  I guess we'll have to do
> > without that in this release.  So, making the above change does not pose a
> > problem.
>
> Okay, I'll make that change.  Any opinions about the 2-vs-3-digit issue?

I just committed a fix so psql \timing shows three digits:

    test=> \timing
    Timing is on.
    test=> select 1;
     ?column?
    ----------
            1
    (1 row)

    Time: 1.306 ms

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
? psql
Index: common.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.74
diff -c -c -r1.74 common.c
*** common.c    16 Sep 2003 17:59:02 -0000    1.74
--- common.c    5 Oct 2003 22:31:26 -0000
***************
*** 550,556 ****

      /* Possible microtiming output */
      if (pset.timing && success)
!         printf(gettext("Time: %.2f ms\n"), DIFF_MSEC(after, before));

      return success;
  }
--- 550,556 ----

      /* Possible microtiming output */
      if (pset.timing && success)
!         printf(gettext("Time: %.3f ms\n"), DIFF_MSEC(after, before));

      return success;
  }

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
> > Tom Lane writes:
> >> BTW, EXPLAIN ANALYZE puts out
> >> Total runtime: 406.53 msec
> >> Do you want to make an exception to the string freeze to change this
> >> to "ms"?
>
> > I just realized, all the things that are sent as a query result instead of
> > an error or notice are not gettext-enabled.  I guess we'll have to do
> > without that in this release.  So, making the above change does not pose a
> > problem.
>
> Okay, I'll make that change.  Any opinions about the 2-vs-3-digit issue?

Here is the patch that makes psql \timing display three digits:

    test=> \timing
    Timing is on.
    test=> select 1;
     ?column?
    ----------
            1
    (1 row)

    Time: 1.306 ms

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
? psql
Index: common.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.74
diff -c -c -r1.74 common.c
*** common.c    16 Sep 2003 17:59:02 -0000    1.74
--- common.c    5 Oct 2003 22:31:26 -0000
***************
*** 550,556 ****

      /* Possible microtiming output */
      if (pset.timing && success)
!         printf(gettext("Time: %.2f ms\n"), DIFF_MSEC(after, before));

      return success;
  }
--- 550,556 ----

      /* Possible microtiming output */
      if (pset.timing && success)
!         printf(gettext("Time: %.3f ms\n"), DIFF_MSEC(after, before));

      return success;
  }

Re: fix log_min_duration_statement logic error

From
Christopher Kings-Lynne
Date:
> The problem with two lines is that another log message could get between
> them.  I agree milliseconds makes more sense for output.

That's not a huge problem. I've run our servers like that for ages, and
there's not really any time when a human can't tell what's going on.
You can also turn on PID logging as well.  (Should that even be on by
default?

Chris



Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Agreed.  elog is the proper place, because then you guarantee that it is
> all on one line.  Is that OK?  Do we have elogs that we want over
> several lines?  Is this something we can do at this stage in beta?

As to the latter: sure.  We've already hacked the formatting of the log
output quite a bit since 7.3.  Better to hit them with this too now,
than spread the pain over multiple releases.

As to the former: the only thing that seems debatable to me is what to
do about the layout of the new multi-part ereport() messages.  I would
be inclined to go for one line per part, viz
    ERROR: blah blah blah
    DETAIL: blah blah\nblah blah
    HINT: blah blah\nblah blah\nblah blah
but perhaps someone would like to argue for somehow collapsing all this
to one line?  If so, how exactly?

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Agreed.  elog is the proper place, because then you guarantee that it is
> > all on one line.  Is that OK?  Do we have elogs that we want over
> > several lines?  Is this something we can do at this stage in beta?
>
> As to the latter: sure.  We've already hacked the formatting of the log
> output quite a bit since 7.3.  Better to hit them with this too now,
> than spread the pain over multiple releases.
>
> As to the former: the only thing that seems debatable to me is what to
> do about the layout of the new multi-part ereport() messages.  I would
> be inclined to go for one line per part, viz
>     ERROR: blah blah blah
>     DETAIL: blah blah\nblah blah
>     HINT: blah blah\nblah blah\nblah blah
> but perhaps someone would like to argue for somehow collapsing all this
> to one line?  If so, how exactly?

Are those lines sent to the elog as one write() or separate ones --- do
they always appear together in the log?

I had a new idea on output format.  Instead of converting newline to
"\n", and double-escaping backslashes, we add a tab after any newline,
so the output looks like:

    LOG:  duration: 4.035 ms  query: select *
            from pg_language;

This makes the logs look better, and it is easier for script to grab
queries.  Grep doesn't work as well, but I think that is OK.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Are those lines sent to the elog as one write() or separate ones --- do
> they always appear together in the log?

Currently they are sent in a single fprintf(stderr), which might or
might not be good enough to ensure atomicity.  We could hack this
to a direct write() if you don't mind depending on fileno(stderr),
but I think that'd create some portability issues on non-Unix
platforms.

If you're using syslog then I think all bets are off anyway.

> I had a new idea on output format.  Instead of converting newline to
> "\n", and double-escaping backslashes, we add a tab after any newline,

That's a thought... seems less invasive than the backslashing.  Not sure
how well it'll work for syslog output though.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Alvaro Herrera Munoz
Date:
On Mon, Oct 06, 2003 at 10:42:57AM -0400, Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:

> > I had a new idea on output format.  Instead of converting newline to
> > "\n", and double-escaping backslashes, we add a tab after any newline,
>
> That's a thought... seems less invasive than the backslashing.  Not sure
> how well it'll work for syslog output though.

Not good.  Some syslogs will replace the literal tab with a ^I.
Maybe it should be a bunch of spaces when using syslog.
It seems a good idea to me anyway.

How would it handle multiple fields?  Say
LOG: blah blah
DETAIL: something
HINT: something else

Will it be
LOG: blah blah
        DETAIL: something else
        HINT: something else
?

--
Alvaro Herrera (<alvherre[@]dcc.uchile.cl>)
"Find a bug in a program, and fix it, and the program will work today.
Show the program how to find and fix a bug, and the program
will work forever" (Oliver Silfridge)

Re: fix log_min_duration_statement logic error

From
Tom Lane
Date:
Alvaro Herrera Munoz <alvherre@dcc.uchile.cl> writes:
>> Bruce Momjian <pgman@candle.pha.pa.us> writes:
>> I had a new idea on output format.  Instead of converting newline to
>> "\n", and double-escaping backslashes, we add a tab after any newline,

> Not good.  Some syslogs will replace the literal tab with a ^I.

That seems okay.  We just want to make sure continuation lines are
easily distinguishable.  (But leading spaces would be okay with me too.)

> How would it handle multiple fields?  Say
> LOG: blah blah
> DETAIL: something
> HINT: something else

> Will it be
> LOG: blah blah
>         DETAIL: something else
>         HINT: something else

No, one would hope no tab before DETAIL/HINT/etc.  The idea is to be
able to recognize when the contents of one of these entries spans lines.

            regards, tom lane

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Alvaro Herrera Munoz <alvherre@dcc.uchile.cl> writes:
> >> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> >> I had a new idea on output format.  Instead of converting newline to
> >> "\n", and double-escaping backslashes, we add a tab after any newline,
>
> > Not good.  Some syslogs will replace the literal tab with a ^I.
>
> That seems okay.  We just want to make sure continuation lines are
> easily distinguishable.  (But leading spaces would be okay with me too.)

Agreed.  It is easy to strip off the tab to rebuild the original query
--- striping off 8 spaces seems less logical.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Are those lines sent to the elog as one write() or separate ones --- do
> > they always appear together in the log?
>
> Currently they are sent in a single fprintf(stderr), which might or
> might not be good enough to ensure atomicity.  We could hack this
> to a direct write() if you don't mind depending on fileno(stderr),
> but I think that'd create some portability issues on non-Unix
> platforms.
>
> If you're using syslog then I think all bets are off anyway.
>
> > I had a new idea on output format.  Instead of converting newline to
> > "\n", and double-escaping backslashes, we add a tab after any newline,
>
> That's a thought... seems less invasive than the backslashing.  Not sure
> how well it'll work for syslog output though.

OK, new version attached that puts a tab before any elog continuation
line in the server logs.  This will give us consistent multi-line server
log output.  It does not affect the client output, which I think is
correct.

Output looks like:

LOG:  duration: 4.138 ms  query: select *
        from pg_language;
LOG:  duration: 7.560 ms  query: select * from pg_class;

Now, this does not address Tom's objection that you have can't use grep
anyway to pull lines from the server logs, but it is closer to usable
for scripts, and easier for people to read in the file.

The problem with doing statement and duration on separate lines is this:

LOG:  duration: 4.138 ms
LOG:  query: select *
        from pg_language;
LOG:  duration: 7.560 ms
LOG:  query: select * from pg_class;

It isn't clear which duration goes with which line, even if they don't
intermingle.  If you output on separate lines, you would have to use
log_pid.  However, since people can use log_duration and log_statement
separately already anyway, I think this merged line is easier for casual
users.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.210
diff -c -c -r1.210 runtime.sgml
*** doc/src/sgml/runtime.sgml    3 Oct 2003 19:26:49 -0000    1.210
--- doc/src/sgml/runtime.sgml    6 Oct 2003 21:33:06 -0000
***************
*** 1689,1704 ****
         <listitem>
          <para>
           Sets a minimum statement execution time (in milliseconds)
!          above which a statement will be logged.  All SQL statements
!          that run longer than the time specified will be logged together
!          with their actual duration.  Setting this to zero (the default)
!      disables time-based logging.  For example, if you set it
!          to <literal>250</literal> then all SQL statements that run longer
!          than 250ms will be logged.  Enabling this
!          option can be useful in tracking down unoptimized queries in
!          your applications.
!          Only superusers can increase this or set it to zero if this option
!          is set to non-zero by the administrator.
          </para>
         </listitem>
        </varlistentry>
--- 1689,1704 ----
         <listitem>
          <para>
           Sets a minimum statement execution time (in milliseconds)
!          for statement to be logged.  All SQL statements
!          that run in the time specified or longer will be logged with
!          their duration.  Setting this to zero will print
!          all queries and their durations.  Minus-one (the default)
!          disables this.  For example, if you set it to
!          <literal>250</literal> then all SQL statements that run 250ms
!          or longer will be logged.  Enabling this option can be
!          useful in tracking down unoptimized queries in your applications.
!          Only superusers can increase this or set it to minus-one if this
!          option is set by the administrator.
          </para>
         </listitem>
        </varlistentry>
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.370
diff -c -c -r1.370 postgres.c
*** src/backend/tcop/postgres.c    4 Oct 2003 02:47:04 -0000    1.370
--- src/backend/tcop/postgres.c    6 Oct 2003 21:33:11 -0000
***************
*** 694,700 ****
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
--- 694,700 ----
       * because gettimeofday() wasn't called. Similarly,
       * log_statement_stats has to be captured once.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
          gettimeofday(&start_t, NULL);

      if (save_log_statement_stats)
***************
*** 940,946 ****
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement > 0)
      {
          long        usecs;
          bool        print_statement;
--- 940,946 ----
       * Combine processing here as we need to calculate the query duration
       * in both instances.
       */
!     if (save_log_duration || save_log_min_duration_statement != -1)
      {
          long        usecs;
          bool        print_statement;
***************
*** 957,971 ****
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement > 0 &&
!                            usecs >= save_log_min_duration_statement * 1000);

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration(secs): %ld.%06ld%s%s",
!                             (long) (stop_t.tv_sec - start_t.tv_sec),
!                             (long) (stop_t.tv_usec - start_t.tv_usec),
!                             print_statement ? " " : "",
                              print_statement ? query_string : "")));
      }

--- 957,973 ----
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement == 0 ||
!                            (save_log_min_duration_statement > 0 &&
!                             usecs >= save_log_min_duration_statement * 1000));

          if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration: %ld.%03ld ms%s%s",
!                             (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
!                             (stop_t.tv_usec - start_t.tv_usec) / 1000),
!                             (long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
!                             print_statement ? "  query: " : "",
                              print_statement ? query_string : "")));
      }

***************
*** 3196,3198 ****
--- 3198,3201 ----

      pfree(str.data);
  }
+
Index: src/backend/utils/error/elog.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/error/elog.c,v
retrieving revision 1.123
diff -c -c -r1.123 elog.c
*** src/backend/utils/error/elog.c    25 Sep 2003 06:58:05 -0000    1.123
--- src/backend/utils/error/elog.c    6 Oct 2003 21:33:12 -0000
***************
*** 145,150 ****
--- 145,151 ----
  static const char *error_severity(int elevel);
  static const char *print_timestamp(void);
  static const char *print_pid(void);
+ static char *str_prepend_tabs(const char *str);


  /*
***************
*** 1135,1140 ****
--- 1136,1143 ----
      /* Write to stderr, if enabled */
      if (Use_syslog <= 1 || whereToSendOutput == Debug)
      {
+         char *p = str_prepend_tabs(buf.data);
+
          /*
           * Timestamp and PID are only used for stderr output --- we assume
           * the syslog daemon will supply them for us in the other case.
***************
*** 1142,1148 ****
          fprintf(stderr, "%s%s%s",
                  Log_timestamp ? print_timestamp() : "",
                  Log_pid ? print_pid() : "",
!                 buf.data);
      }

      pfree(buf.data);
--- 1145,1152 ----
          fprintf(stderr, "%s%s%s",
                  Log_timestamp ? print_timestamp() : "",
                  Log_pid ? print_pid() : "",
!                 p);
!         pfree(p);
      }

      pfree(buf.data);
***************
*** 1449,1452 ****
--- 1453,1477 ----

      snprintf(buf, sizeof(buf), "[%d] ", (int) MyProcPid);
      return buf;
+ }
+
+ /*
+  *    str_prepend_tabs
+  *
+  *    This string prepends a tab to message continuation lines.
+  */
+ static char *str_prepend_tabs(const char *str)
+ {
+     char *outstr = palloc(strlen(str) * 2 + 1);
+     int    len = strlen(str);
+     int i, outlen = 0;
+
+     for (i = 0; i < len; i++)
+     {
+         outstr[outlen++] = str[i];
+         if (str[i] == '\n' && str[i+1] != '\0' )
+             outstr[outlen++] = '\t';
+     }
+     outstr[outlen++]    = '\0';
+     return outstr;
  }
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.162
diff -c -c -r1.162 guc.c
*** src/backend/utils/misc/guc.c    3 Oct 2003 19:26:49 -0000    1.162
--- src/backend/utils/misc/guc.c    6 Oct 2003 21:33:17 -0000
***************
*** 128,134 ****
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = 0;


  /*
--- 128,134 ----
  int            log_min_messages = NOTICE;
  int            client_min_messages = NOTICE;

! int            log_min_duration_statement = -1;


  /*
***************
*** 1185,1194 ****
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("The default is 0 (turning this feature off).")
          },
          &log_min_duration_statement,
!         0, 0, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
--- 1185,1194 ----
          {"log_min_duration_statement", PGC_USERLIMIT, LOGGING_WHEN,
              gettext_noop("minimum execution time in milliseconds above which statements will "
                           "be logged"),
!             gettext_noop("Zero prints all queries.  The default is -1 (turning this feature off).")
          },
          &log_min_duration_statement,
!         -1, -1, INT_MAX / 1000, NULL, NULL
      },

      /* End-of-list marker */
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.91
diff -c -c -r1.91 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample    3 Oct 2003 19:26:49 -0000    1.91
--- src/backend/utils/misc/postgresql.conf.sample    6 Oct 2003 21:33:17 -0000
***************
*** 157,165 ****
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = 0  # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero disables.

  #silent_mode = false         # DO NOT USE without Syslog!

--- 157,166 ----
                   #   debug5, debug4, debug3, debug2, debug1,
                   #   info, notice, warning, error, panic(off)

! #log_min_duration_statement = -1 # Log all statements whose
                   # execution time exceeds the value, in
!                  # milliseconds.  Zero prints all queries.
!                  # Minus-one disables.

  #silent_mode = false         # DO NOT USE without Syslog!


Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Bruce Momjian writes:

> I had a new idea on output format.  Instead of converting newline to
> "\n", and double-escaping backslashes, we add a tab after any newline,

Then how would you identify the real tabs in the data?

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Bruce Momjian writes:

> Another idea if you like consistency would be:
>
>     LOG:  duration: 4.056 ms  query: select * \nfrom pg_language;

Speaking of consistency...

Imagine someone always having log_statement on and doing some sort of
aggregate query counting, say like grep '^LOG: query:' | wc -l.  Now that
someone (or maybe the admin on the night shift, to make it more dramatic)
also turns on log_min_statement_duration (or whatever it's spelled), say
to find the slowest queries: grep '^LOG: duration:' | sort -xyz | head
-10.  In order to guarantee the consistency of both results, you'd have to
log each query twice in this case.

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Bruce Momjian writes:
>
> > I had a new idea on output format.  Instead of converting newline to
> > "\n", and double-escaping backslashes, we add a tab after any newline,
>
> Then how would you identify the real tabs in the data?

Any log line that starts with a tab was added for readability of
multi-line output.  If the query line starts with a tab, it will be
tab-tab in the file.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Bruce Momjian writes:
>
> > Another idea if you like consistency would be:
> >
> >     LOG:  duration: 4.056 ms  query: select * \nfrom pg_language;
>
> Speaking of consistency...
>
> Imagine someone always having log_statement on and doing some sort of
> aggregate query counting, say like grep '^LOG: query:' | wc -l.  Now that
> someone (or maybe the admin on the night shift, to make it more dramatic)
> also turns on log_min_statement_duration (or whatever it's spelled), say
> to find the slowest queries: grep '^LOG: duration:' | sort -xyz | head
> -10.  In order to guarantee the consistency of both results, you'd have to
> log each query twice in this case.

I guess.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Peter Eisentraut
Date:
Bruce Momjian writes:

> > Imagine someone always having log_statement on and doing some sort of
> > aggregate query counting, say like grep '^LOG: query:' | wc -l.  Now that
> > someone (or maybe the admin on the night shift, to make it more dramatic)
> > also turns on log_min_statement_duration (or whatever it's spelled), say
> > to find the slowest queries: grep '^LOG: duration:' | sort -xyz | head
> > -10.  In order to guarantee the consistency of both results, you'd have to
> > log each query twice in this case.
>
> I guess.

Can we agree to this?

* If log_statement is on, then we log

query: %s

(Should it be "statement: %s"?)  %s has newlines suitable escaped; exactly
how is independent of this discussion.

* If log_duration is on, then we log

duration: x.xxx ms

The user can use log_pid to link it to the statement.  (If the user
doesn't like this, he can use log_min_duration_statement=0.)

* If log_min_duration_statement is triggered, then we log

duration: x.xxx ms; query: %s

* If log_statement is on and log_min_duration_statement is triggered, then
we (pick one):

(a) log both as per above, or
(b) log only log_min_duration_statement

* If log_duration is on and log_min_duration_statement is triggered, then
we (pick one):

(a) log both as per above, or
(b) log only log_min_duration_statement

--
Peter Eisentraut   peter_e@gmx.net


Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Bruce Momjian writes:
>
> > > Imagine someone always having log_statement on and doing some sort of
> > > aggregate query counting, say like grep '^LOG: query:' | wc -l.  Now that
> > > someone (or maybe the admin on the night shift, to make it more dramatic)
> > > also turns on log_min_statement_duration (or whatever it's spelled), say
> > > to find the slowest queries: grep '^LOG: duration:' | sort -xyz | head
> > > -10.  In order to guarantee the consistency of both results, you'd have to
> > > log each query twice in this case.
> >
> > I guess.
>
> Can we agree to this?
>
> * If log_statement is on, then we log
>
> query: %s
>
> (Should it be "statement: %s"?)  %s has newlines suitable escaped; exactly

Yes, it should be 'statement'.

> how is independent of this discussion.

People didn't like the newlines changed because it makes large queries
hard to read (all on one line), and we had to double-escape backslashes,
meaning the logged query had different backslashing from the original.

> * If log_duration is on, then we log
>
> duration: x.xxx ms
>
> The user can use log_pid to link it to the statement.  (If the user
> doesn't like this, he can use log_min_duration_statement=0.)

Exactly.  log_min_duration_statement=0 delays the print of the statement
until it completes, but it prints them together.

> * If log_min_duration_statement is triggered, then we log
>
> duration: x.xxx ms; query: %s
>
> * If log_statement is on and log_min_duration_statement is triggered, then
> we (pick one):
>
> (a) log both as per above, or

I think we have to log both because perhaps they want the query printed
before it completes.

> (b) log only log_min_duration_statement
>
> * If log_duration is on and log_min_duration_statement is triggered, then
> we (pick one):
>
> (a) log both as per above, or
> (b) log only log_min_duration_statement

Good point.  Right now we do only:

    duration: x.xxx ms; query: %s

This seems wrong because it isn't consistent with log_statement.  Glad
you pointed that out.  The only argument for printing one one is that
there isn't any value to printing the duration separately, because it
isn't printing before the query.  However, for consistency, I think you
are right we should print both.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
OK, patch attached and applied.  Changes are:

    "query:" now "statement:"
    log_duration also now prints when log_min_duration_statement prints


---------------------------------------------------------------------------

Peter Eisentraut wrote:
> Bruce Momjian writes:
>
> > > Imagine someone always having log_statement on and doing some sort of
> > > aggregate query counting, say like grep '^LOG: query:' | wc -l.  Now that
> > > someone (or maybe the admin on the night shift, to make it more dramatic)
> > > also turns on log_min_statement_duration (or whatever it's spelled), say
> > > to find the slowest queries: grep '^LOG: duration:' | sort -xyz | head
> > > -10.  In order to guarantee the consistency of both results, you'd have to
> > > log each query twice in this case.
> >
> > I guess.
>
> Can we agree to this?
>
> * If log_statement is on, then we log
>
> query: %s
>
> (Should it be "statement: %s"?)  %s has newlines suitable escaped; exactly
> how is independent of this discussion.
>
> * If log_duration is on, then we log
>
> duration: x.xxx ms
>
> The user can use log_pid to link it to the statement.  (If the user
> doesn't like this, he can use log_min_duration_statement=0.)
>
> * If log_min_duration_statement is triggered, then we log
>
> duration: x.xxx ms; query: %s
>
> * If log_statement is on and log_min_duration_statement is triggered, then
> we (pick one):
>
> (a) log both as per above, or
> (b) log only log_min_duration_statement
>
> * If log_duration is on and log_min_duration_statement is triggered, then
> we (pick one):
>
> (a) log both as per above, or
> (b) log only log_min_duration_statement
>
> --
> Peter Eisentraut   peter_e@gmx.net
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.371
diff -c -c -r1.371 postgres.c
*** src/backend/tcop/postgres.c    8 Oct 2003 03:49:37 -0000    1.371
--- src/backend/tcop/postgres.c    9 Oct 2003 02:37:19 -0000
***************
*** 461,467 ****

      if (log_statement)
          ereport(LOG,
!                 (errmsg("query: %s", query_string)));

      if (log_parser_stats)
          ResetUsage();
--- 461,467 ----

      if (log_statement)
          ereport(LOG,
!                 (errmsg("statement: %s", query_string)));

      if (log_parser_stats)
          ResetUsage();
***************
*** 943,949 ****
      if (save_log_duration || save_log_min_duration_statement != -1)
      {
          long        usecs;
-         bool        print_statement;

          gettimeofday(&stop_t, NULL);
          if (stop_t.tv_usec < start_t.tv_usec)
--- 943,948 ----
***************
*** 953,974 ****
          }
          usecs = (long) (stop_t.tv_sec - start_t.tv_sec) * 1000000 + (long) (stop_t.tv_usec - start_t.tv_usec);

          /*
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         print_statement = (save_log_min_duration_statement == 0 ||
!                            (save_log_min_duration_statement > 0 &&
!                             usecs >= save_log_min_duration_statement * 1000));
!
!         if (save_log_duration || print_statement)
              ereport(LOG,
!                     (errmsg("duration: %ld.%03ld ms%s%s",
                              (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
                              (stop_t.tv_usec - start_t.tv_usec) / 1000),
                              (long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
!                             print_statement ? "  query: " : "",
!                             print_statement ? query_string : "")));
      }

      if (save_log_statement_stats)
--- 952,977 ----
          }
          usecs = (long) (stop_t.tv_sec - start_t.tv_sec) * 1000000 + (long) (stop_t.tv_usec - start_t.tv_usec);

+         if (save_log_duration)
+             ereport(LOG,
+                     (errmsg("duration: %ld.%03ld ms",
+                             (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
+                             (stop_t.tv_usec - start_t.tv_usec) / 1000),
+                             (long) (stop_t.tv_usec - start_t.tv_usec) % 1000)));
+
          /*
           * Output a duration_statement to the log if the query has exceeded
           * the min duration, or if we are to print all durations.
           */
!         if (save_log_min_duration_statement == 0 ||
!             (save_log_min_duration_statement > 0 &&
!              usecs >= save_log_min_duration_statement * 1000))
              ereport(LOG,
!                     (errmsg("duration: %ld.%03ld ms  statement: %s",
                              (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
                              (stop_t.tv_usec - start_t.tv_usec) / 1000),
                              (long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
!                             query_string)));
      }

      if (save_log_statement_stats)

Re: fix log_min_duration_statement logic error

From
Bruce Momjian
Date:
pgman wrote:
>
> OK, patch attached and applied.  Changes are:
>
>     "query:" now "statement:"
>     log_duration also now prints when log_min_duration_statement prints

Oh, sample is:

LOG:  statement: select 1;
LOG:  duration: 0.329 ms
LOG:  duration: 0.329 ms  statement: select 1;

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073