Skip to content

Commit 1bc6b66

Browse files
authored
feat: add an extension to monitor via docker (#300)
Co-authored-by: rick <[email protected]>
1 parent ceebdee commit 1bc6b66

38 files changed

+2011
-77
lines changed

.github/testing/core.yaml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
name: atest
55
api: |
66
{{default "http://localhost:8080/server.Runner" (env "SERVER")}}
7+
param:
8+
name: "{{randAlpha 6}}"
79
items:
810
- name: createSuite
911
request:
1012
api: /CreateTestSuite
1113
method: POST
1214
body: |
13-
{"name": "{{randAlpha 6}}"}
15+
{"name": "{{.param.name}}"}
1416
- name: suites
1517
request:
1618
api: /GetSuites
@@ -20,18 +22,18 @@ items:
2022
api: /GetTestSuite
2123
method: POST
2224
body: |
23-
{"name": "{{randAlpha 6}}"}
25+
{"name": "{{.param.name}}"}
2426
expect:
2527
bodyFieldsExpect:
26-
name: ""
28+
name: "{{.param.name}}"
2729
api: ""
2830
- name: UpdateTestSuite
2931
request:
3032
api: /UpdateTestSuite
3133
method: POST
3234
body: |
3335
{
34-
"name": "{{index (keys .suites.data) 0}}",
36+
"name": "{{.param.name}}",
3537
"api": "{{randAlpha 6}}"}
3638
}
3739
- name: DeleteTestSuiteNotFound
@@ -48,7 +50,7 @@ items:
4850
api: /ListTestCase
4951
method: POST
5052
body: |
51-
{"name": "{{index (keys .suites.data) (randInt 0 (len (keys .suites.data)))}}"}
53+
{"name": "{{.param.name}}"}
5254
- name: list-testcases-not-found
5355
request:
5456
api: /ListTestCase
@@ -95,7 +97,7 @@ items:
9597
method: POST
9698
body: |
9799
{
98-
"TestSuite": "{{index (keys .suites.data) 0}}",
100+
"TestSuite": "{{.param.name}}",
99101
"TestCase": "{{randAlpha 6}}",
100102
"Generator": "golang"
101103
}
@@ -117,7 +119,7 @@ items:
117119
method: POST
118120
body: |
119121
{
120-
"TestSuite": "{{index (keys .suites.data) 0}}",
122+
"TestSuite": "{{.param.name}}",
121123
"Generator": "jmeter"
122124
}
123125
expect:
@@ -155,4 +157,4 @@ items:
155157
api: /DeleteTestSuite
156158
method: POST
157159
body: |
158-
{"name": "{{index (keys .suites.data) 0}}"}
160+
{"name": "{{.param.name}}"}

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-orm extensions/sto
3737
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-s3 extensions/store-s3/main.go
3838
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-etcd extensions/store-etcd/main.go
3939
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-mongodb extensions/store-mongodb/main.go
40-
RUN CGO_ENABLED=0 go build -v -a -ldflags "-w -s" -o atest-store-git extensions/store-git/main.go
40+
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-store-git extensions/store-git/main.go
41+
RUN CGO_ENABLED=0 go build -v -ldflags "-w -s" -o atest-monitor-docker extensions/monitor-docker/main.go
4142

4243
FROM docker.io/library/ubuntu:23.04
4344

