LCOV - differential code coverage report
Current view: top level - src/backend/utils/error - jsonlog.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 84.8 % 105 89 16 3 86 3
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 3 3 1 2
Baseline: 16@8cea358b128 Branches: 62.9 % 70 44 26 4 40
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 3 3 3
(240..) days: 84.3 % 102 86 16 86
Function coverage date bins:
(240..) days: 100.0 % 3 3 1 2
Branch coverage date bins:
[..60] days: 100.0 % 4 4 4
(240..) days: 60.6 % 66 40 26 40

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * jsonlog.c
                                  4                 :                :  *    JSON logging
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/utils/error/jsonlog.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : 
                                 16                 :                : #include "postgres.h"
                                 17                 :                : 
                                 18                 :                : #include "access/xact.h"
                                 19                 :                : #include "libpq/libpq-be.h"
                                 20                 :                : #include "lib/stringinfo.h"
                                 21                 :                : #include "miscadmin.h"
                                 22                 :                : #include "postmaster/syslogger.h"
                                 23                 :                : #include "storage/lock.h"
                                 24                 :                : #include "storage/proc.h"
                                 25                 :                : #include "tcop/tcopprot.h"
                                 26                 :                : #include "utils/backend_status.h"
                                 27                 :                : #include "utils/guc.h"
                                 28                 :                : #include "utils/json.h"
                                 29                 :                : #include "utils/ps_status.h"
                                 30                 :                : 
                                 31                 :                : static void appendJSONKeyValueFmt(StringInfo buf, const char *key,
                                 32                 :                :                                   bool escape_key,
                                 33                 :                :                                   const char *fmt,...) pg_attribute_printf(4, 5);
                                 34                 :                : 
                                 35                 :                : /*
                                 36                 :                :  * appendJSONKeyValue
                                 37                 :                :  *
                                 38                 :                :  * Append to a StringInfo a comma followed by a JSON key and a value.
                                 39                 :                :  * The key is always escaped.  The value can be escaped optionally, that
                                 40                 :                :  * is dependent on the data type of the key.
                                 41                 :                :  */
                                 42                 :                : static void
  818 michael@paquier.xyz        43                 :CBC         259 : appendJSONKeyValue(StringInfo buf, const char *key, const char *value,
                                 44                 :                :                    bool escape_value)
                                 45                 :                : {
                                 46         [ -  + ]:            259 :     Assert(key != NULL);
                                 47                 :                : 
                                 48         [ +  + ]:            259 :     if (value == NULL)
                                 49                 :             20 :         return;
                                 50                 :                : 
                                 51                 :            239 :     appendStringInfoChar(buf, ',');
                                 52                 :            239 :     escape_json(buf, key);
                                 53                 :            239 :     appendStringInfoChar(buf, ':');
                                 54                 :                : 
                                 55         [ +  + ]:            239 :     if (escape_value)
                                 56                 :            158 :         escape_json(buf, value);
                                 57                 :                :     else
                                 58                 :             81 :         appendStringInfoString(buf, value);
                                 59                 :                : }
                                 60                 :                : 
                                 61                 :                : 
                                 62                 :                : /*
                                 63                 :                :  * appendJSONKeyValueFmt
                                 64                 :                :  *
                                 65                 :                :  * Evaluate the fmt string and then invoke appendJSONKeyValue() as the
                                 66                 :                :  * value of the JSON property.  Both the key and value will be escaped by
                                 67                 :                :  * appendJSONKeyValue().
                                 68                 :                :  */
                                 69                 :                : static void
                                 70                 :            110 : appendJSONKeyValueFmt(StringInfo buf, const char *key,
                                 71                 :                :                       bool escape_key, const char *fmt,...)
                                 72                 :                : {
                                 73                 :            110 :     int         save_errno = errno;
                                 74                 :            110 :     size_t      len = 128;      /* initial assumption about buffer size */
                                 75                 :                :     char       *value;
                                 76                 :                : 
                                 77                 :                :     for (;;)
  818 michael@paquier.xyz        78                 :UBC           0 :     {
                                 79                 :                :         va_list     args;
                                 80                 :                :         size_t      newlen;
                                 81                 :                : 
                                 82                 :                :         /* Allocate result buffer */
  818 michael@paquier.xyz        83                 :CBC         110 :         value = (char *) palloc(len);
                                 84                 :                : 
                                 85                 :                :         /* Try to format the data. */
                                 86                 :            110 :         errno = save_errno;
                                 87                 :            110 :         va_start(args, fmt);
                                 88                 :            110 :         newlen = pvsnprintf(value, len, fmt, args);
                                 89                 :            110 :         va_end(args);
                                 90                 :                : 
                                 91         [ +  - ]:            110 :         if (newlen < len)
                                 92                 :            110 :             break;              /* success */
                                 93                 :                : 
                                 94                 :                :         /* Release buffer and loop around to try again with larger len. */
  818 michael@paquier.xyz        95                 :UBC           0 :         pfree(value);
                                 96                 :              0 :         len = newlen;
                                 97                 :                :     }
                                 98                 :                : 
  818 michael@paquier.xyz        99                 :CBC         110 :     appendJSONKeyValue(buf, key, value, escape_key);
                                100                 :                : 
                                101                 :                :     /* Clean up */
                                102                 :            110 :     pfree(value);
                                103                 :            110 : }
                                104                 :                : 
                                105                 :                : /*
                                106                 :                :  * Write logs in json format.
                                107                 :                :  */
                                108                 :                : void
                                109                 :             20 : write_jsonlog(ErrorData *edata)
                                110                 :                : {
                                111                 :                :     StringInfoData buf;
                                112                 :                :     char       *start_time;
                                113                 :                :     char       *log_time;
                                114                 :                : 
                                115                 :                :     /* static counter for line numbers */
                                116                 :                :     static long log_line_number = 0;
                                117                 :                : 
                                118                 :                :     /* Has the counter been reset in the current process? */
                                119                 :                :     static int  log_my_pid = 0;
                                120                 :                : 
                                121                 :                :     /*
                                122                 :                :      * This is one of the few places where we'd rather not inherit a static
                                123                 :                :      * variable's value from the postmaster.  But since we will, reset it when
                                124                 :                :      * MyProcPid changes.
                                125                 :                :      */
                                126         [ +  + ]:             20 :     if (log_my_pid != MyProcPid)
                                127                 :                :     {
                                128                 :             11 :         log_line_number = 0;
                                129                 :             11 :         log_my_pid = MyProcPid;
                                130                 :             11 :         reset_formatted_start_time();
                                131                 :                :     }
                                132                 :             20 :     log_line_number++;
                                133                 :                : 
                                134                 :             20 :     initStringInfo(&buf);
                                135                 :                : 
                                136                 :                :     /* Initialize string */
                                137                 :             20 :     appendStringInfoChar(&buf, '{');
                                138                 :                : 
                                139                 :                :     /* timestamp with milliseconds */
                                140                 :             20 :     log_time = get_formatted_log_time();
                                141                 :                : 
                                142                 :                :     /*
                                143                 :                :      * First property does not use appendJSONKeyValue as it does not have
                                144                 :                :      * comma prefix.
                                145                 :                :      */
                                146                 :             20 :     escape_json(&buf, "timestamp");
                                147                 :             20 :     appendStringInfoChar(&buf, ':');
                                148                 :             20 :     escape_json(&buf, log_time);
                                149                 :                : 
                                150                 :                :     /* username */
                                151         [ +  + ]:             20 :     if (MyProcPort)
                                152                 :              9 :         appendJSONKeyValue(&buf, "user", MyProcPort->user_name, true);
                                153                 :                : 
                                154                 :                :     /* database name */
                                155         [ +  + ]:             20 :     if (MyProcPort)
                                156                 :              9 :         appendJSONKeyValue(&buf, "dbname", MyProcPort->database_name, true);
                                157                 :                : 
                                158                 :                :     /* Process ID */
                                159         [ +  - ]:             20 :     if (MyProcPid != 0)
                                160                 :             20 :         appendJSONKeyValueFmt(&buf, "pid", false, "%d", MyProcPid);
                                161                 :                : 
                                162                 :                :     /* Remote host and port */
                                163   [ +  +  +  - ]:             20 :     if (MyProcPort && MyProcPort->remote_host)
                                164                 :                :     {
                                165                 :              9 :         appendJSONKeyValue(&buf, "remote_host", MyProcPort->remote_host, true);
                                166   [ +  -  -  + ]:              9 :         if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0')
  818 michael@paquier.xyz       167                 :UBC           0 :             appendJSONKeyValue(&buf, "remote_port", MyProcPort->remote_port, false);
                                168                 :                :     }
                                169                 :                : 
                                170                 :                :     /* Session id */
  818 michael@paquier.xyz       171                 :CBC          20 :     appendJSONKeyValueFmt(&buf, "session_id", true, "%lx.%x",
                                172                 :                :                           (long) MyStartTime, MyProcPid);
                                173                 :                : 
                                174                 :                :     /* Line number */
                                175                 :             20 :     appendJSONKeyValueFmt(&buf, "line_num", false, "%ld", log_line_number);
                                176                 :                : 
                                177                 :                :     /* PS display */
                                178         [ +  + ]:             20 :     if (MyProcPort)
                                179                 :                :     {
                                180                 :                :         StringInfoData msgbuf;
                                181                 :                :         const char *psdisp;
                                182                 :                :         int         displen;
                                183                 :                : 
                                184                 :              9 :         initStringInfo(&msgbuf);
                                185                 :              9 :         psdisp = get_ps_display(&displen);
                                186                 :              9 :         appendBinaryStringInfo(&msgbuf, psdisp, displen);
                                187                 :              9 :         appendJSONKeyValue(&buf, "ps", msgbuf.data, true);
                                188                 :                : 
                                189                 :              9 :         pfree(msgbuf.data);
                                190                 :                :     }
                                191                 :                : 
                                192                 :                :     /* session start timestamp */
                                193                 :             20 :     start_time = get_formatted_start_time();
                                194                 :             20 :     appendJSONKeyValue(&buf, "session_start", start_time, true);
                                195                 :                : 
                                196                 :                :     /* Virtual transaction id */
                                197                 :                :     /* keep VXID format in sync with lockfuncs.c */
   42 heikki.linnakangas@i      198   [ +  +  +  + ]:GNC          20 :     if (MyProc != NULL && MyProc->vxid.procNumber != INVALID_PROC_NUMBER)
                                199                 :              9 :         appendJSONKeyValueFmt(&buf, "vxid", true, "%d/%u",
                                200                 :              9 :                               MyProc->vxid.procNumber, MyProc->vxid.lxid);
                                201                 :                : 
                                202                 :                :     /* Transaction id */
  818 michael@paquier.xyz       203                 :CBC          20 :     appendJSONKeyValueFmt(&buf, "txid", false, "%u",
                                204                 :                :                           GetTopTransactionIdIfAny());
                                205                 :                : 
                                206                 :                :     /* Error severity */
                                207         [ +  - ]:             20 :     if (edata->elevel)
                                208                 :             20 :         appendJSONKeyValue(&buf, "error_severity",
                                209                 :                :                            (char *) error_severity(edata->elevel), true);
                                210                 :                : 
                                211                 :                :     /* SQL state code */
                                212         [ +  + ]:             20 :     if (edata->sqlerrcode)
                                213                 :              2 :         appendJSONKeyValue(&buf, "state_code",
                                214                 :              2 :                            unpack_sql_state(edata->sqlerrcode), true);
                                215                 :                : 
                                216                 :                :     /* errmessage */
                                217                 :             20 :     appendJSONKeyValue(&buf, "message", edata->message, true);
                                218                 :                : 
                                219                 :                :     /* errdetail or error_detail log */
                                220         [ -  + ]:             20 :     if (edata->detail_log)
  818 michael@paquier.xyz       221                 :UBC           0 :         appendJSONKeyValue(&buf, "detail", edata->detail_log, true);
                                222                 :                :     else
  818 michael@paquier.xyz       223                 :CBC          20 :         appendJSONKeyValue(&buf, "detail", edata->detail, true);
                                224                 :                : 
                                225                 :                :     /* errhint */
                                226         [ -  + ]:             20 :     if (edata->hint)
  818 michael@paquier.xyz       227                 :UBC           0 :         appendJSONKeyValue(&buf, "hint", edata->hint, true);
                                228                 :                : 
                                229                 :                :     /* internal query */
  818 michael@paquier.xyz       230         [ -  + ]:CBC          20 :     if (edata->internalquery)
  818 michael@paquier.xyz       231                 :UBC           0 :         appendJSONKeyValue(&buf, "internal_query", edata->internalquery,
                                232                 :                :                            true);
                                233                 :                : 
                                234                 :                :     /* if printed internal query, print internal pos too */
  818 michael@paquier.xyz       235   [ -  +  -  - ]:CBC          20 :     if (edata->internalpos > 0 && edata->internalquery != NULL)
  732 peter@eisentraut.org      236                 :UBC           0 :         appendJSONKeyValueFmt(&buf, "internal_position", false, "%d",
                                237                 :                :                               edata->internalpos);
                                238                 :                : 
                                239                 :                :     /* errcontext */
  818 michael@paquier.xyz       240   [ -  +  -  - ]:CBC          20 :     if (edata->context && !edata->hide_ctx)
  818 michael@paquier.xyz       241                 :UBC           0 :         appendJSONKeyValue(&buf, "context", edata->context, true);
                                242                 :                : 
                                243                 :                :     /* user query --- only reported if not disabled by the caller */
  818 michael@paquier.xyz       244         [ +  + ]:CBC          20 :     if (check_log_of_query(edata))
                                245                 :                :     {
                                246                 :              2 :         appendJSONKeyValue(&buf, "statement", debug_query_string, true);
                                247         [ +  + ]:              2 :         if (edata->cursorpos > 0)
                                248                 :              1 :             appendJSONKeyValueFmt(&buf, "cursor_position", false, "%d",
                                249                 :                :                                   edata->cursorpos);
                                250                 :                :     }
                                251                 :                : 
                                252                 :                :     /* file error location */
                                253         [ -  + ]:             20 :     if (Log_error_verbosity >= PGERROR_VERBOSE)
                                254                 :                :     {
  818 michael@paquier.xyz       255         [ #  # ]:UBC           0 :         if (edata->funcname)
                                256                 :              0 :             appendJSONKeyValue(&buf, "func_name", edata->funcname, true);
                                257         [ #  # ]:              0 :         if (edata->filename)
                                258                 :                :         {
                                259                 :              0 :             appendJSONKeyValue(&buf, "file_name", edata->filename, true);
                                260                 :              0 :             appendJSONKeyValueFmt(&buf, "file_line_num", false, "%d",
                                261                 :                :                                   edata->lineno);
                                262                 :                :         }
                                263                 :                :     }
                                264                 :                : 
                                265                 :                :     /* Application name */
  818 michael@paquier.xyz       266   [ +  -  +  + ]:CBC          20 :     if (application_name && application_name[0] != '\0')
                                267                 :              9 :         appendJSONKeyValue(&buf, "application_name", application_name, true);
                                268                 :                : 
                                269                 :                :     /* backend type */
                                270                 :             20 :     appendJSONKeyValue(&buf, "backend_type", get_backend_type_for_log(), true);
                                271                 :                : 
                                272                 :                :     /* leader PID */
                                273         [ +  + ]:             20 :     if (MyProc)
                                274                 :                :     {
                                275                 :             13 :         PGPROC     *leader = MyProc->lockGroupLeader;
                                276                 :                : 
                                277                 :                :         /*
                                278                 :                :          * Show the leader only for active parallel workers.  This leaves out
                                279                 :                :          * the leader of a parallel group.
                                280                 :                :          */
                                281   [ -  +  -  - ]:             13 :         if (leader && leader->pid != MyProcPid)
  818 michael@paquier.xyz       282                 :UBC           0 :             appendJSONKeyValueFmt(&buf, "leader_pid", false, "%d",
                                283                 :                :                                   leader->pid);
                                284                 :                :     }
                                285                 :                : 
                                286                 :                :     /* query id */
  818 michael@paquier.xyz       287                 :CBC          20 :     appendJSONKeyValueFmt(&buf, "query_id", false, "%lld",
                                288                 :             20 :                           (long long) pgstat_get_my_query_id());
                                289                 :                : 
                                290                 :                :     /* Finish string */
                                291                 :             20 :     appendStringInfoChar(&buf, '}');
                                292                 :             20 :     appendStringInfoChar(&buf, '\n');
                                293                 :                : 
                                294                 :                :     /* If in the syslogger process, try to write messages direct to file */
                                295         [ -  + ]:             20 :     if (MyBackendType == B_LOGGER)
  818 michael@paquier.xyz       296                 :UBC           0 :         write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_JSONLOG);
                                297                 :                :     else
  818 michael@paquier.xyz       298                 :CBC          20 :         write_pipe_chunks(buf.data, buf.len, LOG_DESTINATION_JSONLOG);
                                299                 :                : 
                                300                 :             20 :     pfree(buf.data);
                                301                 :             20 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622