Skip to content
This repository has been archived by the owner on Aug 30, 2019. It is now read-only.

Commit

Permalink
filters: apply replace rules only after obfuscation
Browse files Browse the repository at this point in the history
  • Loading branch information
gbbr committed Sep 26, 2018
1 parent c200dbb commit 52c0d30
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 184 deletions.
24 changes: 9 additions & 15 deletions cmd/trace-agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ import (
"github.com/DataDog/datadog-trace-agent/writer"
)

const (
processStatsInterval = time.Minute
)
const processStatsInterval = time.Minute

type processedTrace struct {
Trace model.Trace
Expand Down Expand Up @@ -50,7 +48,8 @@ func (pt *processedTrace) getSamplingPriority() (int, bool) {
type Agent struct {
Receiver *HTTPReceiver
Concentrator *Concentrator
Filters []filters.Filter
Blacklister *filters.Blacklister
Replacer *filters.Replacer
ScoreSampler *Sampler
ErrorsScoreSampler *Sampler
PrioritySampler *Sampler
Expand Down Expand Up @@ -94,7 +93,6 @@ func NewAgent(ctx context.Context, conf *config.AgentConfig) *Agent {
conf.BucketInterval.Nanoseconds(),
statsChan,
)
f := filters.Setup(conf)

obf := obfuscate.NewObfuscator(conf.Obfuscation)
ss := NewScoreSampler(conf)
Expand All @@ -110,7 +108,8 @@ func NewAgent(ctx context.Context, conf *config.AgentConfig) *Agent {
return &Agent{
Receiver: r,
Concentrator: c,
Filters: f,
Blacklister: filters.NewBlacklister(conf.Ignore["resource"]),
Replacer: filters.NewReplacer(conf.ReplaceTags),
ScoreSampler: ss,
ErrorsScoreSampler: ess,
PrioritySampler: ps,
Expand Down Expand Up @@ -179,8 +178,6 @@ func (a *Agent) Run() {
// passes it downstream.
func (a *Agent) Process(t model.Trace) {
if len(t) == 0 {
// XXX Should never happen since we reject empty traces during
// normalization.
log.Debugf("skipping received empty trace")
return
}
Expand Down Expand Up @@ -230,15 +227,10 @@ func (a *Agent) Process(t model.Trace) {
return
}

for _, f := range a.Filters {
if f.Keep(root, &t) {
continue
}

log.Debugf("rejecting trace by filter: %T %v", f, *root)
if !a.Blacklister.Allows(root) {
log.Debugf("trace rejected by blacklister. root: %v", root)
atomic.AddInt64(&ts.TracesFiltered, 1)
atomic.AddInt64(&ts.SpansFiltered, int64(len(t)))

return
}

Expand All @@ -264,6 +256,8 @@ func (a *Agent) Process(t model.Trace) {
span.Truncate()
}

a.Replacer.Replace(&t)

pt := processedTrace{
Trace: t,
WeightedTrace: wt,
Expand Down
19 changes: 0 additions & 19 deletions filters/base.go

This file was deleted.

45 changes: 45 additions & 0 deletions filters/blacklister.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package filters

import (
"regexp"

"github.com/DataDog/datadog-trace-agent/model"

log "github.com/cihub/seelog"
)

// Blacklister holds a list of regular expressions which will match resources
// on spans that should be dropped.
type Blacklister struct {
list []*regexp.Regexp
}

// Allows returns true if the Blacklister permits this span.
func (f *Blacklister) Allows(span *model.Span) bool {
for _, entry := range f.list {
if entry.MatchString(span.Resource) {
return false
}
}
return true
}

// NewBlacklister creates a new Blacklister based on the given list of
// regular expressions.
func NewBlacklister(exprs []string) *Blacklister {
return &Blacklister{list: compileRules(exprs)}
}

// compileRules compiles as many rules as possible from the list of expressions.
func compileRules(exprs []string) []*regexp.Regexp {
list := make([]*regexp.Regexp, 0, len(exprs))
for _, entry := range exprs {
rule, err := regexp.Compile(entry)
if err != nil {
log.Errorf("invalid resource filter: %q", entry)
continue
}
list = append(list, rule)
}
return list
}
47 changes: 47 additions & 0 deletions filters/blacklister_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package filters

import (
"testing"

"github.com/DataDog/datadog-trace-agent/fixtures"
"github.com/stretchr/testify/assert"
)

func TestBlacklister(t *testing.T) {
tests := []struct {
filter []string
resource string
expectation bool
}{
{[]string{"/foo/bar"}, "/foo/bar", false},
{[]string{"/foo/b.r"}, "/foo/bar", false},
{[]string{"[0-9]+"}, "/abcde", true},
{[]string{"[0-9]+"}, "/abcde123", false},
{[]string{"\\(foobar\\)"}, "(foobar)", false},
{[]string{"\\(foobar\\)"}, "(bar)", true},
{[]string{"(GET|POST) /healthcheck"}, "GET /foobar", true},
{[]string{"(GET|POST) /healthcheck"}, "GET /healthcheck", false},
{[]string{"(GET|POST) /healthcheck"}, "POST /healthcheck", false},
{[]string{"SELECT COUNT\\(\\*\\) FROM BAR"}, "SELECT COUNT(*) FROM BAR", false},
{[]string{"[123"}, "[123", true},
{[]string{"\\[123"}, "[123", false},
{[]string{"ABC+", "W+"}, "ABCCCC", false},
{[]string{"ABC+", "W+"}, "WWW", false},
}

for _, test := range tests {
span := fixtures.RandomSpan()
span.Resource = test.resource
filter := NewBlacklister(test.filter)

assert.Equal(t, test.expectation, filter.Allows(span))
}
}

func TestCompileRules(t *testing.T) {
filter := NewBlacklister([]string{"[123", "]123", "{6}"})
for i := 0; i < 100; i++ {
span := fixtures.RandomSpan()
assert.True(t, filter.Allows(span))
}
}
22 changes: 9 additions & 13 deletions filters/tag.go → filters/replacer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,20 @@ import (
"github.com/DataDog/datadog-trace-agent/model"
)

var _ Filter = (*tagReplacer)(nil)

// tagReplacer is a filter which replaces tag values based on its
// Replacer is a filter which replaces tag values based on its
// settings. It keeps all spans.
type tagReplacer struct {
// replace maps tag keys to one or more sets of replacements
replace []*config.ReplaceRule
type Replacer struct {
rules []*config.ReplaceRule
}

func newTagReplacer(c *config.AgentConfig) *tagReplacer {
return &tagReplacer{replace: c.ReplaceTags}
// NewReplacer returns a new Replacer which will use the given set of rules.
func NewReplacer(rules []*config.ReplaceRule) *Replacer {
return &Replacer{rules: rules}
}

// Keep implements Filter.
func (f tagReplacer) Keep(root *model.Span, trace *model.Trace) bool {
for _, rule := range f.replace {
// Replace replaces all tags matching the Replacer's rules.
func (f Replacer) Replace(trace *model.Trace) {
for _, rule := range f.rules {
key, str, re := rule.Name, rule.Repl, rule.Re
for _, s := range *trace {
switch key {
Expand All @@ -42,6 +40,4 @@ func (f tagReplacer) Keep(root *model.Span, trace *model.Trace) bool {
}
}
}
// always return true as the goal of this filter is only to mutate data
return true
}
7 changes: 3 additions & 4 deletions filters/tag_test.go → filters/replacer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
)

func TestTagReplacer(t *testing.T) {
func TestReplacer(t *testing.T) {
assert := assert.New(t)
for _, tt := range []struct {
rules [][3]string
Expand Down Expand Up @@ -54,12 +54,11 @@ func TestTagReplacer(t *testing.T) {
},
} {
rules := parseRulesFromString(tt.rules)
tr := &tagReplacer{replace: rules}
tr := NewReplacer(rules)
root := replaceFilterTestSpan(tt.got)
childSpan := replaceFilterTestSpan(tt.got)
trace := model.Trace{root, childSpan}
ok := tr.Keep(root, &trace)
assert.True(ok)
tr.Replace(&trace)
for k, v := range tt.want {
switch k {
case "resource.name":
Expand Down
49 changes: 0 additions & 49 deletions filters/resource.go

This file was deleted.

84 changes: 0 additions & 84 deletions filters/resource_test.go

This file was deleted.

0 comments on commit 52c0d30

Please sign in to comment.