Skip to content

Commit

Permalink
Refactor tests for indices settings
Browse files Browse the repository at this point in the history
- Refactor tests to test the output of the collector
- Add missing metric descriptions in Describe()

Signed-off-by: Joe Adams <[email protected]>
  • Loading branch information
sysadmind committed Jan 13, 2025
1 parent b550e54 commit d9dd26b
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 70 deletions.
39 changes: 8 additions & 31 deletions collector/indices_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,9 @@ type IndicesSettings struct {
client *http.Client
url *url.URL

up prometheus.Gauge
readOnlyIndices prometheus.Gauge

totalScrapes, jsonParseFailures prometheus.Counter
metrics []*indicesSettingsMetric
metrics []*indicesSettingsMetric
}

var (
Expand All @@ -58,22 +56,11 @@ func NewIndicesSettings(logger *slog.Logger, client *http.Client, url *url.URL)
client: client,
url: url,

up: prometheus.NewGauge(prometheus.GaugeOpts{
Name: prometheus.BuildFQName(namespace, "indices_settings_stats", "up"),
Help: "Was the last scrape of the Elasticsearch Indices Settings endpoint successful.",
}),
totalScrapes: prometheus.NewCounter(prometheus.CounterOpts{
Name: prometheus.BuildFQName(namespace, "indices_settings_stats", "total_scrapes"),
Help: "Current total Elasticsearch Indices Settings scrapes.",
}),
readOnlyIndices: prometheus.NewGauge(prometheus.GaugeOpts{
Name: prometheus.BuildFQName(namespace, "indices_settings_stats", "read_only_indices"),
Help: "Current number of read only indices within cluster",
}),
jsonParseFailures: prometheus.NewCounter(prometheus.CounterOpts{
Name: prometheus.BuildFQName(namespace, "indices_settings_stats", "json_parse_failures"),
Help: "Number of errors while parsing JSON.",
}),

metrics: []*indicesSettingsMetric{
{
Type: prometheus.GaugeValue,
Expand Down Expand Up @@ -126,10 +113,11 @@ func NewIndicesSettings(logger *slog.Logger, client *http.Client, url *url.URL)

// Describe add Snapshots metrics descriptions
func (cs *IndicesSettings) Describe(ch chan<- *prometheus.Desc) {
ch <- cs.up.Desc()
ch <- cs.totalScrapes.Desc()
ch <- cs.readOnlyIndices.Desc()
ch <- cs.jsonParseFailures.Desc()

for _, metric := range cs.metrics {
ch <- metric.Desc
}
}

func (cs *IndicesSettings) getAndParseURL(u *url.URL, data interface{}) error {
Expand All @@ -155,12 +143,10 @@ func (cs *IndicesSettings) getAndParseURL(u *url.URL, data interface{}) error {

bts, err := io.ReadAll(res.Body)
if err != nil {
cs.jsonParseFailures.Inc()
return err
}

if err := json.Unmarshal(bts, data); err != nil {
cs.jsonParseFailures.Inc()
return err
}
return nil
Expand All @@ -181,26 +167,15 @@ func (cs *IndicesSettings) fetchAndDecodeIndicesSettings() (IndicesSettingsRespo

// Collect gets all indices settings metric values
func (cs *IndicesSettings) Collect(ch chan<- prometheus.Metric) {

cs.totalScrapes.Inc()
defer func() {
ch <- cs.up
ch <- cs.totalScrapes
ch <- cs.jsonParseFailures
ch <- cs.readOnlyIndices
}()

asr, err := cs.fetchAndDecodeIndicesSettings()
if err != nil {
cs.readOnlyIndices.Set(0)
cs.up.Set(0)
cs.logger.Warn(
"failed to fetch and decode cluster settings stats",
"err", err,
)
return
}
cs.up.Set(1)

var c int
for indexName, value := range asr {
Expand All @@ -217,4 +192,6 @@ func (cs *IndicesSettings) Collect(ch chan<- prometheus.Metric) {
}
}
cs.readOnlyIndices.Set(float64(c))

ch <- cs.readOnlyIndices
}
94 changes: 55 additions & 39 deletions collector/indices_settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@
package collector

import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path"
"strings"
"testing"

"github.com/prometheus/client_golang/prometheus/testutil"
"github.com/prometheus/common/promslog"
)

Expand Down Expand Up @@ -54,53 +58,65 @@ func TestIndicesSettings(t *testing.T) {

// curl http://localhost:9200/_all/_settings

tcs := map[string]string{
"6.5.4": `{"viber":{"settings":{"index":{"creation_date":"1618593207186","number_of_shards":"5","number_of_replicas":"1","uuid":"lWg86KTARzO3r7lELytT1Q","version":{"created":"6050499"},"provided_name":"viber"}}},"instagram":{"settings":{"index":{"mapping":{"total_fields":{"limit":"10000"}},"number_of_shards":"5","blocks":{"read_only_allow_delete":"true"},"provided_name":"instagram","creation_date":"1618593203353","number_of_replicas":"1","uuid":"msb6eG7aT8GmNe-a4oyVtQ","version":{"created":"6050499"}}}},"twitter":{"settings":{"index":{"number_of_shards":"5","blocks":{"read_only_allow_delete":"true"},"provided_name":"twitter","creation_date":"1618593193641","number_of_replicas":"1","uuid":"YRUT8t4aSkKsNmGl7K3y4Q","version":{"created":"6050499"}}}},"facebook":{"settings":{"index":{"creation_date":"1618593199101","number_of_shards":"5","number_of_replicas":"1","uuid":"trZhb_YOTV-RWKitTYw81A","version":{"created":"6050499"},"provided_name":"facebook"}}}}`,
tests := []struct {
name string
file string
want string
}{
{
name: "6.5.4",
file: "6.5.4.json",
want: `# HELP elasticsearch_indices_settings_creation_timestamp_seconds index setting creation_date
# TYPE elasticsearch_indices_settings_creation_timestamp_seconds gauge
elasticsearch_indices_settings_creation_timestamp_seconds{index="facebook"} 1.618593199101e+09
elasticsearch_indices_settings_creation_timestamp_seconds{index="instagram"} 1.618593203353e+09
elasticsearch_indices_settings_creation_timestamp_seconds{index="twitter"} 1.618593193641e+09
elasticsearch_indices_settings_creation_timestamp_seconds{index="viber"} 1.618593207186e+09
# HELP elasticsearch_indices_settings_replicas index setting number_of_replicas
# TYPE elasticsearch_indices_settings_replicas gauge
elasticsearch_indices_settings_replicas{index="facebook"} 1
elasticsearch_indices_settings_replicas{index="instagram"} 1
elasticsearch_indices_settings_replicas{index="twitter"} 1
elasticsearch_indices_settings_replicas{index="viber"} 1
# HELP elasticsearch_indices_settings_stats_read_only_indices Current number of read only indices within cluster
# TYPE elasticsearch_indices_settings_stats_read_only_indices gauge
elasticsearch_indices_settings_stats_read_only_indices 2
# HELP elasticsearch_indices_settings_total_fields index mapping setting for total_fields
# TYPE elasticsearch_indices_settings_total_fields gauge
elasticsearch_indices_settings_total_fields{index="facebook"} 1000
elasticsearch_indices_settings_total_fields{index="instagram"} 10000
elasticsearch_indices_settings_total_fields{index="twitter"} 1000
elasticsearch_indices_settings_total_fields{index="viber"} 1000
`,
},
}
for ver, out := range tcs {
for hn, handler := range map[string]http.Handler{
"plain": http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, out)
}),
} {
ts := httptest.NewServer(handler)

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := os.Open(path.Join("../fixtures/indices_settings", tt.file))
if err != nil {
t.Fatal(err)
}
defer f.Close()

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
io.Copy(w, f)
}))
defer ts.Close()

u, err := url.Parse(ts.URL)
if err != nil {
t.Fatalf("Failed to parse URL: %s", err)
t.Fatal(err)
}

c := NewIndicesSettings(promslog.NewNopLogger(), http.DefaultClient, u)
nsr, err := c.fetchAndDecodeIndicesSettings()
if err != nil {
t.Fatalf("Failed to fetch or decode indices settings: %s", err)
}
t.Logf("[%s/%s] All Indices Settings Response: %+v", hn, ver, nsr)
// if nsr.Cluster.Routing.Allocation.Enabled != "ALL" {
// t.Errorf("Wrong setting for cluster routing allocation enabled")
// }
var counter int
var totalFields int
for key, value := range nsr {
if value.Settings.IndexInfo.Blocks.ReadOnly == "true" {
counter++
if key != "instagram" && key != "twitter" {
t.Errorf("Wrong read_only index")
}
}
if value.Settings.IndexInfo.Mapping.TotalFields.Limit == "10000" {
totalFields++
if key != "instagram" {
t.Errorf("Expected 10000 total_fields only for instagram")
}
}
t.Fatal(err)
}
if counter != 2 {
t.Errorf("Wrong number of read_only indexes")
}
if totalFields != 1 {
t.Errorf(("Wrong number of total_fields found"))

if err := testutil.CollectAndCompare(c, strings.NewReader(tt.want)); err != nil {
t.Fatal(err)
}
}
})
}
}
69 changes: 69 additions & 0 deletions fixtures/indices_settings/6.5.4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"viber": {
"settings": {
"index": {
"creation_date": "1618593207186",
"number_of_shards": "5",
"number_of_replicas": "1",
"uuid": "lWg86KTARzO3r7lELytT1Q",
"version": {
"created": "6050499"
},
"provided_name": "viber"
}
}
},
"instagram": {
"settings": {
"index": {
"mapping": {
"total_fields": {
"limit": "10000"
}
},
"number_of_shards": "5",
"blocks": {
"read_only_allow_delete": "true"
},
"provided_name": "instagram",
"creation_date": "1618593203353",
"number_of_replicas": "1",
"uuid": "msb6eG7aT8GmNe-a4oyVtQ",
"version": {
"created": "6050499"
}
}
}
},
"twitter": {
"settings": {
"index": {
"number_of_shards": "5",
"blocks": {
"read_only_allow_delete": "true"
},
"provided_name": "twitter",
"creation_date": "1618593193641",
"number_of_replicas": "1",
"uuid": "YRUT8t4aSkKsNmGl7K3y4Q",
"version": {
"created": "6050499"
}
}
}
},
"facebook": {
"settings": {
"index": {
"creation_date": "1618593199101",
"number_of_shards": "5",
"number_of_replicas": "1",
"uuid": "trZhb_YOTV-RWKitTYw81A",
"version": {
"created": "6050499"
},
"provided_name": "facebook"
}
}
}
}

0 comments on commit d9dd26b

Please sign in to comment.