On Monday August 30 2004 11:07, Ed L. wrote: > On Monday August 30 2004 10:56, Tom Lane wrote: > > "Ed L." <[EMAIL PROTECTED]> writes: > > > Attached is a revised patch: > > > > Applied with minor revisions. > > > > > I did not add UTC offset logic nor logic to shift to top of the > > > hour/day for rotation periods of 60/1440 minutes, but would like to > > > add that shortly if time permits. > > > > I did the latter but not the former -- ie, rotation target times are > > rounded off, but rounded with respect to GMT not local time. I didn't > > see an obviously correct behavior of round-to-local-time across DST > > transitions ...
This patch rotates logs on local time boundaries instead of UTC boundaries, e.g., midnight local for daily rotation instead of midnight UTC. It does so by parsing the "%z" result from strftime(). Correct me if I'm mistaken, but I *think* the correct behavior across DST transitions may be an orthogonal issue. Consider the case if one is truncating logs on rotation and rotating hourly. UTC vs local is irrelevant. If local time shifts backward from 02:00 to 01:00, our UTC offset will move in the negative direction. If 1) our policy were to truncate on rotation, and 2) we were rotating hourly or more frequently, and 3) our filename would be identical the 2nd time through that clock hour (i.e., it did not contain the epoch or UTC offset), this could cause a log file rotation into the same filename we just had open, thereby erasing an hour of log data. Apache's rotatelogs apparently has the same issue without a solution, and warns of it in the code. I am arguing for inclusion of this patch because 1) the utility of local time boundary rotations exceeds the risk for us, and because 2) the risk can be mitigated by a comment in the documentation and maybe postgresql.conf, and because 3) I think the issue already exists and this doesn't make it worse. Ed
Index: syslogger.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/syslogger.c,v retrieving revision 1.8 diff -C1 -r1.8 syslogger.c *** syslogger.c 31 Aug 2004 04:53:44 -0000 1.8 --- syslogger.c 20 Sep 2004 22:26:01 -0000 *************** *** 849,850 **** --- 849,882 ---- + + /* + * Determine our offset from GMT so we can rotate on localtime boundaries. + */ + pg_time_t + utc_offset (pg_time_t now) { + int offset = 1.0, count; + char msg[8], hrs[3], min[3]; + + /* + * We expect a strftime(%z) result of the form "[+-]HHMM" according to + * RFC822-conformant dates, where HH:MM is the unsigned UTC offset. + * If we don't get it, just return zero offset, and let the logs + * rotate on UTC time boundaries. + */ + + count = strftime(msg, 6, "%z", localtime(&now)); + if ( count != 5 ) { + return 0; + } + + if ( msg[0] == '-' ) + offset = -1.0; + strncpy(hrs, msg[1], 2); + offset = offset * atoi(hrs) * 3600; + strncpy(min, msg[3], 2); + offset += atoi(min) * 60; + + return offset; + } + + /* *************** *** 865,868 **** * "multiple" of the log rotation interval. "Multiple" can be interpreted ! * fairly loosely --- in particular, for intervals larger than an hour, ! * it might be interesting to align to local time instead of GMT. */ --- 897,909 ---- * "multiple" of the log rotation interval. "Multiple" can be interpreted ! * fairly loosely and we attempt to align with local time. ! * ! * In cases of Daylight Savings Time, if local time shifts backward ! * from 02:00 to 01:00, our UTC offset will move in the negative ! * direction. This could cause a logfile rotation into the same ! * filename we just had open, thereby erasing an hour of log data ! * if 1) our policy were to truncate, 2) we were rotating hourly ! * or more frequently, and 3) our filename did not contain the ! * epoch or UTC offset. Apache's rotatelogs apparently has the ! * same issue. Naming files with the epoch (%s) and/or UTC ! * offset (%z) avoids that problem. */ *************** *** 870,873 **** now = time(NULL); now -= now % rotinterval; ! now += rotinterval; next_rotation_time = now; --- 911,915 ---- now = time(NULL); + now += (offset = utc_offset(now)); now -= now % rotinterval; ! now += rotinterval - offset; next_rotation_time = now;
---------------------------(end of broadcast)--------------------------- TIP 3: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly