Skip to content

Commit 2ab9611

Browse files
authored
Don't try to connect to nginx on client creation (#504)
The client now is created without making a call to nginx. When Collect() is called we try to get the metrics from nginx and if it's not available it will set 'up' to 0 and not fail anymore.
1 parent 06af414 commit 2ab9611

File tree

3 files changed

+8
-117
lines changed

3 files changed

+8
-117
lines changed

client/nginx.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,13 @@ type StubConnections struct {
3737
}
3838

3939
// NewNginxClient creates an NginxClient.
40-
func NewNginxClient(httpClient *http.Client, apiEndpoint string) (*NginxClient, error) {
40+
func NewNginxClient(httpClient *http.Client, apiEndpoint string) *NginxClient {
4141
client := &NginxClient{
4242
apiEndpoint: apiEndpoint,
4343
httpClient: httpClient,
4444
}
4545

46-
_, err := client.GetStubStats()
47-
return client, err
46+
return client
4847
}
4948

5049
// GetStubStats fetches the stub_status metrics.

exporter.go

+6-34
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"github.com/nginxinc/nginx-prometheus-exporter/collector"
2020

2121
"github.com/alecthomas/kingpin/v2"
22-
"github.com/go-kit/log"
2322
"github.com/go-kit/log/level"
2423
"github.com/prometheus/client_golang/prometheus"
2524
"github.com/prometheus/client_golang/prometheus/promhttp"
@@ -61,23 +60,6 @@ func createPositiveDurationFlag(s kingpin.Settings) (target *time.Duration) {
6160
return
6261
}
6362

64-
func createClientWithRetries(getClient func() (interface{}, error), retries uint, retryInterval time.Duration, logger log.Logger) (interface{}, error) {
65-
var err error
66-
var nginxClient interface{}
67-
68-
for i := 0; i <= int(retries); i++ {
69-
nginxClient, err = getClient()
70-
if err == nil {
71-
return nginxClient, nil
72-
}
73-
if i < int(retries) {
74-
level.Error(logger).Log("msg", fmt.Sprintf("Could not create Nginx Client. Retrying in %v...", retryInterval))
75-
time.Sleep(retryInterval)
76-
}
77-
}
78-
return nil, err
79-
}
80-
8163
func parseUnixSocketAddress(address string) (string, string, error) {
8264
addressParts := strings.Split(address, ":")
8365
addressPartsLength := len(addressParts)
@@ -106,11 +88,9 @@ var (
10688
sslCaCert = kingpin.Flag("nginx.ssl-ca-cert", "Path to the PEM encoded CA certificate file used to validate the servers SSL certificate.").Default("").Envar("SSL_CA_CERT").String()
10789
sslClientCert = kingpin.Flag("nginx.ssl-client-cert", "Path to the PEM encoded client certificate file to use when connecting to the server.").Default("").Envar("SSL_CLIENT_CERT").String()
10890
sslClientKey = kingpin.Flag("nginx.ssl-client-key", "Path to the PEM encoded client certificate key file to use when connecting to the server.").Default("").Envar("SSL_CLIENT_KEY").String()
109-
nginxRetries = kingpin.Flag("nginx.retries", "A number of retries the exporter will make on start to connect to the NGINX stub_status page/NGINX Plus API before exiting with an error.").Default("0").Envar("NGINX_RETRIES").Uint()
11091

11192
// Custom command-line flags
112-
timeout = createPositiveDurationFlag(kingpin.Flag("nginx.timeout", "A timeout for scraping metrics from NGINX or NGINX Plus.").Default("5s").Envar("TIMEOUT"))
113-
nginxRetryInterval = createPositiveDurationFlag(kingpin.Flag("nginx.retry-interval", "An interval between retries to connect to the NGINX stub_status page/NGINX Plus API on start.").Default("5s").Envar("NGINX_RETRY_INTERVAL"))
93+
timeout = createPositiveDurationFlag(kingpin.Flag("nginx.timeout", "A timeout for scraping metrics from NGINX or NGINX Plus.").Default("5s").Envar("TIMEOUT"))
11494
)
11595

11696
const exporterName = "nginx_exporter"
@@ -123,7 +103,7 @@ func main() {
123103

124104
// convert deprecated flags to new format
125105
for i, arg := range os.Args {
126-
if strings.HasPrefix(arg, "-") && len(arg) > 1 {
106+
if strings.HasPrefix(arg, "-") && !strings.HasPrefix(arg, "--") && len(arg) > 2 {
127107
newArg := fmt.Sprintf("-%s", arg)
128108
level.Warn(logger).Log("msg", "the flag format is deprecated and will be removed in a future release, please use the new format", "old", arg, "new", newArg)
129109
os.Args[i] = newArg
@@ -195,24 +175,16 @@ func main() {
195175
}
196176

197177
if *nginxPlus {
198-
plusClient, err := createClientWithRetries(func() (interface{}, error) {
199-
return plusclient.NewNginxClient(*scrapeURI, plusclient.WithHTTPClient(httpClient))
200-
}, *nginxRetries, *nginxRetryInterval, logger)
178+
plusClient, err := plusclient.NewNginxClient(*scrapeURI, plusclient.WithHTTPClient(httpClient))
201179
if err != nil {
202180
level.Error(logger).Log("msg", "Could not create Nginx Plus Client", "error", err.Error())
203181
os.Exit(1)
204182
}
205183
variableLabelNames := collector.NewVariableLabelNames(nil, nil, nil, nil, nil, nil)
206-
prometheus.MustRegister(collector.NewNginxPlusCollector(plusClient.(*plusclient.NginxClient), "nginxplus", variableLabelNames, constLabels, logger))
184+
prometheus.MustRegister(collector.NewNginxPlusCollector(plusClient, "nginxplus", variableLabelNames, constLabels, logger))
207185
} else {
208-
ossClient, err := createClientWithRetries(func() (interface{}, error) {
209-
return client.NewNginxClient(httpClient, *scrapeURI)
210-
}, *nginxRetries, *nginxRetryInterval, logger)
211-
if err != nil {
212-
level.Error(logger).Log("msg", "Could not create Nginx Client", "error", err.Error())
213-
os.Exit(1)
214-
}
215-
prometheus.MustRegister(collector.NewNginxCollector(ossClient.(*client.NginxClient), "nginx", constLabels, logger))
186+
ossClient := client.NewNginxClient(httpClient, *scrapeURI)
187+
prometheus.MustRegister(collector.NewNginxCollector(ossClient, "nginx", constLabels, logger))
216188
}
217189

218190
http.Handle(*metricsPath, promhttp.Handler())

exporter_test.go

-80
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,11 @@
11
package main
22

33
import (
4-
"errors"
54
"reflect"
65
"testing"
76
"time"
8-
9-
"github.com/go-kit/log"
107
)
118

12-
func TestCreateClientWithRetries(t *testing.T) {
13-
t.Parallel()
14-
15-
type args struct {
16-
client interface{}
17-
err error
18-
retries uint
19-
retryInterval time.Duration
20-
}
21-
22-
tests := []struct {
23-
name string
24-
args args
25-
expectedRetries int
26-
want interface{}
27-
wantErr bool
28-
}{
29-
{
30-
name: "getClient returns a valid client",
31-
args: args{
32-
client: "client",
33-
err: nil,
34-
},
35-
expectedRetries: 0,
36-
want: "client",
37-
wantErr: false,
38-
},
39-
{
40-
name: "getClient returns an error after no retries",
41-
args: args{
42-
client: nil,
43-
err: errors.New("error"),
44-
},
45-
expectedRetries: 0,
46-
want: nil,
47-
wantErr: true,
48-
},
49-
{
50-
name: "getClient returns an error after retries",
51-
args: args{
52-
client: nil,
53-
err: errors.New("error"),
54-
retries: 3,
55-
retryInterval: time.Millisecond * 1,
56-
},
57-
expectedRetries: 3,
58-
want: nil,
59-
wantErr: true,
60-
},
61-
}
62-
for _, tt := range tests {
63-
t.Run(tt.name, func(t *testing.T) {
64-
invocations := 0
65-
getClient := func() (interface{}, error) {
66-
invocations++
67-
return tt.args.client, tt.args.err
68-
}
69-
70-
got, err := createClientWithRetries(getClient, tt.args.retries, tt.args.retryInterval, log.NewNopLogger())
71-
72-
actualRetries := invocations - 1
73-
74-
if actualRetries != tt.expectedRetries {
75-
t.Errorf("createClientWithRetries() got %v retries, expected %v", actualRetries, tt.expectedRetries)
76-
return
77-
} else if (err != nil) != tt.wantErr {
78-
t.Errorf("createClientWithRetries() error = %v, wantErr %v", err, tt.wantErr)
79-
return
80-
} else if err != nil && tt.wantErr {
81-
return
82-
} else if !reflect.DeepEqual(got, tt.want) {
83-
t.Errorf("createClientWithRetries() = %v, want %v", got, tt.want)
84-
}
85-
})
86-
}
87-
}
88-
899
func TestParsePositiveDuration(t *testing.T) {
9010
t.Parallel()
9111

0 commit comments

Comments
 (0)