LCOV - differential code coverage report
Current view: top level - src/common - logging.c (source / functions) Coverage Total Hit UNC UBC GNC CBC
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 70.4 % 152 107 6 39 11 96
Current Date: 2026-05-05 10:23:31 +0900 Functions: 90.0 % 10 9 1 2 7
Baseline: lcov-20260505-025707-baseline Branches: 50.5 % 97 49 3 45 7 42
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 64.7 % 17 11 6 11
(360..) days: 71.1 % 135 96 39 96
Function coverage date bins:
(7,30] days: 50.0 % 2 1 1 1
(360..) days: 100.0 % 8 8 1 7
Branch coverage date bins:
(7,30] days: 70.0 % 10 7 3 7
(360..) days: 48.3 % 87 42 45 42

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  * Logging framework for frontend programs
                                  3                 :                :  *
                                  4                 :                :  * Copyright (c) 2018-2026, PostgreSQL Global Development Group
                                  5                 :                :  *
                                  6                 :                :  * src/common/logging.c
                                  7                 :                :  *
                                  8                 :                :  *-------------------------------------------------------------------------
                                  9                 :                :  */
                                 10                 :                : 
                                 11                 :                : #ifndef FRONTEND
                                 12                 :                : #error "This file is not expected to be compiled for backend code"
                                 13                 :                : #endif
                                 14                 :                : 
                                 15                 :                : #include "postgres_fe.h"
                                 16                 :                : 
                                 17                 :                : #include <unistd.h>
                                 18                 :                : 
                                 19                 :                : #include "common/logging.h"
                                 20                 :                : 
                                 21                 :                : enum pg_log_level __pg_log_level;
                                 22                 :                : 
                                 23                 :                : static const char *progname;
                                 24                 :                : static int  log_flags;
                                 25                 :                : 
                                 26                 :                : static void (*log_pre_callback) (void);
                                 27                 :                : static void (*log_locus_callback) (const char **, uint64 *);
                                 28                 :                : 
                                 29                 :                : static FILE *log_logfile;
                                 30                 :                : 
                                 31                 :                : static const char *sgr_error = NULL;
                                 32                 :                : static const char *sgr_warning = NULL;
                                 33                 :                : static const char *sgr_note = NULL;
                                 34                 :                : static const char *sgr_locus = NULL;
                                 35                 :                : 
                                 36                 :                : #define SGR_ERROR_DEFAULT "01;31"
                                 37                 :                : #define SGR_WARNING_DEFAULT "01;35"
                                 38                 :                : #define SGR_NOTE_DEFAULT "01;36"
                                 39                 :                : #define SGR_LOCUS_DEFAULT "01"
                                 40                 :                : 
                                 41                 :                : #define ANSI_ESCAPE_FMT "\x1b[%sm"
                                 42                 :                : #define ANSI_ESCAPE_RESET "\x1b[0m"
                                 43                 :                : 
                                 44                 :                : #ifdef WIN32
                                 45                 :                : 
                                 46                 :                : #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
                                 47                 :                : #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
                                 48                 :                : #endif
                                 49                 :                : 
                                 50                 :                : /*
                                 51                 :                :  * Attempt to enable VT100 sequence processing for colorization on Windows.
                                 52                 :                :  * If current environment is not VT100-compatible or if this mode could not
                                 53                 :                :  * be enabled, return false.
                                 54                 :                :  */
                                 55                 :                : static bool
                                 56                 :                : enable_vt_processing(void)
                                 57                 :                : {
                                 58                 :                :     /* Check stderr */
                                 59                 :                :     HANDLE      hOut = GetStdHandle(STD_ERROR_HANDLE);
                                 60                 :                :     DWORD       dwMode = 0;
                                 61                 :                : 
                                 62                 :                :     if (hOut == INVALID_HANDLE_VALUE)
                                 63                 :                :         return false;
                                 64                 :                : 
                                 65                 :                :     /*
                                 66                 :                :      * Look for the current console settings and check if VT100 is already
                                 67                 :                :      * enabled.
                                 68                 :                :      */
                                 69                 :                :     if (!GetConsoleMode(hOut, &dwMode))
                                 70                 :                :         return false;
                                 71                 :                :     if ((dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0)
                                 72                 :                :         return true;
                                 73                 :                : 
                                 74                 :                :     dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
                                 75                 :                :     if (!SetConsoleMode(hOut, dwMode))
                                 76                 :                :         return false;
                                 77                 :                :     return true;
                                 78                 :                : }
                                 79                 :                : #endif                          /* WIN32 */
                                 80                 :                : 
                                 81                 :                : /*
                                 82                 :                :  * This should be called before any output happens.
                                 83                 :                :  */
                                 84                 :                : void
 2591 peter@eisentraut.org       85                 :CBC       16054 : pg_logging_init(const char *argv0)
                                 86                 :                : {
                                 87                 :          16054 :     const char *pg_color_env = getenv("PG_COLOR");
                                 88                 :          16054 :     bool        log_color = false;
 2255 michael@paquier.xyz        89                 :          16054 :     bool        color_terminal = isatty(fileno(stderr));
                                 90                 :                : 
                                 91                 :                : #ifdef WIN32
                                 92                 :                : 
                                 93                 :                :     /*
                                 94                 :                :      * On Windows, check if environment is VT100-compatible if using a
                                 95                 :                :      * terminal.
                                 96                 :                :      */
                                 97                 :                :     if (color_terminal)
                                 98                 :                :         color_terminal = enable_vt_processing();
                                 99                 :                : #endif
                                100                 :                : 
                                101                 :                :     /* usually the default, but not on Windows */
 2591 peter@eisentraut.org      102                 :          16054 :     setvbuf(stderr, NULL, _IONBF, 0);
                                103                 :                : 
                                104                 :          16054 :     progname = get_progname(argv0);
                                105                 :          16054 :     __pg_log_level = PG_LOG_INFO;
                                106                 :                : 
                                107         [ -  + ]:          16054 :     if (pg_color_env)
                                108                 :                :     {
 2591 peter@eisentraut.org      109         [ #  # ]:UBC           0 :         if (strcmp(pg_color_env, "always") == 0 ||
 2255 michael@paquier.xyz       110   [ #  #  #  # ]:              0 :             (strcmp(pg_color_env, "auto") == 0 && color_terminal))
 2591 peter@eisentraut.org      111                 :              0 :             log_color = true;
                                112                 :                :     }
                                113                 :                : 
 2591 peter@eisentraut.org      114         [ -  + ]:CBC       16054 :     if (log_color)
                                115                 :                :     {
 2591 peter@eisentraut.org      116                 :UBC           0 :         const char *pg_colors_env = getenv("PG_COLORS");
                                117                 :                : 
                                118         [ #  # ]:              0 :         if (pg_colors_env)
                                119                 :                :         {
 2540 tgl@sss.pgh.pa.us         120                 :              0 :             char       *colors = strdup(pg_colors_env);
                                121                 :                : 
 2591 peter@eisentraut.org      122         [ #  # ]:              0 :             if (colors)
                                123                 :                :             {
                                124                 :                :                 char       *token;
  564                           125                 :              0 :                 char       *cp = colors;
                                126                 :                : 
                                127         [ #  # ]:              0 :                 while ((token = strsep(&cp, ":")))
                                128                 :                :                 {
 2540 tgl@sss.pgh.pa.us         129                 :              0 :                     char       *e = strchr(token, '=');
                                130                 :                : 
 2591 peter@eisentraut.org      131         [ #  # ]:              0 :                     if (e)
                                132                 :                :                     {
                                133                 :                :                         char       *name;
                                134                 :                :                         char       *value;
                                135                 :                : 
                                136                 :              0 :                         *e = '\0';
                                137                 :              0 :                         name = token;
                                138                 :              0 :                         value = e + 1;
                                139                 :                : 
                                140         [ #  # ]:              0 :                         if (strcmp(name, "error") == 0)
                                141                 :              0 :                             sgr_error = strdup(value);
                                142         [ #  # ]:              0 :                         if (strcmp(name, "warning") == 0)
                                143                 :              0 :                             sgr_warning = strdup(value);
 1485                           144         [ #  # ]:              0 :                         if (strcmp(name, "note") == 0)
                                145                 :              0 :                             sgr_note = strdup(value);
 2591                           146         [ #  # ]:              0 :                         if (strcmp(name, "locus") == 0)
                                147                 :              0 :                             sgr_locus = strdup(value);
                                148                 :                :                     }
                                149                 :                :                 }
                                150                 :                : 
                                151                 :              0 :                 free(colors);
                                152                 :                :             }
                                153                 :                :         }
                                154                 :                :         else
                                155                 :                :         {
                                156                 :              0 :             sgr_error = SGR_ERROR_DEFAULT;
                                157                 :              0 :             sgr_warning = SGR_WARNING_DEFAULT;
 1485                           158                 :              0 :             sgr_note = SGR_NOTE_DEFAULT;
 2591                           159                 :              0 :             sgr_locus = SGR_LOCUS_DEFAULT;
                                160                 :                :         }
                                161                 :                :     }
 2591 peter@eisentraut.org      162                 :CBC       16054 : }
                                163                 :                : 
                                164                 :                : /*
                                165                 :                :  * Change the logging flags.
                                166                 :                :  */
                                167                 :                : void
                                168                 :          20702 : pg_logging_config(int new_flags)
                                169                 :                : {
                                170                 :          20702 :     log_flags = new_flags;
                                171                 :          20702 : }
                                172                 :                : 
                                173                 :                : /*
                                174                 :                :  * pg_logging_init sets the default log level to INFO.  Programs that prefer
                                175                 :                :  * a different default should use this to set it, immediately afterward.
                                176                 :                :  */
                                177                 :                : void
                                178                 :            638 : pg_logging_set_level(enum pg_log_level new_level)
                                179                 :                : {
                                180                 :            638 :     __pg_log_level = new_level;
                                181                 :            638 : }
                                182                 :                : 
                                183                 :                : /*
                                184                 :                :  * Command line switches such as --verbose should invoke this.
                                185                 :                :  */
                                186                 :                : void
 2056 tgl@sss.pgh.pa.us         187                 :             96 : pg_logging_increase_verbosity(void)
                                188                 :                : {
                                189                 :                :     /*
                                190                 :                :      * The enum values are chosen such that we have to decrease __pg_log_level
                                191                 :                :      * in order to become more verbose.
                                192                 :                :      */
                                193         [ +  - ]:             96 :     if (__pg_log_level > PG_LOG_NOTSET + 1)
                                194                 :             96 :         __pg_log_level--;
                                195                 :             96 : }
                                196                 :                : 
                                197                 :                : void
 2540                           198                 :          10725 : pg_logging_set_pre_callback(void (*cb) (void))
                                199                 :                : {
 2591 peter@eisentraut.org      200                 :          10725 :     log_pre_callback = cb;
                                201                 :          10725 : }
                                202                 :                : 
                                203                 :                : void
 2540 tgl@sss.pgh.pa.us         204                 :          10725 : pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno))
                                205                 :                : {
 2591 peter@eisentraut.org      206                 :          10725 :     log_locus_callback = cb;
                                207                 :          10725 : }
                                208                 :                : 
                                209                 :                : void
   22 peter@eisentraut.org      210                 :GNC           1 : pg_logging_set_logfile(FILE *logfile)
                                211                 :                : {
                                212                 :              1 :     log_logfile = logfile;
                                213                 :              1 : }
                                214                 :                : 
                                215                 :                : void
   22 peter@eisentraut.org      216                 :UNC           0 : pg_logging_unset_logfile(void)
                                217                 :                : {
                                218                 :              0 :     log_logfile = NULL;
                                219                 :              0 : }
                                220                 :                : 
                                221                 :                : void
 1488 tgl@sss.pgh.pa.us         222                 :CBC      132849 : pg_log_generic(enum pg_log_level level, enum pg_log_part part,
                                223                 :                :                const char *pg_restrict fmt,...)
                                224                 :                : {
                                225                 :                :     va_list     ap;
                                226                 :                : 
 2591 peter@eisentraut.org      227                 :         132849 :     va_start(ap, fmt);
 1488 tgl@sss.pgh.pa.us         228                 :         132849 :     pg_log_generic_v(level, part, fmt, ap);
 2591 peter@eisentraut.org      229                 :         132849 :     va_end(ap);
                                230                 :         132849 : }
                                231                 :                : 
                                232                 :                : void
 1488 tgl@sss.pgh.pa.us         233                 :         133964 : pg_log_generic_v(enum pg_log_level level, enum pg_log_part part,
                                234                 :                :                  const char *pg_restrict fmt, va_list ap)
                                235                 :                : {
 2591 peter@eisentraut.org      236                 :         133964 :     int         save_errno = errno;
                                237                 :         133964 :     const char *filename = NULL;
                                238                 :         133964 :     uint64      lineno = 0;
                                239                 :                :     va_list     ap2;
                                240                 :                :     size_t      required_len;
                                241                 :                :     char       *buf;
                                242                 :                : 
                                243         [ -  + ]:         133964 :     Assert(progname);
                                244         [ -  + ]:         133964 :     Assert(level);
                                245         [ -  + ]:         133964 :     Assert(fmt);
                                246         [ -  + ]:         133964 :     Assert(fmt[strlen(fmt) - 1] != '\n');
                                247                 :                : 
                                248                 :                :     /* Do nothing if log level is too low. */
 1484 tgl@sss.pgh.pa.us         249         [ +  + ]:         133964 :     if (level < __pg_log_level)
                                250                 :          57022 :         return;
                                251                 :                : 
                                252                 :                :     /*
                                253                 :                :      * Flush stdout before output to stderr, to ensure sync even when stdout
                                254                 :                :      * is buffered.
                                255                 :                :      */
 2591 peter@eisentraut.org      256                 :          76942 :     fflush(stdout);
                                257                 :                : 
                                258         [ +  + ]:          76942 :     if (log_pre_callback)
                                259                 :          47831 :         log_pre_callback();
                                260                 :                : 
                                261         [ +  + ]:          76942 :     if (log_locus_callback)
                                262                 :          47831 :         log_locus_callback(&filename, &lineno);
                                263                 :                : 
                                264                 :          76942 :     fmt = _(fmt);
                                265                 :                : 
 1436                           266   [ +  +  -  + ]:          76942 :     if (!(log_flags & PG_LOG_FLAG_TERSE) || filename)
                                267                 :                :     {
 2591                           268         [ -  + ]:          30214 :         if (sgr_locus)
 2591 peter@eisentraut.org      269                 :UBC           0 :             fprintf(stderr, ANSI_ESCAPE_FMT, sgr_locus);
 2591 peter@eisentraut.org      270         [ +  - ]:CBC       30214 :         if (!(log_flags & PG_LOG_FLAG_TERSE))
                                271                 :          30214 :             fprintf(stderr, "%s:", progname);
                                272         [ +  + ]:          30214 :         if (filename)
                                273                 :                :         {
                                274                 :            771 :             fprintf(stderr, "%s:", filename);
                                275         [ +  - ]:            771 :             if (lineno > 0)
                                276                 :            771 :                 fprintf(stderr, UINT64_FORMAT ":", lineno);
                                277                 :                :         }
                                278                 :          30214 :         fprintf(stderr, " ");
                                279         [ -  + ]:          30214 :         if (sgr_locus)
 2591 peter@eisentraut.org      280                 :UBC           0 :             fprintf(stderr, ANSI_ESCAPE_RESET);
                                281                 :                :     }
                                282                 :                : 
 2591 peter@eisentraut.org      283         [ +  + ]:CBC       76942 :     if (!(log_flags & PG_LOG_FLAG_TERSE))
                                284                 :                :     {
 1488 tgl@sss.pgh.pa.us         285   [ +  +  +  - ]:          30214 :         switch (part)
                                286                 :                :         {
                                287                 :          30057 :             case PG_LOG_PRIMARY:
                                288      [ +  +  + ]:          30057 :                 switch (level)
                                289                 :                :                 {
                                290                 :           2113 :                     case PG_LOG_ERROR:
                                291         [ -  + ]:           2113 :                         if (sgr_error)
 1488 tgl@sss.pgh.pa.us         292                 :UBC           0 :                             fprintf(stderr, ANSI_ESCAPE_FMT, sgr_error);
 1488 tgl@sss.pgh.pa.us         293                 :CBC        2113 :                         fprintf(stderr, _("error: "));
   22 peter@eisentraut.org      294         [ -  + ]:GNC        2113 :                         if (log_logfile)
   22 peter@eisentraut.org      295                 :UNC           0 :                             fprintf(log_logfile, _("error: "));
 1488 tgl@sss.pgh.pa.us         296         [ -  + ]:CBC        2113 :                         if (sgr_error)
 1488 tgl@sss.pgh.pa.us         297                 :UBC           0 :                             fprintf(stderr, ANSI_ESCAPE_RESET);
 1488 tgl@sss.pgh.pa.us         298                 :CBC        2113 :                         break;
                                299                 :            140 :                     case PG_LOG_WARNING:
                                300         [ -  + ]:            140 :                         if (sgr_warning)
 1488 tgl@sss.pgh.pa.us         301                 :UBC           0 :                             fprintf(stderr, ANSI_ESCAPE_FMT, sgr_warning);
 1488 tgl@sss.pgh.pa.us         302                 :CBC         140 :                         fprintf(stderr, _("warning: "));
   22 peter@eisentraut.org      303         [ -  + ]:GNC         140 :                         if (log_logfile)
   22 peter@eisentraut.org      304                 :UNC           0 :                             fprintf(log_logfile, _("warning: "));
 1488 tgl@sss.pgh.pa.us         305         [ -  + ]:CBC         140 :                         if (sgr_warning)
 1488 tgl@sss.pgh.pa.us         306                 :UBC           0 :                             fprintf(stderr, ANSI_ESCAPE_RESET);
 1488 tgl@sss.pgh.pa.us         307                 :CBC         140 :                         break;
                                308                 :          27804 :                     default:
                                309                 :          27804 :                         break;
                                310                 :                :                 }
 2591 peter@eisentraut.org      311                 :          30057 :                 break;
 1488 tgl@sss.pgh.pa.us         312                 :             18 :             case PG_LOG_DETAIL:
 1485 peter@eisentraut.org      313         [ -  + ]:             18 :                 if (sgr_note)
 1485 peter@eisentraut.org      314                 :UBC           0 :                     fprintf(stderr, ANSI_ESCAPE_FMT, sgr_note);
 1488 tgl@sss.pgh.pa.us         315                 :CBC          18 :                 fprintf(stderr, _("detail: "));
   22 peter@eisentraut.org      316         [ -  + ]:GNC          18 :                 if (log_logfile)
   22 peter@eisentraut.org      317                 :UNC           0 :                     fprintf(log_logfile, _("detail: "));
 1485 peter@eisentraut.org      318         [ -  + ]:CBC          18 :                 if (sgr_note)
 1485 peter@eisentraut.org      319                 :UBC           0 :                     fprintf(stderr, ANSI_ESCAPE_RESET);
 2591 peter@eisentraut.org      320                 :CBC          18 :                 break;
 1488 tgl@sss.pgh.pa.us         321                 :            139 :             case PG_LOG_HINT:
 1485 peter@eisentraut.org      322         [ -  + ]:            139 :                 if (sgr_note)
 1485 peter@eisentraut.org      323                 :UBC           0 :                     fprintf(stderr, ANSI_ESCAPE_FMT, sgr_note);
 1488 tgl@sss.pgh.pa.us         324                 :CBC         139 :                 fprintf(stderr, _("hint: "));
   22 peter@eisentraut.org      325         [ +  + ]:GNC         139 :                 if (log_logfile)
                                326                 :              1 :                     fprintf(log_logfile, _("hint: "));
 1485 peter@eisentraut.org      327         [ -  + ]:CBC         139 :                 if (sgr_note)
 1485 peter@eisentraut.org      328                 :UBC           0 :                     fprintf(stderr, ANSI_ESCAPE_RESET);
 2591 peter@eisentraut.org      329                 :CBC         139 :                 break;
                                330                 :                :         }
                                331                 :                :     }
                                332                 :                : 
                                333                 :          76942 :     errno = save_errno;
                                334                 :                : 
                                335                 :          76942 :     va_copy(ap2, ap);
                                336                 :          76942 :     required_len = vsnprintf(NULL, 0, fmt, ap2) + 1;
                                337                 :          76942 :     va_end(ap2);
                                338                 :                : 
                                339                 :          76942 :     buf = pg_malloc_extended(required_len, MCXT_ALLOC_NO_OOM);
                                340                 :                : 
 2495 tgl@sss.pgh.pa.us         341                 :          76942 :     errno = save_errno;         /* malloc might change errno */
                                342                 :                : 
 2591 peter@eisentraut.org      343         [ -  + ]:          76942 :     if (!buf)
                                344                 :                :     {
                                345                 :                :         /* memory trouble, just print what we can and get out of here */
 2591 peter@eisentraut.org      346                 :UBC           0 :         vfprintf(stderr, fmt, ap);
                                347                 :              0 :         return;
                                348                 :                :     }
                                349                 :                : 
 2591 peter@eisentraut.org      350                 :CBC       76942 :     vsnprintf(buf, required_len, fmt, ap);
                                351                 :                : 
                                352                 :                :     /* strip one newline, for PQerrorMessage() */
 2548 tgl@sss.pgh.pa.us         353   [ +  -  +  + ]:          76942 :     if (required_len >= 2 && buf[required_len - 2] == '\n')
 2591 peter@eisentraut.org      354                 :          47025 :         buf[required_len - 2] = '\0';
                                355                 :                : 
                                356                 :          76942 :     fprintf(stderr, "%s\n", buf);
   22 peter@eisentraut.org      357         [ +  + ]:GNC       76942 :     if (log_logfile)
                                358                 :                :     {
                                359                 :             40 :         fprintf(log_logfile, "%s\n", buf);
                                360                 :             40 :         fflush(log_logfile);
                                361                 :                :     }
                                362                 :                : 
 2591 peter@eisentraut.org      363                 :CBC       76942 :     free(buf);
                                364                 :                : }
        

Generated by: LCOV version 2.5.0-beta