master
go 108 lines 3 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 //go:build linux && cgo && ibm_mq
4
5 package mq
6
7 import (
8 "fmt"
9 "github.com/netdata/netdata/go/plugins/plugin/ibm.d/modules/mq/contexts"
10 "strings"
11 )
12
13 // collectSubscriptions collects subscription metrics from the queue manager
14 func (c *Collector) collectSubscriptions() error {
15 c.Debugf("Collecting subscriptions with selector '%s'", c.Config.SubscriptionSelector)
16
17 // Get list of subscriptions
18 subscriptions, err := c.client.InquireSubscription("")
19 if err != nil {
20 return fmt.Errorf("failed to inquire subscriptions: %w", err)
21 }
22
23 c.Debugf("Found %d subscriptions", len(subscriptions))
24
25 collected := 0
26 excluded := 0
27 failed := 0
28
29 for _, sub := range subscriptions {
30 // Check if subscription should be included based on selector
31 if c.Config.SubscriptionSelector != "" && c.Config.SubscriptionSelector != "*" {
32 if !matchesPattern(sub.Name, c.Config.SubscriptionSelector) {
33 c.Debugf("Skipping subscription '%s' (doesn't match selector)", sub.Name)
34 excluded++
35 continue
36 }
37 }
38
39 // Get subscription status (message count, last message time)
40 status, err := c.client.InquireSubscriptionStatus(sub.Name)
41 if err != nil {
42 c.Warningf("Failed to get status for subscription '%s': %v", sub.Name, err)
43 failed++
44 continue
45 }
46
47 labels := contexts.SubscriptionLabels{
48 Subscription: sub.Name,
49 Topic: sub.TopicString,
50 }
51
52 // Message count
53 if status.MessageCount.IsCollected() {
54 contexts.Subscription.MessageCount.Set(c.State, labels, contexts.SubscriptionMessageCountValues{
55 Pending: status.MessageCount.Int64(),
56 })
57 }
58
59 // Last message age (only if we have timestamp)
60 if status.LastMessageDate != "" && status.LastMessageTime != "" {
61 age, err := status.GetSubscriptionAge()
62 if err == nil && age >= 0 {
63 contexts.Subscription.LastMessageAge.Set(c.State, labels, contexts.SubscriptionLastMessageAgeValues{
64 Age: age,
65 })
66 }
67 }
68
69 collected++
70 }
71
72 c.Debugf("Subscription collection complete - discovered:%d excluded:%d collected:%d failed:%d",
73 len(subscriptions), excluded, collected, failed)
74
75 return nil
76 }
77
78 // matchesPattern checks if a name matches a pattern with wildcards
79 func matchesPattern(name, pattern string) bool {
80 // Convert wildcard pattern to simple matching
81 // * matches any sequence of characters
82 // ? matches any single character
83
84 // Special cases
85 if pattern == "" || pattern == "*" {
86 return true
87 }
88
89 // Simple wildcard matching
90 pattern = strings.ReplaceAll(pattern, "*", ".*")
91 pattern = strings.ReplaceAll(pattern, "?", ".")
92 pattern = "^" + pattern + "$"
93
94 // For simplicity, use string contains for now
95 // In production, we'd use a proper regex matcher
96 if strings.Contains(pattern, ".*") {
97 // Handle wildcard
98 parts := strings.Split(pattern, ".*")
99 if len(parts) == 2 {
100 prefix := strings.TrimPrefix(parts[0], "^")
101 suffix := strings.TrimSuffix(parts[1], "$")
102 return strings.HasPrefix(name, prefix) && strings.HasSuffix(name, suffix)
103 }
104 }
105
106 // Exact match
107 return name == strings.Trim(pattern, "^$")
108 }