Added profile purge endpoint
This commit is contained in:
@@ -63,6 +63,17 @@ func (p *Profiler) Hits(s Sort) Hits {
|
||||
return ll
|
||||
}
|
||||
|
||||
func (p *Profiler) Purge(f *PurgeFilter) {
|
||||
if f.RouteID == 0 {
|
||||
p.l = make(Hits, 0)
|
||||
return
|
||||
}
|
||||
|
||||
p.l = p.l.Filter(func(k string, v *Hit) bool {
|
||||
return v.Route != f.RouteID
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Profiler) id(r *h.Request) string {
|
||||
return r.URL.Path
|
||||
}
|
||||
|
||||
@@ -111,3 +111,53 @@ func Test_ApigwProfiler_filterHit(t *testing.T) {
|
||||
req.True(found)
|
||||
req.Len(list[id], 1)
|
||||
}
|
||||
|
||||
func Test_ApigwProfiler_purgeAll(t *testing.T) {
|
||||
var (
|
||||
pp = New()
|
||||
req = require.New(t)
|
||||
|
||||
now = time.Date(2022, time.March, 1, 1, 1, 1, 0, time.UTC)
|
||||
then = now.Add(-1 * day)
|
||||
later = now.Add(day)
|
||||
|
||||
hr, _ = h.NewRequest(httptest.NewRequest("POST", "/foo", strings.NewReader(`foo`)))
|
||||
hr2, _ = h.NewRequest(httptest.NewRequest("GET", "/bar", strings.NewReader(`foo`)))
|
||||
)
|
||||
|
||||
pp.Push(&Hit{R: hr, Ts: &then})
|
||||
pp.Push(&Hit{R: hr, Ts: &now})
|
||||
pp.Push(&Hit{R: hr2, Ts: &now})
|
||||
pp.Push(&Hit{R: hr2, Ts: &later})
|
||||
pp.Push(&Hit{R: hr2, Ts: &later})
|
||||
|
||||
req.Len(pp.l, 2)
|
||||
pp.Purge(&PurgeFilter{})
|
||||
req.Len(pp.l, 0)
|
||||
}
|
||||
|
||||
func Test_ApigwProfiler_purgeRoute(t *testing.T) {
|
||||
var (
|
||||
pp = New()
|
||||
req = require.New(t)
|
||||
|
||||
now = time.Date(2022, time.March, 1, 1, 1, 1, 0, time.UTC)
|
||||
then = now.Add(-1 * day)
|
||||
later = now.Add(day)
|
||||
|
||||
hr, _ = h.NewRequest(httptest.NewRequest("POST", "/foo", strings.NewReader(`foo`)))
|
||||
hr2, _ = h.NewRequest(httptest.NewRequest("GET", "/bar", strings.NewReader(`foo`)))
|
||||
)
|
||||
|
||||
pp.Push(&Hit{Route: 1, R: hr, Ts: &then})
|
||||
pp.Push(&Hit{Route: 1, R: hr, Ts: &now})
|
||||
pp.Push(&Hit{Route: 2, R: hr2, Ts: &now})
|
||||
pp.Push(&Hit{Route: 2, R: hr2, Ts: &later})
|
||||
pp.Push(&Hit{Route: 2, R: hr2, Ts: &later})
|
||||
|
||||
req.Len(pp.l, 2)
|
||||
|
||||
pp.Purge(&PurgeFilter{RouteID: 2})
|
||||
|
||||
req.Len(pp.l, 1)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package profiler
|
||||
|
||||
type (
|
||||
PurgeFilter struct {
|
||||
RouteID uint64
|
||||
}
|
||||
)
|
||||
@@ -2084,6 +2084,15 @@ endpoints:
|
||||
title: Hit details
|
||||
path: "/hit/{hitID}"
|
||||
parameters: { path: [ { name: hitID, type: string, required: true, title: "Hit ID" } ] }
|
||||
- name: purge all
|
||||
method: POST
|
||||
title: Purge all profiler hits
|
||||
path: "/purge"
|
||||
- name: purge
|
||||
method: POST
|
||||
title: Purge route profiler hits
|
||||
path: "/purge/{routeID}"
|
||||
parameters: { path: [ { name: routeID, type: "uint64", title: "Route ID", required: true } ] }
|
||||
|
||||
- title: Locale
|
||||
entrypoint: locale
|
||||
|
||||
@@ -3,6 +3,7 @@ package rest
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/apigw/profiler"
|
||||
"github.com/cortezaproject/corteza/server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza/server/system/rest/request"
|
||||
"github.com/cortezaproject/corteza/server/system/service"
|
||||
@@ -13,6 +14,7 @@ type (
|
||||
profilerService interface {
|
||||
Hits(context.Context, types.ApigwProfilerFilter) (types.ApigwProfilerHitSet, types.ApigwProfilerFilter, error)
|
||||
HitsAggregated(context.Context, types.ApigwProfilerFilter) (types.ApigwProfilerAggregationSet, types.ApigwProfilerFilter, error)
|
||||
Purge(context.Context, *profiler.PurgeFilter)
|
||||
}
|
||||
|
||||
ApigwProfiler struct {
|
||||
@@ -109,6 +111,26 @@ func (ctrl *ApigwProfiler) Hit(ctx context.Context, r *request.ApigwProfilerHit)
|
||||
return ctrl.makeRoutePayload(ctx, set[0], err)
|
||||
}
|
||||
|
||||
func (ctrl *ApigwProfiler) PurgeAll(ctx context.Context, r *request.ApigwProfilerPurgeAll) (_ interface{}, _ error) {
|
||||
var (
|
||||
f = &profiler.PurgeFilter{}
|
||||
)
|
||||
|
||||
ctrl.svc.Purge(ctx, f)
|
||||
return
|
||||
}
|
||||
|
||||
func (ctrl *ApigwProfiler) Purge(ctx context.Context, r *request.ApigwProfilerPurge) (_ interface{}, _ error) {
|
||||
var (
|
||||
f = &profiler.PurgeFilter{
|
||||
RouteID: r.RouteID,
|
||||
}
|
||||
)
|
||||
|
||||
ctrl.svc.Purge(ctx, f)
|
||||
return
|
||||
}
|
||||
|
||||
func (ctrl *ApigwProfiler) makePayload(ctx context.Context, q *types.ApigwProfilerAggregation, err error) (*profilerHitPayload, error) {
|
||||
if err != nil || q == nil {
|
||||
return nil, err
|
||||
|
||||
@@ -22,6 +22,8 @@ type (
|
||||
Aggregation(context.Context, *request.ApigwProfilerAggregation) (interface{}, error)
|
||||
Route(context.Context, *request.ApigwProfilerRoute) (interface{}, error)
|
||||
Hit(context.Context, *request.ApigwProfilerHit) (interface{}, error)
|
||||
PurgeAll(context.Context, *request.ApigwProfilerPurgeAll) (interface{}, error)
|
||||
Purge(context.Context, *request.ApigwProfilerPurge) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
@@ -29,6 +31,8 @@ type (
|
||||
Aggregation func(http.ResponseWriter, *http.Request)
|
||||
Route func(http.ResponseWriter, *http.Request)
|
||||
Hit func(http.ResponseWriter, *http.Request)
|
||||
PurgeAll func(http.ResponseWriter, *http.Request)
|
||||
Purge func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -80,6 +84,38 @@ func NewApigwProfiler(h ApigwProfilerAPI) *ApigwProfiler {
|
||||
return
|
||||
}
|
||||
|
||||
api.Send(w, r, value)
|
||||
},
|
||||
PurgeAll: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewApigwProfilerPurgeAll()
|
||||
if err := params.Fill(r); err != nil {
|
||||
api.Send(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.PurgeAll(r.Context(), params)
|
||||
if err != nil {
|
||||
api.Send(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
api.Send(w, r, value)
|
||||
},
|
||||
Purge: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewApigwProfilerPurge()
|
||||
if err := params.Fill(r); err != nil {
|
||||
api.Send(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Purge(r.Context(), params)
|
||||
if err != nil {
|
||||
api.Send(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
api.Send(w, r, value)
|
||||
},
|
||||
}
|
||||
@@ -91,5 +127,7 @@ func (h ApigwProfiler) MountRoutes(r chi.Router, middlewares ...func(http.Handle
|
||||
r.Get("/apigw/profiler/", h.Aggregation)
|
||||
r.Get("/apigw/profiler/route/{routeID}", h.Route)
|
||||
r.Get("/apigw/profiler/hit/{hitID}", h.Hit)
|
||||
r.Post("/apigw/profiler/purge", h.PurgeAll)
|
||||
r.Post("/apigw/profiler/purge/{routeID}", h.Purge)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -88,6 +88,16 @@ type (
|
||||
// Hit ID
|
||||
HitID string
|
||||
}
|
||||
|
||||
ApigwProfilerPurgeAll struct {
|
||||
}
|
||||
|
||||
ApigwProfilerPurge struct {
|
||||
// RouteID PATH parameter
|
||||
//
|
||||
// Route ID
|
||||
RouteID uint64 `json:",string"`
|
||||
}
|
||||
)
|
||||
|
||||
// NewApigwProfilerAggregation request
|
||||
@@ -284,3 +294,54 @@ func (r *ApigwProfilerHit) Fill(req *http.Request) (err error) {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// NewApigwProfilerPurgeAll request
|
||||
func NewApigwProfilerPurgeAll() *ApigwProfilerPurgeAll {
|
||||
return &ApigwProfilerPurgeAll{}
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApigwProfilerPurgeAll) Auditable() map[string]interface{} {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *ApigwProfilerPurgeAll) Fill(req *http.Request) (err error) {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// NewApigwProfilerPurge request
|
||||
func NewApigwProfilerPurge() *ApigwProfilerPurge {
|
||||
return &ApigwProfilerPurge{}
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApigwProfilerPurge) Auditable() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"routeID": r.RouteID,
|
||||
}
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApigwProfilerPurge) GetRouteID() uint64 {
|
||||
return r.RouteID
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *ApigwProfilerPurge) Fill(req *http.Request) (err error) {
|
||||
|
||||
{
|
||||
var val string
|
||||
// path params
|
||||
|
||||
val = chi.URLParam(req, "routeID")
|
||||
r.RouteID, err = payload.ParseUint64(val), nil
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -192,6 +192,11 @@ func (svc *apigwProfiler) HitsAggregated(ctx context.Context, filter types.Apigw
|
||||
return
|
||||
}
|
||||
|
||||
func (svc *apigwProfiler) Purge(ctx context.Context, f *profiler.PurgeFilter) {
|
||||
apigw.Service().Profiler().Purge(f)
|
||||
return
|
||||
}
|
||||
|
||||
func sortAggregation(list *types.ApigwProfilerAggregationSet, filter *types.ApigwProfilerFilter) {
|
||||
for _, ff := range sortAggFields {
|
||||
fe := filter.Sort.Get(ff)
|
||||
|
||||
Reference in New Issue
Block a user