Skip to content

Commit b4149e1

Browse files
committed
Refactor cluster_license, use the collector interface
Signed-off-by: kekkokers <[email protected]>
1 parent 728e447 commit b4149e1

File tree

2 files changed

+90
-120
lines changed

2 files changed

+90
-120
lines changed

collector/cluster_license.go

Lines changed: 75 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package collector
1515

1616
import (
17+
"context"
1718
"encoding/json"
1819
"fmt"
1920
"io"
@@ -27,13 +28,6 @@ import (
2728
"github.com/prometheus/client_golang/prometheus"
2829
)
2930

30-
type clusterLicenseMetric struct {
31-
Type prometheus.ValueType
32-
Desc *prometheus.Desc
33-
Value func(clusterLicenseStats clusterLicenseResponse) float64
34-
Labels func(clusterLicenseStats clusterLicenseResponse) []string
35-
}
36-
3731
type clusterLicenseResponse struct {
3832
License struct {
3933
Status string `json:"status"`
@@ -51,143 +45,115 @@ type clusterLicenseResponse struct {
5145
}
5246

5347
var (
54-
defaultClusterLicenseLabels = []string{"cluster_license_type"}
55-
defaultClusterLicenseValues = func(clusterLicense clusterLicenseResponse) []string {
56-
return []string{clusterLicense.License.Type}
48+
defaultClusterLicenseLabels = []string{"issued_to", "issuer", "type", "status"}
49+
defaultClusterLicenseLabelsValues = func(clusterLicense clusterLicenseResponse) []string {
50+
return []string{clusterLicense.License.IssuedTo, clusterLicense.License.Issuer, clusterLicense.License.Type, clusterLicense.License.Status}
5751
}
5852
)
5953

54+
var (
55+
licenseMaxNodes = prometheus.NewDesc(
56+
prometheus.BuildFQName(namespace, "cluster_license", "max_nodes"),
57+
"The max amount of nodes allowed by the license",
58+
defaultClusterLicenseLabels, nil,
59+
)
60+
licenseIssueDate = prometheus.NewDesc(
61+
prometheus.BuildFQName(namespace, "cluster_license", "issue_date_in_millis"),
62+
"License issue date in milliseconds",
63+
defaultClusterLicenseLabels, nil,
64+
)
65+
licenseExpiryDate = prometheus.NewDesc(
66+
prometheus.BuildFQName(namespace, "cluster_license", "expiry_date_in_millis"),
67+
"License expiry date in milliseconds",
68+
defaultClusterLicenseLabels, nil,
69+
)
70+
licenseStartDate = prometheus.NewDesc(
71+
prometheus.BuildFQName(namespace, "cluster_license", "start_date_in_millis"),
72+
"License start date in milliseconds",
73+
defaultClusterLicenseLabels, nil,
74+
)
75+
)
76+
77+
func init() {
78+
registerCollector("cluster_license", defaultDisabled, NewClusterLicense)
79+
}
80+
6081
// License Information Struct
6182
type ClusterLicense struct {
6283
logger log.Logger
63-
client *http.Client
64-
url *url.URL
65-
66-
clusterLicenseMetrics []*clusterLicenseMetric
84+
hc *http.Client
85+
u *url.URL
6786
}
6887

69-
// NewClusterLicense defines ClusterLicense Prometheus metrics
70-
func NewClusterLicense(logger log.Logger, client *http.Client, url *url.URL) *ClusterLicense {
88+
func NewClusterLicense(logger log.Logger, u *url.URL, hc *http.Client) (Collector, error) {
7189
return &ClusterLicense{
7290
logger: logger,
73-
client: client,
74-
url: url,
75-
76-
clusterLicenseMetrics: []*clusterLicenseMetric{
77-
{
78-
Type: prometheus.GaugeValue,
79-
Desc: prometheus.NewDesc(
80-
prometheus.BuildFQName(namespace, "cluster_license", "max_nodes"),
81-
"The max amount of nodes allowed by the license",
82-
defaultClusterLicenseLabels, nil,
83-
),
84-
Value: func(clusterLicenseStats clusterLicenseResponse) float64 {
85-
return float64(clusterLicenseStats.License.MaxNodes)
86-
},
87-
Labels: defaultClusterLicenseValues,
88-
},
89-
{
90-
Type: prometheus.GaugeValue,
91-
Desc: prometheus.NewDesc(
92-
prometheus.BuildFQName(namespace, "cluster_license", "issue_date_in_millis"),
93-
"License issue date in milliseconds",
94-
defaultClusterLicenseLabels, nil,
95-
),
96-
Value: func(clusterLicenseStats clusterLicenseResponse) float64 {
97-
return float64(clusterLicenseStats.License.IssueDateInMillis)
98-
},
99-
Labels: defaultClusterLicenseValues,
100-
},
101-
{
102-
Type: prometheus.GaugeValue,
103-
Desc: prometheus.NewDesc(
104-
prometheus.BuildFQName(namespace, "cluster_license", "expiry_date_in_millis"),
105-
"License expiry date in milliseconds",
106-
defaultClusterLicenseLabels, nil,
107-
),
108-
Value: func(clusterLicenseStats clusterLicenseResponse) float64 {
109-
return float64(clusterLicenseStats.License.ExpiryDateInMillis)
110-
},
111-
Labels: defaultClusterLicenseValues,
112-
},
113-
{
114-
Type: prometheus.GaugeValue,
115-
Desc: prometheus.NewDesc(
116-
prometheus.BuildFQName(namespace, "cluster_license", "start_date_in_millis"),
117-
"License start date in milliseconds",
118-
defaultClusterLicenseLabels, nil,
119-
),
120-
Value: func(clusterLicenseStats clusterLicenseResponse) float64 {
121-
return float64(clusterLicenseStats.License.StartDateInMillis)
122-
},
123-
Labels: defaultClusterLicenseValues,
124-
},
125-
},
126-
}
127-
}
128-
129-
// Describe adds License metrics descriptions
130-
func (cl *ClusterLicense) Describe(ch chan<- *prometheus.Desc) {
131-
for _, metric := range cl.clusterLicenseMetrics {
132-
ch <- metric.Desc
133-
}
91+
u: u,
92+
hc: hc,
93+
}, nil
13494
}
13595

136-
func (cl *ClusterLicense) fetchAndDecodeClusterLicense() (clusterLicenseResponse, error) {
96+
func (c *ClusterLicense) Update(ctx context.Context, ch chan<- prometheus.Metric) error {
13797
var clr clusterLicenseResponse
13898

139-
u := *cl.url
99+
u := *c.u
140100
u.Path = path.Join(u.Path, "/_license")
141-
res, err := cl.client.Get(u.String())
101+
res, err := c.hc.Get(u.String())
102+
142103
if err != nil {
143-
return clr, fmt.Errorf("failed to get license stats from %s://%s:%s%s: %s",
144-
u.Scheme, u.Hostname(), u.Port(), u.Path, err)
104+
return err
145105
}
146106

147107
defer func() {
148108
err = res.Body.Close()
149109
if err != nil {
150-
level.Warn(cl.logger).Log(
110+
level.Warn(c.logger).Log(
151111
"msg", "failed to close http.Client",
152112
"err", err,
153113
)
154114
}
155115
}()
156116

157117
if res.StatusCode != http.StatusOK {
158-
return clr, fmt.Errorf("HTTP Request failed with code %d", res.StatusCode)
118+
return fmt.Errorf("HTTP Request failed with code %d", res.StatusCode)
159119
}
160120

161121
bts, err := io.ReadAll(res.Body)
162122
if err != nil {
163-
return clr, err
123+
return err
164124
}
165125

166126
if err := json.Unmarshal(bts, &clr); err != nil {
167-
return clr, err
168-
}
169-
170-
return clr, nil
171-
}
172-
173-
// Collect gets ClusterLicense metric values
174-
func (cl *ClusterLicense) Collect(ch chan<- prometheus.Metric) {
175-
176-
clusterLicenseResp, err := cl.fetchAndDecodeClusterLicense()
177-
if err != nil {
178-
level.Warn(cl.logger).Log(
179-
"msg", "failed to fetch and decode license stats",
180-
"err", err,
181-
)
182-
return
127+
return err
183128
}
184129

185-
for _, metric := range cl.clusterLicenseMetrics {
186-
ch <- prometheus.MustNewConstMetric(
187-
metric.Desc,
188-
metric.Type,
189-
metric.Value(clusterLicenseResp),
190-
metric.Labels(clusterLicenseResp)...,
191-
)
192-
}
130+
ch <- prometheus.MustNewConstMetric(
131+
licenseMaxNodes,
132+
prometheus.GaugeValue,
133+
float64(clr.License.MaxNodes),
134+
defaultClusterLicenseLabelsValues(clr)...,
135+
)
136+
137+
ch <- prometheus.MustNewConstMetric(
138+
licenseIssueDate,
139+
prometheus.GaugeValue,
140+
float64(clr.License.IssueDateInMillis),
141+
defaultClusterLicenseLabelsValues(clr)...,
142+
)
143+
144+
ch <- prometheus.MustNewConstMetric(
145+
licenseExpiryDate,
146+
prometheus.GaugeValue,
147+
float64(clr.License.ExpiryDateInMillis),
148+
defaultClusterLicenseLabelsValues(clr)...,
149+
)
150+
151+
ch <- prometheus.MustNewConstMetric(
152+
licenseStartDate,
153+
prometheus.GaugeValue,
154+
float64(clr.License.StartDateInMillis),
155+
defaultClusterLicenseLabelsValues(clr)...,
156+
)
157+
158+
return nil
193159
}

collector/cluster_license_test.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
"github.com/prometheus/client_golang/prometheus/testutil"
2727
)
2828

29-
func TestIndicesHealth(t *testing.T) {
29+
func TestClusterLicense(t *testing.T) {
3030
// Testcases created using:
3131
// docker run -d -p 9200:9200 elasticsearch:VERSION
3232
// curl http://localhost:9200/_license
@@ -41,16 +41,16 @@ func TestIndicesHealth(t *testing.T) {
4141
want: `
4242
# HELP elasticsearch_cluster_license_expiry_date_in_millis License expiry date in milliseconds
4343
# TYPE elasticsearch_cluster_license_expiry_date_in_millis gauge
44-
elasticsearch_cluster_license_expiry_date_in_millis{cluster_license_type="basic"} 0
44+
elasticsearch_cluster_license_expiry_date_in_millis{issued_to="redacted",issuer="elasticsearch",status="active",type="basic"} 0
4545
# HELP elasticsearch_cluster_license_issue_date_in_millis License issue date in milliseconds
4646
# TYPE elasticsearch_cluster_license_issue_date_in_millis gauge
47-
elasticsearch_cluster_license_issue_date_in_millis{cluster_license_type="basic"} 1.702196247064e+12
47+
elasticsearch_cluster_license_issue_date_in_millis{issued_to="redacted",issuer="elasticsearch",status="active",type="basic"} 1.702196247064e+12
4848
# HELP elasticsearch_cluster_license_max_nodes The max amount of nodes allowed by the license
4949
# TYPE elasticsearch_cluster_license_max_nodes gauge
50-
elasticsearch_cluster_license_max_nodes{cluster_license_type="basic"} 1000
50+
elasticsearch_cluster_license_max_nodes{issued_to="redacted",issuer="elasticsearch",status="active",type="basic"} 1000
5151
# HELP elasticsearch_cluster_license_start_date_in_millis License start date in milliseconds
5252
# TYPE elasticsearch_cluster_license_start_date_in_millis gauge
53-
elasticsearch_cluster_license_start_date_in_millis{cluster_license_type="basic"} -1
53+
elasticsearch_cluster_license_start_date_in_millis{issued_to="redacted",issuer="elasticsearch",status="active",type="basic"} -1
5454
`,
5555
},
5656
{
@@ -59,16 +59,16 @@ func TestIndicesHealth(t *testing.T) {
5959
want: `
6060
# HELP elasticsearch_cluster_license_expiry_date_in_millis License expiry date in milliseconds
6161
# TYPE elasticsearch_cluster_license_expiry_date_in_millis gauge
62-
elasticsearch_cluster_license_expiry_date_in_millis{cluster_license_type="platinum"} 1.714521599999e+12
62+
elasticsearch_cluster_license_expiry_date_in_millis{issued_to="redacted",issuer="API",status="active",type="platinum"} 1.714521599999e+12
6363
# HELP elasticsearch_cluster_license_issue_date_in_millis License issue date in milliseconds
6464
# TYPE elasticsearch_cluster_license_issue_date_in_millis gauge
65-
elasticsearch_cluster_license_issue_date_in_millis{cluster_license_type="platinum"} 1.6192224e+12
65+
elasticsearch_cluster_license_issue_date_in_millis{issued_to="redacted",issuer="API",status="active",type="platinum"} 1.6192224e+12
6666
# HELP elasticsearch_cluster_license_max_nodes The max amount of nodes allowed by the license
6767
# TYPE elasticsearch_cluster_license_max_nodes gauge
68-
elasticsearch_cluster_license_max_nodes{cluster_license_type="platinum"} 10
68+
elasticsearch_cluster_license_max_nodes{issued_to="redacted",issuer="API",status="active",type="platinum"} 10
6969
# HELP elasticsearch_cluster_license_start_date_in_millis License start date in milliseconds
7070
# TYPE elasticsearch_cluster_license_start_date_in_millis gauge
71-
elasticsearch_cluster_license_start_date_in_millis{cluster_license_type="platinum"} 1.6192224e+12
71+
elasticsearch_cluster_license_start_date_in_millis{issued_to="redacted",issuer="API",status="active",type="platinum"} 1.6192224e+12
7272
`,
7373
},
7474
}
@@ -92,9 +92,13 @@ func TestIndicesHealth(t *testing.T) {
9292
t.Fatal(err)
9393
}
9494

95-
c := NewClusterLicense(log.NewNopLogger(), http.DefaultClient, u)
95+
c, err := NewClusterLicense(log.NewNopLogger(), u, http.DefaultClient)
9696

97-
if err := testutil.CollectAndCompare(c, strings.NewReader(tt.want)); err != nil {
97+
if err != nil {
98+
t.Fatal(err)
99+
}
100+
101+
if err := testutil.CollectAndCompare(wrapCollector{c}, strings.NewReader(tt.want)); err != nil {
98102
t.Fatal(err)
99103
}
100104
})

0 commit comments

Comments
 (0)