Skip to content

Commit

Permalink
fix: revisit errors package, match the error
Browse files Browse the repository at this point in the history
  • Loading branch information
burningalchemist committed Oct 7, 2023
1 parent 6c7c328 commit 55ac709
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 33 deletions.
44 changes: 25 additions & 19 deletions cmd/sql_exporter/promhttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"compress/gzip"
"context"
"errors"
"fmt"
"io"
"net/http"
"strconv"
Expand All @@ -24,6 +23,13 @@ const (
contentLengthHeader string = "Content-Length"
contentEncodingHeader string = "Content-Encoding"
acceptEncodingHeader string = "Accept-Encoding"
scrapeTimeoutHeader string = "X-Prometheus-Scrape-Timeout-Seconds"
)

const (
prometheusHeaderErr = "Failed to parse timeout from Prometheus header"
noMetricsGathered = "No metrics gathered"
noMetricsEncoded = "No metrics encoded"
)

// ExporterHandlerFor returns an http.Handler for the provided Exporter.
Expand All @@ -36,15 +42,19 @@ func ExporterHandlerFor(exporter sql_exporter.Exporter) http.Handler {
gatherer := prometheus.Gatherers{exporter.WithContext(ctx)}
mfs, err := gatherer.Gather()
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
klog.Errorf("Timeout collecting metrics from target: %s", err)
}
if len(mfs) == 0 {
klog.Errorf("No metrics gathered: %s", err)
http.Error(w, "No metrics gathered, "+err.Error(), http.StatusInternalServerError)
klog.Errorf("%s: %s", noMetricsGathered, err)
http.Error(w, noMetricsGathered+", "+err.Error(), http.StatusInternalServerError)
return
}
klog.Errorf("Error gathering metrics: %s", err)
multierr := err.(prometheus.MultiError)
for _, err := range multierr {
if errors.Is(err, context.DeadlineExceeded) {
klog.Errorf("%s: timeout collecting metrics", err)
} else {
klog.Errorf("Error gathering metrics: %s", err)
}
}
}

contentType := expfmt.Negotiate(req.Header)
Expand All @@ -63,12 +73,13 @@ func ExporterHandlerFor(exporter sql_exporter.Exporter) http.Handler {
closer.Close()
}
if errs.MaybeUnwrap() != nil && buf.Len() == 0 {
http.Error(w, "No metrics encoded, "+errs.Error(), http.StatusInternalServerError)
klog.Errorf("%s: %s", noMetricsEncoded, errs)
http.Error(w, noMetricsEncoded+", "+errs.Error(), http.StatusInternalServerError)
return
}
header := w.Header()
header.Set(contentTypeHeader, string(contentType))
header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
header.Set(contentLengthHeader, strconv.Itoa(buf.Len()))
if encoding != "" {
header.Set(contentEncodingHeader, encoding)
}
Expand All @@ -80,19 +91,14 @@ func contextFor(req *http.Request, exporter sql_exporter.Exporter) (context.Cont
timeout := time.Duration(0)
configTimeout := time.Duration(exporter.Config().Globals.ScrapeTimeout)
// If a timeout is provided in the Prometheus header, use it.
if v := req.Header.Get("X-Prometheus-Scrape-Timeout-Seconds"); v != "" {
if v := req.Header.Get(scrapeTimeoutHeader); v != "" {
timeoutSeconds, err := strconv.ParseFloat(v, 64)
if err != nil {
parseError := errors.Unwrap(err)
switch {
case errors.Is(parseError, strconv.ErrSyntax):
{
klog.Errorf("Failed to parse timeout from Prometheus header: unsupported value")
}
case errors.Is(parseError, strconv.ErrRange):
{
klog.Errorf("Failed to parse timeout from Prometheus header: value is out of range")
}
case errors.Is(err, strconv.ErrSyntax):
klog.Errorf("%s: unsupported value", prometheusHeaderErr)
case errors.Is(err, strconv.ErrRange):
klog.Errorf("%s: value out of range", prometheusHeaderErr)
}
} else {
timeout = time.Duration(timeoutSeconds * float64(time.Second))
Expand Down
28 changes: 17 additions & 11 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,24 @@ type WithContext interface {
error

Context() string
RawError() string
RawError() error
Unwrap() error
}

// withContext implements WithContext.
type withContext struct {
context string
err string
err error
}

// New creates a new WithContext.
func New(context, err string) WithContext {
return &withContext{context, err}
func New(context string, err string) WithContext {
return &withContext{context, fmt.Errorf(err)}
}

// Errorf formats according to a format specifier and returns a new WithContext.
func Errorf(context, format string, a ...any) WithContext {
return &withContext{context, fmt.Sprintf(format, a...)}
return &withContext{context, fmt.Errorf(format, a...)}
}

// Wrap returns a WithContext wrapping err. If err is nil, it returns nil. If err is a WithContext, it is returned
Expand All @@ -40,7 +41,7 @@ func Wrap(context string, err error) WithContext {
if w, ok := err.(WithContext); ok {
return w
}
return &withContext{context, err.Error()}
return &withContext{context, err}
}

// Wrapf returns a WithContext that prepends a formatted message to err.Error(). If err is nil, it returns nil. If err
Expand All @@ -55,17 +56,17 @@ func Wrapf(context string, err error, format string, a ...any) WithContext {
prefix = fmt.Sprintf(format, a...)
}
if w, ok := err.(WithContext); ok {
return &withContext{w.Context(), prefix + ": " + w.RawError()}
return &withContext{w.Context(), fmt.Errorf("%s: %w", prefix, w.RawError())}
}
return &withContext{context, prefix + ": " + err.Error()}
return &withContext{context, err}
}

// Error implements error.
func (w *withContext) Error() string {
if len(w.context) == 0 {
return w.err
return w.err.Error()
}
return "[" + w.context + "] " + w.err
return "[" + w.context + "] " + w.err.Error()
}

// Context implements WithContext.
Expand All @@ -74,6 +75,11 @@ func (w *withContext) Context() string {
}

// RawError implements WithContext.
func (w *withContext) RawError() string {
func (w *withContext) RawError() error {
return w.err
}

// Unwrap implements WithContext.
func (w *withContext) Unwrap() error {
return fmt.Errorf("[%s] %w", w.context, w.err)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,4 @@ require (
howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
)

replace k8s.io/klog/v2 => github.com/simonpasquier/klog-gokit/v3 v3.1.0
replace k8s.io/klog/v2 => github.com/simonpasquier/klog-gokit/v3 v3.3.0
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/simonpasquier/klog-gokit/v3 v3.1.0 h1:xQGqjZdgo1lFA4eZ9PcGnKKXgIPz9t+jc25q/fXooIE=
github.com/simonpasquier/klog-gokit/v3 v3.1.0/go.mod h1:+WRhGy707Lp2Q4r727m9Oc7FxazOHgW76FIyCr23nus=
github.com/simonpasquier/klog-gokit/v3 v3.3.0 h1:HMzH999kO5gEgJTaWWO+xjncW5oycspcsBnjn9b853Q=
github.com/simonpasquier/klog-gokit/v3 v3.3.0/go.mod h1:uSbnWC3T7kt1dQyY9sjv0Ao1SehMAJdVnUNSKhjaDsg=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
Expand Down

0 comments on commit 55ac709

Please sign in to comment.