@@ -175,15 +175,10 @@ static const char *err_gettext(const char *str) pg_attribute_format_arg(1);
175175static pg_noinline void set_backtrace (ErrorData * edata ,int num_skip );
176176static void set_errdata_field (MemoryContextData * cxt ,char * * ptr ,const char * str );
177177static void write_console (const char * line ,int len );
178- static void setup_formatted_log_time (void );
179- static void setup_formatted_start_time (void );
180178static const char * process_log_prefix_padding (const char * p ,int * padding );
181179static void log_line_prefix (StringInfo buf ,ErrorData * edata );
182- static void write_csvlog (ErrorData * edata );
183180static void send_message_to_server_log (ErrorData * edata );
184- static void write_pipe_chunks (char * data ,int len ,int dest );
185181static void send_message_to_frontend (ErrorData * edata );
186- static const char * error_severity (int elevel );
187182static void append_with_tabs (StringInfo buf ,const char * str );
188183
189184
@@ -2289,14 +2284,23 @@ write_console(const char *line, int len)
22892284}
22902285
22912286/*
2292- * setup formatted_log_time, for consistent times between CSV and regular logs
2287+ * get_formatted_log_time -- compute and get the log timestamp.
2288+ *
2289+ * The timestamp is computed if not set yet, so as it is kept consistent
2290+ * among all the log destinations that require it to be consistent. Note
2291+ * that the computed timestamp is returned in a static buffer, not
2292+ * palloc()'d.
22932293 */
2294- static void
2295- setup_formatted_log_time (void )
2294+ char *
2295+ get_formatted_log_time (void )
22962296{
22972297pg_time_t stamp_time ;
22982298char msbuf [13 ];
22992299
2300+ /* leave if already computed */
2301+ if (formatted_log_time [0 ]!= '\0' )
2302+ return formatted_log_time ;
2303+
23002304if (!saved_timeval_set )
23012305{
23022306gettimeofday (& saved_timeval ,NULL );
@@ -2318,16 +2322,34 @@ setup_formatted_log_time(void)
23182322/* 'paste' milliseconds into place... */
23192323sprintf (msbuf ,".%03d" , (int ) (saved_timeval .tv_usec /1000 ));
23202324memcpy (formatted_log_time + 19 ,msbuf ,4 );
2325+
2326+ return formatted_log_time ;
23212327}
23222328
23232329/*
2324- *setup formatted_start_time
2330+ *reset_formatted_start_time -- reset the start timestamp
23252331 */
2326- static void
2327- setup_formatted_start_time (void )
2332+ void
2333+ reset_formatted_start_time (void )
2334+ {
2335+ formatted_start_time [0 ]= '\0' ;
2336+ }
2337+
2338+ /*
2339+ * get_formatted_start_time -- compute and get the start timestamp.
2340+ *
2341+ * The timestamp is computed if not set yet. Note that the computed
2342+ * timestamp is returned in a static buffer, not palloc()'d.
2343+ */
2344+ char *
2345+ get_formatted_start_time (void )
23282346{
23292347pg_time_t stamp_time = (pg_time_t )MyStartTime ;
23302348
2349+ /* leave if already computed */
2350+ if (formatted_start_time [0 ]!= '\0' )
2351+ return formatted_start_time ;
2352+
23312353/*
23322354 * Note: we expect that guc.c will ensure that log_timezone is set up (at
23332355 * least with a minimal GMT value) before Log_line_prefix can become
@@ -2336,6 +2358,49 @@ setup_formatted_start_time(void)
23362358pg_strftime (formatted_start_time ,FORMATTED_TS_LEN ,
23372359"%Y-%m-%d %H:%M:%S %Z" ,
23382360pg_localtime (& stamp_time ,log_timezone ));
2361+
2362+ return formatted_start_time ;
2363+ }
2364+
2365+ /*
2366+ * check_log_of_query -- check if a query can be logged
2367+ */
2368+ bool
2369+ check_log_of_query (ErrorData * edata )
2370+ {
2371+ /* log required? */
2372+ if (!is_log_level_output (edata -> elevel ,log_min_error_statement ))
2373+ return false;
2374+
2375+ /* query log wanted? */
2376+ if (edata -> hide_stmt )
2377+ return false;
2378+
2379+ /* query string available? */
2380+ if (debug_query_string == NULL )
2381+ return false;
2382+
2383+ return true;
2384+ }
2385+
2386+ /*
2387+ * get_backend_type_for_log -- backend type for log entries
2388+ *
2389+ * Returns a pointer to a static buffer, not palloc()'d.
2390+ */
2391+ const char *
2392+ get_backend_type_for_log (void )
2393+ {
2394+ const char * backend_type_str ;
2395+
2396+ if (MyProcPid == PostmasterPid )
2397+ backend_type_str = "postmaster" ;
2398+ else if (MyBackendType == B_BG_WORKER )
2399+ backend_type_str = MyBgworkerEntry -> bgw_type ;
2400+ else
2401+ backend_type_str = GetBackendTypeDesc (MyBackendType );
2402+
2403+ return backend_type_str ;
23392404}
23402405
23412406/*
@@ -2397,7 +2462,7 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
23972462{
23982463log_line_number = 0 ;
23992464log_my_pid = MyProcPid ;
2400- formatted_start_time [ 0 ] = '\0' ;
2465+ reset_formatted_start_time () ;
24012466}
24022467log_line_number ++ ;
24032468
@@ -2466,14 +2531,7 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
24662531break ;
24672532case 'b' :
24682533{
2469- const char * backend_type_str ;
2470-
2471- if (MyProcPid == PostmasterPid )
2472- backend_type_str = "postmaster" ;
2473- else if (MyBackendType == B_BG_WORKER )
2474- backend_type_str = MyBgworkerEntry -> bgw_type ;
2475- else
2476- backend_type_str = GetBackendTypeDesc (MyBackendType );
2534+ const char * backend_type_str = get_backend_type_for_log ();
24772535
24782536if (padding != 0 )
24792537appendStringInfo (buf ,"%*s" ,padding ,backend_type_str );
@@ -2561,7 +2619,10 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
25612619appendStringInfo (buf ,"%ld" ,log_line_number );
25622620break ;
25632621case 'm' :
2564- setup_formatted_log_time ();
2622+ /* force a log timestamp reset */
2623+ formatted_log_time [0 ]= '\0' ;
2624+ (void )get_formatted_log_time ();
2625+
25652626if (padding != 0 )
25662627appendStringInfo (buf ,"%*s" ,padding ,formatted_log_time );
25672628else
@@ -2602,12 +2663,14 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
26022663}
26032664break ;
26042665case 's' :
2605- if (formatted_start_time [0 ]== '\0' )
2606- setup_formatted_start_time ();
2607- if (padding != 0 )
2608- appendStringInfo (buf ,"%*s" ,padding ,formatted_start_time );
2609- else
2610- appendStringInfoString (buf ,formatted_start_time );
2666+ {
2667+ char * start_time = get_formatted_start_time ();
2668+
2669+ if (padding != 0 )
2670+ appendStringInfo (buf ,"%*s" ,padding ,start_time );
2671+ else
2672+ appendStringInfoString (buf ,start_time );
2673+ }
26112674break ;
26122675case 'i' :
26132676if (MyProcPort )
@@ -2758,7 +2821,7 @@ appendCSVLiteral(StringInfo buf, const char *data)
27582821 * Constructs the error message, depending on the Errordata it gets, in a CSV
27592822 * format which is described in doc/src/sgml/config.sgml.
27602823 */
2761- static void
2824+ void
27622825write_csvlog (ErrorData * edata )
27632826{
27642827StringInfoData buf ;
@@ -2779,23 +2842,14 @@ write_csvlog(ErrorData *edata)
27792842{
27802843log_line_number = 0 ;
27812844log_my_pid = MyProcPid ;
2782- formatted_start_time [ 0 ] = '\0' ;
2845+ reset_formatted_start_time () ;
27832846}
27842847log_line_number ++ ;
27852848
27862849initStringInfo (& buf );
27872850
2788- /*
2789- * timestamp with milliseconds
2790- *
2791- * Check if the timestamp is already calculated for the syslog message,
2792- * and use it if so. Otherwise, get the current timestamp. This is done
2793- * to put same timestamp in both syslog and csvlog messages.
2794- */
2795- if (formatted_log_time [0 ]== '\0' )
2796- setup_formatted_log_time ();
2797-
2798- appendStringInfoString (& buf ,formatted_log_time );
2851+ /* timestamp with milliseconds */
2852+ appendStringInfoString (& buf ,get_formatted_log_time ());
27992853appendStringInfoChar (& buf ,',' );
28002854
28012855/* username */
@@ -2853,9 +2907,7 @@ write_csvlog(ErrorData *edata)
28532907appendStringInfoChar (& buf ,',' );
28542908
28552909/* session start timestamp */
2856- if (formatted_start_time [0 ]== '\0' )
2857- setup_formatted_start_time ();
2858- appendStringInfoString (& buf ,formatted_start_time );
2910+ appendStringInfoString (& buf ,get_formatted_start_time ());
28592911appendStringInfoChar (& buf ,',' );
28602912
28612913/* Virtual transaction id */
@@ -2906,10 +2958,7 @@ write_csvlog(ErrorData *edata)
29062958appendStringInfoChar (& buf ,',' );
29072959
29082960/* user query --- only reported if not disabled by the caller */
2909- if (is_log_level_output (edata -> elevel ,log_min_error_statement )&&
2910- debug_query_string != NULL &&
2911- !edata -> hide_stmt )
2912- print_stmt = true;
2961+ print_stmt = check_log_of_query (edata );
29132962if (print_stmt )
29142963appendCSVLiteral (& buf ,debug_query_string );
29152964appendStringInfoChar (& buf ,',' );
@@ -2943,13 +2992,7 @@ write_csvlog(ErrorData *edata)
29432992appendStringInfoChar (& buf ,',' );
29442993
29452994/* backend type */
2946- if (MyProcPid == PostmasterPid )
2947- appendCSVLiteral (& buf ,"postmaster" );
2948- else if (MyBackendType == B_BG_WORKER )
2949- appendCSVLiteral (& buf ,MyBgworkerEntry -> bgw_type );
2950- else
2951- appendCSVLiteral (& buf ,GetBackendTypeDesc (MyBackendType ));
2952-
2995+ appendCSVLiteral (& buf ,get_backend_type_for_log ());
29532996appendStringInfoChar (& buf ,',' );
29542997
29552998/* leader PID */
@@ -3101,9 +3144,7 @@ send_message_to_server_log(ErrorData *edata)
31013144/*
31023145 * If the user wants the query that generated this error logged, do it.
31033146 */
3104- if (is_log_level_output (edata -> elevel ,log_min_error_statement )&&
3105- debug_query_string != NULL &&
3106- !edata -> hide_stmt )
3147+ if (check_log_of_query (edata ))
31073148{
31083149log_line_prefix (& buf ,edata );
31093150appendStringInfoString (& buf ,_ ("STATEMENT: " ));
@@ -3233,7 +3274,7 @@ send_message_to_server_log(ErrorData *edata)
32333274 * warning from ignoring write()'s result, so do a little dance with casting
32343275 * rc to void to shut up the compiler.
32353276 */
3236- static void
3277+ void
32373278write_pipe_chunks (char * data ,int len ,int dest )
32383279{
32393280PipeProtoChunk p ;
@@ -3469,7 +3510,7 @@ send_message_to_frontend(ErrorData *edata)
34693510 * The string is not localized here, but we mark the strings for translation
34703511 * so that callers can invoke _() on the result.
34713512 */
3472- static const char *
3513+ const char *
34733514error_severity (int elevel )
34743515{
34753516const char * prefix ;