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]