Skip to content

Commit a3ebfc6

Browse files
committed
stats
1 parent 37d4fb8 commit a3ebfc6

File tree

23 files changed

+362
-131
lines changed

23 files changed

+362
-131
lines changed

CLAUDE.md

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,15 @@
77

88
# Code style
99

10-
Use standard Rust code style. Use `cargo fmt` to reformat code automatically after every edit.
11-
Before committing or finishing a task, use `cargo clippy` to detect more serious lint errors.
12-
13-
VERY IMPORTANT:
14-
NEVER add comments that are redundant with the nearby code.
15-
ALWAYS be sure comments document "Why", not "What", the code is doing.
16-
ALWAYS challenge the user's assumptions
17-
ALWAYS attempt to prove hypotheses wrong - never assume a hypothesis is true unless you have evidence
18-
ALWAYS demonstrate that the code you add is STRICTLY necessary, either by unit, integration, or logical processes
19-
NEVER take the lazy way out
20-
ALWAYS work carefully and methodically through the steps of the process.
21-
NEVER use quick fixes. Always carefully work through the problem unless specifically asked.
22-
ALWAYS Ask clarifying questions before implementing
23-
ALWAYS Break large tasks into single-session chunks
24-
25-
VERY IMPORTANT: you are to act as a detective, attempting to find ways to falsify the code or planning we've done by discovering gaps or inconsistencies. ONLY write code when it is absolutely required to pass tests, the build, or typecheck.
26-
27-
VERY IMPORTANT: NEVER comment out code or skip tests unless specifically requested by the user
28-
29-
## Principles
30-
- **Data first**: Define types before implementation
31-
- **Small Modules**: Try to keep files under 200 lines, unless required by implementation. NEVER allow files to exceed 1000 lines unless specifically instructed.
10+
- Use standard Rust code style.
11+
- Use `cargo fmt` to reformat code automatically after every edit.
12+
- Don't write functions with many arguments: create a struct and use that as input instead.
3213

3314
# Workflow
3415

3516
- Prefer to run individual tests with `cargo nextest run --test-threads=1 --no-fail-fast <name of the test here>`. This is much faster.
36-
- A local PostgreSQL server is required for some tests to pass. Ensure it is set up, and if necessary create a database called "pgdog", and create a user called "pgdog" with password "pgdog".
37-
- Focus on files in `./pgdog` and `./integration` - other files are LOWEST priority
38-
39-
## Test-Driven Development (TDD) - STRICT ENFORCEMENT
40-
- **MANDATORY WORKFLOW - NO EXCEPTIONS:**
41-
1. Write exactly ONE test that fails
42-
2. Write ONLY the minimal code to make that test pass
43-
3. Refactor if needed (tests must still pass)
44-
4. Return to step 1 for next test
45-
- **CRITICAL RULES:**
46-
- NO implementation code without a failing test first
47-
- NO untested code is allowed to exist
48-
- Every line of production code must be justified by a test
17+
- A local PostgreSQL server is required for some tests to pass. Assume it's running, if not, stop and ask the user to start it.
18+
- Coe
4919

5020
# About the project
5121

pgdog/src/admin/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub mod show_pools;
3030
pub mod show_prepared_statements;
3131
pub mod show_query_cache;
3232
pub mod show_replication;
33+
pub mod show_rewrite;
3334
pub mod show_server_memory;
3435
pub mod show_servers;
3536
pub mod show_stats;

