Skip to content

Commit

Permalink
add latest data columns into triggers table
Browse files Browse the repository at this point in the history
  • Loading branch information
seletskiy committed Jul 19, 2016
1 parent 932edd7 commit 1cbb36b
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 36 deletions.
9 changes: 8 additions & 1 deletion docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ Workflow options:
-f --noconfirm
Do not prompt acknowledge confirmation dialog.
-d --extended
Once for printing item's last value from the first component of the
trigger expression. Twice for adding last value change date. Thrice for
printing item description as well.
-L --latest-data
Search and show latest data for specified host(s). Hosts can be searched
using wildcard character '*'. Latest data can be filtered using /<pattern>
Expand Down Expand Up @@ -125,7 +130,7 @@ Misc options:
Show version.
`)
usage = `
zabbixctl [options] -T [-v]... [-x]... [<pattern>]...
zabbixctl [options] -T [-v]... [-x]... [-d]... [<pattern>]...
zabbixctl [options] -L [-v]... <pattern>...
zabbixctl [options] -G [-v]... [<pattern>]...
zabbixctl [options] -G [-v]... <pattern>... -a <user>
Expand All @@ -148,8 +153,10 @@ Options:
-n --limit <amount> [default: 0]
-f --noconfirm
-k --acknowledge
-d --extended
-L --latest-data
-g --graph
-d --extended
-G --groups
-a --add <user>
-r --remove <user>
Expand Down
9 changes: 9 additions & 0 deletions function.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

