Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix elasticsearch v8 cluster_settings unmarshal error #915

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 6 additions & 52 deletions collector/cluster_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,49 +103,6 @@ var clusterSettingsDesc = map[string]*prometheus.Desc{
),
}

// clusterSettingsResponse is a representation of a Elasticsearch Cluster Settings
type clusterSettingsResponse struct {
Defaults clusterSettingsSection `json:"defaults"`
Persistent clusterSettingsSection `json:"persistent"`
Transient clusterSettingsSection `json:"transient"`
}

// clusterSettingsSection is a representation of a Elasticsearch Cluster Settings
type clusterSettingsSection struct {
Cluster clusterSettingsCluster `json:"cluster"`
}

// clusterSettingsCluster is a representation of a Elasticsearch clusterSettingsCluster Settings
type clusterSettingsCluster struct {
Routing clusterSettingsRouting `json:"routing"`
// This can be either a JSON object (which does not contain the value we are interested in) or a string
MaxShardsPerNode interface{} `json:"max_shards_per_node"`
}

// clusterSettingsRouting is a representation of a Elasticsearch Cluster shard routing configuration
type clusterSettingsRouting struct {
Allocation clusterSettingsAllocation `json:"allocation"`
}

// clusterSettingsAllocation is a representation of a Elasticsearch Cluster shard routing allocation settings
type clusterSettingsAllocation struct {
Enabled string `json:"enable"`
Disk clusterSettingsDisk `json:"disk"`
}

// clusterSettingsDisk is a representation of a Elasticsearch Cluster shard routing disk allocation settings
type clusterSettingsDisk struct {
ThresholdEnabled string `json:"threshold_enabled"`
Watermark clusterSettingsWatermark `json:"watermark"`
}

// clusterSettingsWatermark is representation of Elasticsearch Cluster shard routing disk allocation watermark settings
type clusterSettingsWatermark struct {
FloodStage string `json:"flood_stage"`
High string `json:"high"`
Low string `json:"low"`
}

