github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/metric/graphite_exporter.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package metric 12 13 import ( 14 "context" 15 "fmt" 16 "os" 17 "time" 18 19 "github.com/cockroachdb/cockroach/pkg/util/log" 20 "github.com/cockroachdb/errors" 21 "github.com/prometheus/client_golang/prometheus/graphite" 22 ) 23 24 var errNoEndpoint = errors.New("external.graphite.endpoint is not set") 25 26 // GraphiteExporter scrapes PrometheusExporter for metrics and pushes 27 // them to a Graphite or Carbon server. 28 type GraphiteExporter struct { 29 pm *PrometheusExporter 30 } 31 32 // MakeGraphiteExporter returns an initialized graphite exporter. 33 func MakeGraphiteExporter(pm *PrometheusExporter) GraphiteExporter { 34 return GraphiteExporter{pm: pm} 35 } 36 37 type loggerFunc func(...interface{}) 38 39 // Println implements graphite.Logger. 40 func (lf loggerFunc) Println(v ...interface{}) { 41 lf(v...) 42 } 43 44 // Push metrics scraped from registry to Graphite or Carbon server. 45 // It converts the same metrics that are pulled by Prometheus into Graphite-format. 46 func (ge *GraphiteExporter) Push(ctx context.Context, endpoint string) error { 47 if endpoint == "" { 48 return errNoEndpoint 49 } 50 h, err := os.Hostname() 51 if err != nil { 52 return err 53 } 54 // Make the bridge. 55 var b *graphite.Bridge 56 if b, err = graphite.NewBridge(&graphite.Config{ 57 URL: endpoint, 58 Gatherer: ge.pm, 59 Prefix: fmt.Sprintf("%s.cockroach", h), 60 Timeout: 10 * time.Second, 61 ErrorHandling: graphite.AbortOnError, 62 Logger: loggerFunc(func(args ...interface{}) { 63 log.InfofDepth(ctx, 1, "", args...) 64 }), 65 }); err != nil { 66 return err 67 } 68 // Regardless of whether Push() errors, clear metrics. Only latest metrics 69 // are pushed. If there is an error, this will cause a gap in receiver. The 70 // receiver associates timestamp with when metric arrived, so storing missed 71 // metrics has no benefit. 72 defer ge.pm.clearMetrics() 73 return b.Push() 74 }