feat(instrumentation): work on settings model for internal metrics publishing, #4696

This commit is contained in:
Torkel Ödegaard
2016-06-02 14:32:17 +02:00
parent 74101eaf7c
commit 6b2a4fe8e8
10 changed files with 163 additions and 70 deletions

View File

@@ -9,40 +9,36 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/metrics/senders"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/setting"
)
type MetricSender interface {
Send(metrics map[string]interface{}) error
func Init() {
go instrumentationLoop()
}
func StartUsageReportLoop() chan struct{} {
func instrumentationLoop() chan struct{} {
M_Instance_Start.Inc(1)
hourTicker := time.NewTicker(time.Hour * 24)
secondTicker := time.NewTicker(time.Second * 10)
settings := readSettings()
sender := &receiver.GraphiteSender{
Host: "localhost",
Port: "2003",
Protocol: "tcp",
Prefix: "grafana.",
}
onceEveryDayTick := time.NewTicker(time.Hour * 24)
secondTicker := time.NewTicker(time.Second * time.Duration(settings.IntervalSeconds))
for {
select {
case <-hourTicker.C:
case <-onceEveryDayTick.C:
sendUsageStats()
case <-secondTicker.C:
sendMetricUsage(sender)
if settings.Enabled {
sendMetrics(settings)
}
}
}
}
func sendMetricUsage(sender MetricSender) {
func sendMetrics(settings *MetricSettings) {
metrics := map[string]interface{}{}
MetricStats.Each(func(name string, i interface{}) {
@@ -63,13 +59,16 @@ func sendMetricUsage(sender MetricSender) {
}
})
err := sender.Send(metrics)
if err != nil {
log.Error(1, "Failed to send metrics:", err)
for _, publisher := range settings.Publishers {
publisher.Publish(metrics)
}
}
func sendUsageStats() {
if !setting.ReportingEnabled {
return
}
log.Trace("Sending anonymous usage stats to stats.grafana.org")
version := strings.Replace(setting.BuildVersion, ".", "_", -1)

View File

@@ -0,0 +1,55 @@
package publishers
import (
"bytes"
"fmt"
"net"
"time"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/setting"
)
type GraphitePublisher struct {
Address string
Protocol string
Prefix string
}
func CreateGraphitePublisher() (*GraphitePublisher, error) {
graphiteSection, err := setting.Cfg.GetSection("metrics.graphite")
if err != nil {
return nil, nil
}
graphiteReceiver := &GraphitePublisher{}
graphiteReceiver.Protocol = "tcp"
graphiteReceiver.Address = graphiteSection.Key("address").MustString("localhost:2003")
graphiteReceiver.Prefix = graphiteSection.Key("prefix").MustString("service.grafana.%(instance_name)s")
return graphiteReceiver, nil
}
func (this *GraphitePublisher) Publish(metrics map[string]interface{}) {
conn, err := net.DialTimeout(this.Protocol, this.Address, time.Second*5)
if err != nil {
log.Error(3, "Metrics: GraphitePublisher: Failed to connect to %s!", err)
return
}
buf := bytes.NewBufferString("")
now := time.Now().Unix()
for key, value := range metrics {
metricName := this.Prefix + key
line := fmt.Sprintf("%s %d %d\n", metricName, value, now)
buf.WriteString(line)
}
log.Trace("Metrics: GraphitePublisher.Publish() \n%s", buf)
_, err = conn.Write(buf.Bytes())
if err != nil {
log.Error(3, "Metrics: GraphitePublisher: Failed to send metrics! %s", err)
}
}

View File

@@ -1,44 +0,0 @@
package receiver
import (
"bytes"
"fmt"
"github.com/grafana/grafana/pkg/log"
"net"
"time"
)
type GraphiteSender struct {
Host string
Port string
Protocol string
Prefix string
}
func (this *GraphiteSender) Send(metrics map[string]interface{}) error {
log.Debug("GraphiteSender: Sending metrics to graphite")
address := fmt.Sprintf("%s:%s", this.Host, this.Port)
conn, err := net.DialTimeout(this.Protocol, address, time.Second*5)
if err != nil {
return fmt.Errorf("Graphite Sender: Failed to connec to %s!", err)
}
buf := bytes.NewBufferString("")
now := time.Now().Unix()
for key, value := range metrics {
metricName := this.Prefix + key
line := fmt.Sprintf("%s %d %d\n", metricName, value, now)
log.Debug("SendMetric: sending %s", line)
buf.WriteString(line)
}
_, err = conn.Write(buf.Bytes())
if err != nil {
return fmt.Errorf("Graphite Sender: Failed to send metrics! %s", err)
}
return nil
}

47
pkg/metrics/settings.go Normal file
View File

@@ -0,0 +1,47 @@
package metrics
import (
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/metrics/publishers"
"github.com/grafana/grafana/pkg/setting"
)
type MetricPublisher interface {
Publish(metrics map[string]interface{})
}
type MetricSettings struct {
Enabled bool
IntervalSeconds int64
Publishers []MetricPublisher
}
func readSettings() *MetricSettings {
var settings = &MetricSettings{
Enabled: false,
Publishers: make([]MetricPublisher, 0),
}
var section, err = setting.Cfg.GetSection("metrics")
if err != nil {
log.Fatal(3, "Unable to find metrics config section")
return nil
}
settings.Enabled = section.Key("enabled").MustBool(false)
settings.IntervalSeconds = section.Key("interval_seconds").MustInt64(10)
if !settings.Enabled {
return settings
}
if graphitePublisher, err := publishers.CreateGraphitePublisher(); err != nil {
log.Error(3, "Metrics: Failed to init Graphite metric publisher", err)
} else if graphitePublisher != nil {
log.Info("Metrics: Internal metrics publisher Graphite initialized")
settings.Publishers = append(settings.Publishers, graphitePublisher)
}
return settings
}