type Function struct {
ID string `json:"functionid"`
ItemID string `json:"itemid"`
TriggerID string `json:"triggerid"`
Name string `json:"function"`
Parameter string `json:"parameter"`
}
2 changes: 1 addition & 1 deletion handle_latest_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func handleLatestData(
for _, item := range items {
line := fmt.Sprintf(
"%s\t%s\t%s\t%-10s",
hash[item.HostID].Name, item.Name,
hash[item.HostID].Name, item.Format(),
item.DateTime(), item.LastValue,
)

Expand Down
95 changes: 94 additions & 1 deletion handle_triggers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ import (
"github.com/zazab/hierr"
)

type ExtendedOutput int

const (
ExtendedOutputNone ExtendedOutput = iota
ExtendedOutputValue
ExtendedOutputDate
ExtendedOutputAll
)

func handleTriggers(
zabbix *Zabbix,
config *Config,
Expand All @@ -19,6 +28,7 @@ func handleTriggers(
acknowledge = args["--acknowledge"].(bool)
words, pattern = parseSearchQuery(args["<pattern>"].([]string))
confirmation = !args["--noconfirm"].(bool)
extended = ExtendedOutput(args["--extended"].(int))

table = tabwriter.NewWriter(os.Stdout, 1, 4, 2, ' ', 0)
)
Expand Down Expand Up @@ -52,6 +62,18 @@ func handleTriggers(
)
}

var history = make(map[string]ItemHistory)

if extended != ExtendedOutputNone {
history, err = getTriggerItemsHistory(zabbix, triggers)
if err != nil {
return hierr.Errorf(
err,
`can't obtain history for items of triggers`,
)
}
}

debugln("* showing triggers table")
if pattern != "" {
debugf("** searching %s", pattern)
Expand All @@ -65,7 +87,7 @@ func handleTriggers(

fmt.Fprintf(
table,
"%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
"%s\t%s\t%s\t%s\t%s\t%s\t%s",
trigger.LastEvent.ID, trigger.DateTime(),
trigger.Severity(),
trigger.StatusProblem(),
Expand All @@ -74,6 +96,24 @@ func handleTriggers(
trigger.Description,
)

if len(trigger.Functions) > 0 {
if last, ok := history[trigger.Functions[0].ItemID]; ok {
if extended >= ExtendedOutputValue {
fmt.Fprintf(table, "\t%s", last.History.String())
}

if extended >= ExtendedOutputDate {
fmt.Fprintf(table, "\t%s", last.History.DateTime())
}

if extended >= ExtendedOutputAll {
fmt.Fprintf(table, "\t%s", last.Item.Format())
}
}
}

fmt.Fprint(table, "\n")

identifiers = append(identifiers, trigger.LastEvent.ID)
}

Expand Down Expand Up @@ -112,6 +152,59 @@ func handleTriggers(
return nil
}

func getTriggerItemsHistory(
zabbix *Zabbix,
triggers []Trigger,
) (map[string]ItemHistory, error) {
history := map[string]ItemHistory{}

itemIDs := []string{}
for _, trigger := range triggers {
if len(trigger.Functions) > 0 {
itemIDs = append(itemIDs, trigger.Functions[0].ItemID)
}
}

items, err := zabbix.GetItems(Params{
"itemids": itemIDs,
})
if err != nil {
return nil, hierr.Errorf(
err,
`can't obtain items of triggers`,
)
}

err = withSpinner(
":: Requesting history for items of triggers",
func() error {
for _, item := range items {
lastValues, err := zabbix.GetHistory(Params{
"history": item.ValueType,
"itemids": item.ID,
"limit": 1,
})
if err != nil {
return err
}

if len(lastValues) == 0 {
continue
}

history[item.ID] = ItemHistory{
Item: item,
History: lastValues[0],
}
}

return nil
},
)

return history, err
}

func parseParams(args map[string]interface{}) (Params, error) {
var (
severity = args["--severity"].(int)
Expand Down
33 changes: 33 additions & 0 deletions history.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"fmt"
"strconv"
"time"
)

type HistoryValue interface{}

type History struct {
ItemID string `json:"itemid"`
Value HistoryValue `json:"value"`
Clock string `json:"clock"`
}

type ItemHistory struct {
Item Item
History History
}

func (history *History) String() string {
return fmt.Sprint(history.Value)
}

func (history *History) date() time.Time {
date, _ := strconv.ParseInt(history.Clock, 10, 64)
return time.Unix(date, 0)
}

func (history *History) DateTime() string {
return history.date().Format("2006-01-02 15:04:05")
}
24 changes: 24 additions & 0 deletions item.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package main

import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
)

var (
reItemKeyParams = regexp.MustCompile(`\[([^\]]+)\]`)
)

type Item struct {
ID string `json:"itemid"`
HostID string `json:"hostid"`
Name string `json:"name"`
ValueType string `json:"value_type"`
LastValue string `json:"lastvalue"`
LastChange string `json:"lastclock"`
Key string `json:"key_"`
Expand All @@ -26,3 +34,19 @@ func (item *Item) date() time.Time {
date, _ := strconv.ParseInt(item.LastChange, 10, 64)
return time.Unix(date, 0)
}

func (item *Item) Format() string {
name := item.Name

match := reItemKeyParams.FindStringSubmatch(item.Key)
if len(match) == 0 {
return name
}

args := strings.Split(match[1], ",")
for index, arg := range args {
name = strings.Replace(name, fmt.Sprintf(`$%d`, index+1), arg, -1)
}

return name
}
5 changes: 5 additions & 0 deletions responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,8 @@ type ResponseUsers struct {
ResponseRaw
Data []User `json:"result"`
}

type ResponseHistory struct {
ResponseRaw
Data []History `json:"result"`
}
12 changes: 7 additions & 5 deletions trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import (
)

type Trigger struct {
ID string `json:"triggerid"`
Description string `json:"description"`
Hostname string `json:"host"`
Value string `json:"value"`
LastChange string `json:"lastchange"`
ID string `json:"triggerid"`
Description string `json:"description"`
Hostname string `json:"host"`
Value string `json:"value"`
Comments string `json:"comments"`
Functions []Function `json:"functions"`
LastChange string `json:"lastchange"`
LastEvent struct {
ID string `json:"eventid"`
Acknowledged string `json:"acknowledged"`
Expand Down
52 changes: 24 additions & 28 deletions zabbix.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"reflect"
"regexp"
"strings"
"sync/atomic"
"time"
Expand All @@ -21,10 +19,6 @@ const (
ZabbixSessionTTL = 900 - 60
)

var (
reItemKeyParams = regexp.MustCompile(`\[([^\]]+)\]`)
)

type Params map[string]interface{}

type Request struct {
Expand Down Expand Up @@ -192,6 +186,7 @@ func (zabbix *Zabbix) GetTriggers(extend Params) ([]Trigger, error) {
"selectHosts": []string{"name"},
"selectGroups": []string{"groupid", "name"},
"selectLastEvent": "extend",
"selectFunctions": "extend",
"expandExpression": true,
"expandData": true,
"expandDescription": true,
Expand Down Expand Up @@ -226,14 +221,7 @@ func (zabbix *Zabbix) GetItems(params Params) ([]Item, error) {
return nil, err
}

result := make([]Item, len(response.Data))
for i, item := range response.Data {
item.Name = expandKeyArgumentsInName(item.Name, item.Key)

result[i] = item
}

return result, nil
return response.Data, nil
}

func (zabbix *Zabbix) GetUsersGroups(params Params) ([]UserGroup, error) {
Expand Down Expand Up @@ -339,6 +327,28 @@ func (zabbix *Zabbix) GetGraphURL(identifier string) string {
"/history.php?action=showgraph&itemids%5B%5D=" + identifier
}

func (zabbix *Zabbix) GetHistory(extend Params) ([]History, error) {
debugf("* retrieving items history")

params := Params{
"output": "extend",
"sortfield": "clock",
"sortorder": "DESC",
}

for key, value := range extend {
params[key] = value
}

var response ResponseHistory
err := zabbix.call("history.get", params, &response)
if err != nil {
return nil, err
}

return response.Data, nil
}

func (zabbix *Zabbix) call(
method string, params Params, response Response,
) error {
Expand Down Expand Up @@ -466,17 +476,3 @@ func unshuffle(target interface{}) []interface{} {

return values
}

func expandKeyArgumentsInName(name string, key string) string {
match := reItemKeyParams.FindStringSubmatch(key)
if len(match) == 0 {
return name
}

args := strings.Split(match[1], ",")
for index, arg := range args {
name = strings.Replace(name, fmt.Sprintf(`$%d`, index+1), arg, -1)
}

return name
}

0 comments on commit 1cbb36b

Please sign in to comment.