[icinga-checkins] icinga.org: icinga2-api-examples/master: go-icinga2-events: Add JSON encoding and sample count handlers

git at icinga.org git at icinga.org
Tue Oct 18 21:55:44 CEST 2016


Module: icinga2-api-examples
Branch: master
Commit: 8b01485b8d473873adb9b352fe712f1658cd5e1a
URL:    https://git.icinga.org/?p=icinga2-api-examples.git;a=commit;h=8b01485b8d473873adb9b352fe712f1658cd5e1a

Author: Michael Friedrich <michael.friedrich at icinga.com>
Date:   Sat Oct 15 20:23:05 2016 +0200

go-icinga2-events: Add JSON encoding and sample count handlers

---

 go-icinga2-events/main.go |  134 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 130 insertions(+), 4 deletions(-)

diff --git a/go-icinga2-events/main.go b/go-icinga2-events/main.go
index cd1109b..958c3d0 100644
--- a/go-icinga2-events/main.go
+++ b/go-icinga2-events/main.go
@@ -29,9 +29,80 @@ import (
 	"crypto/tls"
 	"bytes"
 	"bufio"
+	"encoding/json"
 	"time"
 )
 
+/*****************************************************************************/
+
+//Golang has static types and does not like dynamic json
+//https://github.com/xert/go-icinga2/blob/master/icinga/hosts.go
+//we need to decode the following event messages which may differ based on their selected types
+//type: CheckResult
+//{"check_result":{"active":true,"check_source":"icinga2","command":["/usr/lib64/nagios/plugins/check_ssh","54.218.59.62"],"execution_end":1476468766.2535429001,"execution_start":1476468756.2439880371,"exit_status":2.0,"output":"CRITICAL - Socket timeout after 10 seconds","performance_data":[],"schedule_end":1476468766.2536571026,"schedule_start":1476468756.2430608273,"state":2.0,"type":"CheckResult","vars_after":{"attempt":1.0,"reachable":false,"state":2.0,"state_type":1.0},"vars_before":{"attempt":1.0,"reachable":false,"state":2.0,"state_type":1.0}},"host":"i-a78837bf","service":"ssh","timestamp":1476468766.2537300587,"type":"CheckResult"}
+
+type EventTypeCheckResult struct {
+	CheckResult	CheckResultAttrs `json:"check_result"`
+	Host		string		`json:"host,omitempty"`
+	Service		string		`json:"service,omitempty"`
+	Timestamp	float64		`json:"timestamp,omitempty"`
+	Type		string		`json:"type,omitempty"`
+}
+
+//performance data requires a different handling - strings or parsed data as PerfdataValue
+//http://stackoverflow.com/questions/13364181/how-to-unmarshall-an-array-of-different-types-correctly
+//{"check_result":{"active":true,"check_source":"icinga2","command":null,"execution_end":1476472102.1215960979,"execution_start":1476472102.1214408875,"exit_status":0.0,"output":"Hello from icinga2","performance_data":[{"counter":false,"crit":null,"label":"time","max":null,"min":null,"type":"PerfdataValue","unit":"","value":1476472102.12155509,"warn":null}],"schedule_end":1476472102.1215960979,"schedule_start":1476472102.1199998856,"state":3.0,"type":"CheckResult","vars_after":{"attempt":1.0,"reachable":true,"state":3.0,"state_type":0.0},"vars_before":{"attempt":1.0,"reachable":true,"state":0.0,"state_type":1.0}},"host":"icinga2","service":"random-002","timestamp":1476472102.121901989,"type":"CheckResult"}
+
+type PerformanceDataValue struct {
+	Counter		bool		`json:"counter,omitempty"`
+	Crit		json.Number	`json:"crit,omitempty"`
+	Label		string		`json:"label,omitempty"`
+	Max		json.Number	`json:"max,omitempty"`
+	Min		json.Number	`json:"min,omitempty"`
+	Type		string		`json:"type,omitempty"`
+	Unit		string		`json:"unit,omitempty"`
+	Value		json.Number	`json:"value,omitempty"`
+	Warn		json.Number	`json:"warn,omitempty"`
+}
+
+type CheckResultAttrs struct {
+	Active		bool		`json:"active,omitempty"`
+	CheckSource	string		`json:"check_source,omitempty"`
+	Command		[]string	`json:"command,omitempty"`
+	ExecutionEnd	float64		`json:"execution_end,omitempty"`
+	ExecutionStart	float64		`json:"execution_start,omitempty"`
+	ExitStatus	json.Number	`json:"exit_status,omitempty"`
+	Output		string		`json:"output,omitempty"`
+	PerformanceDataParsed []PerformanceDataValue `json:"performance_data,omitempty"`
+	PerformanceDataStr []string	`json:"performance_data,omitempty"`
+	ScheduleEnd	float64		`json:"schedule_end,omitempty"`
+	ScheduleStart	float64		`json:"schedule_start,omitempty"`
+	State		json.Number	`json:"state,omitempty"`
+	Type		string		`json:"type,omitempty"`
+	VarsAfter	*struct {
+		Attempt		json.Number	`json:"attempt,omitempty"`
+		Reachable	bool		`json:"reachable,omitempty"`
+		State		json.Number	`json:"state,omitempty"`
+		StateType	json.Number	`json:"state_type,omitempty"`
+	} `json:"vars_after,omitempty"`
+	VarsBefore	*struct {
+		Attempt		json.Number	`json:"attempt,omitempty"`
+		Reachable	bool		`json:"reachable,omitempty"`
+		State		json.Number	`json:"state,omitempty"`
+		StateType	json.Number	`json:"state_type,omitempty"`
+	} `json:"vars_before,omitempty"`
+}
+
+/*****************************************************************************/
+
+var StartTime int64
+var CheckResultCount int64
+var CheckResultCountObject map[string]int64
+
+var StateChangesObject map[string][]int64
+
+/*****************************************************************************/
+
 func initHTTPClient() *http.Client {
 	sslSkipVerify := true //TODO: config option
 
@@ -54,6 +125,48 @@ func initHTTPClient() *http.Client {
 	return httpClient
 }
 
+func handleEventTypes(response string) {
+	var CheckResult EventTypeCheckResult
+	err := json.Unmarshal([]byte(response), &CheckResult)
+	if err == nil {
+//		fmt.Printf("%+v\n", CheckResult)
+		//TODO: Add fall through for different types
+	} else {
+//		fmt.Println(err)
+//		fmt.Printf("%+v\n", CheckResult)
+	}
+
+	if CheckResult.Type == "CheckResult" {
+		fmt.Println("Processing type 'CheckResult'")
+
+		fmt.Println()
+
+		CheckResultCount++
+
+		var ObjectName = CheckResult.Host
+		if CheckResult.Service != "" {
+			ObjectName = ObjectName + "!" + CheckResult.Service
+		}
+
+		CheckResultCountObject[ObjectName] = CheckResultCountObject[ObjectName] + 1
+
+		//TODO keep array size static
+		state, _ := json.Number.Int64(CheckResult.CheckResult.State)
+
+		StateChangesObject[ObjectName] = append(StateChangesObject[ObjectName], state)
+
+		//periodic statistics
+		if time.Now().Unix() % 5 == 0 {
+			var CheckResultRate = CheckResultCount / (time.Now().Unix() - StartTime)
+			fmt.Println("Global check result rate:", CheckResultRate)
+
+			var CheckResultObjectRate = CheckResultCountObject[ObjectName] / (time.Now().Unix() - StartTime)
+			fmt.Printf("Check result rate for object %s: %f", ObjectName, CheckResultObjectRate)
+		}
+	}
+}
+
+
 func eventLoop() {
 	//TODO
 	var urlBase = "https://192.168.33.5:5665"
@@ -62,16 +175,17 @@ func eventLoop() {
 
 	eventsEndpoint := urlBase + "/v1/events"
 	fmt.Println("Check if HTTP connection is intact")
-	//TODO
 
-	netClient := initHTTPClient()
+	httpClient := initHTTPClient()
 
 	var requestBody = []byte(`{ "queue": "mine", "types": [ "CheckResult" ]}`)
+	//TODO: Depending on the types the user chooses we need to select our response handling
+
 	req, err := http.NewRequest("POST", eventsEndpoint, bytes.NewBuffer(requestBody))
 	req.Header.Set("Accept", "application/json")
 	req.SetBasicAuth(apiUser, apiPass)
 
-	resp, err := netClient.Do(req)
+	resp, err := httpClient.Do(req)
 	if err != nil {
 		fmt.Println("Server error:", err)
 		return
@@ -87,9 +201,13 @@ func eventLoop() {
 
 		if err != nil {
 			fmt.Println("Error reading stream", err)
+			return
 		}
 		fmt.Println("Processing message")
 		fmt.Println(string(line))
+
+		//call handler for json decoding and message processing
+		handleEventTypes(string(line))
 	}
 
 	fmt.Println("Connection was closed by the server")
@@ -99,6 +217,8 @@ func cleanup() {
 	fmt.Println("Exit cleanup.")
 }
 
+/*****************************************************************************/
+
 func main() {
 	c := make(chan os.Signal, 2)
 	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
@@ -108,8 +228,14 @@ func main() {
 		os.Exit(1)
 	}()
 
+	StartTime = time.Now().Unix()
+
+	CheckResultCount = 0
+	CheckResultCountObject = make(map[string]int64)
+	StateChangesObject = make(map[string][]int64)
+
 	for {
-		//does long polling until infinity
+		//does long polling until infinity or the server closes the connection
 		eventLoop()
 
 		//before retrying immediately, wait a while



More information about the icinga-checkins mailing list