referit changes
Some checks failed
Close stale issues and PRs / stale (push) Has been cancelled
Create Plugin Update / release (push) Has been cancelled

This commit is contained in:
Wesley van Tilburg
2026-01-29 09:33:03 +00:00
parent 57bfef6a23
commit 3d70908285
6 changed files with 214 additions and 20 deletions

View File

@@ -11,13 +11,20 @@ import (
)
func (ds *ZabbixDatasourceInstance) queryProblemsAlerting(ctx context.Context, query *QueryModel) ([]*data.Frame, error) {
ds.logger.Info("queryProblemsAlerting called", "groupFilter", query.Group.Filter, "hostFilter", query.Host.Filter)
triggers, err := ds.zabbix.GetTriggers(ctx, query.Group.Filter, query.Host.Filter)
if err != nil {
ds.logger.Error("GetTriggers failed", "error", err)
return nil, err
}
ds.logger.Info("GetTriggers returned", "count", len(triggers))
if len(triggers) == 0 {
return []*data.Frame{}, nil
frame := data.NewFrame("No triggers found")
frame.RefID = query.RefID
return []*data.Frame{frame}, nil
}
triggerIDs := make([]string, len(triggers))
@@ -30,6 +37,7 @@ func (ds *ZabbixDatasourceInstance) queryProblemsAlerting(ctx context.Context, q
return nil, err
}
// Map trigger ID to problem (includes opdata captured at problem creation)
problemMap := buildProblemMap(problems)
currentTime := time.Now()
@@ -37,10 +45,14 @@ func (ds *ZabbixDatasourceInstance) queryProblemsAlerting(ctx context.Context, q
for _, trigger := range triggers {
for _, host := range trigger.Hosts {
value := 0.0
if problemMap[trigger.ID] {
problemName := ""
opdata := ""
if problem, hasProblem := problemMap[trigger.ID]; hasProblem {
value = 1.0
problemName = problem.Name // Expanded trigger description at problem creation
opdata = problem.Opdata // Operational data if configured
}
frame := createAlertingFrame(trigger, host, value, currentTime, query.RefID)
frame := createAlertingFrame(trigger, host, value, problemName, opdata, currentTime, query.RefID)
frames = append(frames, frame)
}
}
@@ -48,21 +60,24 @@ func (ds *ZabbixDatasourceInstance) queryProblemsAlerting(ctx context.Context, q
return frames, nil
}
func buildProblemMap(problems []zabbix.Problem) map[string]bool {
problemMap := make(map[string]bool)
// buildProblemMap returns a map of trigger ID to Problem object
func buildProblemMap(problems []zabbix.Problem) map[string]zabbix.Problem {
problemMap := make(map[string]zabbix.Problem)
for _, p := range problems {
problemMap[p.ObjectID] = true
problemMap[p.ObjectID] = p
}
return problemMap
}
func createAlertingFrame(trigger zabbix.Trigger, host zabbix.ItemHost, value float64, ts time.Time, refID string) *data.Frame {
func createAlertingFrame(trigger zabbix.Trigger, host zabbix.ItemHost, value float64, problemName string, opdata string, ts time.Time, refID string) *data.Frame {
labels := data.Labels{
"host": host.Name,
"trigger": trigger.Description,
"trigger_id": trigger.ID,
"severity": trigger.Priority,
"tags": formatTags(trigger.Tags),
"host": host.Name,
"trigger": trigger.Description,
"trigger_id": trigger.ID,
"severity": mapSeverity(trigger.Priority),
"tags": formatTags(trigger.Tags),
"problem_name": problemName, // Expanded trigger description at problem creation
"opdata": opdata, // Operational data if configured on trigger
}
timeField := data.NewField("time", nil, []time.Time{ts})
@@ -75,6 +90,25 @@ func createAlertingFrame(trigger zabbix.Trigger, host zabbix.ItemHost, value flo
return frame
}
func mapSeverity(priority string) string {
switch priority {
case "0":
return "Not classified"
case "1":
return "Information"
case "2":
return "Warning"
case "3":
return "Average"
case "4":
return "High"
case "5":
return "Disaster"
default:
return priority
}
}
func formatTags(tags []zabbix.Tag) string {
if len(tags) == 0 {
return ""

View File

@@ -5,6 +5,7 @@ import (
"sort"
"strconv"
"strings"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
)
@@ -567,10 +568,15 @@ func (ds *Zabbix) GetVersion(ctx context.Context) (int, error) {
}
func (ds *Zabbix) GetTriggers(ctx context.Context, groupFilter string, hostFilter string) ([]Trigger, error) {
ds.logger.Info("GetTriggers called", "groupFilter", groupFilter, "hostFilter", hostFilter)
hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter)
if err != nil {
ds.logger.Error("GetHosts failed", "error", err)
return nil, err
}
ds.logger.Info("GetHosts returned", "count", len(hosts))
if len(hosts) == 0 {
return []Trigger{}, nil
}
@@ -580,23 +586,71 @@ func (ds *Zabbix) GetTriggers(ctx context.Context, groupFilter string, hostFilte
hostids = append(hostids, host.ID)
}
params := ZabbixAPIParams{
// Get triggers currently in PROBLEM state (always include these)
problemParams := ZabbixAPIParams{
"output": []string{"triggerid", "description", "priority", "value"},
"hostids": hostids,
"selectHosts": []string{"hostid", "name"},
"selectTags": "extend",
"monitored": true,
"expandDescription": true,
"skipDependent": true, // Only show root cause triggers, not dependent ones
"filter": map[string]interface{}{
"value": "1",
},
}
result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "trigger.get", Params: params})
problemResult, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "trigger.get", Params: problemParams})
if err != nil {
return nil, err
}
var triggers []Trigger
err = convertTo(result, &triggers)
return triggers, err
var problemTriggers []Trigger
err = convertTo(problemResult, &problemTriggers)
if err != nil {
return nil, err
}
// Get triggers that changed state in the last 24 hours (for alert resolution)
oneDayAgo := time.Now().Add(-24 * time.Hour).Unix()
recentParams := ZabbixAPIParams{
"output": []string{"triggerid", "description", "priority", "value"},
"hostids": hostids,
"selectHosts": []string{"hostid", "name"},
"selectTags": "extend",
"monitored": true,
"expandDescription": true,
"skipDependent": true, // Only show root cause triggers, not dependent ones
"lastChangeSince": oneDayAgo,
}
recentResult, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "trigger.get", Params: recentParams})
if err != nil {
return nil, err
}
var recentTriggers []Trigger
err = convertTo(recentResult, &recentTriggers)
if err != nil {
return nil, err
}
// Merge and deduplicate
triggerMap := make(map[string]Trigger)
for _, t := range problemTriggers {
triggerMap[t.ID] = t
}
for _, t := range recentTriggers {
triggerMap[t.ID] = t
}
triggers := make([]Trigger, 0, len(triggerMap))
for _, t := range triggerMap {
triggers = append(triggers, t)
}
ds.logger.Info("GetTriggers returning", "problemCount", len(problemTriggers), "recentCount", len(recentTriggers), "totalCount", len(triggers))
return triggers, nil
}
func (ds *Zabbix) GetProblems(ctx context.Context, triggerIDs []string) ([]Problem, error) {
@@ -605,7 +659,7 @@ func (ds *Zabbix) GetProblems(ctx context.Context, triggerIDs []string) ([]Probl
}
params := ZabbixAPIParams{
"output": []string{"eventid", "objectid", "severity", "name"},
"output": []string{"eventid", "objectid", "severity", "name", "opdata"},
"objectids": triggerIDs,
"source": "0",
"object": "0",

View File

@@ -126,5 +126,6 @@ type Problem struct {
ObjectID string `json:"objectid"`
Severity string `json:"severity"`
Name string `json:"name"`
Opdata string `json:"opdata"`
Tags []Tag `json:"tags,omitempty"`
}