Skip to content

Commit b50c1d7

Browse files
author
Илья
committed
Init SLO
1 parent c5ecca6 commit b50c1d7

File tree

16 files changed

+1169
-4
lines changed

16 files changed

+1169
-4
lines changed

.github/workflows/slo.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
on:
2+
push:
3+
branches: [main]
4+
pull_request:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
name: SLO
9+
10+
jobs:
11+
test-slo:
12+
concurrency:
13+
group: slo-${{ github.ref }}
14+
if: (!contains(github.event.pull_request.labels.*.name, 'no slo'))
15+
16+
runs-on: ubuntu-latest
17+
name: SLO test
18+
permissions:
19+
checks: write
20+
pull-requests: write
21+
contents: read
22+
issues: write
23+
24+
steps:
25+
- name: Checkout repository
26+
uses: actions/checkout@v3
27+
if: env.DOCKER_REPO != null # check permissions
28+
env:
29+
DOCKER_REPO: ${{ secrets.SLO_DOCKER_REPO }}
30+
31+
- name: Run SLO
32+
uses: ydb-platform/slo-tests@php-version
33+
if: env.DOCKER_REPO != null # check permissions
34+
env:
35+
DOCKER_REPO: ${{ secrets.SLO_DOCKER_REPO }}
36+
with:
37+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38+
KUBECONFIG_B64: ${{ secrets.SLO_KUBE_CONFIG }}
39+
AWS_CREDENTIALS_B64: ${{ secrets.SLO_AWS_CREDENTIALS }}
40+
AWS_CONFIG_B64: ${{ secrets.SLO_AWS_CONFIG }}
41+
DOCKER_USERNAME: ${{ secrets.SLO_DOCKER_USERNAME }}
42+
DOCKER_PASSWORD: ${{ secrets.SLO_DOCKER_PASSWORD }}
43+
DOCKER_REPO: ${{ secrets.SLO_DOCKER_REPO }}
44+
DOCKER_FOLDER: ${{ secrets.SLO_DOCKER_FOLDER }}
45+
s3_endpoint: ${{ secrets.SLO_S3_ENDPOINT }}
46+
s3_images_folder: ${{ vars.SLO_S3_IMAGES_FOLDER }}
47+
grafana_domain: ${{ vars.SLO_GRAFANA_DOMAIN }}
48+
grafana_dashboard: dca60386-0d3d-43f5-a2af-5f3fd3e3b295
49+
grafana_dashboard_width: 2000
50+
grafana_dashboard_height: 2300
51+
ydb_version: 'newest'
52+
timeBetweenPhases: 30
53+
shutdownTime: 30
54+
55+
language_id0: 'php'
56+
workload_path0: 'slo-workload'
57+
language0: 'php'
58+
workload_build_context0: ../.
59+
workload_build_options0: -f Dockerfile
60+
61+
- uses: actions/upload-artifact@v3
62+
if: always() && env.DOCKER_REPO != null # check permissions and execute, even if the previous stage was failed
63+
env:
64+
DOCKER_REPO: ${{ secrets.SLO_DOCKER_REPO }}
65+
with:
66+
name: slo-logs
67+
path: logs/

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
"autoload-dev": {
3333
"psr-4": {
3434
"YdbPlatform\\Ydb\\Test\\": "tests",
35-
"App\\": "examples/"
35+
"App\\": "examples/",
36+
"YdbPlatform\\Ydb\\Slo\\": "slo-workload"
3637
}
3738
}
3839
}

slo-workload/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
composer.lock
2+
./vendor
3+
.idea

slo-workload/Dockerfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM ilyakharev/php-grpc:7.2
2+
3+
COPY . /src
4+
WORKDIR /src/slo-workload
5+
RUN composer update
6+
#RUN apt update; apt install htop
7+
ENTRYPOINT ["php", "application.php"]

