我选择使用Go收集数据并希望将其可视化,因此我选择了Datadog,但没有找到Go用来向Datadog发送指标的示例或实时项目。但是在官方网站上说支持Go。
答案 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, "_")
}