pgpool2.git / summary / log / commit / refs

commit    f04ef82be528c5e5e706f9e2e7231db369427eee
Author:   Tatsuo Ishii <ishii@sraoss.co.jp>
Date:     Fri Aug 14 06:42:58 2020 +0000

    Add error stats from backend to "show pool_backend_stats" command.


doc/src/sgml/ref/show_pool_backend_stats.sgml | 15 +++++---- src/include/pcp/libpcp_ext.h | 3 ++ src/include/protocol/pool_process_query.h | 2 ++ src/include/utils/statistics.h | 24 +++++++++------ src/protocol/pool_process_query.c | 44 +++++++++++++++++++++------ src/protocol/pool_proto_modules.c | 8 +++++ src/utils/pool_process_reporting.c | 11 +++++-- src/utils/statistics.c | 35 +++++++++++++++++++++ 8 files changed, 115 insertions(+), 27 deletions(-) diff --git a/doc/src/sgml/ref/show_pool_backend_stats.sgml b/doc/src/sgml/ref/show_pool_backend_stats.sgml index dd33f9f04..abc97401b 100644 --- a/doc/src/sgml/ref/show_pool_backend_stats.sgml +++ b/doc/src/sgml/ref/show_pool_backend_stats.sgml @@ -34,8 +34,10 @@ <command>SHOW POOL_BACKEND_STATS</command> displays the node id, the hostname, the port, the status, the role, the SELECT/INSERT/UPDATE/DELETE/DDL/other query counts issued to each - backend. The node id, the hostname, the port, the status, the role - are same as <xref linkend="sql-show-pool-nodes">. + backend. Also error messages returned from backend are counted and + shown, classified by the severity. The node id, the hostname, the + port, the status, the role are same as <xref + linkend="sql-show-pool-nodes">. </para> <para> select_cnt, insert_cnt, update_cnt, delete_cnt, ddl_cnt, other_cnt @@ -51,10 +53,11 @@ Here is an example session: <programlisting> test=# show pool_backend_stats; - node_id | hostname | port | status | role | select_cnt | insert_cnt | update_cnt | delete_cnt | ddl_cnt | other_cnt ----------+----------+-------+--------+---------+------------+------------+------------+------------+---------+----------- - 0 | /tmp | 11002 | up | primary | 27773 | 27784 | 83273 | 0 | 11 | 83298 - 1 | /tmp | 11003 | up | standby | 1 | 0 | 0 | 0 | 0 | 41410 +test=# show pool_backend_stats; + node_id | hostname | port | status | role | select_cnt | insert_cnt | update_cnt | delete_cnt | ddl_cnt | other_cnt | panic_cnt | fatal_cnt | error_cnt +---------+----------+-------+--------+---------+------------+------------+------------+------------+---------+-----------+-----------+-----------+----------- + 0 | /tmp | 11002 | up | primary | 12 | 10 | 30 | 0 | 2 | 30 | 0 | 0 | 1 + 1 | /tmp | 11003 | up | standby | 12 | 0 | 0 | 0 | 0 | 23 | 0 | 0 | 1 (2 rows) </programlisting> </para> diff --git a/src/include/pcp/libpcp_ext.h b/src/include/pcp/libpcp_ext.h index 271b23e71..e816656f1 100644 --- a/src/include/pcp/libpcp_ext.h +++ b/src/include/pcp/libpcp_ext.h @@ -271,6 +271,9 @@ typedef struct char delete_cnt[POOLCONFIG_MAXWEIGHTLEN + 1]; char ddl_cnt[POOLCONFIG_MAXWEIGHTLEN + 1]; char other_cnt[POOLCONFIG_MAXWEIGHTLEN + 1]; + char panic_cnt[POOLCONFIG_MAXWEIGHTLEN + 1]; + char fatal_cnt[POOLCONFIG_MAXWEIGHTLEN + 1]; + char error_cnt[POOLCONFIG_MAXWEIGHTLEN + 1]; } POOL_BACKEND_STATS; typedef enum diff --git a/src/include/protocol/pool_process_query.h b/src/include/protocol/pool_process_query.h index a8a832cd0..3de86a3e5 100644 --- a/src/include/protocol/pool_process_query.h +++ b/src/include/protocol/pool_process_query.h @@ -83,4 +83,6 @@ int reset_request); extern bool is_backend_cache_empty(POOL_CONNECTION_POOL * backend); extern void pool_send_readyforquery(POOL_CONNECTION * frontend); +extern char *extract_error_kind(char *message, int major); + #endif /* pool_process_query_h */ diff --git a/src/include/utils/statistics.h b/src/include/utils/statistics.h index d235cc37d..8691b9b25 100644 --- a/src/include/utils/statistics.h +++ b/src/include/utils/statistics.h @@ -21,15 +21,19 @@ #ifndef statistics_h #define statistics_h -size_t stat_shared_memory_size(void); -void stat_set_stat_area(void *address); -void stat_init_stat_area(void); -void stat_count_up(int backend_node_id, Node *parsetree); -uint64 stat_get_select_count(int backend_node_id); -uint64 stat_get_insert_count(int backend_node_id); -uint64 stat_get_update_count(int backend_node_id); -uint64 stat_get_delete_count(int backend_node_id); -uint64 stat_get_ddl_count(int backend_node_id); -uint64 stat_get_other_count(int backend_node_id); +extern size_t stat_shared_memory_size(void); +extern void stat_set_stat_area(void *address); +extern void stat_init_stat_area(void); +extern void stat_count_up(int backend_node_id, Node *parsetree); +extern void error_stat_count_up(int backend_node_id, char *str); +extern uint64 stat_get_select_count(int backend_node_id); +extern uint64 stat_get_insert_count(int backend_node_id); +extern uint64 stat_get_update_count(int backend_node_id); +extern uint64 stat_get_delete_count(int backend_node_id); +extern uint64 stat_get_ddl_count(int backend_node_id); +extern uint64 stat_get_other_count(int backend_node_id); +extern uint64 stat_get_panic_count(int backend_node_id); +extern uint64 stat_get_fatal_count(int backend_node_id); +extern uint64 stat_get_error_count(int backend_node_id); #endif /* statistics_h */ diff --git a/src/protocol/pool_process_query.c b/src/protocol/pool_process_query.c index 3390d0af1..8d6f765f0 100644 --- a/src/protocol/pool_process_query.c +++ b/src/protocol/pool_process_query.c @@ -58,6 +58,7 @@ #include "utils/pool_select_walker.h" #include "utils/pool_relcache.h" #include "utils/pool_stream.h" +#include "utils/statistics.h" #include "context/pool_session_context.h" #include "context/pool_query_context.h" #include "query_cache/pool_memqcache.h" @@ -81,7 +82,7 @@ static int reset_backend(POOL_CONNECTION_POOL * backend, int qcnt); static char *get_insert_command_table_name(InsertStmt *node); static bool is_cache_empty(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend); -static bool is_panic_or_fatal_error(const char *message, int major); +static bool is_panic_or_fatal_error(char *message, int major); static int extract_message(POOL_CONNECTION * master, char *error_code, int major, char class, bool unread); static int detect_postmaster_down_error(POOL_CONNECTION * master, int major); static bool is_internal_transaction_needed(Node *node); @@ -717,6 +718,11 @@ SimpleForwardToFrontend(char kind, POOL_CONNECTION * frontend, p1 = palloc(len); memcpy(p1, p, len); + if (kind == 'E') + { + error_stat_count_up(MASTER_NODE_ID, extract_error_kind(p1, PROTO_MAJOR_V3)); + } + /* * If we received a notification message in master/slave mode, other * backends will not receive the message. So we should skip other nodes @@ -4131,8 +4137,28 @@ end_internal_transaction(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * back * Returns true if error message contains PANIC or FATAL. */ static bool -is_panic_or_fatal_error(const char *message, int major) +is_panic_or_fatal_error(char *message, int major) +{ + char *str; + + str = extract_error_kind(message, major); + + if (strncasecmp("PANIC", str, 5) == 0 || strncasecmp("FATAL", str, 5) == 0) + return true; + + return false; +} + +/* + * Look for token in the given ERROR response message, and return the message + * pointer in the message if 'V' or 'S' token found. + * Other wise returns "unknown". + */ +char * +extract_error_kind(char *message, int major) { + char *ret = "unknown"; + if (major == PROTO_MAJOR_V3) { for (;;) @@ -4141,14 +4167,14 @@ is_panic_or_fatal_error(const char *message, int major) id = *message++; if (id == '\0') - break; + return ret; /* V is never localized. Only available 9.6 or later. */ - if (id == 'V' && (strcasecmp("PANIC", message) == 0 || strcasecmp("FATAL", message) == 0)) - return true; + if (id == 'V') + return message; - if (id == 'S' && (strcasecmp("PANIC", message) == 0 || strcasecmp("FATAL", message) == 0)) - return true; + if (id == 'S') + return message; else { while (*message++) @@ -4160,9 +4186,9 @@ is_panic_or_fatal_error(const char *message, int major) else { if (strncmp(message, "PANIC", 5) == 0 || strncmp(message, "FATAL", 5) == 0) - return true; + return message; } - return false; + return ret; } static int diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c index 32a74bd1c..011c14a23 100644 --- a/src/protocol/pool_proto_modules.c +++ b/src/protocol/pool_proto_modules.c @@ -2445,6 +2445,14 @@ ErrorResponse3(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend) { POOL_STATUS ret; + char *message; + char *str; + + if (pool_extract_error_message(false, MASTER(backend), PROTO_MAJOR_V3, true, &message) == 1) + { + str = extract_error_kind(message, PROTO_MAJOR_V3); + error_stat_count_up(MASTER_NODE_ID, str); + } ret = SimpleForwardToFrontend('E', frontend, backend); if (ret != POOL_CONTINUE) diff --git a/src/utils/pool_process_reporting.c b/src/utils/pool_process_reporting.c index 2bbb371c4..db5a608e3 100644 --- a/src/utils/pool_process_reporting.c +++ b/src/utils/pool_process_reporting.c @@ -2133,6 +2133,9 @@ get_backend_stats(int *nrows) snprintf(backend_stats[i].delete_cnt, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, stat_get_delete_count(i)); snprintf(backend_stats[i].ddl_cnt, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, stat_get_ddl_count(i)); snprintf(backend_stats[i].other_cnt, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, stat_get_other_count(i)); + snprintf(backend_stats[i].panic_cnt, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, stat_get_panic_count(i)); + snprintf(backend_stats[i].fatal_cnt, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, stat_get_fatal_count(i)); + snprintf(backend_stats[i].error_cnt, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, stat_get_error_count(i)); if (STREAM) { @@ -2166,7 +2169,8 @@ void show_backend_stats(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend) { static char *field_names[] = {"node_id", "hostname", "port", "status", "role", - "select_cnt", "insert_cnt", "update_cnt", "delete_cnt", "ddl_cnt", "other_cnt"}; + "select_cnt", "insert_cnt", "update_cnt", "delete_cnt", "ddl_cnt", "other_cnt", + "panic_cnt", "fatal_cnt", "error_cnt"}; static int offsettbl[] = { offsetof(POOL_BACKEND_STATS, node_id), @@ -2179,7 +2183,10 @@ show_backend_stats(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend) offsetof(POOL_BACKEND_STATS, update_cnt), offsetof(POOL_BACKEND_STATS, delete_cnt), offsetof(POOL_BACKEND_STATS, ddl_cnt), - offsetof(POOL_BACKEND_STATS, other_cnt) + offsetof(POOL_BACKEND_STATS, other_cnt), + offsetof(POOL_BACKEND_STATS, panic_cnt), + offsetof(POOL_BACKEND_STATS, fatal_cnt), + offsetof(POOL_BACKEND_STATS, error_cnt), }; int nrows; diff --git a/src/utils/statistics.c b/src/utils/statistics.c index 373ba5e2c..045c28255 100644 --- a/src/utils/statistics.c +++ b/src/utils/statistics.c @@ -34,6 +34,9 @@ typedef struct uint64 delete_cnt; /* number of DELETE queries issued */ uint64 ddl_cnt; /* number of DDL queries issued */ uint64 other_cnt; /* number of any other queries issued */ + uint64 panic_cnt; /* number of PANIC messages */ + uint64 fatal_cnt; /* number of FATAL messages */ + uint64 error_cnt; /* number of ERROR messages */ } PER_NODE_STAT; static volatile PER_NODE_STAT *per_node_stat; @@ -136,6 +139,20 @@ stat_count_up(int backend_node_id, Node *parse_tree) } } +/* + * Update error stat counter + */ +void +error_stat_count_up(int backend_node_id, char *str) +{ + if (strcasecmp(str, "PANIC") == 0) + per_node_stat[backend_node_id].panic_cnt++; + else if (strcasecmp(str, "FATAL") == 0) + per_node_stat[backend_node_id].fatal_cnt++; + else if (strcasecmp(str, "ERROR") == 0) + per_node_stat[backend_node_id].error_cnt++; +} + /* * Stat counter read functions */ @@ -174,3 +191,21 @@ stat_get_other_count(int backend_node_id) { return per_node_stat[backend_node_id].other_cnt; } + +uint64 +stat_get_panic_count(int backend_node_id) +{ + return per_node_stat[backend_node_id].panic_cnt; +} + +uint64 +stat_get_fatal_count(int backend_node_id) +{ + return per_node_stat[backend_node_id].fatal_cnt; +} + +uint64 +stat_get_error_count(int backend_node_id) +{ + return per_node_stat[backend_node_id].error_cnt; +} [parent: c9c1f429d2dc]