Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
knusbaum committed Jun 25, 2020
1 parent 8bde7e3 commit 2e7bf1c
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 103 deletions.
2 changes: 1 addition & 1 deletion ddtrace/tracer/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func (tg *testStatsdClient) Wait(n int, d time.Duration) error {

func TestReportRuntimeMetrics(t *testing.T) {
var tg testStatsdClient
trc := newUnstartedTracer(withStatsdClient(&tg))
trc, _ := newUnstartedTracer(withStatsdClient(&tg))

trc.wg.Add(1)
go func() {
Expand Down
16 changes: 8 additions & 8 deletions ddtrace/tracer/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,23 @@ func TestTracerOptionsDefaults(t *testing.T) {

t.Run("dogstatsd", func(t *testing.T) {
t.Run("default", func(t *testing.T) {
tracer := newTracer()
tracer, _ := newTracer()
c := tracer.config
assert.Equal(t, c.dogstatsdAddr, "localhost:8125")
})

t.Run("env-host", func(t *testing.T) {
os.Setenv("DD_AGENT_HOST", "my-host")
defer os.Unsetenv("DD_AGENT_HOST")
tracer := newTracer()
tracer, _ := newTracer()
c := tracer.config
assert.Equal(t, c.dogstatsdAddr, "my-host:8125")
})

t.Run("env-port", func(t *testing.T) {
os.Setenv("DD_DOGSTATSD_PORT", "123")
defer os.Unsetenv("DD_DOGSTATSD_PORT")
tracer := newTracer()
tracer, _ := newTracer()
c := tracer.config
assert.Equal(t, c.dogstatsdAddr, "localhost:123")
})
Expand All @@ -79,21 +79,21 @@ func TestTracerOptionsDefaults(t *testing.T) {
os.Setenv("DD_DOGSTATSD_PORT", "123")
defer os.Unsetenv("DD_AGENT_HOST")
defer os.Unsetenv("DD_DOGSTATSD_PORT")
tracer := newTracer()
tracer, _ := newTracer()
c := tracer.config
assert.Equal(t, c.dogstatsdAddr, "my-host:123")
})

t.Run("env-env", func(t *testing.T) {
os.Setenv("DD_ENV", "testEnv")
defer os.Unsetenv("DD_ENV")
tracer := newTracer()
tracer, _ := newTracer()
c := tracer.config
assert.Equal(t, "testEnv", c.env)
})

t.Run("option", func(t *testing.T) {
tracer := newTracer(WithDogstatsdAddress("10.1.0.12:4002"))
tracer, _ := newTracer(WithDogstatsdAddress("10.1.0.12:4002"))
c := tracer.config
assert.Equal(t, c.dogstatsdAddr, "10.1.0.12:4002")
})
Expand All @@ -104,14 +104,14 @@ func TestTracerOptionsDefaults(t *testing.T) {
defer os.Unsetenv("DD_ENV")
assert := assert.New(t)
env := "production"
tracer := newTracer(WithEnv(env))
tracer, _ := newTracer(WithEnv(env))
c := tracer.config
assert.Equal(env, c.env)
})

t.Run("other", func(t *testing.T) {
assert := assert.New(t)
tracer := newTracer(
tracer, _ := newTracer(
WithSampler(NewRateSampler(0.5)),
WithAgentAddr("ddagent.consul.local:58126"),
WithGlobalTag("k", "v"),
Expand Down
75 changes: 44 additions & 31 deletions ddtrace/tracer/sampler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"strconv"
"sync"
"time"
"fmt"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
Expand Down Expand Up @@ -185,42 +186,54 @@ func newRulesSampler(rules []SamplingRule) *rulesSampler {
}
}

// appliedSamplingRules validates the user-provided rules and returns an internal representation.
// If the DD_TRACE_SAMPLING_RULES environment variable is set, it will replace the given rules.
func appliedSamplingRules(rules []SamplingRule) []SamplingRule {
func samplingRulesFromEnv() ([]SamplingRule, error) {
rulesFromEnv := os.Getenv("DD_TRACE_SAMPLING_RULES")
if rulesFromEnv != "" {
rules = rules[:0]
jsonRules := []struct {
Service string `json:"service"`
Name string `json:"name"`
Rate json.Number `json:"sample_rate"`
}{}
err := json.Unmarshal([]byte(rulesFromEnv), &jsonRules)
if rulesFromEnv == "" {
return nil, nil
}
//var rules []SamplingRule
rules := make([]SamplingRule, 0)
jsonRules := []struct {
Service string `json:"service"`
Name string `json:"name"`
Rate json.Number `json:"sample_rate"`
}{}
err := json.Unmarshal([]byte(rulesFromEnv), &jsonRules)
if err != nil {
log.Warn("error parsing DD_TRACE_SAMPLING_RULES: %v", err)
return nil, fmt.Errorf("error parsing DD_TRACE_SAMPLING_RULES: %v", err)
}
var errStr string
for _, v := range jsonRules {
if v.Rate == "" {
log.Warn("error parsing rule: rate not provided")
errStr += "error parsing rule: rate not provided"
continue
}
rate, err := v.Rate.Float64()
if err != nil {
log.Warn("error parsing DD_TRACE_SAMPLING_RULES: %v", err)
return nil
log.Warn("error parsing rule: invalid rate: %v", err)
errStr += fmt.Sprintf("error parsing rule: invalid rate: %v", err)
continue
}
for _, v := range jsonRules {
if v.Rate == "" {
log.Warn("error parsing rule: rate not provided")
continue
}
rate, err := v.Rate.Float64()
if err != nil {
log.Warn("error parsing rule: invalid rate: %v", err)
continue
}
switch {
case v.Service != "" && v.Name != "":
rules = append(rules, NameServiceRule(v.Name, v.Service, rate))
case v.Service != "":
rules = append(rules, ServiceRule(v.Service, rate))
case v.Name != "":
rules = append(rules, NameRule(v.Name, rate))
}
switch {
case v.Service != "" && v.Name != "":
rules = append(rules, NameServiceRule(v.Name, v.Service, rate))
case v.Service != "":
rules = append(rules, ServiceRule(v.Service, rate))
case v.Name != "":
rules = append(rules, NameRule(v.Name, rate))
}
}
if errStr != "" {
return rules, fmt.Errorf("WARN parsing DD_TRACE_SAMPLING_RULES: %s", errStr)
}
return rules, nil
}

// appliedSamplingRules validates the user-provided rules and returns an internal representation.
// If the DD_TRACE_SAMPLING_RULES environment variable is set, it will replace the given rules.
func appliedSamplingRules(rules []SamplingRule) []SamplingRule {
validRules := make([]SamplingRule, 0, len(rules))
for _, v := range rules {
if !(v.Rate >= 0.0 && v.Rate <= 1.0) {
Expand Down
22 changes: 13 additions & 9 deletions ddtrace/tracer/sampler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,41 +234,45 @@ func TestRuleEnvVars(t *testing.T) {
t.Run("sampling-rules", func(t *testing.T) {
assert := assert.New(t)
defer os.Unsetenv("DD_TRACE_SAMPLING_RULES")
// represents hard-coded rules
rules := []SamplingRule{
RateRule(1.0),
}


// env overrides provided rules
os.Setenv("DD_TRACE_SAMPLING_RULES", "[]")
rules, _ := samplingRulesFromEnv()
validRules := appliedSamplingRules(rules)
assert.Len(validRules, 0)

// valid rules
os.Setenv("DD_TRACE_SAMPLING_RULES", `[{"service": "abcd", "sample_rate": 1.0}]`)
rules, _ = samplingRulesFromEnv()
validRules = appliedSamplingRules(rules)
assert.Len(validRules, 1)

os.Setenv("DD_TRACE_SAMPLING_RULES", `[{"service": "abcd", "sample_rate": 1.0},`+
`{"name": "wxyz", "sample_rate": 0.9},`+
`{"service": "efgh", "name": "lmnop", "sample_rate": 0.42}]`)
rules, _ = samplingRulesFromEnv()
validRules = appliedSamplingRules(rules)
assert.Len(validRules, 3)

// invalid rule ignored
os.Setenv("DD_TRACE_SAMPLING_RULES", `[{"service": "abcd", "sample_rate": 42.0}]`)
rules, _ = samplingRulesFromEnv()
validRules = appliedSamplingRules(rules)
assert.Len(validRules, 0)

os.Setenv("DD_TRACE_SAMPLING_RULES", `[{"service": "abcd", "sample_rate": "all of them"}]`)
rules, _ = samplingRulesFromEnv()
validRules = appliedSamplingRules(rules)
assert.Len(validRules, 0)

os.Setenv("DD_TRACE_SAMPLING_RULES", `[{"service": "abcd"}]`)
rules, _ = samplingRulesFromEnv()
validRules = appliedSamplingRules(rules)
assert.Len(validRules, 0)

os.Setenv("DD_TRACE_SAMPLING_RULES", `not JSON at all`)
rules, _ = samplingRulesFromEnv()
validRules = appliedSamplingRules(rules)
assert.Len(validRules, 0)
})
Expand Down Expand Up @@ -368,7 +372,7 @@ func TestRulesSamplerConcurrency(t *testing.T) {
NameServiceRule("db.query", "postgres.db", 1.0),
NameRule("notweb.request", 1.0),
}
tracer := newTracer(WithSamplingRules(rules))
tracer, _ := newTracer(WithSamplingRules(rules))
span := func(wg *sync.WaitGroup) {
defer wg.Done()
tracer.StartSpan("db.query", ServiceName("postgres.db")).Finish()
Expand Down Expand Up @@ -537,7 +541,7 @@ func BenchmarkRulesSampler(b *testing.B) {
}

b.Run("no-rules", func(b *testing.B) {
tracer := newUnstartedTracer()
tracer, _ := newUnstartedTracer()
benchmarkStartSpan(b, tracer)
})

Expand All @@ -547,7 +551,7 @@ func BenchmarkRulesSampler(b *testing.B) {
NameServiceRule("db.query", "postgres.db", 1.0),
NameRule("notweb.request", 1.0),
}
tracer := newUnstartedTracer(WithSamplingRules(rules))
tracer, _ := newUnstartedTracer(WithSamplingRules(rules))
benchmarkStartSpan(b, tracer)
})

Expand All @@ -557,7 +561,7 @@ func BenchmarkRulesSampler(b *testing.B) {
NameServiceRule("db.query", "postgres.db", 1.0),
NameRule("web.request", 1.0),
}
tracer := newUnstartedTracer(WithSamplingRules(rules))
tracer, _ := newUnstartedTracer(WithSamplingRules(rules))
benchmarkStartSpan(b, tracer)
})

Expand Down Expand Up @@ -587,7 +591,7 @@ func BenchmarkRulesSampler(b *testing.B) {
NameRule("notweb.request", 1.0),
NameRule("web.request", 1.0),
}
tracer := newUnstartedTracer(WithSamplingRules(rules))
tracer, _ := newUnstartedTracer(WithSamplingRules(rules))
benchmarkStartSpan(b, tracer)
})
}
16 changes: 8 additions & 8 deletions ddtrace/tracer/span_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func TestSpanOperationName(t *testing.T) {
func TestSpanFinish(t *testing.T) {
assert := assert.New(t)
wait := time.Millisecond * 2
tracer := newTracer(withTransport(newDefaultTransport()))
tracer, _ := newTracer(withTransport(newDefaultTransport()))
span := tracer.newRootSpan("pylons.request", "pylons", "/")

// the finish should set finished and the duration
Expand Down Expand Up @@ -219,7 +219,7 @@ func TestSpanSetDatadogTags(t *testing.T) {

func TestSpanStart(t *testing.T) {
assert := assert.New(t)
tracer := newTracer(withTransport(newDefaultTransport()))
tracer, _ := newTracer(withTransport(newDefaultTransport()))
span := tracer.newRootSpan("pylons.request", "pylons", "/")

// a new span sets the Start after the initialization
Expand All @@ -228,7 +228,7 @@ func TestSpanStart(t *testing.T) {

func TestSpanString(t *testing.T) {
assert := assert.New(t)
tracer := newTracer(withTransport(newDefaultTransport()))
tracer, _ := newTracer(withTransport(newDefaultTransport()))
span := tracer.newRootSpan("pylons.request", "pylons", "/")
// don't bother checking the contents, just make sure it works.
assert.NotEqual("", span.String())
Expand Down Expand Up @@ -286,7 +286,7 @@ func TestSpanSetMetric(t *testing.T) {
} {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
tracer := newTracer(withTransport(newDefaultTransport()))
tracer, _ := newTracer(withTransport(newDefaultTransport()))
span := tracer.newRootSpan("http.request", "mux.router", "/")
tt(assert, span)
})
Expand All @@ -295,7 +295,7 @@ func TestSpanSetMetric(t *testing.T) {

func TestSpanError(t *testing.T) {
assert := assert.New(t)
tracer := newTracer(withTransport(newDefaultTransport()))
tracer, _ := newTracer(withTransport(newDefaultTransport()))
span := tracer.newRootSpan("pylons.request", "pylons", "/")

// check the error is set in the default meta
Expand All @@ -320,7 +320,7 @@ func TestSpanError(t *testing.T) {

func TestSpanError_Typed(t *testing.T) {
assert := assert.New(t)
tracer := newTracer(withTransport(newDefaultTransport()))
tracer, _ := newTracer(withTransport(newDefaultTransport()))
span := tracer.newRootSpan("pylons.request", "pylons", "/")

// check the error is set in the default meta
Expand All @@ -334,7 +334,7 @@ func TestSpanError_Typed(t *testing.T) {

func TestSpanErrorNil(t *testing.T) {
assert := assert.New(t)
tracer := newTracer(withTransport(newDefaultTransport()))
tracer, _ := newTracer(withTransport(newDefaultTransport()))
span := tracer.newRootSpan("pylons.request", "pylons", "/")

// don't set the error if it's nil
Expand Down Expand Up @@ -375,7 +375,7 @@ func TestSpanModifyWhileFlushing(t *testing.T) {

func TestSpanSamplingPriority(t *testing.T) {
assert := assert.New(t)
tracer := newTracer(withTransport(newDefaultTransport()))
tracer, _ := newTracer(withTransport(newDefaultTransport()))

span := tracer.newRootSpan("my.name", "my.service", "my.resource")
_, ok := span.Metrics[keySamplingPriority]
Expand Down
21 changes: 12 additions & 9 deletions ddtrace/tracer/startup.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import (

"gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig"
"gopkg.in/DataDog/dd-trace-go.v1/internal/version"
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
)

type startupLog struct {
type startupInfo struct {
// Common startup status
Date string `json:"date"`
OSName string `json:"os_name"`
Expand All @@ -33,7 +34,7 @@ type startupLog struct {
AnalyticsEnabled bool `json:"analytics_enabled"`
SampleRate float64 `json:"sample_rate"`
SamplingRules []SamplingRule `json:"sampling_rules"`
SamplingRulesError string `json:"sampling_rules_error"`
SamplingRulesError error `json:"sampling_rules_error"`
Tags map[string]interface{} `json:"tags"`
RuntimeMetricsEnabled bool `json:"runtime_metrics_enabled"`

Expand All @@ -46,10 +47,9 @@ func agentReachable(t *tracer) (bool, error) {
return false, nil
}

func logStartup(t *tracer) {
func newStartupInfo(t *tracer) *startupInfo {
reachable, reachableErr := agentReachable(t)

sl := startupLog{
return &startupInfo{
Date: time.Now().Format("2006-01-02 15:04:05"),
OSName: osName(),
OSVersion: osVersion(),
Expand All @@ -65,15 +65,18 @@ func logStartup(t *tracer) {
AnalyticsEnabled: globalconfig.AnalyticsRate() != math.NaN(),
SampleRate: t.prioritySampling.defaultRate,
SamplingRules: t.rulesSampling.rules,
SamplingRulesError: "TODO",
SamplingRulesError: nil,
Tags: t.globalTags,
RuntimeMetricsEnabled: t.config.runtimeMetrics,
GlobalService: globalconfig.ServiceName(),
}
bs, err := json.Marshal(sl)
}

func logStartup(info *startupInfo) {
bs, err := json.Marshal(info)
if err != nil {
fmt.Printf("Failed to serialize json for startup log: %#v\n", sl)
fmt.Printf("Failed to serialize json for startup log: %#v\n", info)
return
}
fmt.Printf("Startup: %s\n", string(bs))
log.Warn("Startup: %s\n", string(bs))
}
Loading

0 comments on commit 2e7bf1c

Please sign in to comment.