3
0

Added global profiler setting, options to apigw handlers

This commit is contained in:
Peter Grlica 2022-03-17 14:27:11 +01:00
parent 476084a3bf
commit f33336b21d
24 changed files with 342 additions and 243 deletions

View File

@ -723,6 +723,7 @@ func updatePasswdSettings(opt options.AuthOpt, current *types.AppSettings) {
func updateApigwSettings(opt options.ApigwOpt, current *types.AppSettings) {
current.Apigw.ProfilerEnabled = opt.ProfilerEnabled
current.Apigw.ProfilerGlobal = opt.ProfilerGlobal
}
// Checks if discovery is enabled in the options

View File

@ -29,6 +29,10 @@ apigw: schema.#optionsGroup & {
type: "bool"
description: "Enable profiler"
}
profiler_global: {
type: "bool"
description: "Profiler enabled for all routes"
}
log_request_body: {
type: "bool"
description: "Enable incoming request body output in logs"

View File

@ -12,6 +12,7 @@ import (
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
errors "github.com/cortezaproject/corteza-server/pkg/errors"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/options"
)
type (
@ -55,7 +56,7 @@ type (
}
)
func NewRedirection() (e *redirection) {
func NewRedirection(opts *options.ApigwOpt) (e *redirection) {
e = &redirection{}
e.Name = "redirection"
@ -78,8 +79,12 @@ func NewRedirection() (e *redirection) {
return
}
func (h redirection) New() types.Handler {
return NewRedirection()
func (h redirection) New(opts *options.ApigwOpt) types.Handler {
return NewRedirection(opts)
}
func (h redirection) Enabled() bool {
return true
}
func (h redirection) String() string {
@ -124,7 +129,7 @@ func (h redirection) Handler() types.HandlerFunc {
}
}
func NewDefaultJsonResponse() (e *defaultJsonResponse) {
func NewDefaultJsonResponse(opts *options.ApigwOpt) (e *defaultJsonResponse) {
e = &defaultJsonResponse{}
e.Name = "defaultJsonResponse"
@ -134,8 +139,12 @@ func NewDefaultJsonResponse() (e *defaultJsonResponse) {
return
}
func (j defaultJsonResponse) New() types.Handler {
return NewDefaultJsonResponse()
func (j defaultJsonResponse) New(opts *options.ApigwOpt) types.Handler {
return NewDefaultJsonResponse(opts)
}
func (j defaultJsonResponse) Enabled() bool {
return true
}
func (j defaultJsonResponse) String() string {
@ -172,7 +181,7 @@ func checkStatus(typ string, status int) bool {
}
}
func NewJsonResponse(reg typesRegistry) (e *jsonResponse) {
func NewJsonResponse(opts *options.ApigwOpt, reg typesRegistry) (e *jsonResponse) {
e = &jsonResponse{}
e.Name = "jsonResponse"
@ -192,8 +201,12 @@ func NewJsonResponse(reg typesRegistry) (e *jsonResponse) {
return
}
func (j jsonResponse) New() types.Handler {
return NewJsonResponse(j.reg)
func (j jsonResponse) New(opts *options.ApigwOpt) types.Handler {
return NewJsonResponse(opts, j.reg)
}
func (j jsonResponse) Enabled() bool {
return true
}
func (j jsonResponse) String() string {

View File

@ -10,6 +10,7 @@ import (
agctx "github.com/cortezaproject/corteza-server/pkg/apigw/ctx"
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/options"
"github.com/stretchr/testify/require"
)
@ -34,7 +35,7 @@ func Test_redirectionMerge(t *testing.T) {
)
for _, tc := range tcc {
t.Run(tc.name, testMerge(NewRedirection(), tc))
t.Run(tc.name, testMerge(NewRedirection(&options.ApigwOpt{}), tc))
}
}
@ -74,7 +75,7 @@ func Test_redirection(t *testing.T) {
rc = httptest.NewRecorder()
)
h := getHandler(NewRedirection())
h := getHandler(NewRedirection(&options.ApigwOpt{}))
h, err := h.Merge([]byte(tc.expr))
req.NoError(err)
@ -144,7 +145,7 @@ func Test_jsonResponse(t *testing.T) {
r = r.WithContext(agctx.ScopeToContext(context.Background(), scope))
h := getHandler(NewJsonResponse(&mockHandlerRegistry{}))
h := getHandler(NewJsonResponse(&options.ApigwOpt{}, &mockHandlerRegistry{}))
h, err := h.Merge([]byte(tc.expr))
req.NoError(err)

View File

@ -13,6 +13,7 @@ import (
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
pe "github.com/cortezaproject/corteza-server/pkg/errors"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/options"
)
type (
@ -41,11 +42,12 @@ type (
}
profiler struct {
opts *options.ApigwOpt
types.FilterMeta
}
)
func NewHeader() (v *header) {
func NewHeader(opts *options.ApigwOpt) (v *header) {
v = &header{}
v.Name = "header"
@ -63,8 +65,12 @@ func NewHeader() (v *header) {
return
}
func (h header) New() types.Handler {
return NewHeader()
func (h header) New(opts *options.ApigwOpt) types.Handler {
return NewHeader(opts)
}
func (h header) Enabled() bool {
return true
}
func (h header) String() string {
@ -129,7 +135,7 @@ func (h header) Handler() types.HandlerFunc {
}
}
func NewQueryParam() (v *queryParam) {
func NewQueryParam(opts *options.ApigwOpt) (v *queryParam) {
v = &queryParam{}
v.Name = "queryParam"
@ -147,8 +153,12 @@ func NewQueryParam() (v *queryParam) {
return
}
func (qp queryParam) New() types.Handler {
return NewQueryParam()
func (qp queryParam) New(opts *options.ApigwOpt) types.Handler {
return NewQueryParam(opts)
}
func (qp queryParam) Enabled() bool {
return true
}
func (qp queryParam) String() string {
@ -213,9 +223,10 @@ func (qp *queryParam) Handler() types.HandlerFunc {
}
}
func NewProfiler() (pp *profiler) {
func NewProfiler(opts *options.ApigwOpt) (pp *profiler) {
pp = &profiler{}
pp.opts = opts
pp.Name = "profiler"
pp.Label = "Profiler"
pp.Kind = types.PreFilter
@ -223,8 +234,12 @@ func NewProfiler() (pp *profiler) {
return
}
func (pr profiler) New() types.Handler {
return NewProfiler()
func (pr profiler) New(opts *options.ApigwOpt) types.Handler {
return NewProfiler(opts)
}
func (pr profiler) Enabled() bool {
return pr.opts.ProfilerEnabled
}
func (pr profiler) String() string {
@ -246,8 +261,8 @@ func (pr *profiler) Handler() types.HandlerFunc {
scope = agctx.ScopeFromContext(ctx)
)
if scope.Opts().ProfilerEnabled {
// profiler enabled overrides any profiling prefilter
if pr.opts.ProfilerEnabled && pr.opts.ProfilerGlobal {
// profiler global overrides any profiling prefilter
// the hit is registered on lower level
return
}

View File

@ -6,6 +6,7 @@ import (
"testing"
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
"github.com/cortezaproject/corteza-server/pkg/options"
"github.com/stretchr/testify/require"
)
@ -33,7 +34,7 @@ func Test_headerMerge(t *testing.T) {
)
for _, tc := range tcc {
t.Run(tc.name, testMerge(NewHeader(), tc))
t.Run(tc.name, testMerge(NewHeader(&options.ApigwOpt{}), tc))
}
}
@ -79,7 +80,7 @@ func Test_headerHandle(t *testing.T) {
r := httptest.NewRequest(http.MethodGet, "/foo", http.NoBody)
r.Header = tc.headers
t.Run(tc.name, testHandle(NewHeader(), r, tc))
t.Run(tc.name, testHandle(NewHeader(&options.ApigwOpt{}), r, tc))
}
}
@ -111,7 +112,7 @@ func Test_queryParamMerge(t *testing.T) {
)
for _, tc := range tcc {
t.Run(tc.name, testMerge(NewQueryParam(), tc))
t.Run(tc.name, testMerge(NewQueryParam(&options.ApigwOpt{}), tc))
}
}
@ -144,7 +145,7 @@ func Test_queryParamHandle(t *testing.T) {
for _, tc := range tcc {
r := httptest.NewRequest(http.MethodGet, tc.url, http.NoBody)
t.Run(tc.name, testHandle(NewQueryParam(), r, tc))
t.Run(tc.name, testHandle(NewQueryParam(&options.ApigwOpt{}), r, tc))
}
}

View File

@ -15,6 +15,7 @@ import (
pe "github.com/cortezaproject/corteza-server/pkg/errors"
"github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/jsenv"
"github.com/cortezaproject/corteza-server/pkg/options"
"go.uber.org/zap"
)
@ -47,7 +48,7 @@ type (
}
)
func NewWorkflow(wf WfExecer) (p *workflow) {
func NewWorkflow(opts *options.ApigwOpt, wf WfExecer) (p *workflow) {
p = &workflow{}
p.d = wf
@ -67,8 +68,12 @@ func NewWorkflow(wf WfExecer) (p *workflow) {
return
}
func (h workflow) New() types.Handler {
return NewWorkflow(h.d)
func (h workflow) New(opts *options.ApigwOpt) types.Handler {
return NewWorkflow(opts, h.d)
}
func (h workflow) Enabled() bool {
return true
}
func (h workflow) String() string {
@ -147,7 +152,7 @@ func (h workflow) Handler() types.HandlerFunc {
}
}
func NewPayload(l *zap.Logger) (p *processerPayload) {
func NewPayload(opts *options.ApigwOpt, l *zap.Logger) (p *processerPayload) {
p = &processerPayload{}
p.vm = jsenv.New(jsenv.NewTransformer(jsenv.LoaderJS, jsenv.TargetES2016))
@ -171,8 +176,12 @@ func NewPayload(l *zap.Logger) (p *processerPayload) {
return
}
func (h processerPayload) New() types.Handler {
return NewPayload(h.log)
func (h processerPayload) New(opts *options.ApigwOpt) types.Handler {
return NewPayload(opts, h.log)
}
func (h processerPayload) Enabled() bool {
return true
}
func (h processerPayload) String() string {

View File

@ -78,7 +78,7 @@ func Test_processerWorkflow(t *testing.T) {
rc = httptest.NewRecorder()
rq, _ = http.NewRequest("POST", "/foo", http.NoBody)
ar, err = h.NewRequest(rq)
pp = NewWorkflow(tc.wfs)
pp = NewWorkflow(&options.ApigwOpt{}, tc.wfs)
)
_, err = pp.Merge([]byte(tc.params))
@ -173,7 +173,7 @@ func Test_processerPayload(t *testing.T) {
ar, err = h.NewRequest(tc.rq)
)
pp := NewPayload(zap.NewNop())
pp := NewPayload(&options.ApigwOpt{}, zap.NewNop())
_, err = pp.Merge([]byte(tc.params))
if tc.errv != "" {

View File

@ -14,6 +14,7 @@ import (
actx "github.com/cortezaproject/corteza-server/pkg/apigw/ctx"
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
pe "github.com/cortezaproject/corteza-server/pkg/errors"
"github.com/cortezaproject/corteza-server/pkg/options"
"go.uber.org/zap"
)
@ -45,7 +46,7 @@ type (
}
)
func New(l *zap.Logger, c *http.Client, s types.SecureStorager) (p *proxy) {
func New(opts *options.ApigwOpt, l *zap.Logger, c *http.Client, s types.SecureStorager) (p *proxy) {
p = &proxy{}
p.c = c
@ -67,8 +68,12 @@ func New(l *zap.Logger, c *http.Client, s types.SecureStorager) (p *proxy) {
return
}
func (h proxy) New() types.Handler {
return New(h.log, h.c, h.s)
func (h proxy) New(opts *options.ApigwOpt) types.Handler {
return New(opts, h.log, h.c, h.s)
}
func (h proxy) Enabled() bool {
return true
}
func (h proxy) String() string {

View File

@ -174,7 +174,7 @@ func Test_proxy(t *testing.T) {
rq = httptest.NewRequest("POST", "/foo", strings.NewReader(`custom request body`))
}
proxy := New(zap.NewNop(), c, struct{}{})
proxy := New(&options.ApigwOpt{}, zap.NewNop(), c, struct{}{})
_, err := proxy.Merge([]byte(tc.params))
req.NoError(err)

View File

@ -41,7 +41,7 @@ func helperMethodNotAllowed(opt *options.ApigwOpt, pr *profiler.Profiler) http.H
}
func addToProfiler(opt *options.ApigwOpt, pr *profiler.Profiler, r *http.Request, status int) {
if !opt.ProfilerEnabled {
if !(opt.ProfilerEnabled && opt.ProfilerGlobal) {
return
}

View File

@ -0,0 +1,79 @@
package profiler
import (
"encoding/base64"
"github.com/cortezaproject/corteza-server/system/types"
)
func FilterAggregation(list *types.ApigwProfilerAggregationSet, filter *types.ApigwProfilerFilter) {
var (
dec string = ""
i uint = 0
b = filter.Before == ""
)
if filter.Limit == 0 {
filter.Limit = FILTER_NUM_AGG_ITEMS
}
dec, _ = decodeRoutePath(filter.Before)
*list, _ = list.Filter(func(apa *types.ApigwProfilerAggregation) (bool, error) {
// after a specific hit and inside the limits
if b && i < filter.Limit {
i++
filter.Next = encodeRoutePath(apa.Path)
return true, nil
}
// after the specific hit check
if dec != "" && b == false {
b = apa.Path == dec
}
return false, nil
})
return
}
func FilterHits(list *types.ApigwProfilerHitSet, filter *types.ApigwProfilerFilter) {
var (
i uint = 0
b = filter.Before == ""
)
if filter.Limit == 0 {
filter.Limit = FILTER_NUM_ITEMS
}
*list, _ = list.Filter(func(aph *types.ApigwProfilerHit) (bool, error) {
// after a specific hit and inside the limits
if b && i < filter.Limit {
i++
filter.Next = aph.ID
return true, nil
}
// after the specific hit check
if filter.Before != "" && b == false {
b = aph.ID == filter.Before
}
return false, nil
})
return
}
func encodeRoutePath(p string) string {
return base64.URLEncoding.EncodeToString([]byte(p))
}
func decodeRoutePath(p string) (s string, err error) {
b, err := base64.URLEncoding.DecodeString(p)
s = string(b)
return
}

View File

@ -0,0 +1,16 @@
package profiler
import "net/http"
func StartHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// add some info to context
next.ServeHTTP(rw, r)
})
}
func FinishHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
next.ServeHTTP(rw, r)
})
}

View File

@ -4,11 +4,9 @@ import (
"encoding/base64"
"fmt"
"net/http"
"sort"
"time"
h "github.com/cortezaproject/corteza-server/pkg/http"
"github.com/cortezaproject/corteza-server/system/types"
)
const (
@ -19,9 +17,6 @@ const (
FILTER_NUM_AGG_ITEMS = 10
)
var sortAggFields = []string{"path", "count", "size_min", "size_max", "size_avg", "time_min", "time_max", "time_avg"}
var sortRouteFields = []string{"time_start", "time_finish", "time_duration"}
type (
Hits map[string][]*Hit
@ -48,13 +43,6 @@ type (
Ts *time.Time
Tf *time.Time
}
Sort struct {
Hit string
Path string
Size uint64
Before string
}
)
func New() *Profiler {
@ -89,7 +77,7 @@ func (p *Profiler) Push(h *Hit) (id string) {
return
}
func (p *Profiler) Dump(s Sort) Hits {
func (p *Profiler) Hits(s Sort) Hits {
ll := p.l.Filter(func(k string, v *Hit) bool {
var b bool = true
@ -131,19 +119,6 @@ func (s Hits) Filter(fn func(k string, v *Hit) bool) Hits {
return ss
}
func StartHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// add some info to context
next.ServeHTTP(rw, r)
})
}
func FinishHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
next.ServeHTTP(rw, r)
})
}
func (h Hits) Len() int {
return h.Len()
}
@ -155,147 +130,3 @@ func (h Hits) Less(i, j int) bool {
func (h Hits) Swap(i, j int) {
return
}
func SortAggregation(list *types.ApigwProfilerAggregationSet, filter *types.ApigwProfilerFilter) {
for _, ff := range sortAggFields {
fe := filter.Sort.Get(ff)
if fe == nil {
continue
}
if filter.Sort.Get(ff).Descending {
sort.Sort(sort.Reverse(getSortType(ff, list)))
break
}
sort.Sort(getSortType(ff, list))
break
}
}
func FilterAggregation(list *types.ApigwProfilerAggregationSet, filter *types.ApigwProfilerFilter) {
var (
dec string = ""
i uint = 0
b = filter.Before == ""
)
if filter.Limit == 0 {
filter.Limit = FILTER_NUM_AGG_ITEMS
}
dec, _ = decodeRoutePath(filter.Before)
*list, _ = list.Filter(func(apa *types.ApigwProfilerAggregation) (bool, error) {
// after a specific hit and inside the limits
if b && i < filter.Limit {
i++
filter.Next = encodeRoutePath(apa.Path)
return true, nil
}
// after the specific hit check
if dec != "" && b == false {
b = apa.Path == dec
}
return false, nil
})
return
}
func FilterHits(list *types.ApigwProfilerHitSet, filter *types.ApigwProfilerFilter) {
var (
i uint = 0
b = filter.Before == ""
)
if filter.Limit == 0 {
filter.Limit = FILTER_NUM_ITEMS
}
*list, _ = list.Filter(func(aph *types.ApigwProfilerHit) (bool, error) {
// after a specific hit and inside the limits
if b && i < filter.Limit {
i++
filter.Next = aph.ID
return true, nil
}
// after the specific hit check
if filter.Before != "" && b == false {
b = aph.ID == filter.Before
}
return false, nil
})
return
}
func SortHits(list *types.ApigwProfilerHitSet, filter *types.ApigwProfilerFilter) {
for _, ff := range sortRouteFields {
fe := filter.Sort.Get(ff)
if fe == nil {
continue
}
if filter.Sort.Get(ff).Descending {
sort.Sort(sort.Reverse(getSortTypeHit(ff, list)))
break
}
sort.Sort(getSortTypeHit(ff, list))
break
}
}
func getSortType(s string, list *types.ApigwProfilerAggregationSet) sort.Interface {
switch s {
case "path":
return types.ByPath(*list)
case "count":
return types.ByCount(*list)
case "size_min":
return types.BySizeMin(*list)
case "size_max":
return types.BySizeMax(*list)
case "size_avg":
return types.BySizeAvg(*list)
case "time_min":
return types.ByTimeMin(*list)
case "time_max":
return types.ByTimeMax(*list)
case "time_avg":
return types.ByTimeAvg(*list)
default:
return types.ByCount(*list)
}
}
func getSortTypeHit(s string, list *types.ApigwProfilerHitSet) sort.Interface {
switch s {
case "time_start":
return types.BySTime(*list)
case "time_finish":
return types.ByFTime(*list)
case "time_duration":
return types.ByDuration(*list)
default:
return types.BySTime(*list)
}
}
func encodeRoutePath(p string) string {
return base64.URLEncoding.EncodeToString([]byte(p))
}
func decodeRoutePath(p string) (s string, err error) {
b, err := base64.URLEncoding.DecodeString(p)
s = string(b)
return
}

View File

@ -0,0 +1,93 @@
package profiler
import (
"sort"
"github.com/cortezaproject/corteza-server/system/types"
)
var (
sortAggFields = []string{"path", "count", "size_min", "size_max", "size_avg", "time_min", "time_max", "time_avg"}
sortRouteFields = []string{"time_start", "time_finish", "time_duration"}
)
type (
Sort struct {
Hit string
Path string
Size uint64
Before string
}
)
func SortAggregation(list *types.ApigwProfilerAggregationSet, filter *types.ApigwProfilerFilter) {
for _, ff := range sortAggFields {
fe := filter.Sort.Get(ff)
if fe == nil {
continue
}
if filter.Sort.Get(ff).Descending {
sort.Sort(sort.Reverse(getSortType(ff, list)))
break
}
sort.Sort(getSortType(ff, list))
break
}
}
func SortHits(list *types.ApigwProfilerHitSet, filter *types.ApigwProfilerFilter) {
for _, ff := range sortRouteFields {
fe := filter.Sort.Get(ff)
if fe == nil {
continue
}
if filter.Sort.Get(ff).Descending {
sort.Sort(sort.Reverse(getSortTypeHit(ff, list)))
break
}
sort.Sort(getSortTypeHit(ff, list))
break
}
}
func getSortType(s string, list *types.ApigwProfilerAggregationSet) sort.Interface {
switch s {
case "path":
return types.ByPath(*list)
case "count":
return types.ByCount(*list)
case "size_min":
return types.BySizeMin(*list)
case "size_max":
return types.BySizeMax(*list)
case "size_avg":
return types.BySizeAvg(*list)
case "time_min":
return types.ByTimeMin(*list)
case "time_max":
return types.ByTimeMax(*list)
case "time_avg":
return types.ByTimeAvg(*list)
default:
return types.ByCount(*list)
}
}
func getSortTypeHit(s string, list *types.ApigwProfilerHitSet) sort.Interface {
switch s {
case "time_start":
return types.BySTime(*list)
case "time_finish":
return types.ByFTime(*list)
case "time_duration":
return types.ByDuration(*list)
default:
return types.BySTime(*list)
}
}

View File

@ -8,19 +8,22 @@ import (
"github.com/cortezaproject/corteza-server/pkg/apigw/filter"
"github.com/cortezaproject/corteza-server/pkg/apigw/filter/proxy"
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
"github.com/cortezaproject/corteza-server/pkg/options"
)
type (
Registry struct {
h map[string]types.Handler
opts *options.ApigwOpt
h map[string]types.Handler
}
secureStorageTodo struct{}
)
func NewRegistry() *Registry {
func NewRegistry(opts *options.ApigwOpt) *Registry {
return &Registry{
h: map[string]types.Handler{},
h: map[string]types.Handler{},
opts: opts,
}
}
@ -43,11 +46,15 @@ func (r *Registry) Get(identifier string) (types.Handler, error) {
return nil, fmt.Errorf("could not get element from registry: %s", identifier)
}
return f.New(), nil
return f.New(r.opts), nil
}
func (r *Registry) All() (list types.FilterMetaList) {
for _, handler := range r.h {
if !handler.Enabled() {
continue
}
meta := handler.Meta()
list = append(list, &meta)
}
@ -57,19 +64,19 @@ func (r *Registry) All() (list types.FilterMetaList) {
func (r *Registry) Preload() {
// prefilters
r.Add("queryParam", filter.NewQueryParam())
r.Add("header", filter.NewHeader())
r.Add("profiler", filter.NewProfiler())
r.Add("queryParam", filter.NewQueryParam(r.opts))
r.Add("header", filter.NewHeader(r.opts))
r.Add("profiler", filter.NewProfiler(r.opts))
// processers
r.Add("workflow", filter.NewWorkflow(NewWorkflow()))
r.Add("proxy", proxy.New(service.DefaultLogger, http.DefaultClient, secureStorageTodo{}))
r.Add("payload", filter.NewPayload(service.DefaultLogger))
r.Add("workflow", filter.NewWorkflow(r.opts, NewWorkflow()))
r.Add("proxy", proxy.New(r.opts, service.DefaultLogger, http.DefaultClient, secureStorageTodo{}))
r.Add("payload", filter.NewPayload(r.opts, service.DefaultLogger))
// postfilters
r.Add("redirection", filter.NewRedirection())
r.Add("jsonResponse", filter.NewJsonResponse(service.Registry()))
r.Add("defaultJsonResponse", filter.NewDefaultJsonResponse())
r.Add("redirection", filter.NewRedirection(r.opts))
r.Add("jsonResponse", filter.NewJsonResponse(r.opts, service.Registry()))
r.Add("defaultJsonResponse", filter.NewDefaultJsonResponse(r.opts))
}
func NewWorkflow() (wf filter.WfExecer) {

View File

@ -4,13 +4,14 @@ import (
"testing"
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
"github.com/cortezaproject/corteza-server/pkg/options"
"github.com/stretchr/testify/require"
)
func Test_registryAddGet(t *testing.T) {
var (
req = require.New(t)
r = NewRegistry()
r = NewRegistry(&options.ApigwOpt{})
)
r.Add("mockHandler", types.MockHandler{})
@ -25,7 +26,7 @@ func Test_registryAddGet(t *testing.T) {
func Test_registryAddGetErr(t *testing.T) {
var (
req = require.New(t)
r = NewRegistry()
r = NewRegistry(&options.ApigwOpt{})
)
r.Add("mockHandler", types.MockHandler{})
@ -71,7 +72,7 @@ func Test_registryMerge(t *testing.T) {
for _, tc := range tcc {
var (
req = require.New(t)
r = NewRegistry()
r = NewRegistry(&options.ApigwOpt{})
)
m, err := r.Merge(types.MockHandler{}, []byte(tc.params))
@ -89,7 +90,7 @@ func Test_registryMerge(t *testing.T) {
func Test_registryAll(t *testing.T) {
var (
req = require.New(t)
r = NewRegistry()
r = NewRegistry(&options.ApigwOpt{})
)
r.Add("mockHandler", types.MockHandler{})

View File

@ -11,6 +11,7 @@ import (
"github.com/cortezaproject/corteza-server/pkg/auth"
h "github.com/cortezaproject/corteza-server/pkg/http"
"github.com/cortezaproject/corteza-server/pkg/options"
"github.com/davecgh/go-spew/spew"
"go.uber.org/zap"
)
@ -54,8 +55,11 @@ func (r route) ServeHTTP(w http.ResponseWriter, req *http.Request) {
scope.Set("opts", r.opts)
scope.Set("request", ar)
spew.Dump("OPTS", r.opts)
// use profiler, override any profiling prefilter
if r.opts.ProfilerEnabled {
if r.opts.ProfilerEnabled && r.opts.ProfilerGlobal {
spew.Dump("adding to profiler")
// add request to profiler
hit = r.pr.Hit(ar)
hit.Route = r.ID
@ -66,20 +70,28 @@ func (r route) ServeHTTP(w http.ResponseWriter, req *http.Request) {
r.handler.ServeHTTP(w, req)
if r.opts.ProfilerEnabled {
r.pr.Push(hit)
} else {
if hit = actx.ProfilerFromContext(req.Context()).(*profiler.Hit); hit != nil && hit.R != nil {
// updated hit from a possible prefilter
// we need to push route ID even if the profiler is disabled
hit.Route = r.ID
r.pr.Push(hit)
}
}
r.log.Debug("finished serving route",
zap.Duration("duration", time.Since(start)),
)
if !r.opts.ProfilerEnabled {
return
}
if r.opts.ProfilerGlobal {
r.pr.Push(hit)
return
}
if hit = actx.ProfilerFromContext(req.Context()).(*profiler.Hit); hit != nil && hit.R != nil {
// updated hit from a possible prefilter
// we need to push route ID even if the profiler is disabled
hit.Route = r.ID
hit.Status = http.StatusOK
r.pr.Push(hit)
r.log.Debug("pushing request to profiler")
}
}
func (r route) String() string {

View File

@ -59,7 +59,7 @@ func Setup(opts *options.ApigwOpt, log *zap.Logger, storer storer) {
func New(opts *options.ApigwOpt, logger *zap.Logger, storer storer) *apigw {
var (
pr = profiler.New()
reg = registry.NewRegistry()
reg = registry.NewRegistry(opts)
)
reg.Preload()

View File

@ -7,6 +7,7 @@ import (
"github.com/cortezaproject/corteza-server/pkg/apigw/registry"
"github.com/cortezaproject/corteza-server/pkg/apigw/types"
"github.com/cortezaproject/corteza-server/pkg/options"
st "github.com/cortezaproject/corteza-server/system/types"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
@ -159,7 +160,7 @@ func Test_serviceInit(t *testing.T) {
ctx = context.Background()
)
reg := registry.NewRegistry()
reg := registry.NewRegistry(&options.ApigwOpt{})
for hn, h := range tc.reg {
reg.Add(hn, h)

View File

@ -3,6 +3,8 @@ package types
import (
"fmt"
"net/http"
"github.com/cortezaproject/corteza-server/pkg/options"
)
type (
@ -18,9 +20,10 @@ type (
HTTPHandler
fmt.Stringer
New() Handler
New(*options.ApigwOpt) Handler
Merge([]byte) (Handler, error)
Meta() FilterMeta
Enabled() bool
}
HandlerFunc func(rw http.ResponseWriter, r *http.Request) error

View File

@ -6,6 +6,7 @@ import (
"encoding/json"
"net/http"
"github.com/cortezaproject/corteza-server/pkg/options"
st "github.com/cortezaproject/corteza-server/system/types"
)
@ -32,10 +33,14 @@ type (
MockRoundTripper func(*http.Request) (*http.Response, error)
)
func (h MockHandler) New() Handler {
func (h MockHandler) New(opts *options.ApigwOpt) Handler {
return MockHandler{}
}
func (h MockHandler) Enabled() bool {
return true
}
func (h MockHandler) String() string {
return "MockHandler"
}

View File

@ -86,6 +86,7 @@ type (
Debug bool `env:"APIGW_DEBUG"`
LogEnabled bool `env:"APIGW_LOG_ENABLED"`
ProfilerEnabled bool `env:"APIGW_PROFILER_ENABLED"`
ProfilerGlobal bool `env:"APIGW_PROFILER_GLOBAL"`
LogRequestBody bool `env:"APIGW_LOG_REQUEST_BODY"`
ProxyEnableDebugLog bool `env:"APIGW_PROXY_ENABLE_DEBUG_LOG"`
ProxyFollowRedirects bool `env:"APIGW_PROXY_FOLLOW_REDIRECTS"`

View File

@ -212,6 +212,7 @@ type (
// This only holds the value of APIGW_PROFILER_ENABLED for now
//
ProfilerEnabled bool `kv:"-" json:"profilerEnabled"`
ProfilerGlobal bool `kv:"-" json:"profilerGlobal"`
} `kv:"apigw" json:"apigw"`
// UserInterface settings