Skip to content

Commit

Permalink
Add local debug, Stackdriver trace and AWS X-Ray client
Browse files Browse the repository at this point in the history
  • Loading branch information
evalphobia committed Aug 7, 2017
1 parent 6abcb1a commit eb211f0
Show file tree
Hide file tree
Showing 21 changed files with 1,257 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@

# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

.DS_Store
174 changes: 172 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,172 @@
# apptracer
Multiple trace system wrapper for Stackdriver Trace asd AWS X-Ray
apptracer
----

[![GoDoc][1]][2] [![License: MIT][3]][4] [![Release][5]][6] [![Build Status][7]][8] [![Co decov Coverage][11]][12] [![Go Report Card][13]][14] [![Downloads][15]][16]

[1]: https://godoc.org/github.com/evalphobia/apptracer?status.svg
[2]: https://godoc.org/github.com/evalphobia/apptracer
[3]: https://img.shields.io/badge/License-MIT-blue.svg
[4]: LICENSE.md
[5]: https://img.shields.io/github/release/evalphobia/apptracer.svg
[6]: https://github.com/evalphobia/apptracer/releases/latest
[7]: https://travis-ci.org/evalphobia/apptracer.svg?branch=master
[8]: https://travis-ci.org/evalphobia/apptracer
[9]: https://coveralls.io/repos/evalphobia/apptracer/badge.svg?branch=master&service=github
[10]: https://coveralls.io/github/evalphobia/apptracer?branch=master
[11]: https://codecov.io/github/evalphobia/apptracer/coverage.svg?branch=master
[12]: https://codecov.io/github/evalphobia/apptracer?branch=master
[13]: https://goreportcard.com/badge/github.com/evalphobia/apptracer
[14]: https://goreportcard.com/report/github.com/evalphobia/apptracer
[15]: https://img.shields.io/github/downloads/evalphobia/apptracer/total.svg?maxAge=1800
[16]: https://github.com/evalphobia/apptracer/releases
[17]: https://img.shields.io/github/stars/evalphobia/apptracer.svg
[18]: https://github.com/evalphobia/apptracer/stargazers

`apptracer` is multiple trace system wrapper for Stackdriver Trace and AWS X-Ray.

# Usage

```go
import (
"github.com/evalphobia/apptracer"
"github.com/evalphobia/apptracer/platform/localdebug"
"github.com/evalphobia/apptracer/platform/stackdriver"
"github.com/evalphobia/apptracer/platform/xray"
)

// global singleton tracer.
var tracer *apptracer.AppTracer

// Init initializes trace setting.
func Init() {
// init tracer
tracer = apptracer.New(apptracer.Config{
Enable: true,
ServiceName: "my-cool-app",
Version: "v0.0.1",
Environment: "stage",
})

// add localdebug trace (show trace data on the given Logger).
if isDebug() {
localCli := localdebug.NewClient(localdebug.Config{
Logger: nil, // when it's nil, default std.err logger is set.
})
tracer.AddClient(localCli)
}

// add stackdriver trace
sdCli = stackdriver.NewClient(stackdriver.Config{
// auth setting
PrivateKey: "<GCP private key>",
Email: "<GCP email address>",
// Filename: "/path/to/pem.json", //

// sampling setting
SamplingFraction: 0.5, // sampling rate => 50%
SamplingQPS: 100.0, // max late => 100 req/s

// stackdriver trace can only filter by URI(name),
// so adding prefix can make difference between other service or environment in same projectID.
Prefix: "stage-my-cool-app",
}, "<GCP projectID>")
tracer.AddClient(sdCli)

// add aws xray trace
xrayCli := xray.NewClient(xray.Config{
AccessKey: "<AWS access key>",
SecretKey: "<AWS secret key>",
Region: "<AWS region>",

// sampling setting
SamplingFraction: 0.5,
SamplingQPS: 10.0,

// client sends span data on each checkpoint,
CheckpointSize: 10,
CheckpointInterval: 1*time.Second,
})
tracer.AddClient(xrayCli)
}

func MainFunction(ctx context.Context, r *http.Request) {
// Before use tracer and get span, you have to call Init() to initialzed tracer.

span := tracer.Trace(ctx).NewRootSpanFromRequest(r)
defer func(){
span.SetResponse(200).Finish()
// debug print for localdebug client
// span.OutputSummary()
}()

childFunction1(ctx)
childFunction2(ctx)
childFunction3(ctx)
}

func childFunction1(ctx context.Context) {
defer tracer.Trace(ctx).NewChildSpan("childFunction1").Finish()
// ... process something
}

// get user data
func childFunction2(ctx context.Context) error {
var user string
var err error

span := tracer.Trace(ctx).NewChildSpan("childFunction2")
defer func(){
span.SetUser(user).SetError(err).Finish()
}()

user, err = getUserName()
if err != nil {
return err
}

// process something ...

return nil
}


// exec sql
func childFunction3(ctx context.Context) error {
var sql string

span := tracer.Trace(ctx).NewChildSpan("childFunction3")
defer func(){
span.SetSQL(sql).Finish()
}()

sql = "SELECT * FROM users"
users, err = execSQL(sql)
if err != nil {
return err
}

// process something ...

return nil
}
```

