Add hooks for generating result summaries
This commit is contained in:
parent
a747b76ecf
commit
ce0e077175
|
@ -44,12 +44,12 @@ func init() {
|
||||||
time.Now().UTC().Format(time.RFC3339Nano)))
|
time.Now().UTC().Format(time.RFC3339Nano)))
|
||||||
|
|
||||||
ctl := nettests.NewController(nt, ctx, result, msmtPath)
|
ctl := nettests.NewController(nt, ctx, result, msmtPath)
|
||||||
if err := nt.Run(ctl); err != nil {
|
if err = nt.Run(ctl); err != nil {
|
||||||
log.WithError(err).Errorf("Failed to run %s", group.Label)
|
log.WithError(err).Errorf("Failed to run %s", group.Label)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err = result.Finished(ctx.DB); err != nil {
|
if err = result.Finished(ctx.DB, group.Summary); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -12,6 +12,12 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ResultSummaryFunc is the function used to generate result summaries
|
||||||
|
type ResultSummaryFunc func(SummaryMap) (string, error)
|
||||||
|
|
||||||
|
// SummaryMap contains a mapping from test name to serialized summary for it
|
||||||
|
type SummaryMap map[string]string
|
||||||
|
|
||||||
// UpdateOne will run the specified update query and check that it only affected one row
|
// UpdateOne will run the specified update query and check that it only affected one row
|
||||||
func UpdateOne(db *sqlx.DB, query string, arg interface{}) error {
|
func UpdateOne(db *sqlx.DB, query string, arg interface{}) error {
|
||||||
res, err := db.NamedExec(query, arg)
|
res, err := db.NamedExec(query, arg)
|
||||||
|
@ -187,17 +193,43 @@ type Result struct {
|
||||||
MeasurementDir string `db:"measurement_dir"`
|
MeasurementDir string `db:"measurement_dir"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeSummaryMap return a mapping of test names to summaries for the given
|
||||||
|
// result
|
||||||
|
func MakeSummaryMap(db *sqlx.DB, r *Result) (SummaryMap, error) {
|
||||||
|
summaryMap := SummaryMap{}
|
||||||
|
|
||||||
|
msmts := []Measurement{}
|
||||||
|
// XXX maybe we only want to select some of the columns
|
||||||
|
err := db.Select(&msmts, "SELECT name, summary FROM measurements WHERE result_id = $1", r.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to get measurements")
|
||||||
|
}
|
||||||
|
for _, msmt := range msmts {
|
||||||
|
summaryMap[msmt.Name] = msmt.Summary
|
||||||
|
}
|
||||||
|
return summaryMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Finished marks the result as done and sets the runtime
|
// Finished marks the result as done and sets the runtime
|
||||||
func (r *Result) Finished(db *sqlx.DB) error {
|
func (r *Result) Finished(db *sqlx.DB, makeSummary ResultSummaryFunc) error {
|
||||||
if r.Done == true || r.Runtime != 0 {
|
if r.Done == true || r.Runtime != 0 {
|
||||||
return errors.New("Result is already finished")
|
return errors.New("Result is already finished")
|
||||||
}
|
}
|
||||||
r.Runtime = time.Now().UTC().Sub(r.StartTime).Seconds()
|
r.Runtime = time.Now().UTC().Sub(r.StartTime).Seconds()
|
||||||
r.Done = true
|
r.Done = true
|
||||||
// XXX add in here functionality to compute the summary
|
// XXX add in here functionality to compute the summary
|
||||||
|
summaryMap, err := MakeSummaryMap(db, r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
err := UpdateOne(db, `UPDATE results
|
r.Summary, err = makeSummary(summaryMap)
|
||||||
SET done = :done, runtime = :runtime
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = UpdateOne(db, `UPDATE results
|
||||||
|
SET done = :done, runtime = :runtime, summary = :summary
|
||||||
WHERE id = :id`, r)
|
WHERE id = :id`, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "updating finished result")
|
return errors.Wrap(err, "updating finished result")
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package groups
|
package groups
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/apex/log"
|
||||||
|
"github.com/openobservatory/gooni/internal/database"
|
||||||
"github.com/openobservatory/gooni/nettests"
|
"github.com/openobservatory/gooni/nettests"
|
||||||
"github.com/openobservatory/gooni/nettests/performance"
|
"github.com/openobservatory/gooni/nettests/performance"
|
||||||
"github.com/openobservatory/gooni/nettests/websites"
|
"github.com/openobservatory/gooni/nettests/websites"
|
||||||
|
@ -10,7 +14,15 @@ import (
|
||||||
type NettestGroup struct {
|
type NettestGroup struct {
|
||||||
Label string
|
Label string
|
||||||
Nettests []nettests.Nettest
|
Nettests []nettests.Nettest
|
||||||
Summary func(s string) string
|
Summary database.ResultSummaryFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PerformanceSummary is the result summary for a performance test
|
||||||
|
type PerformanceSummary struct {
|
||||||
|
Upload int64
|
||||||
|
Download int64
|
||||||
|
Ping float64
|
||||||
|
Bitrate int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NettestGroups that can be run by the user
|
// NettestGroups that can be run by the user
|
||||||
|
@ -20,8 +32,8 @@ var NettestGroups = map[string]NettestGroup{
|
||||||
Nettests: []nettests.Nettest{
|
Nettests: []nettests.Nettest{
|
||||||
websites.WebConnectivity{},
|
websites.WebConnectivity{},
|
||||||
},
|
},
|
||||||
Summary: func(s string) string {
|
Summary: func(m database.SummaryMap) (string, error) {
|
||||||
return "{}"
|
return "{}", nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"performance": NettestGroup{
|
"performance": NettestGroup{
|
||||||
|
@ -30,22 +42,46 @@ var NettestGroups = map[string]NettestGroup{
|
||||||
performance.Dash{},
|
performance.Dash{},
|
||||||
performance.NDT{},
|
performance.NDT{},
|
||||||
},
|
},
|
||||||
Summary: func(s string) string {
|
Summary: func(m database.SummaryMap) (string, error) {
|
||||||
return "{}"
|
var (
|
||||||
|
err error
|
||||||
|
ndtSummary performance.NDTSummary
|
||||||
|
dashSummary performance.DashSummary
|
||||||
|
summary PerformanceSummary
|
||||||
|
)
|
||||||
|
err = json.Unmarshal([]byte(m["Dash"]), &dashSummary)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("failed to unmarshal Dash summary")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal([]byte(m["Ndt"]), &ndtSummary)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("failed to unmarshal Dash summary")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
summary.Bitrate = dashSummary.Bitrate
|
||||||
|
summary.Download = ndtSummary.Download
|
||||||
|
summary.Upload = ndtSummary.Upload
|
||||||
|
summary.Ping = ndtSummary.AvgRTT
|
||||||
|
summaryBytes, err := json.Marshal(summary)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(summaryBytes), nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"middleboxes": NettestGroup{
|
"middleboxes": NettestGroup{
|
||||||
Label: "Middleboxes",
|
Label: "Middleboxes",
|
||||||
Nettests: []nettests.Nettest{},
|
Nettests: []nettests.Nettest{},
|
||||||
Summary: func(s string) string {
|
Summary: func(m database.SummaryMap) (string, error) {
|
||||||
return "{}"
|
return "{}", nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"im": NettestGroup{
|
"im": NettestGroup{
|
||||||
Label: "Instant Messaging",
|
Label: "Instant Messaging",
|
||||||
Nettests: []nettests.Nettest{},
|
Nettests: []nettests.Nettest{},
|
||||||
Summary: func(s string) string {
|
Summary: func(m database.SummaryMap) (string, error) {
|
||||||
return "{}"
|
return "{}", nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ type NDTSummary struct {
|
||||||
Upload int64
|
Upload int64
|
||||||
Download int64
|
Download int64
|
||||||
Ping int64
|
Ping int64
|
||||||
MaxRTT int64
|
MaxRTT float64
|
||||||
AvgRTT int64
|
AvgRTT float64
|
||||||
MinRTT int64
|
MinRTT float64
|
||||||
MSS int64
|
MSS int64
|
||||||
OutOfOrder int64
|
OutOfOrder int64
|
||||||
PacketLoss float64
|
PacketLoss float64
|
||||||
|
@ -39,9 +39,9 @@ func (n NDT) Summary(tk map[string]interface{}) interface{} {
|
||||||
Upload: int64(simple["upload"].(float64)),
|
Upload: int64(simple["upload"].(float64)),
|
||||||
Download: int64(simple["download"].(float64)),
|
Download: int64(simple["download"].(float64)),
|
||||||
Ping: int64(simple["ping"].(float64)),
|
Ping: int64(simple["ping"].(float64)),
|
||||||
MaxRTT: int64(advanced["max_rtt"].(float64)),
|
MaxRTT: advanced["max_rtt"].(float64),
|
||||||
AvgRTT: int64(advanced["avg_rtt"].(float64)),
|
AvgRTT: advanced["avg_rtt"].(float64),
|
||||||
MinRTT: int64(advanced["min_rtt"].(float64)),
|
MinRTT: advanced["min_rtt"].(float64),
|
||||||
MSS: int64(advanced["mss"].(float64)),
|
MSS: int64(advanced["mss"].(float64)),
|
||||||
OutOfOrder: int64(advanced["out_of_order"].(float64)),
|
OutOfOrder: int64(advanced["out_of_order"].(float64)),
|
||||||
PacketLoss: advanced["packet_loss"].(float64),
|
PacketLoss: advanced["packet_loss"].(float64),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user