Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

performance monitor package #2046

Merged
merged 10 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions cmds/modules/noded/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package noded
import (
"context"
"crypto/ed25519"
"encoding/json"
"fmt"
"os/exec"
"strings"
Expand All @@ -19,6 +20,7 @@ import (
"github.com/threefoldtech/zos/pkg/environment"
"github.com/threefoldtech/zos/pkg/events"
"github.com/threefoldtech/zos/pkg/monitord"
"github.com/threefoldtech/zos/pkg/perf"
"github.com/threefoldtech/zos/pkg/registrar"
"github.com/threefoldtech/zos/pkg/stubs"
"github.com/threefoldtech/zos/pkg/utils"
Expand Down Expand Up @@ -193,6 +195,29 @@ func action(cli *cli.Context) error {
return hypervisor, nil
})

log.Info().Msg("start perf scheduler")

perfMon, err := perf.NewPerformanceMonitor(msgBrokerCon)
if err != nil {
return errors.Wrap(err, "failed to create a new perfMon")
}

if err = perfMon.Run(ctx); err != nil {
return errors.Wrap(err, "failed to run the scheduler")
}
bus.WithHandler("zos.perf.get", func(ctx context.Context, payload []byte) (interface{}, error) {
var taskName string
err := json.Unmarshal(payload, &taskName)
if err != nil {
return nil, errors.Wrapf(err, "failed to unmarshal payload: %v", payload)
}

return perfMon.Get(taskName)
})
bus.WithHandler("zos.perf.get_all", func(ctx context.Context, payload []byte) (interface{}, error) {
return perfMon.GetAll()
})

// answer calls for dmi
go func() {
if err := bus.Run(ctx); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion docs/development/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- [Starting a local zos node](#starting-a-local-zos-node)
- [Accessing node](#accessing-node)
- [Development](#development)
- [Qemu docs](../../qemu/README.md)

## Starting a local zos node

Expand All @@ -19,7 +20,7 @@ Then, inside zos repository
make -C cmds
cd qemu
mv <downloaded image path> ./zos.efi
sudo ./vm.sh -n myzos-01 -c "farmer_id=<your farm id here> printk.devmsg=on runmode=dev"
sudo ./vm.sh -n node-01 -c "farmer_id=<your farm id here> printk.devmsg=on runmode=dev"
```

You should see the qemu console and boot logs, wait for awhile and you can [browse farms](https://dashboard.dev.grid.tf/explorer/farms) to see your node is added/detected automatically.
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ require (
github.com/diskfs/go-diskfs v1.2.0
github.com/fsnotify/fsnotify v1.6.0
github.com/g0rbe/go-chattr v0.0.0-20190906133247-aa435a6a0a37
github.com/garyburd/redigo v1.6.2
github.com/gizak/termui/v3 v3.1.0
github.com/go-co-op/gocron v1.33.1
github.com/go-redis/redis v6.15.9+incompatible
github.com/gomodule/redigo v1.8.9
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
Expand Down Expand Up @@ -74,7 +76,6 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/ethereum/go-ethereum v1.11.6 // indirect
github.com/garyburd/redigo v1.6.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/goccy/go-json v0.4.8 // indirect
Expand Down Expand Up @@ -121,6 +122,7 @@ require (
github.com/pkg/xattr v0.4.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rs/cors v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/safchain/ethtool v0.0.0-20201023143004-874930cb3ce0 // indirect
Expand All @@ -136,6 +138,7 @@ require (
github.com/xxtea/xxtea-go v0.0.0-20170828040851-35c4b17eecf6 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/text v0.12.0 // indirect
Expand Down
11 changes: 11 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
Expand Down Expand Up @@ -156,6 +157,8 @@ github.com/garyburd/redigo v1.6.2/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc=
github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY=
github.com/go-co-op/gocron v1.33.1 h1:wjX+Dg6Ae29a/f9BSQjY1Rl+jflTpW9aDyMqseCj78c=
github.com/go-co-op/gocron v1.33.1/go.mod h1:NLi+bkm4rRSy1F8U7iacZOz0xPseMoIOnvabGoSe/no=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
Expand Down Expand Up @@ -292,6 +295,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand Down Expand Up @@ -413,6 +417,7 @@ github.com/pierrec/lz4 v2.3.0+incompatible h1:CZzRn4Ut9GbUkHlQ7jqBXeZQV41ZSKWFc3
github.com/pierrec/lz4 v2.3.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/xxHash v0.1.5 h1:n/jBpwTHiER4xYvK3/CdPVnLDPchj8eTJFFLUb4QHBo=
github.com/pierrec/xxHash v0.1.5/go.mod h1:w2waW5Zoa/Wc4Yqe0wgrIYAGKqRMf7czn2HNKXmuL+I=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand All @@ -437,9 +442,13 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE=
Expand Down Expand Up @@ -558,6 +567,8 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
Expand Down
39 changes: 39 additions & 0 deletions pkg/perf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Perf

Perf is a performance test module that is scheduled to run and cache those tests results in redis which can be retrieved later over RMB call.

Perf tests are monitored by `noded` service from zos modules.

### Usage Example

1. Create a task that implement `Task` interface

```go
type LoggingTask struct {
TaskID string
Schedule string // should be in cron syntax with seconds ("* 0 * * * *")
}

func (t *LoggingTask) ID() string {
return t.TaskID
}

func (t *LoggingTask) Cron() string {
return t.Schedule
}

// a simple task that returns a string with the current time
func (t *LoggingTask) Run(ctx context.Context) (interface{}, error) {
result := fmt.Sprintf("time is: %v", time.Now())
return result, nil
}
```

2. Add the created task to scheduler

```go
perfMon.AddTask(&perf.LoggingTask{
TaskID: "LoggingTask",
Schedule: "* 0 * * * *", // when minutes is 0 (aka: every hour)
})
```
121 changes: 121 additions & 0 deletions pkg/perf/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package perf

import (
"context"
"encoding/json"
"fmt"

"github.com/garyburd/redigo/redis"
"github.com/pkg/errors"
)

const (
moduleName = "perf"
)

var (
ErrResultNotFound = errors.New("result not found")
)

// TaskResult the result test schema
type TaskResult struct {
Name string `json:"name"`
Timestamp uint64 `json:"timestamp"`
Result interface{} `json:"result"`
}

// generateKey is helper method to add moduleName as prefix for the taskName
func generateKey(taskName string) string {
return fmt.Sprintf("%s.%s", moduleName, taskName)
}

// setCache set result in redis
func (pm *PerformanceMonitor) setCache(ctx context.Context, result TaskResult) error {
data, err := json.Marshal(result)
if err != nil {
return errors.Wrap(err, "failed to marshal data to JSON")
}

conn := pm.pool.Get()
defer conn.Close()

_, err = conn.Do("SET", generateKey(result.Name), data)
return err
}

// get directly gets result for some key
func get(conn redis.Conn, key string) (TaskResult, error) {
var res TaskResult

data, err := conn.Do("GET", key)
if err != nil {
return res, errors.Wrap(err, "failed to get the result")
}

if data == nil {
return res, ErrResultNotFound
}

err = json.Unmarshal(data.([]byte), &res)
if err != nil {
return res, errors.Wrap(err, "failed to unmarshal data from json")
}

return res, nil
}

// Get gets data from redis
func (pm *PerformanceMonitor) Get(taskName string) (TaskResult, error) {
conn := pm.pool.Get()
defer conn.Close()
return get(conn, generateKey(taskName))
}

// GetAll gets the results for all the tests with moduleName as prefix
func (pm *PerformanceMonitor) GetAll() ([]TaskResult, error) {
var res []TaskResult

conn := pm.pool.Get()
defer conn.Close()

var keys []string

cursor := 0
for {
values, err := redis.Values(conn.Do("SCAN", cursor, "MATCH", generateKey("*")))
if err != nil {
return nil, err
}

_, err = redis.Scan(values, &cursor, &keys)
if err != nil {
return nil, err
}

for _, key := range keys {
result, err := get(conn, key)
if err != nil {
continue
}
res = append(res, result)
}

if cursor == 0 {
break
}

}
return res, nil
}

// exists check if a key exists
func (pm *PerformanceMonitor) exists(key string) (bool, error) {
conn := pm.pool.Get()
defer conn.Close()

ok, err := redis.Bool(conn.Do("EXISTS", generateKey(key)))
if err != nil {
return false, errors.Wrapf(err, "error checking if key %s exists", generateKey(key))
}
return ok, nil
}
Loading