https://github.com/perbu/ostresser
Object store stress test.
https://github.com/perbu/ostresser
Last synced: about 1 year ago
JSON representation
Object store stress test.
- Host: GitHub
- URL: https://github.com/perbu/ostresser
- Owner: perbu
- License: bsd-2-clause
- Created: 2025-04-01T12:07:49.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-05-06T07:01:06.000Z (about 1 year ago)
- Last Synced: 2025-05-07T19:15:06.346Z (about 1 year ago)
- Language: Go
- Size: 59.6 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Object Store Stress Tester - Developer Guide
[](https://opensource.org/licenses/BSD-2-Clause)
This document provides developer-specific information about the Go object store stress tester, focusing on its
configuration, programmatic usage, and internal design.
## Install
```bash
go install github.com/perbu/ostresser@latest
```
## Example output.
```text
--- Stress Test Summary --- (7.556s) ---
Overall:
Total Requests: 10000 (1323.46 req/s)
Total Success: 10000
Total Errors: 0
GET Operations (0 total):
Success: 0
Bytes D/L: 0 (0.00 MiB)
Avg Throughput: 0.00 MiB/s
No successful GETs to calculate latency.
PUT Operations (10000 total):
Success: 10000
Bytes U/L: 10485760000 (10000.00 MiB)
Avg Throughput: 1323.46 MiB/s
Latency (ms): | Min | Avg | P50 | P90 | P99 | Max
--------------|--------|--------|--------|--------|--------|--------
TTLB (total) | 3.21 | 7.50 | 6.18 | 11.59 | 27.16 | 84.92
----------------------------------------
Detailed results written to stress_results.csv
time=2025-04-01T14:00:16.933+02:00 level=INFO msg="Stress test completed successfully"
```
## Manifest File (manifest.txt)
The manifest file provides a list of object keys that the stress tester will interact with during 'read' or 'mixed'
operations.
Format:
* Plain text file.
* Each line contains one object key.
* Leading/trailing whitespace around keys is automatically trimmed.
* Empty lines are ignored.
* Lines containing only whitespace are ignored.
Example (manifest.txt):
```text
path/to/object1.dat
images/archive.zip
another/key/with/leading/space.txt
videos/important_video.mp4
backup-2024-01-15.tar.gz
trailing-space-key.log
```
### Write Mode and Manifest File
In write mode, there are two ways to use the manifest file:
1. **Continuous Generation**: The stress tester will continuously generate and upload objects with random keys for the
duration of the test.
- The manifest file path is still required as a command-line argument.
- By default, it will write all successfully uploaded object keys to the manifest file.
- Use `-genmf=false` to disable writing to the manifest file.
2. **Fixed File Count Generation**: You can generate a specific number of files using the `-files` flag.
- Example: `-files 1000` will generate 1000 files with random keys.
- By default, all successfully uploaded keys will be written to the manifest file.
- The test will exit after all files have been generated and uploaded.
- File size is controlled with the `-putsize` flag (in KB).
## Configuration options
### 1. S3 Connection Details
These parameters define how to connect to the S3-compatible object storage service.
* **`endpoint` (YAML) / `AWS_ENDPOINT_URL` (Env)**
* **Description:** The full URL of the S3-compatible endpoint (e.g., `http://localhost:9000` or `https://s3.amazonaws.com`).
* **Required:** Yes (must be set via YAML or Environment Variable).
* **Type:** `string`
* **`region` (YAML) / `AWS_REGION` (Env)**
* **Description:** The AWS region associated with the endpoint. This is often required by the AWS SDK for proper signing and functioning, even when using a non-AWS S3-compatible endpoint.
* **Required:** No (Defaults to `us-east-1` if not set).
* **Type:** `string`
* **Default:** `us-east-1`
* **`bucket` (YAML) / `S3_BUCKET` (Env)**
* **Description:** The name of the S3 bucket to target for the stress test operations. Note the specific environment variable `S3_BUCKET` is used.
* **Required:** Yes (must be set via YAML or Environment Variable).
* **Type:** `string`
* **`accessKey` (YAML) / `AWS_ACCESS_KEY_ID` (Env)**
* **Description:** The access key credential for authenticating with the S3 service.
* **Required:** No (Optional. If not provided, the SDK may attempt to use other credential sources like IAM instance profiles or shared credential files).
* **Type:** `string`
* **`secretKey` (YAML) / `AWS_SECRET_ACCESS_KEY` (Env)**
* **Description:** The secret key credential for authenticating with the S3 service.
* **Required:** No (Optional, typically provided alongside `accessKey`).
* **Type:** `string`
* **`insecureSkipVerify` (YAML) / `STRESSER_INSECURE_SKIP_VERIFY` (Env)**
* **Description:** If set to `true`, TLS certificate verification for the S3 endpoint will be skipped. Use with caution, primarily for testing with self-signed certificates. The environment variable must be set to the string `"true"` or `"false"`.
* **Required:** No (Defaults to `false`).
* **Type:** `bool`
* **Default:** `false`
---
### 2. Test Parameters
These parameters control the execution of the stress test itself. Most are primarily set via command-line flags/arguments.
* **`Duration` (Flag `-d`)**
* **Description:** Specifies the total duration the stress test should run (e.g., "10s", "5m", "1h").
* **Required:** Yes (must be set via flag).
* **Type:** `string` (parsed into a duration)
* **Source:** Command-line flag (`-d`) only.
* **`Concurrency` (Flag `-c`)**
* **Description:** The number of concurrent workers (goroutines) performing S3 operations.
* **Required:** Yes (must be set via flag and be > 0).
* **Type:** `int`
* **Source:** Command-line flag (`-c`) only.
* **`Randomize` (Flag `--randomize`)**
* **Description:** If set, the order of keys read from the manifest file will be randomized for each worker. If false, each worker processes a distinct, sequential chunk of the manifest.
* **Required:** No (Defaults to `false` likely, based on typical flag handling).
* **Type:** `bool`
* **Source:** Command-line flag (`--randomize`) only.
* **`ManifestPath` (Positional Argument)**
* **Description:** The path to the input manifest file. This file should contain a list of object keys (one per line) to be used for `read` or `mixed` operations. In `write` mode, if `generateManifest` is true, this is the *output* path where generated keys will be written.
* **Required:** Yes (must be provided as a command-line argument).
* **Type:** `string`
* **Source:** Command-line argument only.
* **`OutputFile` (Flag `-o`)**
* **Description:** The path to the CSV file where the results (performance metrics) of the stress test will be written.
* **Required:** Yes (must be set via flag).
* **Type:** `string`
* **Source:** Command-line flag (`-o`) only.
* **`OperationType` (Flag `-op`, YAML `operationType`, Env `STRESSER_OPERATION_TYPE`)**
* **Description:** Specifies the type of S3 operations to perform. Valid values are `"read"` (GET objects), `"write"` (PUT objects), or `"mixed"` (both GET and PUT objects). Values are case-insensitive but normalized to lowercase.
* **Required:** No (Defaults to `read`).
* **Type:** `string`
* **Valid Values:** `read`, `write`, `mixed`
* **Default:** `read`
* **`PutObjectSizeKB` (Flag `-putsize`, YAML `putObjectSizeKB`, Env `STRESSER_PUT_SIZE_KB`)**
* **Description:** The size (in Kilobytes) of the objects to create when the `operationType` is `"write"` or `"mixed"`. Must be greater than 0 in these modes.
* **Required:** Yes, if `operationType` is `write` or `mixed`.
* **Type:** `int`
* **Default:** `1024` (1 MiB)
---
### 3. File Generation Parameters (Write Mode)
These parameters are specifically used when `operationType` is set to `write`.
* **`FileCount` (Flag `-filecount`, YAML `fileCount`, Env `STRESSER_FILE_COUNT`)**
* **Description:** The number of unique object keys (and thus files) to generate and potentially upload if running in `write` mode. This is used to determine how many PUT operations to attempt if generating data.
* **Required:** No (Defaults to `1000`).
* **Type:** `int`
* **Default:** `1000`
* **`GenerateManifest` (Flag `--generate-manifest / --no-generate-manifest` , YAML `generateManifest`, Env `STRESSER_GENERATE_MANIFEST`)**
* **Description:** Controls whether the list of generated object keys (determined by `FileCount`) should be written to the file specified by `ManifestPath` when running in `write` mode. The environment variable must be set to the string `"true"` or `"false"`. Flags likely control this boolean directly.
* **Required:** No (Defaults to `true`).
* **Type:** `bool`
* **Default:** `true`
---
### 4. Logging Configuration
* **`LogLevel` (Flag `-loglevel`, YAML `logLevel`, Env `STRESSER_LOG_LEVEL`)**
* **Description:** Controls the verbosity of the application's logging output. Valid values are `"debug"`, `"info"`, `"warn"`, `"error"`. Values are case-insensitive but normalized to lowercase.
* **Required:** No (Defaults to `info`).
* **Type:** `string`
* **Valid Values:** `debug`, `info`, `warn`, `error`
* **Default:** `info`
## Programmatic Usage (within the same module)
While the tool is primarily designed as a command-line application, its core logic in the internal/stresser package can
be invoked programmatically from other Go code within the same module.
Steps:
* Create Configuration: Instantiate and populate the stresser.Config struct. You can manually set fields instead of
relying on file/env/flag parsing.
* Create Context: Set up a context.Context, potentially with a timeout or cancellation signal.
* Call RunStressTest: Invoke the main execution function, passing the context and config.
* Process Results: Handle the returned results slice ([]stresser.Result) and statistics (*stresser.Stats).
Example Snippet:
```go
package main // Or your package
import (
"context"
"log"
"os"
"time"
Adjust import path
)
func runProgrammatically() {
// 1. Configure the test manually
cfg := &stresser.Config{
// Connection Details
Endpoint: "http://localhost:9000", // Example endpoint
Region: "us-east-1",
Bucket: "my-test-bucket",
AccessKey: "minioadmin", // Example credentials
SecretKey: "minioadmin",
InsecureSkipVerify: true, // Example: Allow self-signed certs
// Test Parameters (set directly)
Duration: "15s", // Use string format expected by time.ParseDuration internally
Concurrency: 5,
Randomize: true,
ManifestPath: "path/to/your/manifest.txt", // Still needed for read/mixed
OutputFile: "programmatic_results.csv", // Where to save CSV
OperationType: "mixed", // "read", "write", or "mixed"
PutObjectSizeKB: 256, // 256 KB uploads
}
// Basic validation after manual setup
if err := cfg.Validate(); err != nil {
log.Fatalf("Manual configuration validation failed: %v", err)
}
// 2. Create a context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // Overall timeout slightly longer than test
duration
defer cancel()
log.Println("Starting programmatic stress test run...")
// 3. Run the stress test
results, stats, err := stresser.RunStressTest(ctx, cfg)
if err != nil {
// Handle potential errors (excluding expected context cancellations)
if ctx.Err() == context.Canceled || ctx.Err() == context.DeadlineExceeded {
log.Printf("Test run ended via context: %v", ctx.Err())
} else {
log.Fatalf("Stress test execution failed: %v", err)
}
}
log.Printf("Programmatic run finished. Collected %d results.", len(results))
// 4. Process results and stats (example: print summary)
if stats != nil {
stats.PrintSummary(os.Stdout) // Print summary to console
} else {
log.Println("Stats object is nil.")
}
// You can also iterate through 'results' or save the CSV manually if needed
if len(results) > 0 {
// Example: Manually trigger CSV write if needed (RunStressTest usually does this)
// if err := stresser.WriteResultsCSV(results, cfg.OutputFile); err != nil {
// log.Printf("Error writing results CSV: %v", err)
// }
// log.Printf("First result TTFB (ms): %.3f", stresser.ms(results[0].TTFB)) // Requires helper func
} else {
log.Println("No results collected.")
}
}
```