Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions src/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (

const (
nodeStatsEndpoint = "/_nodes/stats"
localNodeStatsEndpoint = "/_nodes/_local/stats"
localNodeInventoryEndpoint = "/_nodes/_local"
localNodeIdEndpoint = "/_nodes/_local/id"
commonStatsEndpoint = "/_stats"
clusterEndpoint = "/_cluster/health"
indicesStatsEndpoint = "/_cat/indices?format=json"
Expand Down
4 changes: 4 additions & 0 deletions src/elasticsearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type argumentList struct {
IndicesRegex string `default:"" help:"A regex pattern that matches the index names to collect. Collects all if unspecified"`
ShowVersion bool `default:"false" help:"Print build information and exit"`
MasterOnly bool `default:"false" help:"Collect cluster metrics on the elected master only"`
LocalOnly bool `default:"false" help:"Collect node metrics on the local node only"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add an integration test?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need help with this

TLSInsecureSkipVerify bool `default:"false" help:"Enabled TLS insecure skip verify"`
}

Expand Down Expand Up @@ -61,6 +62,9 @@ func main() {
buildDate)
os.Exit(0)
}
if args.MasterOnly && args.LocalOnly {
logErrorAndExit(fmt.Errorf("Select argument -master_only or -local_only, not both"))
}

// Create a client for metrics
metricsClient, err := NewClient(args.Hostname)
Expand Down
3 changes: 2 additions & 1 deletion src/inventory_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package main

// LocalNodeResponse struct (/_nodes/_local endpoint)
type LocalNodeResponse struct {
Nodes map[string]*LocalNode `json:"nodes"`
ClusterName string `json:"cluster_name"`
Nodes map[string]*LocalNode `json:"nodes"`
}

// LocalNode is the node API object
Expand Down
61 changes: 40 additions & 21 deletions src/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,49 @@ var (

// populateMetrics wrapper to call each of the individual populate functions
func populateMetrics(i *integration.Integration, client Client, env string) {
if args.MasterOnly {
nodeID, err := getLocalNodeID(client)
nodeID, clusterName, err := getLocalNodeID(client)
if err != nil {
log.Error("There was an error gathering the host node ID: %v", err)
return
}

var getCluster bool
if args.MasterOnly || args.LocalOnly {
var masterID string
masterID, err = getMasterNodeID(client)
if err != nil {
log.Error("There was an error gathering the host node ID: %v", err)
log.Error("There was an error gathering the elected master node ID: %v", err)
return
}
masterID, err := getMasterNodeID(client)
if err != nil {
log.Error("There was an error gathering the elected master node ID: %v", err)
getCluster = nodeID == masterID
}

if args.MasterOnly {
if !getCluster {
log.Info("The host is not the elected master, node/cluster metrics will be skipped")
return
}
if nodeID != masterID {
log.Info("The host is the elected master, node/cluster metrics will be collected")
}

err = populateNodesMetrics(i, client, clusterName, args.LocalOnly)
if err != nil {
log.Error("There was an error populating metrics for nodes: %v", err)
}

if args.LocalOnly {
if !getCluster {
log.Info("The host is not the elected master, cluster metrics will be skipped")
return
}
log.Info("The host is the elected master, cluster metrics will be collected")
}

clusterName, err := populateClusterMetrics(i, client, env)
_, err = populateClusterMetrics(i, client, env)
if err != nil {
log.Error("There was an error populating metrics for clusters: %v", err)
}

err = populateNodesMetrics(i, client, clusterName)
if err != nil {
log.Error("There was an error populating metrics for nodes: %v", err)
}

// we want to use the response from common to populate some index-specific stats.
commonResponse, err := populateCommonMetrics(i, client, clusterName)
if err != nil {
Expand All @@ -60,23 +75,23 @@ func populateMetrics(i *integration.Integration, client Client, env string) {
}
}

func getLocalNodeID(client Client) (nodeId string, err error) {
func getLocalNodeID(client Client) (nodeId, clusterName string, err error) {
var nodeResponseObject LocalNodeResponse
err = client.Request(localNodeInventoryEndpoint, &nodeResponseObject)
err = client.Request(localNodeIdEndpoint, &nodeResponseObject)
if err != nil {
return "", err
return "", "", err
}
return parseLocalNodeID(nodeResponseObject)
}

func parseLocalNodeID(nodeStats LocalNodeResponse) (string, error) {
func parseLocalNodeID(nodeStats LocalNodeResponse) (nodeId, clusterName string, err error) {
nodes := nodeStats.Nodes
if len(nodes) == 1 {
for k := range nodes {
return k, nil
return k, nodeStats.ClusterName, nil
}
}
return "", errLocalNodeID
return "", "", errLocalNodeID
}

func getMasterNodeID(client Client) (masterId string, err error) {
Expand All @@ -91,10 +106,14 @@ func getMasterNodeID(client Client) (masterId string, err error) {
return masterIdResponseObject[0].ID, nil
}

func populateNodesMetrics(i *integration.Integration, client Client, clusterName string) error {
func populateNodesMetrics(i *integration.Integration, client Client, clusterName string, localOnly bool) error {
endpoint := nodeStatsEndpoint
if localOnly {
endpoint = localNodeStatsEndpoint
}
log.Info("Collecting node metrics")
nodeResponse := new(NodeResponse)
err := client.Request(nodeStatsEndpoint, &nodeResponse)
err := client.Request(endpoint, &nodeResponse)
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions src/metrics_test.go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mock: Unexpected Method Call
-----------------------------

Request(string)
		0: "/_nodes/_local/id"

The closest call I have is: 

Request(string)
		0: "/_nodes/_local"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need help updating mock

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated integration tests so that it passes now

Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func TestGetLocalNodeID(t *testing.T) {
mockedReturnVal := filepath.Join("testdata", "good-nodes-local.json")
fakeClient.On("Request", localNodeInventoryEndpoint).Return(mockedReturnVal, nil).Once()

nodeID, err := getLocalNodeID(&fakeClient)
nodeID, _, err := getLocalNodeID(&fakeClient)
assert.NoError(t, err)
assert.Equal(t, "z9ZPp87vT92qG1cRVRIcMQ", nodeID)
}
Expand All @@ -68,7 +68,7 @@ func TestGetLocalNodeID_Error(t *testing.T) {
mockedReturnVal := filepath.Join("testdata", "bad-nodes-local.json")
fakeClient.On("Request", localNodeInventoryEndpoint).Return(mockedReturnVal, nil).Once()

_, err := getLocalNodeID(&fakeClient)
_, _, err := getLocalNodeID(&fakeClient)
assert.Error(t, err)
assert.Equal(t, errLocalNodeID, err)
}
Expand Down Expand Up @@ -97,7 +97,7 @@ func TestPopulateNodesMetrics(t *testing.T) {
client := createNewTestClient()
client.init("nodeStatsMetricsResult.json", nodeStatsEndpoint, t)

err := populateNodesMetrics(i, client, testClusterName)
err := populateNodesMetrics(i, client, testClusterName, false)
assert.NoError(t, err)

sourceFile := filepath.Join("testdata", "nodeStatsMetricsResult.json")
Expand All @@ -118,7 +118,7 @@ func TestPopulateNodesMetrics_Error(t *testing.T) {
mockClient.ReturnRequestError = true

i := getTestingIntegration(t)
err := populateNodesMetrics(i, mockClient, testClusterName)
err := populateNodesMetrics(i, mockClient, testClusterName, false)
assert.Error(t, err, "should be an error")
}

Expand Down