mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-04 19:25:40 +00:00
test(internode): cover adapter metrics validation (#3071)
Co-authored-by: Henry Guo <marshawcoco@users.noreply.github.com>
This commit is contained in:
@@ -38,6 +38,7 @@ Related design notes in this directory:
|
|||||||
- `transport-buffer-lifecycle.md`
|
- `transport-buffer-lifecycle.md`
|
||||||
- `transport-buffer-contract.md`
|
- `transport-buffer-contract.md`
|
||||||
- `transport-fallback-and-selection.md`
|
- `transport-fallback-and-selection.md`
|
||||||
|
- `transport-metrics-and-baseline.md`
|
||||||
|
|
||||||
## Open-source Scope
|
## Open-source Scope
|
||||||
|
|
||||||
@@ -335,6 +336,9 @@ S3 PUT/GET matrix against `local` and `distributed` scenarios and export:
|
|||||||
- `internode_metric_deltas.csv` (operation-level internode metric deltas when
|
- `internode_metric_deltas.csv` (operation-level internode metric deltas when
|
||||||
`--metrics-url` is provided)
|
`--metrics-url` is provided)
|
||||||
|
|
||||||
|
See `transport-metrics-and-baseline.md` for current metric names, labels,
|
||||||
|
operation values, baseline inputs, and baseline artifact fields.
|
||||||
|
|
||||||
## Transport Abstraction Proposal
|
## Transport Abstraction Proposal
|
||||||
|
|
||||||
### Design principle
|
### Design principle
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
# Internode Transport Metrics and Baseline
|
||||||
|
|
||||||
|
Status: current OSS behavior. This document describes the metrics and baseline
|
||||||
|
runner used to observe the existing `tcp-http` internode transport adapter. It
|
||||||
|
does not add a backend, change runtime behavior, or make performance claims.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
The current OSS adapter scope is:
|
||||||
|
|
||||||
|
- `tcp-http` is the default and only supported internode data transport backend;
|
||||||
|
- `tcp` is a legacy alias for `tcp-http`;
|
||||||
|
- unsupported backend values fail closed during transport construction;
|
||||||
|
- metrics and baseline artifacts are used to understand the current data-plane
|
||||||
|
behavior.
|
||||||
|
|
||||||
|
## Operation Metrics
|
||||||
|
|
||||||
|
Operation-level internode metrics are defined in
|
||||||
|
`crates/io-metrics/src/internode_metrics.rs`.
|
||||||
|
|
||||||
|
| Metric | Labels | Meaning |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `rustfs_system_network_internode_operation_sent_bytes_total` | `operation`, `backend` | Bytes sent for a known internode operation. |
|
||||||
|
| `rustfs_system_network_internode_operation_recv_bytes_total` | `operation`, `backend` | Bytes received for a known internode operation. |
|
||||||
|
| `rustfs_system_network_internode_operation_requests_outgoing_total` | `operation`, `backend` | Outgoing requests opened for a known internode operation. |
|
||||||
|
| `rustfs_system_network_internode_operation_requests_incoming_total` | `operation`, `backend` | Incoming requests handled for a known internode operation. |
|
||||||
|
| `rustfs_system_network_internode_operation_errors_total` | `operation`, `backend` | Errors observed for a known internode operation. |
|
||||||
|
|
||||||
|
Current operation label values are:
|
||||||
|
|
||||||
|
| Operation | Transport path | Notes |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `read_file_stream` | HTTP `/rustfs/rpc/read_file_stream` | Remote disk read stream opened by `InternodeDataTransport::open_read`. |
|
||||||
|
| `put_file_stream` | HTTP `/rustfs/rpc/put_file_stream` | Remote disk write stream opened by `InternodeDataTransport::open_write`. |
|
||||||
|
| `walk_dir` | HTTP `/rustfs/rpc/walk_dir` | Remote walk-dir stream opened by `InternodeDataTransport::open_walk_dir`. |
|
||||||
|
| `grpc_read_all` | gRPC `ReadAll` | Unary bytes response outside the adapter. |
|
||||||
|
| `grpc_write_all` | gRPC `WriteAll` | Unary bytes request outside the adapter. |
|
||||||
|
|
||||||
|
Current backend label values are:
|
||||||
|
|
||||||
|
| Backend | Meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `tcp-http` | Current HTTP stream backend for adapter-routed operations. |
|
||||||
|
| `grpc` | Current gRPC path for `ReadAll` and `WriteAll`. |
|
||||||
|
| `unknown` | Aggregate internode metric path when an operation-specific backend is not available. |
|
||||||
|
|
||||||
|
The `backend` label reflects the current instrumentation source, for example
|
||||||
|
the `tcp-http` stream path, gRPC path, or aggregate unknown path. It does not
|
||||||
|
imply additional supported transport backends.
|
||||||
|
|
||||||
|
Metric labels must stay low cardinality. Do not add object names, full paths,
|
||||||
|
full URLs, peer-specific dynamic strings, request IDs, or other per-request
|
||||||
|
values as labels.
|
||||||
|
|
||||||
|
## Current Instrumentation Points
|
||||||
|
|
||||||
|
| Area | File | Current signal |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Outgoing HTTP stream requests | `crates/rio/src/http_reader.rs` | Outgoing request count, sent bytes for writer bodies, received bytes for reader bodies, and errors for known `/rustfs/rpc/` operations. |
|
||||||
|
| Incoming HTTP stream requests | `rustfs/src/storage/rpc/http_service.rs` | Incoming request count, sent bytes for read and walk streams, received bytes for put streams, and route errors. |
|
||||||
|
| gRPC `ReadAll` / `WriteAll` | `rustfs/src/storage/rpc/disk.rs` | Incoming request count, sent/received bytes, and errors with the `grpc` backend label. |
|
||||||
|
|
||||||
|
Known gaps:
|
||||||
|
|
||||||
|
- Operation-level metrics do not currently expose latency histograms.
|
||||||
|
- The baseline runner reads Prometheus text output only when `--metrics-url` is
|
||||||
|
provided.
|
||||||
|
- Metrics are useful for attribution, but they do not replace end-to-end
|
||||||
|
correctness tests or object benchmark output.
|
||||||
|
|
||||||
|
## Baseline Runner
|
||||||
|
|
||||||
|
Use `scripts/run_internode_transport_baseline.sh` to run the current S3 PUT/GET
|
||||||
|
matrix against one or more configured endpoints.
|
||||||
|
|
||||||
|
Required inputs:
|
||||||
|
|
||||||
|
- `--access-key`
|
||||||
|
- `--secret-key`
|
||||||
|
|
||||||
|
Common optional inputs:
|
||||||
|
|
||||||
|
- `--tool warp|s3bench`
|
||||||
|
- `--scenarios name=url,...`
|
||||||
|
- `--sizes 4KiB,1MiB,...`
|
||||||
|
- `--concurrencies 1,16,...`
|
||||||
|
- `--duration 90s`
|
||||||
|
- `--metrics-url http://host:port/metrics`
|
||||||
|
- `--out-dir target/bench/internode-transport/manual-run`
|
||||||
|
- `--dry-run`
|
||||||
|
|
||||||
|
Dry-run example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scripts/run_internode_transport_baseline.sh \
|
||||||
|
--access-key minioadmin \
|
||||||
|
--secret-key minioadmin \
|
||||||
|
--scenarios local=http://127.0.0.1:9000,distributed=http://127.0.0.1:9001 \
|
||||||
|
--sizes 4KiB,1MiB \
|
||||||
|
--concurrencies 1 \
|
||||||
|
--duration 10s \
|
||||||
|
--dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
Real baseline example with metrics:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
RUSTFS_INTERNODE_DATA_TRANSPORT=tcp-http \
|
||||||
|
scripts/run_internode_transport_baseline.sh \
|
||||||
|
--access-key "$RUSTFS_ACCESS_KEY" \
|
||||||
|
--secret-key "$RUSTFS_SECRET_KEY" \
|
||||||
|
--scenarios local=http://127.0.0.1:9000,distributed=http://127.0.0.1:9001 \
|
||||||
|
--metrics-url http://127.0.0.1:9000/metrics \
|
||||||
|
--out-dir target/bench/internode-transport/manual-run
|
||||||
|
```
|
||||||
|
|
||||||
|
The real baseline requires a running RustFS deployment and working benchmark
|
||||||
|
tool. Do not invent or copy synthetic benchmark numbers into PR descriptions.
|
||||||
|
|
||||||
|
## Output Artifacts
|
||||||
|
|
||||||
|
The baseline runner writes:
|
||||||
|
|
||||||
|
| File | Created when | Contents |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `run_manifest.txt` | Always | Timestamp, git commit, dirty flag, Rust compiler version, kernel string, scenario matrix, tool, workload settings, metrics URL, and redacted credentials. |
|
||||||
|
| `summary.csv` | Always | `scenario`, `endpoint`, `workload`, `concurrency`, `size`, `status`, `throughput`, `requests_per_sec`, `avg_latency`, `error_count`, `log_file`, and `run_dir`. |
|
||||||
|
| `internode_metric_deltas.csv` | When `--metrics-url` is set | `scenario`, `workload`, `concurrency`, `size`, metric name, operation, backend, before value, after value, and delta. |
|
||||||
|
|
||||||
|
In dry-run mode, the runner still creates the manifest and CSV headers, and the
|
||||||
|
underlying object benchmark command is printed with credentials redacted.
|
||||||
|
|
||||||
|
## Interpretation
|
||||||
|
|
||||||
|
Use baseline artifacts to record and inspect the current `tcp-http` adapter
|
||||||
|
behavior across commits, environments, and scenario matrices. A baseline run is
|
||||||
|
valid only for the exact environment and command recorded in
|
||||||
|
`run_manifest.txt`.
|
||||||
|
|
||||||
|
Baseline artifacts should state whether metrics were collected. When
|
||||||
|
`internode_metric_deltas.csv` is absent, benchmark output cannot attribute
|
||||||
|
internode operation deltas from Prometheus metrics.
|
||||||
@@ -328,12 +328,27 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn transport_config_known_backends_are_current_oss_values() {
|
||||||
|
assert_eq!(
|
||||||
|
KNOWN_INTERNODE_DATA_TRANSPORT_BACKENDS,
|
||||||
|
&[DEFAULT_INTERNODE_DATA_TRANSPORT, INTERNODE_DATA_TRANSPORT_TCP]
|
||||||
|
);
|
||||||
|
|
||||||
|
for configured in KNOWN_INTERNODE_DATA_TRANSPORT_BACKENDS {
|
||||||
|
let transport = build_internode_data_transport(Some(configured)).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(transport.name(), DEFAULT_INTERNODE_DATA_TRANSPORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn transport_config_rejects_unknown_backend() {
|
fn transport_config_rejects_unknown_backend() {
|
||||||
let err = build_internode_data_transport(Some("unsupported-backend")).expect_err("unknown backend should fail closed");
|
let err = build_internode_data_transport(Some("unsupported-backend")).expect_err("unknown backend should fail closed");
|
||||||
|
|
||||||
assert!(err.to_string().contains(ENV_RUSTFS_INTERNODE_DATA_TRANSPORT));
|
assert!(err.to_string().contains(ENV_RUSTFS_INTERNODE_DATA_TRANSPORT));
|
||||||
assert!(err.to_string().contains("unsupported-backend"));
|
assert!(err.to_string().contains("unsupported-backend"));
|
||||||
|
assert!(err.to_string().contains("supported values: tcp-http, tcp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -308,4 +308,43 @@ mod tests {
|
|||||||
assert_eq!(metric.labels, &[OPERATION_LABEL, BACKEND_LABEL]);
|
assert_eq!(metric.labels, &[OPERATION_LABEL, BACKEND_LABEL]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn operation_metric_names_and_low_cardinality_values_are_stable() {
|
||||||
|
assert_eq!(INTERNODE_OPERATION_READ_FILE_STREAM, "read_file_stream");
|
||||||
|
assert_eq!(INTERNODE_OPERATION_PUT_FILE_STREAM, "put_file_stream");
|
||||||
|
assert_eq!(INTERNODE_OPERATION_WALK_DIR, "walk_dir");
|
||||||
|
assert_eq!(INTERNODE_OPERATION_GRPC_READ_ALL, "grpc_read_all");
|
||||||
|
assert_eq!(INTERNODE_OPERATION_GRPC_WRITE_ALL, "grpc_write_all");
|
||||||
|
|
||||||
|
assert_eq!(INTERNODE_TRANSPORT_BACKEND_TCP_HTTP, "tcp-http");
|
||||||
|
assert_eq!(INTERNODE_TRANSPORT_BACKEND_GRPC, "grpc");
|
||||||
|
assert_eq!(INTERNODE_TRANSPORT_BACKEND_UNKNOWN, "unknown");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
INTERNODE_OPERATION_METRICS,
|
||||||
|
&[
|
||||||
|
InternodeOperationMetricDescriptor {
|
||||||
|
name: "rustfs_system_network_internode_operation_sent_bytes_total",
|
||||||
|
labels: &[OPERATION_LABEL, BACKEND_LABEL],
|
||||||
|
},
|
||||||
|
InternodeOperationMetricDescriptor {
|
||||||
|
name: "rustfs_system_network_internode_operation_recv_bytes_total",
|
||||||
|
labels: &[OPERATION_LABEL, BACKEND_LABEL],
|
||||||
|
},
|
||||||
|
InternodeOperationMetricDescriptor {
|
||||||
|
name: "rustfs_system_network_internode_operation_requests_outgoing_total",
|
||||||
|
labels: &[OPERATION_LABEL, BACKEND_LABEL],
|
||||||
|
},
|
||||||
|
InternodeOperationMetricDescriptor {
|
||||||
|
name: "rustfs_system_network_internode_operation_requests_incoming_total",
|
||||||
|
labels: &[OPERATION_LABEL, BACKEND_LABEL],
|
||||||
|
},
|
||||||
|
InternodeOperationMetricDescriptor {
|
||||||
|
name: "rustfs_system_network_internode_operation_errors_total",
|
||||||
|
labels: &[OPERATION_LABEL, BACKEND_LABEL],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user