@@ -59,6 +60,7 @@ COPY --from=builder /workspace/atest-store-s3 /usr/local/bin/atest-store-s3
5960
COPY --from=builder /workspace/atest-store-etcd /usr/local/bin/atest-store-etcd
6061
COPY --from=builder /workspace/atest-store-git /usr/local/bin/atest-store-git
6162
COPY --from=builder /workspace/atest-store-mongodb /usr/local/bin/atest-store-mongodb
63+
COPY --from=builder /workspace/atest-monitor-docker /usr/local/bin/atest-monitor-docker
6264
COPY --from=builder /workspace/LICENSE /LICENSE
6365
COPY --from=builder /workspace/README.md /README.md
6466

Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ build:
2020
mkdir -p bin
2121
rm -rf bin/atest
2222
CGO_ENABLED=0 go build ${TOOLEXEC} -a ${BUILD_FLAG} -o bin/${BINARY} main.go
23-
build-ext: build-ext-git build-ext-orm build-ext-s3 build-ext-etcd build-ext-mongodb
23+
build-ext: build-ext-git build-ext-orm build-ext-s3 build-ext-etcd build-ext-mongodb build-ext-monitor-docker
2424
build-ext-git:
2525
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/atest-store-git extensions/store-git/main.go
2626
build-ext-orm:
@@ -31,6 +31,8 @@ build-ext-s3:
3131
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/atest-store-s3 extensions/store-s3/main.go
3232
build-ext-mongodb:
3333
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/atest-store-mongodb extensions/store-mongodb/main.go
34+
build-ext-monitor-docker:
35+
CGO_ENABLED=0 go build -ldflags "-w -s" -o bin/atest-monitor-docker extensions/monitor-docker/main.go
3436
build-ui:
3537
cd console/atest-ui && npm i && npm run build-only
3638
embed-ui:
@@ -67,7 +69,7 @@ run-console:
6769
copy:
6870
sudo cp bin/atest /usr/local/bin/
6971
copy-ext:
70-
sudo cp bin/atest-store-* /usr/local/bin/
72+
sudo cp bin/atest-* /usr/local/bin/
7173
copy-restart: build-embed-ui
7274
atest service stop
7375
make copy
@@ -123,7 +125,8 @@ grpc:
123125
--go_out=. --go_opt=paths=source_relative \
124126
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
125127
pkg/server/server.proto \
126-
pkg/testing/remote/loader.proto
128+
pkg/testing/remote/loader.proto \
129+
pkg/runner/monitor/monitor.proto
127130
grpc-gw:
128131
protoc -I . --grpc-gateway_out . \
129132
--grpc-gateway_opt logtostderr=true \

cmd/run.go

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,22 @@ import (
3030
"io"
3131
"log"
3232
"os"
33+
"os/exec"
34+
"path/filepath"
3335
"strings"
3436
"sync"
3537
"time"
3638

3739
"github.com/linuxsuren/api-testing/pkg/apispec"
3840
"github.com/linuxsuren/api-testing/pkg/limit"
3941
"github.com/linuxsuren/api-testing/pkg/runner"
42+
"github.com/linuxsuren/api-testing/pkg/runner/monitor"
4043
"github.com/linuxsuren/api-testing/pkg/testing"
44+
fakeruntime "github.com/linuxsuren/go-fake-runtime"
4145
"github.com/spf13/cobra"
4246
"github.com/spf13/pflag"
4347
"golang.org/x/sync/semaphore"
48+
"google.golang.org/grpc"
4449
)
4550

4651
type runOption struct {
@@ -63,14 +68,15 @@ type runOption struct {
6368
level string
6469
caseItems []string
6570
githubReportOption *runner.GithubPRCommentOption
71+
monitorDocker string
6672

6773
// for internal use
6874
loader testing.Loader
6975
}
7076

7177
func newDefaultRunOption() *runOption {
7278
return &runOption{
73-
reporter: runner.NewMemoryTestReporter(),
79+
reporter: runner.NewMemoryTestReporter(nil, ""),
7480
reportWriter: runner.NewResultWriter(os.Stdout),
7581
loader: testing.NewFileLoader(),
7682
githubReportOption: &runner.GithubPRCommentOption{},
@@ -112,6 +118,7 @@ See also https://github.com/LinuxSuRen/api-testing/tree/master/sample`,
112118
flags.Int64VarP(&opt.thread, "thread", "", 1, "Threads of the execution")
113119
flags.Int32VarP(&opt.qps, "qps", "", 5, "QPS")
114120
flags.Int32VarP(&opt.burst, "burst", "", 5, "burst")
121+
flags.StringVarP(&opt.monitorDocker, "monitor-docker", "", "", "The docker container name to monitor")
115122
addGitHubReportFlags(flags, opt.githubReportOption)
116123
return
117124
}
@@ -163,16 +170,56 @@ func (o *runOption) preRunE(cmd *cobra.Command, args []string) (err error) {
163170
}
164171
}
165172

173+
if err == nil {
174+
err = o.startMonitor()
175+
}
176+
166177
o.caseItems = args
167178
return
168179
}
169180

