Skip to content

Commit 4c4af58

Browse files
committed
graphite: refactor error handling
Signed-off-by: ifireice <[email protected]> Signed-off-by: Darya Melentsova <[email protected]>
1 parent 671a2f0 commit 4c4af58

File tree

2 files changed

+52
-56
lines changed

2 files changed

+52
-56
lines changed

prometheus/graphite/bridge.go

Lines changed: 15 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,11 @@ const (
3838
millisecondsPerSecond = 1000
3939
)
4040

41-
// HandlerErrorHandling defines how a Handler serving metrics will handle
42-
// errors.
43-
type HandlerErrorHandling int
41+
// ErrorHandler is a function that handles errors
42+
type ErrorHandler func(err error)
4443

45-
// These constants cause handlers serving metrics to behave as described if
46-
// errors are encountered.
47-
const (
48-
// Ignore errors and try to push as many metrics to Graphite as possible.
49-
ContinueOnError HandlerErrorHandling = iota
50-
51-
// Abort the push to Graphite upon the first error encountered.
52-
AbortOnError
53-
)
44+
// DefaultErrorHandler skips received errors
45+
var DefaultErrorHandler = func(err error) {}
5446

5547
// Config defines the Graphite bridge config.
5648
type Config struct {
@@ -72,13 +64,8 @@ type Config struct {
7264
// The Gatherer to use for metrics. Defaults to prometheus.DefaultGatherer.
7365
Gatherer prometheus.Gatherer
7466

75-
// The logger that messages are written to. Defaults to no logging.
76-
Logger Logger
77-
78-
// ErrorHandling defines how errors are handled. Note that errors are
79-
// logged regardless of the configured ErrorHandling provided Logger
80-
// is not nil.
81-
ErrorHandling HandlerErrorHandling
67+
// ErrorHandler defines how errors are handled.
68+
ErrorHandler ErrorHandler
8269
}
8370

8471
// Bridge pushes metrics to the configured Graphite server.
@@ -89,19 +76,11 @@ type Bridge struct {
8976
interval time.Duration
9077
timeout time.Duration
9178

92-
errorHandling HandlerErrorHandling
93-
logger Logger
79+
errorHandler ErrorHandler
9480

9581
g prometheus.Gatherer
9682
}
9783

98-
// Logger is the minimal interface Bridge needs for logging. Note that
99-
// log.Logger from the standard library implements this interface, and it is
100-
// easy to implement by custom loggers, if they don't do so already anyway.
101-
type Logger interface {
102-
Println(v ...interface{})
103-
}
104-
10584
// NewBridge returns a pointer to a new Bridge struct.
10685
func NewBridge(c *Config) (*Bridge, error) {
10786
b := &Bridge{}
@@ -119,10 +98,6 @@ func NewBridge(c *Config) (*Bridge, error) {
11998
b.g = c.Gatherer
12099
}
121100

122-
if c.Logger != nil {
123-
b.logger = c.Logger
124-
}
125-
126101
if c.Prefix != "" {
127102
b.prefix = c.Prefix
128103
}
@@ -140,7 +115,7 @@ func NewBridge(c *Config) (*Bridge, error) {
140115
b.timeout = c.Timeout
141116
}
142117

143-
b.errorHandling = c.ErrorHandling
118+
b.errorHandler = c.ErrorHandler
144119

145120
return b, nil
146121
}
@@ -153,9 +128,7 @@ func (b *Bridge) Run(ctx context.Context) {
153128
for {
154129
select {
155130
case <-ticker.C:
156-
if err := b.Push(); err != nil && b.logger != nil {
157-
b.logger.Println("error pushing to Graphite:", err)
158-
}
131+
b.errorHandler(b.Push())
159132
case <-ctx.Done():
160133
return
161134
}
@@ -165,17 +138,12 @@ func (b *Bridge) Run(ctx context.Context) {
165138
// Push pushes Prometheus metrics to the configured Graphite server.
166139
func (b *Bridge) Push() error {
167140
mfs, err := b.g.Gather()
168-
if err != nil || len(mfs) == 0 {
169-
switch b.errorHandling {
170-
case AbortOnError:
171-
return err
172-
case ContinueOnError:
173-
if b.logger != nil {
174-
b.logger.Println("continue on error:", err)
175-
}
176-
default:
177-
panic("unrecognized error handling value")
178-
}
141+
if err != nil {
142+
return err
143+
}
144+
145+
if len(mfs) == 0 {
146+
return nil
179147
}
180148

181149
conn, err := net.DialTimeout("tcp", b.url, b.timeout)

prometheus/graphite/bridge_test.go

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ import (
1919
"context"
2020
"fmt"
2121
"io"
22-
"log"
2322
"net"
24-
"os"
2523
"reflect"
2624
"regexp"
2725
"sort"
@@ -438,13 +436,12 @@ type mockGraphite struct {
438436

439437
func ExampleBridge() {
440438
b, err := NewBridge(&Config{
441-
URL: "graphite.example.org:3099",
442-
Gatherer: prometheus.DefaultGatherer,
443-
Prefix: "prefix",
444-
Interval: 15 * time.Second,
445-
Timeout: 10 * time.Second,
446-
ErrorHandling: AbortOnError,
447-
Logger: log.New(os.Stdout, "graphite bridge: ", log.Lshortfile),
439+
URL: "graphite.example.org:3099",
440+
Gatherer: prometheus.DefaultGatherer,
441+
Prefix: "prefix",
442+
Interval: 15 * time.Second,
443+
Timeout: 10 * time.Second,
444+
ErrorHandler: func(err error) {},
448445
})
449446
if err != nil {
450447
panic(err)
@@ -467,3 +464,34 @@ func ExampleBridge() {
467464
// Start pushing metrics to Graphite in the Run() loop.
468465
b.Run(ctx)
469466
}
467+
468+
func TestErrorHandler(t *testing.T) {
469+
var internalError error
470+
c := &Config{
471+
URL: "graphite.example.org:3099",
472+
Gatherer: prometheus.DefaultGatherer,
473+
Prefix: "prefix",
474+
Interval: 5 * time.Second,
475+
Timeout: 2 * time.Second,
476+
ErrorHandler: func(err error) { internalError = err },
477+
}
478+
b, err := NewBridge(c)
479+
if err != nil {
480+
panic(err)
481+
}
482+
483+
// Create a Context to control stopping the Run() loop that pushes
484+
// metrics to Graphite. Multiplied by 2, because we need Run to be executed at least one time.
485+
ctx, cancel := context.WithTimeout(context.Background(), c.Interval*2)
486+
defer cancel()
487+
488+
// Start pushing metrics to Graphite in the Run() loop.
489+
b.Run(ctx)
490+
491+
// There are obviously no hosts like "graphite.example.com" available during the tests.
492+
expError := fmt.Errorf("dial tcp: lookup graphite.example.org: no such host")
493+
494+
if internalError.Error() != expError.Error() {
495+
t.Fatalf("Expected: '%s', actual: '%s'", expError, internalError)
496+
}
497+
}

0 commit comments

Comments
 (0)