On 08/27/2013 05:06 AM, David Rowley wrote: > Heikki wrote that it might be useful to allow formatting in the > log_line_prefix here > http://www.postgresql.org/message-id/5187cadb.50...@vmware.com > > I thought I'd take a bash at implementing space padding part on > log_line_prefix options. > > It's been a while since I worked with the PostgreSQL source, so please > forgive me if my coding style is a bit off or the patch is not quite > in the correct format. > > It's a little rough around the edges at the moment and likely the > documentation needs more work, but I'm at the stage of wanting to know > if this is even wanted or needed by people. > > If you apply this patch you can do things like have %10u %-10d in your > log_line_prefix which will include spaces to give the option the > number you specify as the minimum width. Left and right aligning is > supported. > > Let this be the thread to collect consensus to whether this needed and > useful.
I was just working on this last week! I didn't get a chance to post it because I was still polishing it. I first took the same approach as you but decided it reduced the clarity of the code so I re-did it a different way. I'll attach it here along with yours to see which way others like it. Did you test performance? You should add your patch to the next commitfest. -- Vik
*** a/doc/src/sgml/config.sgml --- b/doc/src/sgml/config.sgml *************** *** 4046,4052 **** local0.* /var/log/postgresql --- 4046,4062 ---- </tbody> </tgroup> </informaltable> + </para> + + <para> + Between the <literal>%</> and the escape letter can be added a + minimum field width. If the value is shorter than the specified + width, it is left-padded with spaces. If the value is larger then + it takes the space it needs; it is not truncated. A negative width + will cause the value to be right-padded. + </para> + <para> The <literal>%c</> escape prints a quasi-unique session identifier, consisting of two 4-byte hexadecimal numbers (without leading zeros) separated by a dot. The numbers are the process start time and the *** a/src/backend/utils/error/elog.c --- b/src/backend/utils/error/elog.c *************** *** 2131,2139 **** log_line_prefix(StringInfo buf, ErrorData *edata) --- 2131,2145 ---- /* has counter been reset in current process? */ static int log_my_pid = 0; + StringInfoData workbuf; /* we put the fields in here for later formatting */ + int field_width; + bool left_justify; + int format_len; int i; + initStringInfo(&workbuf); + /* * This is one of the few places where we'd rather not inherit a static * variable's value from the postmaster. But since we will, reset it when *************** *** 2163,2171 **** log_line_prefix(StringInfo buf, ErrorData *edata) } /* go to char after '%' */ i++; ! if (i >= format_len) break; /* format error - ignore it */ /* process the option */ switch (Log_line_prefix[i]) { --- 2169,2198 ---- } /* go to char after '%' */ i++; ! ! /* process the field width modifier, if present */ ! left_justify = i < format_len && Log_line_prefix[i] == '-'; ! if (left_justify) ! i++; ! ! field_width = 0; ! while (i < format_len && Log_line_prefix[i] >= '0' && Log_line_prefix[i] <= '9') ! { ! field_width = 10 * field_width + (Log_line_prefix[i] - '0'); ! if (field_width < 0) ! break; /* integer out of range - consider it a format error */ ! i++; ! } ! ! if (i >= format_len || field_width < 0 || (left_justify && field_width == 0)) break; /* format error - ignore it */ + if (left_justify) + field_width = -field_width; + + /* get the working buffer ready */ + resetStringInfo(&workbuf); + /* process the option */ switch (Log_line_prefix[i]) { *************** *** 2176,2182 **** log_line_prefix(StringInfo buf, ErrorData *edata) if (appname == NULL || *appname == '\0') appname = _("[unknown]"); ! appendStringInfoString(buf, appname); } break; case 'u': --- 2203,2209 ---- if (appname == NULL || *appname == '\0') appname = _("[unknown]"); ! appendStringInfoString(&workbuf, appname); } break; case 'u': *************** *** 2186,2192 **** log_line_prefix(StringInfo buf, ErrorData *edata) if (username == NULL || *username == '\0') username = _("[unknown]"); ! appendStringInfoString(buf, username); } break; case 'd': --- 2213,2219 ---- if (username == NULL || *username == '\0') username = _("[unknown]"); ! appendStringInfoString(&workbuf, username); } break; case 'd': *************** *** 2196,2216 **** log_line_prefix(StringInfo buf, ErrorData *edata) if (dbname == NULL || *dbname == '\0') dbname = _("[unknown]"); ! appendStringInfoString(buf, dbname); } break; case 'c': ! appendStringInfo(buf, "%lx.%x", (long) (MyStartTime), MyProcPid); break; case 'p': ! appendStringInfo(buf, "%d", MyProcPid); break; case 'l': ! appendStringInfo(buf, "%ld", log_line_number); break; case 'm': setup_formatted_log_time(); ! appendStringInfoString(buf, formatted_log_time); break; case 't': { --- 2223,2243 ---- if (dbname == NULL || *dbname == '\0') dbname = _("[unknown]"); ! appendStringInfoString(&workbuf, dbname); } break; case 'c': ! appendStringInfo(&workbuf, "%lx.%x", (long) (MyStartTime), MyProcPid); break; case 'p': ! appendStringInfo(&workbuf, "%d", MyProcPid); break; case 'l': ! appendStringInfo(&workbuf, "%ld", log_line_number); break; case 'm': setup_formatted_log_time(); ! appendStringInfoString(&workbuf, formatted_log_time); break; case 't': { *************** *** 2220,2232 **** log_line_prefix(StringInfo buf, ErrorData *edata) pg_strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", pg_localtime(&stamp_time, log_timezone)); ! appendStringInfoString(buf, strfbuf); } break; case 's': if (formatted_start_time[0] == '\0') setup_formatted_start_time(); ! appendStringInfoString(buf, formatted_start_time); break; case 'i': if (MyProcPort) --- 2247,2259 ---- pg_strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", pg_localtime(&stamp_time, log_timezone)); ! appendStringInfoString(&workbuf, strfbuf); } break; case 's': if (formatted_start_time[0] == '\0') setup_formatted_start_time(); ! appendStringInfoString(&workbuf, formatted_start_time); break; case 'i': if (MyProcPort) *************** *** 2235,2256 **** log_line_prefix(StringInfo buf, ErrorData *edata) int displen; psdisp = get_ps_display(&displen); ! appendBinaryStringInfo(buf, psdisp, displen); } break; case 'r': if (MyProcPort && MyProcPort->remote_host) { ! appendStringInfoString(buf, MyProcPort->remote_host); if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0') ! appendStringInfo(buf, "(%s)", MyProcPort->remote_port); } break; case 'h': if (MyProcPort && MyProcPort->remote_host) ! appendStringInfoString(buf, MyProcPort->remote_host); break; case 'q': /* in postmaster and friends, stop if %q is seen */ --- 2262,2283 ---- int displen; psdisp = get_ps_display(&displen); ! appendBinaryStringInfo(&workbuf, psdisp, displen); } break; case 'r': if (MyProcPort && MyProcPort->remote_host) { ! appendStringInfoString(&workbuf, MyProcPort->remote_host); if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0') ! appendStringInfo(&workbuf, "(%s)", MyProcPort->remote_port); } break; case 'h': if (MyProcPort && MyProcPort->remote_host) ! appendStringInfoString(&workbuf, MyProcPort->remote_host); break; case 'q': /* in postmaster and friends, stop if %q is seen */ *************** *** 2261,2283 **** log_line_prefix(StringInfo buf, ErrorData *edata) case 'v': /* keep VXID format in sync with lockfuncs.c */ if (MyProc != NULL && MyProc->backendId != InvalidBackendId) ! appendStringInfo(buf, "%d/%u", MyProc->backendId, MyProc->lxid); break; case 'x': ! appendStringInfo(buf, "%u", GetTopTransactionIdIfAny()); break; case 'e': ! appendStringInfoString(buf, unpack_sql_state(edata->sqlerrcode)); break; case '%': ! appendStringInfoChar(buf, '%'); break; default: /* format error - ignore it */ break; } } } /* --- 2288,2317 ---- case 'v': /* keep VXID format in sync with lockfuncs.c */ if (MyProc != NULL && MyProc->backendId != InvalidBackendId) ! appendStringInfo(&workbuf, "%d/%u", MyProc->backendId, MyProc->lxid); break; case 'x': ! appendStringInfo(&workbuf, "%u", GetTopTransactionIdIfAny()); break; case 'e': ! appendStringInfoString(&workbuf, unpack_sql_state(edata->sqlerrcode)); break; case '%': ! appendStringInfoChar(&workbuf, '%'); break; default: /* format error - ignore it */ break; } + + if (field_width == 0) + appendStringInfoString(buf, workbuf.data); /* fast path */ + else + appendStringInfo(buf, "%*s", field_width, workbuf.data); } + + pfree(workbuf.data); } /*
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers