package datasource import ( "context" "fmt" "strings" "time" "github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix" "github.com/grafana/grafana-plugin-sdk-go/data" ) 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 { frame := data.NewFrame("No triggers found") frame.RefID = query.RefID return []*data.Frame{frame}, nil } triggerIDs := make([]string, len(triggers)) for i, t := range triggers { triggerIDs[i] = t.ID } problems, err := ds.zabbix.GetProblems(ctx, triggerIDs) if err != nil { return nil, err } // Map trigger ID to problem (includes opdata captured at problem creation) problemMap := buildProblemMap(problems) currentTime := time.Now() frames := make([]*data.Frame, 0) for _, trigger := range triggers { for _, host := range trigger.Hosts { value := 0.0 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, problemName, opdata, currentTime, query.RefID) frames = append(frames, frame) } } return frames, nil } // 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] = p } return problemMap } 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": 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}) valueField := data.NewField("value", labels, []float64{value}) frameName := fmt.Sprintf("%s: %s", host.Name, trigger.Description) frame := data.NewFrame(frameName, timeField, valueField) frame.RefID = refID 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 "" } parts := make([]string, len(tags)) for i, t := range tags { if t.Value != "" { parts[i] = fmt.Sprintf("%s:%s", t.Tag, t.Value) } else { parts[i] = t.Tag } } return strings.Join(parts, ",") }