├── README.md
├── docker-compose.yml
├── grafana
└── datasource.yml
├── openswoole
└── server.php
└── prometheus
└── prometheus.yml
/README.md:
--------------------------------------------------------------------------------
1 | # Open Swoole Dashboard
2 |
3 | [](https://packagist.org/packages/openswoole/ide-helper)
4 | [](LICENSE)
5 | [](https://github.com/openswoole/swoole-src/stargazers)
6 | [](https://twitter.com/openswoole)
7 |
8 | This is the example repo of using Open Swoole Metrics in `v4.9.0` to bootstrap an [Open Swoole Dashboard](https://openswoole.com/dashboard) with [Metrics in Open Swoole](https://openswoole.com/docs/modules/swoole-server-stats), [Grafana](https://grafana.com/) and [Prometheus](https://prometheus.io/).
9 |
10 | Docker and Docker Compose are requried.
11 |
12 | ### Bootstrap Open Swoole Dashboard
13 |
14 | Make sure openswoole version >= 4.9.0:
15 |
16 | ```bash
17 | docker pull openswoole/swoole:latest
18 | docker run --rm openswoole/swoole:latest php --ri openswoole
19 | ```
20 |
21 | Start the demo server and dashboard:
22 |
23 | ```bash
24 | git clone git@github.com:openswoole/dashboard.git
25 | cd dashboard
26 | docker-compose up
27 | ```
28 |
29 | ### Open Swoole Metrics
30 |
31 | Find /metrics output at `http://127.0.0.1:9501/metrics`
32 |
33 | ### Prometheus UI
34 |
35 | Find Prometheus server at `http://127.0.0.1:9090/`
36 |
37 |
38 |
39 | ### Grafana Dashboard
40 |
41 | 1. Find `http://127.0.0.1:3000/login`, the default username and password are `openswoole:openswoole`.
42 | 2. Import Open Swoole Dashboard at `http://127.0.0.1:3000/dashboard/import`, enter ID `15418` and hit load button.
43 | 3. Send some traffic with wrk using `wrk -t4 -c16 -d5 --latency http://127.0.0.1:9501/`
44 | 4. Have fun with OpenSwoole Dashboard
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | openswoole:
3 | image: openswoole/swoole:latest
4 | container_name: openswoole
5 | ports:
6 | - 9501:9501
7 | volumes:
8 | - ./openswoole:/var/www
9 | prometheus:
10 | image: prom/prometheus
11 | container_name: prometheus
12 | command:
13 | - '--config.file=/etc/prometheus/prometheus.yml'
14 | ports:
15 | - 9090:9090
16 | restart: unless-stopped
17 | volumes:
18 | - ./prometheus:/etc/prometheus
19 | - prom_data:/prometheus
20 | grafana:
21 | image: grafana/grafana
22 | container_name: grafana
23 | ports:
24 | - 3000:3000
25 | restart: unless-stopped
26 | environment:
27 | - GF_SECURITY_ADMIN_USER=openswoole
28 | - GF_SECURITY_ADMIN_PASSWORD=openswoole
29 | volumes:
30 | - ./grafana:/etc/grafana/provisioning/datasources
31 | volumes:
32 | prom_data:
--------------------------------------------------------------------------------
/grafana/datasource.yml:
--------------------------------------------------------------------------------
1 | apiVersion: 1
2 |
3 | datasources:
4 | - name: Prometheus
5 | type: prometheus
6 | url: http://prometheus:9090
7 | isDefault: true
8 | access: proxy
9 | editable: true
--------------------------------------------------------------------------------
/openswoole/server.php:
--------------------------------------------------------------------------------
1 | column('name', Swoole\Table::TYPE_STRING, 64);
9 | $table->column('id', Swoole\Table::TYPE_INT, 4); //1,2,4,8
10 | $table->column('num', Swoole\Table::TYPE_FLOAT);
11 | $table->create();
12 |
13 | $table1 = new Swoole\Table(1024);
14 | $table1->column('name', Swoole\Table::TYPE_STRING, 64);
15 | $table1->column('id', Swoole\Table::TYPE_INT, 4); //1,2,4,8
16 | $table1->column('num', Swoole\Table::TYPE_FLOAT);
17 | $table1->create();
18 |
19 | $server = new Swoole\HTTP\Server("0.0.0.0", 9501);
20 | $server->set([
21 | 'worker_num' => 4,
22 | 'task_worker_num' => 10,
23 | //'max_request' => 10000,
24 | //'max_request_grace' => 0,
25 | ]);
26 |
27 | $process = new Swoole\Process(function($process) use ($server)
28 | {
29 | while(true)
30 | {
31 | $msg = $process->read();
32 |
33 | foreach($server->connections as $conn)
34 | {
35 | $server->send($conn, $msg);
36 | }
37 | }
38 | });
39 |
40 | $server->addProcess($process);
41 |
42 | $server->on("Start", function(Server $server)
43 | {
44 | echo "Open Swoole server is started at http://0.0.0.0:9501\n";
45 | });
46 |
47 | class A {
48 | public string $a = '';
49 |
50 | function __construct() {
51 | $this->a = str_repeat('abcd', 1000);
52 | }
53 | };
54 |
55 | $server->on("Request", function(Request $request, Response $response) use ($server)
56 | {
57 | // memory leak example
58 | // global $c;
59 | // $c[] = new A();
60 | // Notice: add ACL rules and don't expose the metrics to the internet
61 | $response->header("Content-Type", "text/plain");
62 | return $response->end($server->stats(\OPENSWOOLE_STATS_OPENMETRICS));
63 |
64 | });
65 |
66 | $server->on('Task', function (Swoole\Server $server, $task_id, $reactorId, $data)
67 | {
68 | echo "Task Worker Process received data";
69 | echo "#{$server->worker_id}\tonTask: [PID={$server->worker_pid}]: task_id=$task_id, data_len=" . strlen($data) . "." . PHP_EOL;
70 | $server->finish($data);
71 | });
72 |
73 | $server->start();
--------------------------------------------------------------------------------
/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 | scrape_timeout: 10s
4 | evaluation_interval: 15s
5 | alerting:
6 | alertmanagers:
7 | - static_configs:
8 | - targets: []
9 | scheme: http
10 | timeout: 10s
11 | api_version: v1
12 | scrape_configs:
13 | - job_name: prometheus
14 | honor_timestamps: true
15 | scrape_interval: 15s
16 | scrape_timeout: 10s
17 | metrics_path: /metrics
18 | scheme: http
19 | static_configs:
20 | - targets:
21 | - localhost:9090
22 | - job_name: openswoole
23 | honor_timestamps: true
24 | scrape_interval: 15s
25 | scrape_timeout: 10s
26 | metrics_path: /metrics
27 | scheme: http
28 | static_configs:
29 | - targets:
30 | - openswoole:9501
--------------------------------------------------------------------------------