Skip to content

Commit

Permalink
engine: report go version on startup
Browse files Browse the repository at this point in the history
The first time you report any metric, additionally report the running
Go version. Add two flags that can be used to disable this behavior.
  • Loading branch information
kevinburkesegment committed Jun 19, 2024
1 parent cf67f29 commit 9611584
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 4 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,3 +385,16 @@ func main() {
// ...
}
```

### Errata

By default, the stats library will report the running go version when you
invoke NewEngine() as three metrics:

- `go_version.major`
- `go_version.minor`
- `go_version.patch`

Set `STATS_DISABLE_GO_VERSION_REPORTING` to `true` in your environment, or set
`stats.GoVersionReportingEnabled` to `false` before collecting any metrics, to
disable this behavior.
1 change: 1 addition & 0 deletions datadog/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func TestServer(t *testing.T) {
}

func startTestServer(t *testing.T, handler Handler) (addr string, closer io.Closer) {
t.Helper()
conn, err := net.ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Error(err)
Expand Down
42 changes: 38 additions & 4 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ import (
"os"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"time"
)

// An Engine carries the context for producing metrics, it is configured by
// An Engine carries the context for producing metrics. It is configured by
// setting the exported fields or using the helper methods to create sub-engines
// that inherit the configuration of the base they were created from.
//
// The program must not modify the engine's handler, prefix, or tags after it
// started using it. If changes need to be made new engines must be created by
// starts using them. If changes need to be made new engines must be created by
// calls to WithPrefix or WithTags.
type Engine struct {
// The measure handler that the engine forwards measures to.
Expand All @@ -26,7 +29,7 @@ type Engine struct {
//
// The list of tags has to be sorted. This is automatically managed by the
// helper methods WithPrefix, WithTags and the NewEngine function. A program
// that manipulates this field directly has to respect this requirement.
// that manipulates this field directly must respect this requirement.
Tags []Tag

// This cache keeps track of the generated measure structures to avoid
Expand All @@ -35,16 +38,19 @@ type Engine struct {
// The cached values include the engine prefix in the measure names, which
// is why the cache must be local to the engine.
cache measureCache

once sync.Once
}

// NewEngine creates and returns a new engine configured with prefix, handler,
// and tags.
func NewEngine(prefix string, handler Handler, tags ...Tag) *Engine {
return &Engine{
e := &Engine{
Handler: handler,
Prefix: prefix,
Tags: SortTags(copyTags(tags)),
}
return e
}

// Register adds handler to eng.
Expand Down Expand Up @@ -138,7 +144,35 @@ func (eng *Engine) ClockAt(name string, start time.Time, tags ...Tag) *Clock {
}
}

var GoVersionReportingEnabled = os.Getenv("STATS_DISABLE_GO_VERSION_REPORTING") != "true"

func (eng *Engine) measure(t time.Time, name string, value interface{}, ftype FieldType, tags ...Tag) {
if GoVersionReportingEnabled {
eng.once.Do(func() {
vsn := strings.TrimPrefix(runtime.Version(), "go")
parts := strings.Split(vsn, ".")
// older Go version might be "go1.13"
if len(parts) == 2 || len(parts) == 3 {
maj, err := strconv.Atoi(parts[0])
if err == nil {
eng.measure_(t, "go_version.major", maj, Gauge)
}
min, err := strconv.Atoi(parts[1])
if err == nil {
eng.measure_(t, "go_version.minor", min, Gauge)
}
if len(parts) == 3 {
patch, err := strconv.Atoi(parts[2])
if err == nil {
eng.measure_(t, "go_version.patch", patch, Gauge)
}
}
}
})
}
eng.measure_(t, name, value, ftype, tags...)
}
func (eng *Engine) measure_(t time.Time, name string, value interface{}, ftype FieldType, tags ...Tag) {
name, field := splitMeasureField(name)
mp := measureArrayPool.Get().(*[1]Measure)

Expand Down

0 comments on commit 9611584

Please sign in to comment.