Skip to content

Commit

Permalink
Add more tags to the admissionControl span to increase visibility
Browse files Browse the repository at this point in the history
Updates #3317

Signed-off-by: Roman Zavodskikh <[email protected]>
  • Loading branch information
Roman Zavodskikh committed Nov 22, 2024
1 parent f6f9efb commit 3abb644
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 0 deletions.
9 changes: 9 additions & 0 deletions filters/shedder/admission.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,13 @@ func sum(a []int64) int64 {
return result
}

func (ac *admissionControl) setCommonTags(span opentracing.Span) {
span.SetTag("admissionControl.group", ac.metricSuffix)
span.SetTag("admissionControl.mode", ac.mode.String())
span.SetTag("admissionControl.d", ac.d.String())
span.SetTag("admissionControl.windowSize", ac.windowSize)
}

// calculates P_{reject} see https://opensource.zalando.com/skipper/reference/filters/#admissioncontrol
func (ac *admissionControl) pReject() float64 {
var rejectP float64
Expand Down Expand Up @@ -412,6 +419,8 @@ func (ac *admissionControl) shouldReject() bool {
func (ac *admissionControl) Request(ctx filters.FilterContext) {
span := ac.startSpan(ctx.Request().Context())
defer span.Finish()

ac.setCommonTags(span)
ac.metrics.IncCounter(counterPrefix + "total." + ac.metricSuffix)

if ac.shouldReject() {
Expand Down
125 changes: 125 additions & 0 deletions filters/shedder/admission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ import (
"testing"
"time"

"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/mocktracer"
"github.com/stretchr/testify/assert"
"github.com/zalando/skipper/eskip"
"github.com/zalando/skipper/filters"
"github.com/zalando/skipper/filters/builtin"
"github.com/zalando/skipper/metrics"
"github.com/zalando/skipper/metrics/metricstest"
"github.com/zalando/skipper/net"
"github.com/zalando/skipper/proxy"
"github.com/zalando/skipper/proxy/proxytest"
"github.com/zalando/skipper/routing"
"github.com/zalando/skipper/routing/testdataclient"
Expand Down Expand Up @@ -594,6 +598,127 @@ func TestAdmissionControlCleanupMultipleFilters(t *testing.T) {
}
}

type testTracer struct {
*mocktracer.MockTracer
spans int32
}

func (t *testTracer) Reset() {
atomic.StoreInt32(&t.spans, 0)
t.MockTracer.Reset()
}

func (t *testTracer) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span {
atomic.AddInt32(&t.spans, 1)
return t.MockTracer.StartSpan(operationName, opts...)
}

func (t *testTracer) FinishedSpans() []*mocktracer.MockSpan {
timeout := time.After(1 * time.Second)
retry := time.NewTicker(100 * time.Millisecond)
defer retry.Stop()
for {
finished := t.MockTracer.FinishedSpans()
if len(finished) == int(atomic.LoadInt32(&t.spans)) {
return finished
}
select {
case <-retry.C:
case <-timeout:
return nil
}
}
}

func TestAdmissionControlSetsSpansTags(t *testing.T) {
tracer := &testTracer{MockTracer: mocktracer.New()}

backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
defer backend.Close()

fspec := NewAdmissionControl(Options{Tracer: tracer})
spec, ok := fspec.(*AdmissionControlSpec)
if !ok {
t.Fatal("FilterSpec is not a AdmissionControlSpec")
}
preProcessor := spec.PreProcessor()
postProcessor := spec.PostProcessor()

args := make([]interface{}, 0, 6)
args = append(args, "testmetric", "active", "10ms", 5, 1, 0.1, 0.95, 0.5)
f, err := spec.CreateFilter(args)
if err != nil {
t.Fatalf("error creating filter: %v", err)
return
}
f.(*admissionControl).Close()

r := &eskip.Route{Filters: []*eskip.Filter{{Name: spec.Name(), Args: args}}, Backend: backend.URL}

fr := make(filters.Registry)
fr.Register(fspec)
fr.Register(builtin.NewSetRequestHeader())
fr.Register(builtin.NewStatus())

dc := testdataclient.New([]*eskip.Route{r})
defer dc.Close()

proxy := proxytest.WithParamsAndRoutingOptions(fr,
proxy.Params{
OpenTracing: &proxy.OpenTracingParams{Tracer: tracer},
},
routing.Options{
DataClients: []routing.DataClient{dc},
PostProcessors: []routing.PostProcessor{postProcessor},
PreProcessors: []routing.PreProcessor{preProcessor},
})
defer proxy.Close()

client := proxy.Client()
req, err := http.NewRequest("GET", proxy.URL, nil)
if err != nil {
t.Error(err)
return
}

_, err = client.Do(req)
if err != nil {
t.Error(err)
}

acSpanFound := false
finishedSpans := tracer.MockTracer.FinishedSpans()
for _, span := range finishedSpans {
if span.OperationName == "admission_control" {
acSpanFound = true
tags := span.Tags()

d, found := tags["admissionControl.d"]
assert.True(t, found)
assert.Equal(t, "10ms", d)

windowSize, found := tags["admissionControl.windowSize"]
assert.True(t, found)
assert.Equal(t, 5, windowSize)

group, found := tags["admissionControl.group"]
assert.True(t, found)
assert.Equal(t, "testmetric", group)

mode, found := tags["admissionControl.mode"]
assert.True(t, found)
assert.Equal(t, "active", mode)

mode, found = tags["mode"]
assert.True(t, found)
assert.Equal(t, "active", mode)
}
}
assert.True(t, acSpanFound)
}

type validationPostProcessorNumberOfFilters struct {
ch chan []*routing.Route
}
Expand Down

0 comments on commit 3abb644

Please sign in to comment.