Skip to content

Commit

Permalink
Merge branch 'v1' into gin-extract
Browse files Browse the repository at this point in the history
  • Loading branch information
samsaggace committed Jul 25, 2018
2 parents 71cb598 + 0a3c14f commit 6550e97
Show file tree
Hide file tree
Showing 15 changed files with 114 additions and 55 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,5 @@ jobs:
name: Testing
command: |
go vet ./...
golint $(go list ./... | grep -v /vendor/)
golint -set_exit_status=1 $(go list ./... | grep -v /vendor/)
INTEGRATION=1 go test -v -race ./...
17 changes: 17 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### Contributing

Pull requests for bug fixes are welcome, but before submitting new features or changes to current functionalities [open an issue](https://github.com/DataDog/dd-trace-go/issues/new)
and discuss your ideas or propose the changes you wish to make. After a resolution is reached a PR can be submitted for review.

For commit messages, try to use the same conventions as most Go projects, for example:
```
contrib/database/sql: use method context on QueryContext and ExecContext
QueryContext and ExecContext were using the wrong context to create
spans. Instead of using the method's argument they were using the
Prepare context, which was wrong.
Fixes #113
```
Please apply the same logic for Pull Requests, start with the package name, followed by a colon and a description of the change, just like
the official [Go language](https://github.com/golang/go/pulls).
4 changes: 2 additions & 2 deletions MIGRATING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Datadog's v1 version of the Go tracer provides not only an overhauled core that

As is common and recommended in the Go community, the best way to approach migrating to this new API is by using the [gradual code repair](https://talks.golang.org/2016/refactor.article) method. We have done the same internally and it has worked just great! For this exact reason we have provided a new, [semver](https://semver.org/) friendly import path to help with using both tracers in parallel, without conflict, for the duration of the migration. This new path is `gopkg.in/DataDog/dd-trace-go.v1`.

Our [godoc page](https://godoc.org/gopkg.in/DataDog/dd-trace-go.v1/ddtrace) should deem helpful during this process. We also have the ":warn: soon to be published" [official documentation](https://docs.datadoghq.com/tracing/setup/go/), which contains a couple of examples.
Our [godoc page](https://godoc.org/gopkg.in/DataDog/dd-trace-go.v1/ddtrace) should deem helpful during this process. We also have the [official documentation](https://docs.datadoghq.com/tracing/setup/go/), which contains a couple of examples.

This document will further outline some _before_ and _after_ examples.

Expand Down Expand Up @@ -49,7 +49,7 @@ span := tracer.NewRootSpan("web.request", "my_service", "resource_name")
Becomes:

```go
span := tracer.StartSpan("web.request", tracer.WithServiceName("my_service"), tracer.WithResourceName("resource_name"))
span := tracer.StartSpan("web.request", tracer.ServiceName("my_service"), tracer.ResourceName("resource_name"))
```

We've done this because in many cases the extra parameters could become tedious, given that service names can be inherited and resource names can default to the operation name. This also allows us to have one single, more dynamic API for starting both root and child spans. Check out all possible [StartSpanOption](https://godoc.org/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer#StartSpanOption) values to get an idea.
Expand Down
29 changes: 5 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
### Installing

```bash
go get gopkg.in/DataDog/dd-trace-go.v1/...
go get gopkg.in/DataDog/dd-trace-go.v1/ddtrace
```

Requires:

* Go 1.9
* Datadog's Trace Agent >= 5.21.1

### Documentation

The API is documented on [godoc](https://godoc.org/gopkg.in/DataDog/dd-trace-go.v1/ddtrace) as well as Datadog's [official documentation](https://docs.datadoghq.com/tracing/setup/go/). If you are migrating
from an older version of the tracer (e.g. 0.6.x) you may also find the [migration document](https://github.com/DataDog/dd-trace-go/blob/v1/MIGRATING.md) we've put together helpful.

### Testing

Expand All @@ -24,26 +28,3 @@ idea about the versions and the set-up take a look at our [CI config](https://gi

The best way to run the entire test suite is using the [CircleCI CLI](https://circleci.com/docs/2.0/local-jobs/). Simply run `circleci build`
in the repository root. Note that you might have to increase the resources dedicated to Docker to around 4GB.

### Contributing

Pull requests for bug fixes are welcome, but before submitting new features or changes to current functionalities [open an issue](https://github.com/DataDog/dd-trace-go/issues/new)
and discuss your ideas or propose the changes you wish to make. After a resolution is reached a PR can be submitted for review.

For commit messages, try to use the same conventions as most Go projects, for example:
```
contrib/database/sql: use method context on QueryContext and ExecContext
QueryContext and ExecContext were using the wrong context to create
spans. Instead of using the method's argument they were using the
Prepare context, which was wrong.
Fixes #113
```
Please apply the same logic for Pull Requests, start with the package name, followed by a colon and a description of the change, just like
the official [Go language](https://github.com/golang/go/pulls).

### Documentation

The API is documented on [godoc](https://godoc.org/gopkg.in/DataDog/dd-trace-go.v1/ddtrace) as well as Datadog's [official documentation](https://docs.datadoghq.com/tracing/setup/go/). If you are migrating
from an older version of the tracer (e.g. 0.6.x) you may also find the [migration document](https://github.com/DataDog/dd-trace-go/blob/v1/MIGRATING.md) we've put together helpful.
10 changes: 9 additions & 1 deletion contrib/gocql/gocql/gocql.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ type params struct {
}

// WrapQuery wraps a gocql.Query into a traced Query under the given service name.
// Note that the returned Query structure embeds the original gocql.Query structure.
// This means that any method returning the query for chaining that is not part
// of this package's Query structure should be called before WrapQuery, otherwise
// the tracing context could be lost.
//
// To be more specific: it is ok (and recommended) to use and chain the return value
// of `WithContext` and `PageState` but not that of `Consistency`, `Trace`,
// `Observer`, etc.
func WrapQuery(q *gocql.Query, opts ...WrapOption) *Query {
cfg := new(queryConfig)
defaults(cfg)
Expand All @@ -55,7 +63,7 @@ func WrapQuery(q *gocql.Query, opts ...WrapOption) *Query {
return tq
}

// WithContext rewrites the original function so that ctx can be used for inheritance
// WithContext adds the specified context to the traced Query structure.
func (tq *Query) WithContext(ctx context.Context) *Query {
tq.traceContext = ctx
tq.Query.WithContext(ctx)
Expand Down
12 changes: 9 additions & 3 deletions contrib/gorilla/mux/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"net/http"

"gopkg.in/DataDog/dd-trace-go.v1/contrib/internal/httputil"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"

"github.com/gorilla/mux"
)
Expand Down Expand Up @@ -82,15 +84,19 @@ func NewRouter(opts ...RouterOption) *Router {
// all the incoming requests to the underlying multiplexer
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
var (
match mux.RouteMatch
route = "unknown"
match mux.RouteMatch
spanopts []ddtrace.StartSpanOption
route = "unknown"
)
// get the resource associated to this request
if r.Match(req, &match) && match.Route != nil {
if r, err := match.Route.GetPathTemplate(); err == nil {
route = r
}
if h, err := match.Route.GetHostTemplate(); err == nil {
spanopts = append(spanopts, tracer.Tag("mux.host", h))
}
}
resource := req.Method + " " + route
httputil.TraceAndServe(r.Router, w, req, r.config.serviceName, resource)
httputil.TraceAndServe(r.Router, w, req, r.config.serviceName, resource, spanopts...)
}
15 changes: 15 additions & 0 deletions contrib/gorilla/mux/mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ func TestHttpTracer(t *testing.T) {
}
}

func TestDomain(t *testing.T) {
assert := assert.New(t)
mt := mocktracer.Start()
defer mt.Stop()
mux := NewRouter(WithServiceName("my-service"))
mux.Handle("/200", okHandler()).Host("localhost")
r := httptest.NewRequest("GET", "http://localhost/200", nil)
w := httptest.NewRecorder()
mux.ServeHTTP(w, r)

spans := mt.FinishedSpans()
assert.Equal(1, len(spans))
assert.Equal("localhost", spans[0].Tag("mux.host"))
}

// TestImplementingMethods is a regression tests asserting that all the mux.Router methods
// returning the router will return the modified traced version of it and not the original
// router.
Expand Down
6 changes: 3 additions & 3 deletions contrib/internal/httputil/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import (
)

// TraceAndServe will apply tracing to the given http.Handler using the passed tracer under the given service and resource.
func TraceAndServe(h http.Handler, w http.ResponseWriter, r *http.Request, service, resource string) {
opts := []ddtrace.StartSpanOption{
func TraceAndServe(h http.Handler, w http.ResponseWriter, r *http.Request, service, resource string, spanopts ...ddtrace.StartSpanOption) {
opts := append([]ddtrace.StartSpanOption{
tracer.SpanType(ext.AppTypeWeb),
tracer.ServiceName(service),
tracer.ResourceName(resource),
tracer.Tag(ext.HTTPMethod, r.Method),
tracer.Tag(ext.HTTPURL, r.URL.Path),
}
}, spanopts...)
if spanctx, err := tracer.Extract(tracer.HTTPHeadersCarrier(r.Header)); err == nil {
opts = append(opts, tracer.ChildOf(spanctx))
}
Expand Down
17 changes: 9 additions & 8 deletions ddtrace/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func Example_opentracing() {
// Start a Datadog tracer, optionally providing a set of options,
// returning an opentracing.Tracer which wraps it.
t := opentracer.New(tracer.WithAgentAddr("host:port"))
defer tracer.Stop() // important for data integrity (flushes any leftovers)

// Use it with the Opentracing API. The (already started) Datadog tracer
// may be used in parallel with the Opentracing API if desired.
Expand All @@ -54,19 +55,19 @@ func Example_opentracing() {
// The code below illustrates a scenario of how one could use a mock tracer in tests
// to assert that spans are created correctly.
func Example_mocking() {
// Start the mock tracer.
// Setup the test environment: start the mock tracer.
mt := mocktracer.Start()
defer mt.Stop()

// Create a test span (this usually happens in your code).
span := tracer.StartSpan("test.span")
span.Finish()
// Run test code: in this example we will simply create a span to illustrate.
tracer.StartSpan("test.span").Finish()

// Query the mock tracer for finished spans.
// Assert the results: query the mock tracer for finished spans.
spans := mt.FinishedSpans()
if len(spans) != 1 {
// should only have 1 span
// fail
}
if spans[0].OperationName() != "test.span" {
// fail
}

// Run assertions...
}
3 changes: 3 additions & 0 deletions ddtrace/ext/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,7 @@ const (

// ErrorStack specifies the stack dump.
ErrorStack = "error.stack"

// Environment specifies the environment to use with a trace.
Environment = "env"
)
4 changes: 4 additions & 0 deletions ddtrace/internal/globaltracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ var (
func SetGlobalTracer(t ddtrace.Tracer) {
mu.Lock()
defer mu.Unlock()
if !Testing {
// avoid infinite loop when calling (*mocktracer.Tracer).Stop
globalTracer.Stop()
}
globalTracer = t
}

Expand Down
4 changes: 2 additions & 2 deletions ddtrace/tracer/span_msgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (z *span) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Meta == nil && zb0002 > 0 {
z.Meta = make(map[string]string, zb0002)
} else if len(z.Meta) > 0 {
for key, _ := range z.Meta {
for key := range z.Meta {
delete(z.Meta, key)
}
}
Expand All @@ -90,7 +90,7 @@ func (z *span) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Metrics == nil && zb0003 > 0 {
z.Metrics = make(map[string]float64, zb0003)
} else if len(z.Metrics) > 0 {
for key, _ := range z.Metrics {
for key := range z.Metrics {
delete(z.Metrics, key)
}
}
Expand Down
2 changes: 0 additions & 2 deletions ddtrace/tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ func Start(opts ...StartOption) {
if internal.Testing {
return // mock tracer active
}
t := internal.GetGlobalTracer()
internal.SetGlobalTracer(newTracer(opts...))
t.Stop()
}

// Stop stops the started tracer. Subsequent calls are valid but become no-op.
Expand Down
27 changes: 18 additions & 9 deletions ddtrace/tracer/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,8 @@ func newHTTPTransport(addr string) *httpTransport {
"Datadog-Meta-Tracer-Version": tracerVersion,
"Content-Type": "application/msgpack",
}
host, port, _ := net.SplitHostPort(addr)
if host == "" {
host = defaultHostname
}
if port == "" {
port = defaultPort
}
addr = fmt.Sprintf("%s:%s", host, port)
return &httpTransport{
traceURL: fmt.Sprintf("http://%s/v0.3/traces", addr),
traceURL: fmt.Sprintf("http://%s/v0.3/traces", resolveAddr(addr)),
client: &http.Client{
// We copy the transport to avoid using the default one, as it might be
// augmented with tracing and we don't want these calls to be recorded.
Expand Down Expand Up @@ -118,3 +110,20 @@ func (t *httpTransport) send(p *payload) error {
}
return nil
}

// resolveAddr resolves the given agent address and fills in any missing host
// and port using the defaults.
func resolveAddr(addr string) string {
host, port, err := net.SplitHostPort(addr)
if err != nil {
// no port in addr
host = addr
}
if host == "" {
host = defaultHostname
}
if port == "" {
port = defaultPort
}
return fmt.Sprintf("%s:%s", host, port)
}
17 changes: 17 additions & 0 deletions ddtrace/tracer/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ func TestTracesAgentIntegration(t *testing.T) {
}
}

func TestResolveAddr(t *testing.T) {
for _, tt := range []struct {
in, out string
}{
{"host", fmt.Sprintf("host:%s", defaultPort)},
{"www.my-address.com", fmt.Sprintf("www.my-address.com:%s", defaultPort)},
{"localhost", fmt.Sprintf("localhost:%s", defaultPort)},
{":1111", fmt.Sprintf("%s:1111", defaultHostname)},
{"", defaultAddress},
{"custom:1234", "custom:1234"},
} {
t.Run(tt.in, func(t *testing.T) {
assert.Equal(t, resolveAddr(tt.in), tt.out)
})
}
}

func TestTransportResponseError(t *testing.T) {
assert := assert.New(t)
ln, err := net.Listen("tcp4", ":0")
Expand Down

0 comments on commit 6550e97

Please sign in to comment.