使用Go将数据发送到Datadog

时间:2018-07-01 16:13:48

标签: go datadog

我选择使用Go收集数据并希望将其可视化,因此我选择了Datadog,但没有找到Go用来向Datadog发送指标的示例或实时项目。但是在官方网站上说支持Go。

2 个答案:

答案 0 :(得分:2)

第一步是在运行应用程序的服务器上安装DataDog代理:

https://docs.datadoghq.com/agent/

然后,您需要在DataDog代理中启用dashed服务:

https://docs.datadoghq.com/developers/dogstatsd/

之后,您可以使用任何连接到DogStatsD的Go库将指标发送到statsd代理。

例如:

https://github.com/DataDog/datadog-go

https://github.com/go-kit/kit/tree/master/metrics/statsd

这是一个使用第一个库发送一些计数的示例程序:

statsd

答案 1 :(得分:0)

这里是DD的便捷包装。它使用ENV vars对其进行配置,但是它是一个很好的实用程序,用于在后台运行代理后打包常见的DD调用。

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