/* -*-pgsql-c-*- */ /* * * $Header$ * * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * * Copyright (c) 2003-2020 PgPool Global Development Group * */ /*-------------------------------------------------------------------- * statistics.c * * Various statistics related functions. *-------------------------------------------------------------------- */ #include #include #include "pool.h" #include "utils/statistics.h" #include "parser/nodes.h" /* * Per backend node stat area in shared memory */ typedef struct { uint64 select_cnt; /* number of read SELECT queries issued */ uint64 insert_cnt; /* number of INSERT queries issued */ uint64 update_cnt; /* number of UPDATE queries issued */ 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; /* * Return shared memory size necessary for this module */ size_t stat_shared_memory_size(void) { size_t size; /* query counter area */ size = MAXALIGN(MAX_NUM_BACKENDS * sizeof(PER_NODE_STAT)); return size; } /* * Set PER_NODE_STAT address in the shared memory area to global variable. * This should be called from pgpool main process upon startup. */ void stat_set_stat_area(void *address) { per_node_stat = (PER_NODE_STAT *) address; } /* * Initialize shared memory stat area */ void stat_init_stat_area(void) { memset((void *) per_node_stat, 0, stat_shared_memory_size()); } /* * Update stat counter */ void stat_count_up(int backend_node_id, Node *parse_tree) { if (parse_tree == NULL) { /* * No parse tree. does not worth to gather statistics (internal * queries). If we want to gather statistics for queries without * parse tree, we could call the parser but I don't think it's worth * the trouble. */ return; } if (IsA(parse_tree, SelectStmt)) { per_node_stat[backend_node_id].select_cnt++; } else if (IsA(parse_tree, InsertStmt)) { per_node_stat[backend_node_id].insert_cnt++; } else if (IsA(parse_tree, UpdateStmt)) { per_node_stat[backend_node_id].update_cnt++; } else if (IsA(parse_tree, DeleteStmt)) { per_node_stat[backend_node_id].delete_cnt++; } else { switch (nodeTag(parse_tree)) { case (T_CheckPointStmt): case (T_DeallocateStmt): case (T_DiscardStmt): case (T_ExecuteStmt): case (T_ExplainStmt): case (T_ListenStmt): case (T_LoadStmt): case (T_LockStmt): case (T_NotifyStmt): case (T_PrepareStmt): case (T_TransactionStmt): case (T_UnlistenStmt): case (T_VacuumStmt): case (T_VariableSetStmt): case (T_VariableShowStmt): per_node_stat[backend_node_id].other_cnt++; break; default: per_node_stat[backend_node_id].ddl_cnt++; } } } /* * 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 */ uint64 stat_get_select_count(int backend_node_id) { return per_node_stat[backend_node_id].select_cnt; } uint64 stat_get_insert_count(int backend_node_id) { return per_node_stat[backend_node_id].insert_cnt; } uint64 stat_get_update_count(int backend_node_id) { return per_node_stat[backend_node_id].update_cnt; } uint64 stat_get_delete_count(int backend_node_id) { return per_node_stat[backend_node_id].delete_cnt; } uint64 stat_get_ddl_count(int backend_node_id) { return per_node_stat[backend_node_id].ddl_cnt; } uint64 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; }