181+
func (o *runOption) startMonitor() (err error) {
182+
if o.monitorDocker == "" {
183+
return
184+
}
185+
186+
var monitorBin string
187+
if monitorBin, err = exec.LookPath("atest-monitor-docker"); err != nil {
188+
return
189+
}
190+
191+
sockFile := os.ExpandEnv(fmt.Sprintf("$HOME/.config/atest/%s.sock", "atest-monitor-docker"))
192+
os.MkdirAll(filepath.Dir(sockFile), 0755)
193+
194+
execer := fakeruntime.DefaultExecer{}
195+
go func(socketURL, plugin string) {
196+
if err = execer.RunCommandWithIO(plugin, "", os.Stdout, os.Stderr, "server", "--socket", socketURL); err != nil {
197+
log.Printf("failed to start %s, error: %v", socketURL, err)
198+
}
199+
}(sockFile, monitorBin)
200+
201+
for i := 0; i < 6; i++ {
202+
_, fErr := os.Stat(sockFile)
203+
if fErr == nil {
204+
break
205+
}
206+
time.Sleep(time.Second)
207+
}
208+
209+
var conn *grpc.ClientConn
210+
monitorServer := fmt.Sprintf("unix://%s", sockFile)
211+
if conn, err = grpc.Dial(monitorServer, grpc.WithInsecure()); err == nil {
212+
o.reporter = runner.NewMemoryTestReporter(monitor.NewMonitorClient(conn), o.monitorDocker)
213+
}
214+
return
215+
}
216+
170217
func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
171218
o.startTime = time.Now()
172219
o.context = cmd.Context()
173220
o.limiter = limit.NewDefaultRateLimiter(o.qps, o.burst)
174221
defer func() {
175-
cmd.Printf("consume: %s\n", time.Since(o.startTime).String())
222+
cmd.Printf("\nconsume: %s\n", time.Since(o.startTime).String())
176223
o.limiter.Stop()
177224
}()
178225

@@ -195,6 +242,7 @@ func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
195242
var reportErr error
196243
var results runner.ReportResultSlice
197244
if results, reportErr = o.reporter.ExportAllReportResults(); reportErr == nil {
245+
o.reportWriter.WithResourceUsage(o.reporter.GetResourceUsage())
198246
outputErr := o.reportWriter.Output(results)
199247
println(cmd, outputErr, "failed to Output all reports", outputErr)
200248
}

docs/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,13 @@ Connect to [a vault extension](https://github.com/LinuxSuRen/api-testing-secret-
300300
atest server --secret-server localhost:7073
301301
```
302302

303+
## Application monitor
304+
You can get the resource usage in the report through Docker:
305+
306+
```shell
307+
atest run -p sample/testsuite-gitlab.yaml --monitor-docker test --report md
308+
```
309+
303310
## Verify
304311

305312
| Item | Description |
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
MIT License
3+
4+
Copyright (c) 2023 API Testing Authors.
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
*/
24+
25+
package cmd
26+
27+
import (
28+
"github.com/docker/cli/cli/command"
29+
"github.com/linuxsuren/api-testing/extensions/monitor-docker/pkg"
30+
ext "github.com/linuxsuren/api-testing/pkg/extension"
31+
"github.com/spf13/cobra"
32+
)
33+
34+
func NewRootCommand(dockerCli command.Cli) (c *cobra.Command) {
35+
opt := options{
36+
dockerCli: dockerCli,
37+
Extension: ext.NewExtension("docker", "monitor", 7074),
38+
}
39+
c = &cobra.Command{
40+
Use: "server",
41+
RunE: opt.runE,
42+
}
43+
opt.AddFlags(c.Flags())
44+
return
45+
}
46+
47+
type options struct {
48+
*ext.Extension
49+
dockerCli command.Cli
50+
}
51+
52+
func (o *options) runE(c *cobra.Command, _ []string) (err error) {
53+
remoteServer := pkg.NewRemoteServer(o.dockerCli)
54+
err = ext.CreateMonitor(o.Extension, c, remoteServer)
55+
return
56+
}

0 commit comments

Comments
 (0)