## Supported Platform

- Google Stackdriver trace
- AWS X-Ray

## TODO

- Supports microservices tracing
- Supports other platforms
- New Relic
- LightStep

# Whats For?

One code for multiple tracing platforms!

- Compare and PoC tracing platforms .
- Multiple platforms with different sampling rates.

61 changes: 61 additions & 0 deletions apptracer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package apptracer

import (
"golang.org/x/net/context"

"github.com/evalphobia/apptracer/platform"
)

// AppTracer has multiple tracing platform clients
// to send tracing activity to the platforms.
type AppTracer struct {
Config
ClientList []PlatformClient
}

// New returns initialized AppTracer.
func New(conf Config) *AppTracer {
return &AppTracer{
Config: conf,
}
}

// AddClient adds PlatformClient into ClientList.
func (a *AppTracer) AddClient(c PlatformClient) {
a.ClientList = append(a.ClientList, c)
}

// Trace creates *TraceWrapper from context.
// TraceWrapper contains platform clients and generates span data for the platforms.
// TraceWrapper is cached in the context and you can get same TraceWrapper
// when pass the same context.
func (a *AppTracer) Trace(ctx context.Context) *TraceWrapper {
switch {
case !a.Config.Enable,
ctx == nil:
return &TraceWrapper{}
}

t, ok := ctx.Value(traceKey{}).(*TraceWrapper)
if ok {
return t
}

t = &TraceWrapper{
traceList: make([]platform.Trace, 0, len(a.ClientList)),
defaultLabels: a.Config.DefaultLabels,
serviceName: a.Config.ServiceName,
version: a.Config.Version,
environment: a.Config.Environment,
}
for _, cli := range a.ClientList {
tr, err := cli.NewTrace(ctx)
if err == nil {
t.traceList = append(t.traceList, tr)
}
}
t.ctx = context.WithValue(ctx, traceKey{}, t)
return t
}

type traceKey struct{} // used to get TraceWrapper from context.
26 changes: 26 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package apptracer

// Config contains tracing settings.
type Config struct {
// Only if Enable is true then tracing data sends to tracing platform.
Enable bool
// DefaultLabels sets labels into every tracing data(span).
DefaultLabels []Label
// ServiceName is your application name.
ServiceName string
// Version is your application version.
Version string
// Environment is your application version. (e.g. dev, stage, prod)
Environment string
}

// Label has key-value pair data for labeling.
type Label struct {
Key string
Value string
}

// NewLabel creates Label.
func NewLabel(key, value string) Label {
return Label{key, value}
}
32 changes: 32 additions & 0 deletions platform/localdebug/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package localdebug

import (
"log"
"os"

"golang.org/x/net/context"

"github.com/evalphobia/apptracer/platform"
)

// Client is struct of local debugging client for tracing.
type Client struct {
conf Config
}

// NewClient returns initialized *Client.
func NewClient(conf Config) *Client {
if conf.Logger == nil {
conf.Logger = log.New(os.Stderr, "", log.LstdFlags)
}

return &Client{
conf: conf,
}
}

func (c *Client) NewTrace(ctx context.Context) (platform.Trace, error) {
return &Trace{
logger: c.conf.Logger,
}, nil
}
7 changes: 7 additions & 0 deletions platform/localdebug/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package localdebug

import "log"

type Config struct {
Logger *log.Logger
}

0 comments on commit eb211f0

Please sign in to comment.