i'm collect data using Go and want to visualize it, i chose Datadog, but didn't find examples or live projects where Go used for sending metrics to Datadog. But in offical site says that Go is supported.
First step is to install the DataDog agent on the server in which you are running your application:
https://docs.datadoghq.com/agent/
You then need to enable the DogStatsD
service in the DataDog agent:
https://docs.datadoghq.com/developers/dogstatsd/
After that, you can send metrics to the statsd
agent using any Go library that connects to statsd
.
For example:
https://github.com/DataDog/datadog-go
https://github.com/go-kit/kit/tree/master/metrics/statsd
Here's an example program sending some counts using the first library:
import (
"github.com/DataDog/datadog-go/statsd"
"log"
)
func main() {
// Create the client
c, err := statsd.New("127.0.0.1:8125")
if err != nil {
log.Fatal(err)
}
// Prefix every metric with the app name
c.Namespace = "myapp."
// Count two events
err = c.Count("my_counter", 2, nil, 1)
if err != nil {
log.Fatal(err)
}
// Close the client
err = c.Close()
if err != nil {
log.Fatal(err)
}
}
Here is a convenience wrapper for DD. It uses ENV vars to configure it, but it's a nice utility to package out common DD calls once you have the agent running in the background.
package datadog
import (
"errors"
"log"
"os"
"regexp"
"sort"
"sync"
"time"
"github.com/DataDog/datadog-go/statsd"
)
var (
mu sync.RWMutex
client = newClient()
GlobalTags Tags = Tags{}
)
// Sometimes, the connection to datadog can fail, but because UDP is connectionless, we don't get insight into
// those failures. This loop just makes sure that once a minute, the client is refreshed.
func init() {
go func() {
for range time.Tick(time.Minute) {
c := newClient()
if c != nil {
mu.Lock()
client = c
mu.Unlock()
}
}
}()
}
func newClient() *statsd.Client {
hp := os.Getenv("DOGSTATSD_HOST_PORT")
if hp == "" {
hp = "127.0.0.1:8125"
}
c, err := statsd.New(hp)
if err != nil {
log.Println("stat/datadog", "Could not create a datadog statsd client.", "error", err)
}
return c
}
type Tags map[string]string
func (tags Tags) StringSlice() []string {
var stringSlice []string
for k, v := range tags {
if k != "" && v != "" {
stringSlice = append(stringSlice, formatName(k)+":"+formatName(v))
}
}
sort.Strings(stringSlice)
return stringSlice
}
func mergeTags(tagsSlice []Tags) Tags {
merged := Tags{}
for k, v := range GlobalTags {
merged[formatName(k)] = formatName(v)
}
for _, tags := range tagsSlice {
for k, v := range tags {
merged[formatName(k)] = formatName(v)
}
}
return merged
}
func Gauge(name string, value float64, tags ...Tags) error {
mu.RLock()
defer mu.RUnlock()
if client == nil {
return errors.New("datadog: nil client")
}
return client.Gauge(formatName(name), value, mergeTags(tags).StringSlice(), 1)
}
func Count(name string, value int64, tags ...Tags) error {
mu.RLock()
defer mu.RUnlock()
if client == nil {
return errors.New("datadog: nil client")
}
return client.Count(formatName(name), value, mergeTags(tags).StringSlice(), 1)
}
func Histogram(name string, value float64, tags ...Tags) error {
mu.RLock()
defer mu.RUnlock()
if client == nil {
return errors.New("datadog: nil client")
}
return client.Histogram(formatName(name), value, mergeTags(tags).StringSlice(), 1)
}
func Incr(name string, tags ...Tags) error {
mu.RLock()
defer mu.RUnlock()
if client == nil {
return errors.New("datadog: nil client")
}
return client.Incr(formatName(name), mergeTags(tags).StringSlice(), 1)
}
func Decr(name string, tags ...Tags) error {
mu.RLock()
defer mu.RUnlock()
if client == nil {
return errors.New("datadog: nil client")
}
return client.Decr(formatName(name), mergeTags(tags).StringSlice(), 1)
}
func Set(name string, value string, tags ...Tags) error {
mu.RLock()
defer mu.RUnlock()
if client == nil {
return errors.New("datadog: nil client")
}
return client.Set(formatName(name), value, mergeTags(tags).StringSlice(), 1)
}
func Timing(name string, value time.Duration, tags ...Tags) error {
mu.RLock()
defer mu.RUnlock()
if client == nil {
return errors.New("datadog: nil client")
}
return client.Timing(formatName(name), value, mergeTags(tags).StringSlice(), 1)
}
// Datadog allows '.', '_' and alphas only.
// If we don't validate this here then the datadog error logs can fill up disk really quickly
var nameRegex = regexp.MustCompile(`[^\._a-zA-Z0-9]+`)
func formatName(name string) string {
return nameRegex.ReplaceAllString(name, "_")
}