Skip to content

Commit

Permalink
Add support for Datadog monitoring
Browse files Browse the repository at this point in the history
PR: #22
  • Loading branch information
eikmadsen authored May 24, 2022
1 parent 47c271d commit 5e60b89
Show file tree
Hide file tree
Showing 9 changed files with 695 additions and 33 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ run: build

build: install
mkdir -p bin/
${BUILD_ARCH} go build -o bin/go-ranks ${PROJECT}/cmd/rankdb
${BUILD_ARCH} go build -ldflags "-X ${PROJECT}/api.gitcommit=${COMMIT}" -o bin/go-ranks ${PROJECT}/cmd/rankdb
${BUILD_ARCH} go build -o bin/go-ranks-cli ${PROJECT}/api/tool/rankdb-cli

dist: build
Expand Down
113 changes: 113 additions & 0 deletions api/datadog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package api

// Copyright 2019 Vivino. All rights reserved
//
// See LICENSE file for license details

import (
"context"
"fmt"
"net/http"
"strings"
"sync"

"github.com/Vivino/rankdb/log"
"github.com/Vivino/rankdb/log/loggoa"
"github.com/goadesign/goa"
shutdown "github.com/klauspost/shutdown2"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

type DatadogOptions struct {
Enabled bool
}

type datadogApp struct{}

func (d *datadogApp) Enabled() bool {
return d != nil
}

var ddApp *datadogApp
var gitcommit string = "0000000000000000000000000000000000000000"

func InitDatadog(ctx context.Context, o DatadogOptions) {
if !o.Enabled {
log.Info(ctx, "Datadog disabled by config")
return
}
ddApp = &datadogApp{}
log.Info(ctx, "Datadog enabled", "gitcommit", gitcommit)
tracer.Start(
tracer.WithServiceVersion(gitcommit),
)
log.Info(ctx, "Datadog tracer started")
shutdown.ThirdFn(func() {
// When the tracer is stopped, it will flush everything it has to the Datadog Agent before quitting.
// Make sure this line stays in your main function.
tracer.Stop()
log.Info(ctx, "Datadog tracer stopped")
})
}

// DatadogTx creates a request datadog middleware.
func DatadogTx() goa.Middleware {
return func(h goa.Handler) goa.Handler {
return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
r := goa.ContextRequest(ctx)
span := tracer.StartSpan("web.request",
tracer.SpanType("web"),
tracer.ResourceName(goa.ContextController(ctx)+"."+goa.ContextAction(ctx)),
)

span.SetTag("http.method", r.Method)
span.SetTag("http.url", r.URL.Path)
span.SetTag("source_ip", from(req))

if len(r.Params) > 0 {
for k, v := range r.Params {
span.SetTag("param_"+k, `"`+strings.Join(v, `","`)+`"`)
}
}
ierr := func(msg string, keyvals ...interface{}) {
for len(keyvals) > 0 {
key := fmt.Sprint(keyvals[0])
keyvals = keyvals[1:]
val := errMissingLogValue
if len(keyvals) > 0 {
val = fmt.Sprint(keyvals[0])
keyvals = keyvals[1:]
}
span.SetTag(key, val)
}
}
var ninfo int
var mu sync.Mutex
iinfo := func(msg string, keyvals ...interface{}) {
mu.Lock()
n := ninfo
ninfo++
mu.Unlock()
if n < 10 {
span.SetTag(fmt.Sprintf("info_msg_%d", n), formatMsg(msg, keyvals, false))
}
}
intLogger := log.Intercept(log.Logger(ctx), iinfo, ierr)
ctx = goa.WithLogger(ctx, loggoa.WrapGoa(intLogger))
ctx = log.WithLogger(ctx, intLogger)
var err error
defer func() {
resp := goa.ContextResponse(ctx)
span.SetTag("http.status_code", resp.Status)
span.SetTag("http.response.size", resp.Length)
if err != nil {
span.Finish(tracer.WithError(err))
} else {
span.Finish()
}
}()
err = h(ctx, rw, req)
return err
}
}
}
7 changes: 4 additions & 3 deletions api/multilist.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,13 @@ func (c *MultilistController) Backup(ctx *app.BackupMultilistContext) error {
// Create runs the create action.
func (c *MultilistController) Restore(ctx *app.RestoreMultilistContext) error {
// MultilistElementsController_Backup: start_implement
if done, err := UpdateRequest(ctx); err != nil {
done, err := UpdateRequest(ctx)
if err != nil {
return err
} else {
defer done()
}
defer done()
defer ctx.Body.Close()

info := backup.RestoreInfo{
Source: backup.WrapReader{ReadCloser: ctx.Body},
DB: db,
Expand Down
12 changes: 9 additions & 3 deletions api/newrelic.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,24 @@ type NewRelicOptions struct {
TxTracerThreshold duration
ExcludeAttributes []string
HostDisplayName string
Enabled bool
}

type newRelic struct {
app newrelic.Application
}

func (nr *newRelic) Enabled() bool {
return nr != nil
}

var nrApp *newRelic

func InitNewRelic(ctx context.Context, o NewRelicOptions) {
if !o.Enabled {
log.Info(ctx, "New Relic agent disabled by config")
return
}
nrCfg := newrelic.NewConfig(o.AppName, o.License)
if len(o.ExcludeAttributes) > 0 {
nrCfg.Attributes.Exclude = append(nrCfg.Attributes.Exclude, o.ExcludeAttributes...)
Expand Down Expand Up @@ -83,9 +92,6 @@ func InitNewRelic(ctx context.Context, o NewRelicOptions) {
func NewRelicTx() goa.Middleware {
return func(h goa.Handler) goa.Handler {
return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
if nrApp == nil {
return h(ctx, rw, req)
}
app := nrApp.app
txn := app.StartTransaction(goa.ContextController(ctx)+"."+goa.ContextAction(ctx), rw, req)
r := goa.ContextRequest(ctx)
Expand Down
5 changes: 4 additions & 1 deletion api/rankdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ var (
}

NewRelic NewRelicOptions

Datadog DatadogOptions
}
)

Expand Down Expand Up @@ -137,7 +139,8 @@ func StartServer(ctx context.Context, confData io.Reader, lr *logrus.Logger) err
shutdown.SetTimeoutN(shutdown.StagePS, config.ShutdownRequestWait.Duration)
}
InitNewRelic(ctx, config.NewRelic)
if nrApp != nil {
InitDatadog(ctx, config.Datadog)
if nrApp.Enabled() {
// Intercept error messages.
ctx = log.WithLogger(ctx, log.Intercept(log.Logger(ctx), nil, func(msg string, keyvals ...interface{}) {
params := make(map[string]interface{}, len(keyvals)/2)
Expand Down
7 changes: 6 additions & 1 deletion api/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ func StartServices(logger goa.LogAdapter, ctx context.Context, err error) {
service.Use(SetLogger())
service.Use(middleware.RequestID())
service.Use(middleware.LogRequest(false))
service.Use(NewRelicTx())
if nrApp.Enabled() {
service.Use(NewRelicTx())
}
if ddApp.Enabled() {
service.Use(DatadogTx())
}
service.Use(middleware.ErrorHandler(service, true))
service.Use(middleware.Recover())
service.Use(ShutdownMiddleware)
Expand Down
3 changes: 3 additions & 0 deletions conf/conf.stub.toml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ Enabled = true
OpTimeout = "1s"

[NewRelic]
Enabled = false
AppName = "rankdb"
License = ""
# TxTracerThreshold controls whether a transaction trace will be
Expand All @@ -170,3 +171,5 @@ ExcludeAttributes = ["password","header_Authorization","header_Cookie"]
# Relic UI. This is an optional setting.
HostDisplayName = ""

[Datadog]
Enabled = false
12 changes: 5 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,28 @@ require (
github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 // indirect
github.com/dimfeld/httptreemux v4.0.1+incompatible // indirect
github.com/goadesign/goa v1.4.1
github.com/gofrs/uuid v3.2.0+incompatible // indirect
github.com/google/go-cmp v0.5.6
github.com/google/go-cmp v0.5.7
github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4 // indirect
github.com/goreleaser/goreleaser v1.2.5
github.com/hashicorp/golang-lru v0.5.4
github.com/klauspost/compress v1.13.6
github.com/klauspost/compress v1.14.2
github.com/klauspost/readahead v1.3.1
github.com/klauspost/shutdown2 v1.1.0
github.com/manveru/faker v0.0.0-20160419072036-717f7cf83fb7 // indirect
github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b // indirect
github.com/mattn/go-colorable v0.1.12
github.com/newrelic/go-agent v1.5.0
github.com/onsi/ginkgo v1.8.0 // indirect
github.com/philhofer/fwd v1.0.0 // indirect
github.com/sirupsen/logrus v1.7.0
github.com/spf13/cobra v1.3.0
github.com/tinylib/msgp v1.1.0
github.com/tinylib/msgp v1.1.2
github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31 // indirect
github.com/ugorji/go/codec v1.1.7
github.com/yuin/gopher-lua v0.0.0-20160527050859-47f0f792b296 // indirect
github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea // indirect
go.etcd.io/bbolt v1.3.5
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
golang.org/x/tools v0.1.8
golang.org/x/tools v0.1.10
gopkg.in/DataDog/dd-trace-go.v1 v1.37.0
)

go 1.16
Loading

0 comments on commit 5e60b89

Please sign in to comment.