LCOV - differential code coverage report
Current view: top level - src/common - logging.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 71.1 % 135 96 39 96
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 8 8 8
Baseline: lcov-20250906-005545-baseline Branches: 48.3 % 87 42 45 42
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 0.0 % 2 0 2
(360..) days: 72.2 % 133 96 37 96
Function coverage date bins:
(360..) days: 100.0 % 8 8 8
Branch coverage date bins:
(30,360] days: 0.0 % 2 0 2
(360..) days: 49.4 % 85 42 43 42

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

Generated by: LCOV version 2.4-beta