使用Go将数据发送到Datadog

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, "_")
}