Finalize bandwidth chart endpoint

This commit is contained in:
Patrick Pacher 2023-10-10 10:04:50 +02:00 committed by Daniel
parent 1484591aea
commit ead0323e43
3 changed files with 39 additions and 42 deletions

View file

@ -19,9 +19,9 @@ type BandwidthChartHandler struct {
} }
type BandwidthChartRequest struct { type BandwidthChartRequest struct {
AllProfiles bool `json:"allProfiles"` Interval int `json:"interval"`
Profiles []string `json:"profiles"` Query Query `json:"query"`
Connections []string `json:"connections"` GroupBy []string `json:"groupBy"`
} }
func (ch *BandwidthChartHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { func (ch *BandwidthChartHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
@ -99,47 +99,45 @@ func (ch *BandwidthChartHandler) parseRequest(req *http.Request) (*BandwidthChar
} }
func (req *BandwidthChartRequest) generateSQL(ctx context.Context, schema *orm.TableSchema) (string, map[string]interface{}, error) { func (req *BandwidthChartRequest) generateSQL(ctx context.Context, schema *orm.TableSchema) (string, map[string]interface{}, error) {
selects := []string{ if req.Interval == 0 {
"(round(time/10, 0)*10) as time", req.Interval = 10
}
interval := fmt.Sprintf("round(time/%d, 0)*%d", req.Interval, req.Interval)
// make sure there are only allowed fields specified in the request group-by
for _, gb := range req.GroupBy {
def := schema.GetColumnDef(gb)
if def == nil {
return "", nil, fmt.Errorf("unsupported groupBy key: %q", gb)
}
}
selects := append([]string{
interval + " as timestamp",
"SUM(incoming) as incoming", "SUM(incoming) as incoming",
"SUM(outgoing) as outgoing", "SUM(outgoing) as outgoing",
}, req.GroupBy...)
groupBy := append([]string{interval}, req.GroupBy...)
whereClause, params, err := req.Query.toSQLWhereClause(ctx, "", schema, orm.DefaultEncodeConfig)
if err != nil {
return "", nil, err
} }
groupBy := []string{"round(time/10, 0)*10"}
whereClause := ""
params := make(map[string]any)
if (len(req.Profiles) > 0) || (req.AllProfiles == true) { if whereClause != "" {
groupBy = []string{"profile", "round(time/10, 0)*10"} whereClause = "WHERE " + whereClause
selects = append(selects, "profile")
if !req.AllProfiles {
clauses := make([]string, len(req.Profiles))
for idx, p := range req.Profiles {
key := fmt.Sprintf(":p%d", idx)
clauses[idx] = "profile = " + key
params[key] = p
}
whereClause = "WHERE " + strings.Join(clauses, " OR ")
}
} else if len(req.Connections) > 0 {
groupBy = []string{"conn_id", "round(time/10, 0)*10"}
selects = append(selects, "conn_id")
clauses := make([]string, len(req.Connections))
for idx, p := range req.Connections {
key := fmt.Sprintf(":c%d", idx)
clauses[idx] = "conn_id = " + key
params[key] = p
}
whereClause = "WHERE " + strings.Join(clauses, " OR ")
} }
template := fmt.Sprintf( template := fmt.Sprintf(
`SELECT %s FROM main.bandwidth %s GROUP BY %s ORDER BY time ASC`, `SELECT %s
FROM main.bandwidth AS bw
JOIN main.connections AS conns
ON bw.conn_id = conns.id
%s
GROUP BY %s
ORDER BY time ASC`,
strings.Join(selects, ", "), strings.Join(selects, ", "),
whereClause, whereClause,
strings.Join(groupBy, ", "), strings.Join(groupBy, ", "),

View file

@ -301,7 +301,6 @@ func (db *Database) ApplyMigrations() error {
bwSchema := `CREATE TABLE IF NOT EXISTS main.bandwidth ( bwSchema := `CREATE TABLE IF NOT EXISTS main.bandwidth (
conn_id TEXT NOT NULL, conn_id TEXT NOT NULL,
profile TEXT NOT NULL,
time INTEGER NOT NULL, time INTEGER NOT NULL,
incoming INTEGER NOT NULL, incoming INTEGER NOT NULL,
outgoing INTEGER NOT NULL, outgoing INTEGER NOT NULL,
@ -555,9 +554,9 @@ func (db *Database) UpdateBandwidth(ctx context.Context, enableHistory bool, pro
} }
parts := []string{} parts := []string{}
parts = append(parts, "bytes_received = :bytes_received") parts = append(parts, "bytes_received = (bytes_received + :bytes_received)")
params[":bytes_received"] = bytesReceived params[":bytes_received"] = bytesReceived
parts = append(parts, "bytes_sent = :bytes_sent") parts = append(parts, "bytes_sent = (bytes_sent + :bytes_sent)")
params[":bytes_sent"] = bytesSent params[":bytes_sent"] = bytesSent
updateSet := strings.Join(parts, ", ") updateSet := strings.Join(parts, ", ")
@ -581,8 +580,7 @@ func (db *Database) UpdateBandwidth(ctx context.Context, enableHistory bool, pro
// also add the date to the in-memory bandwidth database // also add the date to the in-memory bandwidth database
params[":time"] = time.Now().Unix() params[":time"] = time.Now().Unix()
params[":profile"] = profileKey stmt := "INSERT INTO main.bandwidth (conn_id, time, incoming, outgoing) VALUES(:id, :time, :bytes_received, :bytes_sent)"
stmt := "INSERT INTO main.bandwidth (conn_id, profile, time, incoming, outgoing) VALUES(:id, :profile, :time, :bytes_received, :bytes_sent)"
if err := db.ExecuteWrite(ctx, stmt, orm.WithNamedArgs(params)); err != nil { if err := db.ExecuteWrite(ctx, stmt, orm.WithNamedArgs(params)); err != nil {
merr.Errors = append(merr.Errors, fmt.Errorf("failed to update main.bandwidth: %w", err)) merr.Errors = append(merr.Errors, fmt.Errorf("failed to update main.bandwidth: %w", err))
} }

View file

@ -455,6 +455,7 @@ func (query Query) toSQLWhereClause(ctx context.Context, suffix string, m *orm.T
values := query[column] values := query[column]
colDef, ok := lm[column] colDef, ok := lm[column]
if !ok { if !ok {
errs.Errors = append(errs.Errors, fmt.Errorf("column %s is not allowed", column)) errs.Errors = append(errs.Errors, fmt.Errorf("column %s is not allowed", column))
continue continue