@@ -24,13 +24,17 @@ const (
24
24
25
25
monitorOperation = "monitorOperation"
26
26
monitorOpCompleted = "monitorOpCompleted"
27
+
28
+ monitorReplicationFilter = "contextcsn"
29
+ monitorReplication = "monitorReplication"
27
30
)
28
31
29
32
type query struct {
30
33
baseDN string
31
34
searchFilter string
32
35
searchAttr string
33
36
metric * prometheus.GaugeVec
37
+ setData func ([]* ldap.Entry , * query ) error
34
38
}
35
39
36
40
var (
@@ -66,24 +70,50 @@ var (
66
70
},
67
71
[]string {"result" },
68
72
)
73
+ monitorReplicationGauge = prometheus .NewGaugeVec (
74
+ prometheus.GaugeOpts {
75
+ Subsystem : "openldap" ,
76
+ Name : "monitor_replication" ,
77
+ Help : help (baseDN , monitorReplication ),
78
+ },
79
+ []string {"id" , "type" },
80
+ )
69
81
queries = []* query {
70
82
{
71
83
baseDN : baseDN ,
72
84
searchFilter : objectClass (monitoredObject ),
73
85
searchAttr : monitoredInfo ,
74
86
metric : monitoredObjectGauge ,
75
- },
76
- {
87
+ setData : func (entries []* ldap.Entry , q * query ) error {
88
+ return setValue (entries , q )
89
+
90
+ },
91
+ }, {
77
92
baseDN : baseDN ,
78
93
searchFilter : objectClass (monitorCounterObject ),
79
94
searchAttr : monitorCounter ,
80
95
metric : monitorCounterObjectGauge ,
96
+ setData : func (entries []* ldap.Entry , q * query ) error {
97
+ return setValue (entries , q )
98
+ },
99
+ },
100
+ {
101
+ baseDN : opsBaseDN ,
102
+ searchFilter : objectClass (monitorOperation ),
103
+ searchAttr : monitorOpCompleted ,
104
+ metric : monitorOperationGauge ,
105
+ setData : func (entries []* ldap.Entry , q * query ) error {
106
+ return setValue (entries , q )
107
+ },
81
108
},
82
109
{
83
110
baseDN : opsBaseDN ,
84
111
searchFilter : objectClass (monitorOperation ),
85
112
searchAttr : monitorOpCompleted ,
86
113
metric : monitorOperationGauge ,
114
+ setData : func (entries []* ldap.Entry , q * query ) error {
115
+ return setValue (entries , q )
116
+ },
87
117
},
88
118
}
89
119
)
@@ -93,6 +123,7 @@ func init() {
93
123
monitoredObjectGauge ,
94
124
monitorCounterObjectGauge ,
95
125
monitorOperationGauge ,
126
+ monitorReplicationGauge ,
96
127
scrapeCounter ,
97
128
)
98
129
}
@@ -105,17 +136,81 @@ func objectClass(name string) string {
105
136
return fmt .Sprintf ("(objectClass=%v)" , name )
106
137
}
107
138
139
+ func setValue (entries []* ldap.Entry , q * query ) error {
140
+ for _ , entry := range entries {
141
+ val := entry .GetAttributeValue (q .searchAttr )
142
+ if val == "" {
143
+ // not every entry will have this attribute
144
+ continue
145
+ }
146
+ num , err := strconv .ParseFloat (val , 64 )
147
+ if err != nil {
148
+ // some of these attributes are not numbers
149
+ continue
150
+ }
151
+ q .metric .WithLabelValues (entry .DN ).Set (num )
152
+ }
153
+ return nil
154
+
155
+ }
156
+
108
157
type Scraper struct {
109
- Net string
110
- Addr string
111
- User string
112
- Pass string
113
- Tick time.Duration
114
- log log.FieldLogger
158
+ Net string
159
+ Addr string
160
+ User string
161
+ Pass string
162
+ Tick time.Duration
163
+ LdapSync []string
164
+ log log.FieldLogger
165
+ Sync []string
166
+ }
167
+
168
+ func (s * Scraper ) addReplicationQueries () error {
169
+ if len (s .Sync ) != 0 {
170
+ for _ , q := range s .Sync {
171
+ queries = append (queries ,
172
+ & query {
173
+ baseDN : q ,
174
+ searchFilter : objectClass ("*" ),
175
+ searchAttr : "contextCSN" ,
176
+ metric : monitorReplicationGauge ,
177
+ setData : func (entries []* ldap.Entry , q * query ) error {
178
+ for _ , entry := range entries {
179
+ val := entry .GetAttributeValue (q .searchAttr )
180
+ if val == "" {
181
+ // not every entry will have this attribute
182
+ continue
183
+ }
184
+ valueBuffer := strings .Split (val , "#" )
185
+ gt , err := time .Parse ("20060102150405.999999Z" , valueBuffer [0 ])
186
+ if err != nil {
187
+ return err
188
+ }
189
+ count , err := strconv .ParseFloat (valueBuffer [1 ], 64 )
190
+ if err != nil {
191
+ return err
192
+ }
193
+ sid := valueBuffer [2 ]
194
+ mod , err := strconv .ParseFloat (valueBuffer [3 ], 64 )
195
+ if err != nil {
196
+ return err
197
+ }
198
+ q .metric .WithLabelValues (sid , "gt" ).Set (float64 (gt .Unix ()))
199
+ q .metric .WithLabelValues (sid , "count" ).Set (count )
200
+ q .metric .WithLabelValues (sid , "mod" ).Set (mod )
201
+ }
202
+ return nil
203
+ },
204
+ },
205
+ )
206
+ }
207
+ }
208
+ return nil
115
209
}
116
210
117
211
func (s * Scraper ) Start (ctx context.Context ) error {
118
212
s .log = log .WithField ("component" , "scraper" )
213
+ s .addReplicationQueries ()
119
214
address := fmt .Sprintf ("%s://%s" , s .Net , s .Addr )
120
215
s .log .WithField ("addr" , address ).Info ("starting monitor loop" )
121
216
ticker := time .NewTicker (s .Tick )
@@ -167,24 +262,11 @@ func (s *Scraper) scrape() bool {
167
262
func scrapeQuery (conn * ldap.Conn , q * query ) error {
168
263
req := ldap .NewSearchRequest (
169
264
q .baseDN , ldap .ScopeWholeSubtree , ldap .NeverDerefAliases , 0 , 0 , false ,
170
- q .searchFilter , []string {"dn" , q .searchAttr }, nil ,
265
+ q .searchFilter , []string {q .searchAttr }, nil ,
171
266
)
172
267
sr , err := conn .Search (req )
173
268
if err != nil {
174
269
return err
175
270
}
176
- for _ , entry := range sr .Entries {
177
- val := entry .GetAttributeValue (q .searchAttr )
178
- if val == "" {
179
- // not every entry will have this attribute
180
- continue
181
- }
182
- num , err := strconv .ParseFloat (val , 64 )
183
- if err != nil {
184
- // some of these attributes are not numbers
185
- continue
186
- }
187
- q .metric .WithLabelValues (entry .DN ).Set (num )
188
- }
189
- return nil
271
+ return q .setData (sr .Entries , q )
190
272
}
0 commit comments