elog.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 1,486 行 · 第 1/3 页
C
1,486 行
/* already word boundary? */ if (!isspace((unsigned char) line[buflen]) && line[buflen] != '\0') { /* try to divide at word boundary */ i = buflen - 1; while (i > 0 && !isspace((unsigned char) buf[i])) i--; if (i > 0) /* else couldn't divide word boundary */ { buflen = i; buf[i] = '\0'; } } chunk_nr++; syslog(level, "[%lu-%d] %s", seq, chunk_nr, buf); line += buflen; len -= buflen; } } else { /* message short enough */ syslog(level, "[%lu] %s", seq, line); }}#endif /* HAVE_SYSLOG *//* * Write error report to server's log */static voidsend_message_to_server_log(ErrorData *edata){ StringInfoData buf; initStringInfo(&buf); appendStringInfo(&buf, "%s: ", error_severity(edata->elevel)); if (Log_error_verbosity >= PGERROR_VERBOSE) { /* unpack MAKE_SQLSTATE code */ char tbuf[12]; int ssval; int i; ssval = edata->sqlerrcode; for (i = 0; i < 5; i++) { tbuf[i] = PGUNSIXBIT(ssval); ssval >>= 6; } tbuf[i] = '\0'; appendStringInfo(&buf, "%s: ", tbuf); } if (edata->message) append_with_tabs(&buf, edata->message); else append_with_tabs(&buf, gettext("missing error text")); if (edata->cursorpos > 0) appendStringInfo(&buf, gettext(" at character %d"), edata->cursorpos); appendStringInfoChar(&buf, '\n'); if (Log_error_verbosity >= PGERROR_DEFAULT) { if (edata->detail) { appendStringInfoString(&buf, gettext("DETAIL: ")); append_with_tabs(&buf, edata->detail); appendStringInfoChar(&buf, '\n'); } if (edata->hint) { appendStringInfoString(&buf, gettext("HINT: ")); append_with_tabs(&buf, edata->hint); appendStringInfoChar(&buf, '\n'); } if (edata->context) { appendStringInfoString(&buf, gettext("CONTEXT: ")); append_with_tabs(&buf, edata->context); appendStringInfoChar(&buf, '\n'); } if (Log_error_verbosity >= PGERROR_VERBOSE) { /* assume no newlines in funcname or filename... */ if (edata->funcname && edata->filename) appendStringInfo(&buf, gettext("LOCATION: %s, %s:%d\n"), edata->funcname, edata->filename, edata->lineno); else if (edata->filename) appendStringInfo(&buf, gettext("LOCATION: %s:%d\n"), edata->filename, edata->lineno); } } /* * If the user wants the query that generated this error logged, do it. */ if (edata->elevel >= log_min_error_statement && debug_query_string != NULL) { appendStringInfoString(&buf, gettext("STATEMENT: ")); append_with_tabs(&buf, debug_query_string); appendStringInfoChar(&buf, '\n'); }#ifdef HAVE_SYSLOG /* Write to syslog, if enabled */ if (Use_syslog >= 1) { int syslog_level; switch (edata->elevel) { case DEBUG5: case DEBUG4: case DEBUG3: case DEBUG2: case DEBUG1: syslog_level = LOG_DEBUG; break; case LOG: case COMMERROR: case INFO: syslog_level = LOG_INFO; break; case NOTICE: case WARNING: syslog_level = LOG_NOTICE; break; case ERROR: syslog_level = LOG_WARNING; break; case FATAL: syslog_level = LOG_ERR; break; case PANIC: default: syslog_level = LOG_CRIT; break; } write_syslog(syslog_level, buf.data); }#endif /* HAVE_SYSLOG */ /* Write to stderr, if enabled */ if (Use_syslog <= 1 || whereToSendOutput == Debug) { /* * Timestamp and PID are only used for stderr output --- we assume * the syslog daemon will supply them for us in the other case. */ fprintf(stderr, "%s%s%s", Log_timestamp ? print_timestamp() : "", Log_pid ? print_pid() : "", buf.data); } pfree(buf.data);}/* * Write error report to client */static voidsend_message_to_frontend(ErrorData *edata){ StringInfoData msgbuf; /* 'N' (Notice) is for nonfatal conditions, 'E' is for errors */ pq_beginmessage(&msgbuf, (edata->elevel < ERROR) ? 'N' : 'E'); if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { /* New style with separate fields */ char tbuf[12]; int ssval; int i; pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY); pq_sendstring(&msgbuf, error_severity(edata->elevel)); /* unpack MAKE_SQLSTATE code */ ssval = edata->sqlerrcode; for (i = 0; i < 5; i++) { tbuf[i] = PGUNSIXBIT(ssval); ssval >>= 6; } tbuf[i] = '\0'; pq_sendbyte(&msgbuf, PG_DIAG_SQLSTATE); pq_sendstring(&msgbuf, tbuf); /* M field is required per protocol, so always send something */ pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY); if (edata->message) pq_sendstring(&msgbuf, edata->message); else pq_sendstring(&msgbuf, gettext("missing error text")); if (edata->detail) { pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_DETAIL); pq_sendstring(&msgbuf, edata->detail); } if (edata->hint) { pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_HINT); pq_sendstring(&msgbuf, edata->hint); } if (edata->context) { pq_sendbyte(&msgbuf, PG_DIAG_CONTEXT); pq_sendstring(&msgbuf, edata->context); } if (edata->cursorpos > 0) { snprintf(tbuf, sizeof(tbuf), "%d", edata->cursorpos); pq_sendbyte(&msgbuf, PG_DIAG_STATEMENT_POSITION); pq_sendstring(&msgbuf, tbuf); } if (edata->filename) { pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_FILE); pq_sendstring(&msgbuf, edata->filename); } if (edata->lineno > 0) { snprintf(tbuf, sizeof(tbuf), "%d", edata->lineno); pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_LINE); pq_sendstring(&msgbuf, tbuf); } if (edata->funcname) { pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_FUNCTION); pq_sendstring(&msgbuf, edata->funcname); } pq_sendbyte(&msgbuf, '\0'); /* terminator */ } else { /* Old style --- gin up a backwards-compatible message */ StringInfoData buf; initStringInfo(&buf); appendStringInfo(&buf, "%s: ", error_severity(edata->elevel)); if (edata->show_funcname && edata->funcname) appendStringInfo(&buf, "%s: ", edata->funcname); if (edata->message) appendStringInfoString(&buf, edata->message); else appendStringInfoString(&buf, gettext("missing error text")); if (edata->cursorpos > 0) appendStringInfo(&buf, gettext(" at character %d"), edata->cursorpos); appendStringInfoChar(&buf, '\n'); pq_sendstring(&msgbuf, buf.data); pfree(buf.data); } pq_endmessage(&msgbuf); /* * This flush is normally not necessary, since postgres.c will flush * out waiting data when control returns to the main loop. But it * seems best to leave it here, so that the client has some clue what * happened if the backend dies before getting back to the main loop * ... error/notice messages should not be a performance-critical path * anyway, so an extra flush won't hurt much ... */ pq_flush();}/* * Support routines for formatting error messages. *//* * expand_fmt_string --- process special format codes in a format string * * We must replace %m with the appropriate strerror string, since vsnprintf * won't know what to do with it. * * The result is a palloc'd string. */static char *expand_fmt_string(const char *fmt, ErrorData *edata){ StringInfoData buf; const char *cp; initStringInfo(&buf); for (cp = fmt; *cp; cp++) { if (cp[0] == '%' && cp[1] != '\0') { cp++; if (*cp == 'm') { /* * Replace %m by system error string. If there are any * %'s in the string, we'd better double them so that * vsnprintf won't misinterpret. */ const char *cp2; cp2 = useful_strerror(edata->saved_errno); for (; *cp2; cp2++) { if (*cp2 == '%') appendStringInfoCharMacro(&buf, '%'); appendStringInfoCharMacro(&buf, *cp2); } } else { /* copy % and next char --- this avoids trouble with %%m */ appendStringInfoCharMacro(&buf, '%'); appendStringInfoCharMacro(&buf, *cp); } } else appendStringInfoCharMacro(&buf, *cp); } return buf.data;}/* * A slightly cleaned-up version of strerror() */static const char *useful_strerror(int errnum){ /* this buffer is only used if errno has a bogus value */ static char errorstr_buf[48]; const char *str; str = strerror(errnum); /* * Some strerror()s return an empty string for out-of-range errno. * This is ANSI C spec compliant, but not exactly useful. */ if (str == NULL || *str == '\0') { /* * translator: This string will be truncated at 47 characters * expanded. */ snprintf(errorstr_buf, sizeof(errorstr_buf), gettext("operating system error %d"), errnum); str = errorstr_buf; } return str;}/* * error_severity --- get localized string representing elevel */static const char *error_severity(int elevel){ const char *prefix; switch (elevel) { case DEBUG1: case DEBUG2: case DEBUG3: case DEBUG4: case DEBUG5: prefix = gettext("DEBUG"); break; case LOG: case COMMERROR: prefix = gettext("LOG"); break; case INFO: prefix = gettext("INFO"); break; case NOTICE: prefix = gettext("NOTICE"); break; case WARNING: prefix = gettext("WARNING"); break; case ERROR: prefix = gettext("ERROR"); break; case FATAL: prefix = gettext("FATAL"); break; case PANIC: prefix = gettext("PANIC"); break; default: prefix = "???"; break; } return prefix;}/* * Return a timestamp string like * * "2000-06-04 13:12:03 " */static const char *print_timestamp(void){ time_t curtime; static char buf[21]; /* format `YYYY-MM-DD HH:MM:SS ' */ curtime = time(NULL); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S ", localtime(&curtime)); return buf;}/* * Return a string like * * "[123456] " * * with the current pid. */static const char *print_pid(void){ static char buf[10]; /* allow `[123456] ' */ snprintf(buf, sizeof(buf), "[%d] ", (int) MyProcPid); return buf;}/* * append_with_tabs * * Append the string to the StringInfo buffer, inserting a tab after any * newline. */static voidappend_with_tabs(StringInfo buf, const char *str){ char ch; while ((ch = *str++) != '\0') { appendStringInfoCharMacro(buf, ch); if (ch == '\n') appendStringInfoCharMacro(buf, '\t'); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?