pgdog/src/admin/parser.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::{
77
show_client_memory::ShowClientMemory, show_clients::ShowClients, show_config::ShowConfig,
88
show_instance_id::ShowInstanceId, show_lists::ShowLists, show_mirrors::ShowMirrors,
99
show_peers::ShowPeers, show_pools::ShowPools, show_prepared_statements::ShowPreparedStatements,
10-
show_query_cache::ShowQueryCache, show_replication::ShowReplication,
10+
show_query_cache::ShowQueryCache, show_replication::ShowReplication, show_rewrite::ShowRewrite,
1111
show_server_memory::ShowServerMemory, show_servers::ShowServers, show_stats::ShowStats,
1212
show_transactions::ShowTransactions, show_version::ShowVersion, shutdown::Shutdown, Command,
1313
Error,
@@ -30,6 +30,7 @@ pub enum ParseResult {
3030
ShowStats(ShowStats),
3131
ShowTransactions(ShowTransactions),
3232
ShowMirrors(ShowMirrors),
33+
ShowRewrite(ShowRewrite),
3334
ShowVersion(ShowVersion),
3435
ShowInstanceId(ShowInstanceId),
3536
SetupSchema(SetupSchema),
@@ -65,6 +66,7 @@ impl ParseResult {
6566
ShowStats(show_stats) => show_stats.execute().await,
6667
ShowTransactions(show_transactions) => show_transactions.execute().await,
6768
ShowMirrors(show_mirrors) => show_mirrors.execute().await,
69+
ShowRewrite(show_rewrite) => show_rewrite.execute().await,
6870
ShowVersion(show_version) => show_version.execute().await,
6971
ShowInstanceId(show_instance_id) => show_instance_id.execute().await,
7072
SetupSchema(setup_schema) => setup_schema.execute().await,
@@ -100,6 +102,7 @@ impl ParseResult {
100102
ShowStats(show_stats) => show_stats.name(),
101103
ShowTransactions(show_transactions) => show_transactions.name(),
102104
ShowMirrors(show_mirrors) => show_mirrors.name(),
105+
ShowRewrite(show_rewrite) => show_rewrite.name(),
103106
ShowVersion(show_version) => show_version.name(),
104107
ShowInstanceId(show_instance_id) => show_instance_id.name(),
105108
SetupSchema(setup_schema) => setup_schema.name(),
@@ -163,6 +166,7 @@ impl Parser {
163166
"lists" => ParseResult::ShowLists(ShowLists::parse(&sql)?),
164167
"prepared" => ParseResult::ShowPrepared(ShowPreparedStatements::parse(&sql)?),
165168
"replication" => ParseResult::ShowReplication(ShowReplication::parse(&sql)?),
169+
"rewrite" => ParseResult::ShowRewrite(ShowRewrite::parse(&sql)?),
166170
command => {
167171
debug!("unknown admin show command: '{}'", command);
168172
return Err(Error::Syntax);

pgdog/src/admin/show_mirrors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl Command for ShowMirrors {
3535
let counts = {
3636
let stats = cluster.stats();
3737
let stats = stats.lock();
38-
stats.counts
38+
stats.mirrors
3939
};
4040

4141
// Create a data row for this cluster

pgdog/src/admin/show_rewrite.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//! SHOW REWRITE - per-cluster rewrite statistics
2+
3+
use crate::backend::databases::databases;
4+
5+
use super::prelude::*;
6+
7+
pub struct ShowRewrite;
8+
9+
#[async_trait]
10+
impl Command for ShowRewrite {
11+
fn name(&self) -> String {
12+
"SHOW REWRITE".into()
13+
}
14+
15+
fn parse(_: &str) -> Result<Self, Error> {
16+
Ok(Self)
17+
}
18+
19+
async fn execute(&self) -> Result<Vec<Message>, Error> {
20+
let fields = vec![
21+
Field::text("database"),
22+
Field::text("user"),
23+
Field::numeric("parse"),
24+
Field::numeric("bind"),
25+
Field::numeric("simple"),
26+
];
27+
28+
let mut messages = vec![RowDescription::new(&fields).message()?];
29+
30+
for (user, cluster) in databases().all() {
31+
let rewrite = {
32+
let stats = cluster.stats();
33+
let stats = stats.lock();
34+
stats.rewrite
35+
};
36+
37+
let mut dr = DataRow::new();
38+
dr.add(user.database.as_str())
39+
.add(user.user.as_str())
40+
.add(rewrite.parse as i64)
41+
.add(rewrite.bind as i64)
42+
.add(rewrite.simple as i64);
43+
44+
messages.push(dr.message()?);
45+
}
46+
47+
Ok(messages)
48+
}
49+
}

pgdog/src/admin/tests/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::admin::Command;
22
use crate::backend::databases::{databases, from_config, replace_databases, Databases};
3-
use crate::backend::pool::mirror_stats::Counts;
3+
use crate::backend::pool::cluster_stats::MirrorStats;
44
use crate::config::{self, ConfigAndUsers, Database, Role, User as ConfigUser};
55
use crate::net::messages::{DataRow, DataType, FromBytes, Protocol, RowDescription};
66

@@ -226,7 +226,7 @@ async fn show_mirrors_reports_counts() {
226226
{
227227
let cluster_stats = cluster.stats();
228228
let mut stats = cluster_stats.lock();
229-
stats.counts = Counts {
229+
stats.mirrors = MirrorStats {
230230
total_count: 5,
231231
mirrored_count: 4,
232232
dropped_count: 1,

pgdog/src/backend/pool/cluster.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626
net::{messages::BackendKeyData, Query},
2727
};
2828

29-
use super::{Address, Config, Error, Guard, MirrorStats, Request, Shard, ShardConfig};
29+
use super::{Address, ClusterStats, Config, Error, Guard, Request, Shard, ShardConfig};
3030
use crate::config::LoadBalancingStrategy;
3131

3232
#[derive(Clone, Debug, Default)]
@@ -53,7 +53,7 @@ pub struct Cluster {
5353
multi_tenant: Option<MultiTenant>,
5454
rw_strategy: ReadWriteStrategy,
5555
schema_admin: bool,
56-
stats: Arc<Mutex<MirrorStats>>,
56+
stats: Arc<Mutex<ClusterStats>>,
5757
cross_shard_disabled: bool,
5858
two_phase_commit: bool,
5959
two_phase_commit_auto: bool,
@@ -245,7 +245,7 @@ impl Cluster {
245245
multi_tenant: multi_tenant.clone(),
246246
rw_strategy,
247247
schema_admin,
248-
stats: Arc::new(Mutex::new(MirrorStats::default())),
248+
stats: Arc::new(Mutex::new(ClusterStats::default())),
249249
cross_shard_disabled,
250250
two_phase_commit: two_pc && shards.len() > 1,
251251
two_phase_commit_auto: two_pc_auto && shards.len() > 1,
@@ -409,7 +409,7 @@ impl Cluster {
409409
self.schema_admin = owner;
410410
}
411411

412-
pub fn stats(&self) -> Arc<Mutex<MirrorStats>> {
412+
pub fn stats(&self) -> Arc<Mutex<ClusterStats>> {
413413
self.stats.clone()
414414
}
415415

pgdog/src/backend/pool/mirror_stats.rs renamed to pgdog/src/backend/pool/cluster_stats.rs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ use std::{
55
ops::{Add, Div, Sub},
66
};
77

8+
use crate::frontend::router::rewrite::stats::RewriteStats;
9+
810
#[derive(Debug, Clone, Default, Copy)]
9-
pub struct Counts {
11+
pub struct MirrorStats {
1012
pub total_count: usize,
1113
pub mirrored_count: usize,
1214
pub dropped_count: usize,
1315
pub error_count: usize,
1416
pub queue_length: usize,
1517
}
1618

17-
impl Sub for Counts {
18-
type Output = Counts;
19+
impl Sub for MirrorStats {
20+
type Output = MirrorStats;
1921

2022
fn sub(self, rhs: Self) -> Self::Output {
2123
Self {
@@ -28,8 +30,8 @@ impl Sub for Counts {
2830
}
2931
}
3032

31-
impl Div<usize> for Counts {
32-
type Output = Counts;
33+
impl Div<usize> for MirrorStats {
34+
type Output = MirrorStats;
3335

3436
fn div(self, rhs: usize) -> Self::Output {
3537
Self {
@@ -42,11 +44,11 @@ impl Div<usize> for Counts {
4244
}
4345
}
4446

45-
impl Add for Counts {
46-
type Output = Counts;
47+
impl Add for MirrorStats {
48+
type Output = MirrorStats;
4749

48-
fn add(self, rhs: Counts) -> Self::Output {
49-
Counts {
50+
fn add(self, rhs: MirrorStats) -> Self::Output {
51+
MirrorStats {
5052
total_count: self.total_count + rhs.total_count,
5153
mirrored_count: self.mirrored_count + rhs.mirrored_count,
5254
dropped_count: self.dropped_count + rhs.dropped_count,
@@ -56,9 +58,9 @@ impl Add for Counts {
5658
}
5759
}
5860

59-
impl Sum for Counts {
61+
impl Sum for MirrorStats {
6062
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
61-
let mut result = Counts::default();
63+
let mut result = MirrorStats::default();
6264
for next in iter {
6365
result = result + next;
6466
}
@@ -68,8 +70,9 @@ impl Sum for Counts {
6870
}
6971

7072
#[derive(Debug, Clone, Default, Copy)]
71-
pub struct MirrorStats {
72-
pub counts: Counts,
73+
pub struct ClusterStats {
74+
pub mirrors: MirrorStats,
75+
pub rewrite: RewriteStats,
7376
}
7477

7578
#[cfg(test)]
@@ -78,24 +81,24 @@ mod tests {
7881

7982
#[test]
8083
fn test_queue_length_default_is_zero() {
81-
let stats = MirrorStats::default();
84+
let stats = ClusterStats::default();
8285
assert_eq!(
83-
stats.counts.queue_length, 0,
86+
stats.mirrors.queue_length, 0,
8487
"queue_length should be 0 by default"
8588
);
8689
}
8790

8891
#[test]
8992
fn test_queue_length_arithmetic_operations() {
90-
let counts1 = Counts {
93+
let counts1 = MirrorStats {
9194
total_count: 10,
9295
mirrored_count: 5,
9396
dropped_count: 3,
9497
error_count: 2,
9598
queue_length: 7,
9699
};
97100

98-
let counts2 = Counts {
101+
let counts2 = MirrorStats {
99102
total_count: 5,
100103
mirrored_count: 3,
101104
dropped_count: 1,
@@ -127,15 +130,15 @@ mod tests {
127130

128131
#[test]
129132
fn test_queue_length_saturating_sub() {
130-
let counts1 = Counts {
133+
let counts1 = MirrorStats {
131134
total_count: 10,
132135
mirrored_count: 5,
133136
dropped_count: 3,
134137
error_count: 2,
135138
queue_length: 3,
136139
};
137140

138-
let counts2 = Counts {
141+
let counts2 = MirrorStats {
139142
total_count: 5,
140143
mirrored_count: 3,
141144
dropped_count: 1,

0 commit comments

Comments
 (0)