@@ -41,15 +41,45 @@ public function __construct(
4141
4242 $ schema = <<<SQL
4343 CREATE TABLE IF NOT EXISTS metrics (
44- id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL,
45- commands_per_second INTEGER, hit_rate REAL, memory_used INTEGER, memory_peak INTEGER,
46- fragmentation_ratio REAL, connections INTEGER
44+ id INTEGER PRIMARY KEY AUTOINCREMENT,
45+ timestamp INTEGER NOT NULL,
46+ commands_per_second INTEGER,
47+ hit_rate REAL,
48+ memory_used INTEGER,
49+ memory_peak INTEGER,
50+ fragmentation_ratio REAL,
51+ connections INTEGER,
52+ commands_stats TEXT
4753 )
4854 SQL ;
4955
5056 $ this ->pdo ->exec ($ schema );
57+
58+ $ this ->updateSchema ([
59+ 'commands_stats ' => 'TEXT ' ,
60+ ]);
61+ }
62+
63+ /**
64+ * @param array<string, string> $new_columns
65+ */
66+ private function updateSchema (array $ new_columns ): void {
67+ try {
68+ $ statement = $ this ->pdo ->query ('PRAGMA table_info(metrics) ' );
69+ $ existing_columns = $ statement ->fetchAll (PDO ::FETCH_COLUMN , 1 );
70+
71+ foreach ($ new_columns as $ column_name => $ type ) {
72+ if (!in_array ($ column_name , $ existing_columns , true )) {
73+ $ this ->pdo ->exec (sprintf ('ALTER TABLE metrics ADD COLUMN %s %s ' , $ column_name , $ type ));
74+ }
75+ }
76+ } catch (\Exception ) {
77+ }
5178 }
5279
80+ /**
81+ * @throws JsonException
82+ */
5383 public function collectAndRespond (): string {
5484 $ info = $ this ->redis ->getInfo (null , [
5585 'used_memory ' ,
@@ -79,13 +109,23 @@ public function collectAndRespond(): string {
79109 /**
80110 * @param array<string, mixed> $info
81111 *
82- * @return array<string, int|float>
112+ * @return array<string, int|float|string>
113+ *
114+ * @throws JsonException
83115 */
84116 private function calculateMetrics (array $ info ): array {
85117 $ keyspace_hits = $ info ['stats ' ]['keyspace_hits ' ] ?? 0 ;
86118 $ keyspace_misses = $ info ['stats ' ]['keyspace_misses ' ] ?? 0 ;
87119 $ total_commands = $ keyspace_hits + $ keyspace_misses ;
88120
121+ $ parsed_commands = $ this ->redis ->parseSectionData ('commandstats ' );
122+ $ command_calls = [];
123+
124+ foreach ($ parsed_commands as $ cmd => $ details ) {
125+ $ name = str_replace ('cmdstat_ ' , '' , $ cmd );
126+ $ command_calls [$ name ] = (int ) ($ details ['calls ' ] ?? 0 );
127+ }
128+
89129 return [
90130 'timestamp ' => time (),
91131 'commands_per_second ' => $ info ['stats ' ]['instantaneous_ops_per_sec ' ] ?? 0 ,
@@ -94,6 +134,7 @@ private function calculateMetrics(array $info): array {
94134 'memory_peak ' => $ info ['memory ' ]['used_memory_peak ' ] ?? 0 ,
95135 'fragmentation_ratio ' => $ info ['memory ' ]['mem_fragmentation_ratio ' ] ?? 0 ,
96136 'connections ' => $ info ['clients ' ]['connected_clients ' ] ?? 0 ,
137+ 'commands_stats ' => json_encode ($ command_calls , JSON_THROW_ON_ERROR ),
97138 ];
98139 }
99140
@@ -119,15 +160,15 @@ private function fetchRecentMetrics(): array {
119160 $ stmt ->bindValue (':limit ' , $ max_data_points_to_return , PDO ::PARAM_INT );
120161 $ stmt ->execute ();
121162
122- $ results = $ stmt ->fetchAll (PDO ::FETCH_ASSOC );
123-
124- return array_reverse ($ results );
163+ return array_reverse ($ stmt ->fetchAll (PDO ::FETCH_ASSOC ));
125164 }
126165
127166 /**
128167 * @param array<int, array<string, mixed>> $db_rows
129168 *
130169 * @return array<int, array<string, mixed>>
170+ *
171+ * @throws JsonException
131172 */
132173 private function formatDataForResponse (array $ db_rows ): array {
133174 $ formatted_results = [];
@@ -144,6 +185,7 @@ private function formatDataForResponse(array $db_rows): array {
144185 'fragmentation ' => $ row ['fragmentation_ratio ' ],
145186 ],
146187 'connections ' => $ row ['connections ' ],
188+ 'commands_stats ' => json_decode ((string ) $ row ['commands_stats ' ], true , 512 , JSON_THROW_ON_ERROR ),
147189 ];
148190 }
149191
0 commit comments