slo-workload/README.MD

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# SLO workload
2+
3+
SLO is the type of test where app based on ydb-sdk is tested against falling YDB cluster nodes, tablets, network
4+
(that is possible situations for distributed DBs with hundreds of nodes)
5+
6+
### Usage:
7+
8+
It has 3 commands:
9+
10+
- `create` - creates table in database
11+
- `cleanup` - drops table in database
12+
- `run` - runs workload (read and write to table with sets RPS)
13+
14+
### Run examples with all arguments:
15+
16+
create:
17+
18+
`$APP create grpcs://ydb.cool.example.com:2135 /some/folder -t tableName
19+
-min-partitions-count 6 -max-partitions-count 1000 -partition-size 1 -с 1000
20+
-write-timeout 10000`
21+
22+
cleanup:
23+
24+
`$APP cleanup grpcs://ydb.cool.example.com:2135 /some/folder -t tableName`
25+
26+
run:
27+
28+
`$APP create run grpcs://ydb.cool.example.com:2135 /some/folder -t tableName
29+
-prom-pgw http://prometheus-pushgateway:9091 -report-period 250
30+
-read-rps 1000 -read-timeout 10000
31+
-write-rps 100 -write-timeout 10000
32+
-time 600 -shutdown-time 30`
33+
34+
## Arguments for commands:
35+
36+
### create
37+
`$APP create <endpoint> <db> [options]`
38+
39+
```
40+
Arguments:
41+
endpoint YDB endpoint to connect to
42+
db YDB database to connect to
43+
44+
Options:
45+
-t -table-name <string> table name to create
46+
47+
-min-partitions-count <int> minimum amount of partitions in table
48+
-max-partitions-count <int> maximum amount of partitions in table
49+
-partition-size <int> partition size in mb
50+
51+
-c -initial-data-count <int> amount of initially created rows
52+
53+
-write-timeout <int> write timeout milliseconds
54+
```
55+
56+
### cleanup
57+
`$APP cleanup <endpoint> <db> [options]`
58+
59+
```
60+
Arguments:
61+
endpoint YDB endpoint to connect to
62+
db YDB database to connect to
63+
64+
Options:
65+
-t -table-name <string> table name to create
66+
67+
-write-timeout <int> write timeout milliseconds
68+
```
69+
70+
### run
71+
`$APP run <endpoint> <db> [options]`
72+
73+
```
74+
Arguments:
75+
endpoint YDB endpoint to connect to
76+
db YDB database to connect to
77+
78+
Options:
79+
-t -table-name <string> table name to create
80+
81+
-initial-data-count <int> amount of initially created rows
82+
83+
-prom-pgw <string> prometheus push gateway
84+
-report-period <int> prometheus push period in milliseconds
85+
86+
-read-rps <int> read RPS
87+
-read-timeout <int> read timeout milliseconds
88+
89+
-write-rps <int> write RPS
90+
-write-timeout <int> write timeout milliseconds
91+
92+
-time <int> run time in seconds
93+
-shutdown-time <int> graceful shutdown time in seconds
94+
```
95+
96+
## Authentication
97+
98+
Workload using anonymous credentials.
99+
100+
## What's inside
101+
When running `run` command, the program creates three jobs: `readJob`, `writeJob`, `metricsJob`.
102+
103+
- `readJob` reads rows from the table one by one with random identifiers generated by writeJob
104+
- `writeJob` generates and inserts rows
105+
- `metricsJob` periodically sends metrics to Prometheus
106+
107+
Table have these fields:
108+
- `id Uint64`
109+
- `hash Uint64 Digest::NumericHash(id)`
110+
- `payload_str UTF8`
111+
- `payload_double Double`
112+
- `payload_timestamp Timestamp`
113+
- `payload_hash Uint64`
114+
115+
Primary key: `("hash", "id")`
116+
117+
## Collected metrics
118+
- `oks` - amount of OK requests
119+
- `not_oks` - amount of not OK requests
120+
- `inflight` - amount of requests in flight
121+
- `latency` - summary of latencies in ms
122+
- `attempts` - summary of amount for request
123+
- `error` - amount of errors
124+
125+
> You must reset metrics to keep them `0` in prometheus and grafana before beginning and after ending of jobs
126+
127+
In `php` it looks like that:
128+
```php
129+
$pushGateway->delete('workload-php', [
130+
'sdk' => 'php',
131+
'sdkVersion' => Ydb::VERSION
132+
]);
133+
```
134+
135+
## Look at metrics in grafana
136+
You can get dashboard used in that test [here](https://github.com/ydb-platform/slo-tests/blob/main/k8s/helms/grafana.yaml#L69) - you will need to import json into grafana.

slo-workload/composer.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "ydb-platform/ydb-php-slo",
3+
"description": "YDB PHP SDK",
4+
"license": "Apache-2.0",
5+
"authors": [
6+
{
7+
"name": "Ilia Kharev",
8+
"email": "ilyakharev@ydb.tech"
9+
}
10+
],
11+
"repositories": [
12+
{
13+
"type": "path",
14+
"url": "./../"
15+
}
16+
],
17+
"require": {
18+
"ydb-platform/ydb-php-sdk": "@dev",
19+
"promphp/prometheus_push_gateway_php": "^v1.0.1",
20+
"ext-sysvmsg": "*"
21+
},
22+
"autoload": {
23+
"psr-4": {
24+
"YdbPlatform\\Ydb\\Slo\\": "src/"
25+
}
26+
}
27+
}