func (c *ClusterSettingsCollector) Update(ctx context.Context, ch chan<- prometheus.Metric) error {
u := c.u.ResolveReference(&url.URL{Path: "_cluster/settings"})
q := u.Query()
Expand Down Expand Up @@ -185,15 +142,12 @@ func (c *ClusterSettingsCollector) Update(ctx context.Context, ch chan<- prometh
}

// Max shards per node
if maxShardsPerNodeString, ok := merged.Cluster.MaxShardsPerNode.(string); ok {
maxShardsPerNode, err := strconv.ParseInt(maxShardsPerNodeString, 10, 64)
if err == nil {
ch <- prometheus.MustNewConstMetric(
clusterSettingsDesc["maxShardsPerNode"],
prometheus.GaugeValue,
float64(maxShardsPerNode),
)
}
if maxShardsPerNode, err := strconv.ParseInt(merged.Cluster.MaxShardsPerNode, 10, 64); err == nil {
ch <- prometheus.MustNewConstMetric(
clusterSettingsDesc["maxShardsPerNode"],
prometheus.GaugeValue,
float64(maxShardsPerNode),
)
}

// Shard allocation enabled
Expand Down
87 changes: 87 additions & 0 deletions collector/cluster_settings_response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2021 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package collector

import (
"encoding/json"
"github.com/mitchellh/mapstructure"
)

// clusterSettingsResponse is a representation of a Elasticsearch Cluster Settings
type clusterSettingsResponse struct {
Defaults clusterSettingsSection `json:"defaults"`
Persistent clusterSettingsSection `json:"persistent"`
Transient clusterSettingsSection `json:"transient"`
}

// clusterSettingsSection is a representation of a Elasticsearch Cluster Settings
type clusterSettingsSection struct {
Cluster clusterSettingsCluster `json:"cluster" mapstructure:",squash"`
}

// clusterSettingsCluster is a representation of a Elasticsearch clusterSettingsCluster Settings
type clusterSettingsCluster struct {
Routing clusterSettingsRouting `json:"routing" mapstructure:",squash"`

MaxShardsPerNode string `json:"max_shards_per_node" mapstructure:"cluster.max_shards_per_node"`
}

// clusterSettingsRouting is a representation of a Elasticsearch Cluster shard routing configuration
type clusterSettingsRouting struct {
Allocation clusterSettingsAllocation `json:"allocation" mapstructure:",squash"`
}

// clusterSettingsAllocation is a representation of a Elasticsearch Cluster shard routing allocation settings
type clusterSettingsAllocation struct {
Enabled string `json:"enable" mapstructure:"cluster.routing.allocation.enable"`
Disk clusterSettingsDisk `json:"disk" mapstructure:",squash"`
}

// clusterSettingsDisk is a representation of a Elasticsearch Cluster shard routing disk allocation settings
type clusterSettingsDisk struct {
ThresholdEnabled string `json:"threshold_enabled" mapstructure:"cluster.routing.allocation.disk.threshold_enabled"`
Watermark clusterSettingsWatermark `json:"watermark" mapstructure:",squash"`
}

// clusterSettingsWatermark is representation of Elasticsearch Cluster shard routing disk allocation watermark settings
type clusterSettingsWatermark struct {
FloodStage string `json:"flood_stage" mapstructure:"cluster.routing.allocation.disk.watermark.flood_stage"`
High string `json:"high" mapstructure:"cluster.routing.allocation.disk.watermark.high"`
Low string `json:"low" mapstructure:"cluster.routing.allocation.disk.watermark.low"`
}

func (c *clusterSettingsSection) UnmarshalJSON(data []byte) error {
var settings map[string]interface{}

if err := json.Unmarshal(data, &settings); err != nil {
return err
}

settings = flatten(settings)
return mapstructure.Decode(settings, c)
}

func flatten(m map[string]interface{}) map[string]interface{} {
result := make(map[string]interface{})
for k1, v1 := range m {
if n, ok := v1.(map[string]interface{}); ok {
for k2, v2 := range flatten(n) {
result[k1+"."+k2] = v2
}
} else {
result[k1] = v1
}
}
return result
}
24 changes: 24 additions & 0 deletions collector/cluster_settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,30 @@ elasticsearch_clustersettings_allocation_watermark_high_bytes 2.147483648e+11
# HELP elasticsearch_clustersettings_allocation_watermark_low_bytes Low watermark for disk usage in bytes.
# TYPE elasticsearch_clustersettings_allocation_watermark_low_bytes gauge
elasticsearch_clustersettings_allocation_watermark_low_bytes 5.24288e+07
`,
},
{
name: "8.10.4",
file: "../fixtures/settings-8.10.4.json",
want: `
# HELP elasticsearch_clustersettings_stats_max_shards_per_node Current maximum number of shards per node setting.
# TYPE elasticsearch_clustersettings_stats_max_shards_per_node gauge
elasticsearch_clustersettings_stats_max_shards_per_node 1000
# HELP elasticsearch_clustersettings_stats_shard_allocation_enabled Current mode of cluster wide shard routing allocation settings.
# TYPE elasticsearch_clustersettings_stats_shard_allocation_enabled gauge
elasticsearch_clustersettings_stats_shard_allocation_enabled 0
# HELP elasticsearch_clustersettings_allocation_threshold_enabled Is disk allocation decider enabled.
# TYPE elasticsearch_clustersettings_allocation_threshold_enabled gauge
elasticsearch_clustersettings_allocation_threshold_enabled 1
# HELP elasticsearch_clustersettings_allocation_watermark_flood_stage_ratio Flood stage watermark as a ratio.
# TYPE elasticsearch_clustersettings_allocation_watermark_flood_stage_ratio gauge
elasticsearch_clustersettings_allocation_watermark_flood_stage_ratio 0.95
# HELP elasticsearch_clustersettings_allocation_watermark_high_ratio High watermark for disk usage as a ratio.
# TYPE elasticsearch_clustersettings_allocation_watermark_high_ratio gauge
elasticsearch_clustersettings_allocation_watermark_high_ratio 0.9
# HELP elasticsearch_clustersettings_allocation_watermark_low_ratio Low watermark for disk usage as a ratio.
# TYPE elasticsearch_clustersettings_allocation_watermark_low_ratio gauge
elasticsearch_clustersettings_allocation_watermark_low_ratio 0.85
`,
},
}
Expand Down
Loading