@@ -175,15 +175,10 @@ static const char *err_gettext(const char *str) pg_attribute_format_arg(1);
175
175
static pg_noinline void set_backtrace (ErrorData * edata ,int num_skip );
176
176
static void set_errdata_field (MemoryContextData * cxt ,char * * ptr ,const char * str );
177
177
static void write_console (const char * line ,int len );
178
- static void setup_formatted_log_time (void );
179
- static void setup_formatted_start_time (void );
180
178
static const char * process_log_prefix_padding (const char * p ,int * padding );
181
179
static void log_line_prefix (StringInfo buf ,ErrorData * edata );
182
- static void write_csvlog (ErrorData * edata );
183
180
static void send_message_to_server_log (ErrorData * edata );
184
- static void write_pipe_chunks (char * data ,int len ,int dest );
185
181
static void send_message_to_frontend (ErrorData * edata );
186
- static const char * error_severity (int elevel );
187
182
static void append_with_tabs (StringInfo buf ,const char * str );
188
183
189
184
@@ -2289,14 +2284,23 @@ write_console(const char *line, int len)
2289
2284
}
2290
2285
2291
2286
/*
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.
2293
2293
*/
2294
- static void
2295
- setup_formatted_log_time (void )
2294
+ char *
2295
+ get_formatted_log_time (void )
2296
2296
{
2297
2297
pg_time_t stamp_time ;
2298
2298
char msbuf [13 ];
2299
2299
2300
+ /* leave if already computed */
2301
+ if (formatted_log_time [0 ]!= '\0' )
2302
+ return formatted_log_time ;
2303
+
2300
2304
if (!saved_timeval_set )
2301
2305
{
2302
2306
gettimeofday (& saved_timeval ,NULL );
@@ -2318,16 +2322,34 @@ setup_formatted_log_time(void)
2318
2322
/* 'paste' milliseconds into place... */
2319
2323
sprintf (msbuf ,".%03d" , (int ) (saved_timeval .tv_usec /1000 ));
2320
2324
memcpy (formatted_log_time + 19 ,msbuf ,4 );
2325
+
2326
+ return formatted_log_time ;
2321
2327
}
2322
2328
2323
2329
/*
2324
- *setup formatted_start_time
2330
+ *reset_formatted_start_time -- reset the start timestamp
2325
2331
*/
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 )
2328
2346
{
2329
2347
pg_time_t stamp_time = (pg_time_t )MyStartTime ;
2330
2348
2349
+ /* leave if already computed */
2350
+ if (formatted_start_time [0 ]!= '\0' )
2351
+ return formatted_start_time ;
2352
+
2331
2353
/*
2332
2354
* Note: we expect that guc.c will ensure that log_timezone is set up (at
2333
2355
* least with a minimal GMT value) before Log_line_prefix can become
@@ -2336,6 +2358,49 @@ setup_formatted_start_time(void)
2336
2358
pg_strftime (formatted_start_time ,FORMATTED_TS_LEN ,
2337
2359
"%Y-%m-%d %H:%M:%S %Z" ,
2338
2360
pg_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 ;
2339
2404
}
2340
2405
2341
2406
/*
@@ -2397,7 +2462,7 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
2397
2462
{
2398
2463
log_line_number = 0 ;
2399
2464
log_my_pid = MyProcPid ;
2400
- formatted_start_time [ 0 ] = '\0' ;
2465
+ reset_formatted_start_time () ;
2401
2466
}
2402
2467
log_line_number ++ ;
2403
2468
@@ -2466,14 +2531,7 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
2466
2531
break ;
2467
2532
case 'b' :
2468
2533
{
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 ();
2477
2535
2478
2536
if (padding != 0 )
2479
2537
appendStringInfo (buf ,"%*s" ,padding ,backend_type_str );
@@ -2561,7 +2619,10 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
2561
2619
appendStringInfo (buf ,"%ld" ,log_line_number );
2562
2620
break ;
2563
2621
case '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
+
2565
2626
if (padding != 0 )
2566
2627
appendStringInfo (buf ,"%*s" ,padding ,formatted_log_time );
2567
2628
else
@@ -2602,12 +2663,14 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
2602
2663
}
2603
2664
break ;
2604
2665
case '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
+ }
2611
2674
break ;
2612
2675
case 'i' :
2613
2676
if (MyProcPort )
@@ -2758,7 +2821,7 @@ appendCSVLiteral(StringInfo buf, const char *data)
2758
2821
* Constructs the error message, depending on the Errordata it gets, in a CSV
2759
2822
* format which is described in doc/src/sgml/config.sgml.
2760
2823
*/
2761
- static void
2824
+ void
2762
2825
write_csvlog (ErrorData * edata )
2763
2826
{
2764
2827
StringInfoData buf ;
@@ -2779,23 +2842,14 @@ write_csvlog(ErrorData *edata)
2779
2842
{
2780
2843
log_line_number = 0 ;
2781
2844
log_my_pid = MyProcPid ;
2782
- formatted_start_time [ 0 ] = '\0' ;
2845
+ reset_formatted_start_time () ;
2783
2846
}
2784
2847
log_line_number ++ ;
2785
2848
2786
2849
initStringInfo (& buf );
2787
2850
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 ());
2799
2853
appendStringInfoChar (& buf ,',' );
2800
2854
2801
2855
/* username */
@@ -2853,9 +2907,7 @@ write_csvlog(ErrorData *edata)
2853
2907
appendStringInfoChar (& buf ,',' );
2854
2908
2855
2909
/* 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 ());
2859
2911
appendStringInfoChar (& buf ,',' );
2860
2912
2861
2913
/* Virtual transaction id */
@@ -2906,10 +2958,7 @@ write_csvlog(ErrorData *edata)
2906
2958
appendStringInfoChar (& buf ,',' );
2907
2959
2908
2960
/* 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 );
2913
2962
if (print_stmt )
2914
2963
appendCSVLiteral (& buf ,debug_query_string );
2915
2964
appendStringInfoChar (& buf ,',' );
@@ -2943,13 +2992,7 @@ write_csvlog(ErrorData *edata)
2943
2992
appendStringInfoChar (& buf ,',' );
2944
2993
2945
2994
/* 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 ());
2953
2996
appendStringInfoChar (& buf ,',' );
2954
2997
2955
2998
/* leader PID */
@@ -3101,9 +3144,7 @@ send_message_to_server_log(ErrorData *edata)
3101
3144
/*
3102
3145
* If the user wants the query that generated this error logged, do it.
3103
3146
*/
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 ))
3107
3148
{
3108
3149
log_line_prefix (& buf ,edata );
3109
3150
appendStringInfoString (& buf ,_ ("STATEMENT: " ));
@@ -3233,7 +3274,7 @@ send_message_to_server_log(ErrorData *edata)
3233
3274
* warning from ignoring write()'s result, so do a little dance with casting
3234
3275
* rc to void to shut up the compiler.
3235
3276
*/
3236
- static void
3277
+ void
3237
3278
write_pipe_chunks (char * data ,int len ,int dest )
3238
3279
{
3239
3280
PipeProtoChunk p ;
@@ -3469,7 +3510,7 @@ send_message_to_frontend(ErrorData *edata)
3469
3510
* The string is not localized here, but we mark the strings for translation
3470
3511
* so that callers can invoke _() on the result.
3471
3512
*/
3472
- static const char *
3513
+ const char *
3473
3514
error_severity (int elevel )
3474
3515
{
3475
3516
const char * prefix ;