slo-workload/php-grpc.Dockerfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
FROM ubuntu:20.04
2+
LABEL authors="ilyakharev"
3+
4+
RUN apt-get upgrade
5+
RUN apt-get update
6+
RUN apt-get install -y software-properties-common
7+
RUN apt-get update
8+
RUN add-apt-repository -y ppa:ondrej/php
9+
RUN apt-get update
10+
RUN apt-get install -y libz-dev
11+
RUN apt-get update
12+
RUN apt-get install -y php7.2-fpm php7.2-cli php7.2-curl php7.2-json php-pear php7.2-dev php7.2-bcmath
13+
RUN apt-get install -y php7.2-xml
14+
RUN apt-get update
15+
RUN curl -sS https://getcomposer.org/installer | php
16+
RUN mv composer.phar /usr/local/bin/composer
17+
RUN pecl install grpc-1.45.0
18+
RUN echo "extension=grpc.so" >> /etc/php/7.2/cli/php.ini
19+
RUN apt-get install --fix-missing -y git
20+
RUN echo "grpc.enable_fork_support = 1" >> /etc/php/7.2/cli/php.ini
21+
RUN echo "grpc.poll_strategy = poll" >> /etc/php/7.2/cli/php.ini

slo-workload/src/Command.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace YdbPlatform\Ydb\Slo;
4+
5+
abstract class Command
6+
{
7+
public $name = "";
8+
public $description = "";
9+
public $options = [];
10+
11+
12+
public abstract function execute(string $endpoint, string $path, array $options);
13+
14+
public function generateOptions(array $args): array
15+
{
16+
$result = [];
17+
for ($i = 0; $i < count($args) - 1; $i++) {
18+
if (substr($args[$i], 0, 1) != "-") continue;
19+
if (substr($args[$i + 1], 0, 1) == "-") continue;
20+
$arg = substr($args[$i], 1);
21+
$option = null;
22+
foreach ($this->options as $opt) {
23+
if (in_array($arg, $opt["alias"])) {
24+
$option = $opt;
25+
break;
26+
}
27+
}
28+
if ($option) {
29+
$result[$opt["alias"][0]] = $args[$i + 1];
30+
}
31+
}
32+
return $result;
33+
}
34+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace YdbPlatform\Ydb\Slo\Commands;
4+
5+
use YdbPlatform\Ydb\Session;
6+
use YdbPlatform\Ydb\Slo\Defaults;
7+
use YdbPlatform\Ydb\Slo\Utils;
8+
9+
class CleanupCommand extends \YdbPlatform\Ydb\Slo\Command
10+
{
11+
12+
public $name = "cleanup";
13+
public $description = "drops table in database";
14+
public $options = [
15+
[
16+
"alias" => ["t", "table-name"],
17+
"type" => "string",
18+
"description" => "table name to create"
19+
],
20+
[
21+
"alias" => ["c", "initial-data-count"],
22+
"type" => "int",
23+
"description" => "table name to create"
24+
]
25+
];
26+
public $help = "cleanup <endpoint> <db> [options]
27+
Arguments:
28+
endpoint YDB endpoint to connect to
29+
db YDB database to connect to
30+
31+
Options:
32+
-t -table-name <string> table name to create
33+
34+
-write-timeout <int> write timeout milliseconds";
35+
36+
public function execute(string $endpoint, string $path, array $options)
37+
{
38+
$tableName = $options["table-name"] ?? Defaults::TABLE_NAME;
39+
40+
$ydb = Utils::initDriver($endpoint, $path, "cleanup");
41+
42+
$table = $ydb->table();
43+
44+
$ydb->table()->getLogger()->info("Drop table", [
45+
"tableName" => $tableName
46+
]);
47+
48+
$table->retrySession(function (Session $session) use ($tableName) {
49+
$session->dropTable($tableName);
50+
}, true);
51+
52+
$ydb->table()->getLogger()->info("Dropped table", [
53+
"tableName" => $tableName
54+
]);
55+
}
56+
57+
/**
58+
* @return string
59+
*/
60+
public function getName(): string
61+
{
62+
return $this->name;
63+
}
64+
65+
/**
66+
* @return array[]
67+
*/
68+
public function getOptions(): array
69+
{
70+
return $this->options;
71+
}
72+
73+
}

0 commit comments

Comments
 (0)