Add additional metrics and reverse metric names option to openldap (#3722)

This commit is contained in:
Andy Cobaugh 2018-02-05 15:48:41 -05:00 committed by Daniel Nelson
parent 5639d5608d
commit ea0be51985
3 changed files with 101 additions and 46 deletions

View File

@ -25,50 +25,62 @@ To use this plugin you must enable the [monitoring](https://www.openldap.org/dev
# dn/password to bind with. If bind_dn is empty, an anonymous bind is performed. # dn/password to bind with. If bind_dn is empty, an anonymous bind is performed.
bind_dn = "" bind_dn = ""
bind_password = "" bind_password = ""
# reverse metric names so they sort more naturally
# Defaults to false if unset, but is set to true when generating a new config
reverse_metric_names = true
``` ```
### Measurements & Fields: ### Measurements & Fields:
All **monitorCounter**, **monitorOpInitiated**, and **monitorOpCompleted** attributes are gathered based on this LDAP query: All **monitorCounter**, **monitoredInfo**, **monitorOpInitiated**, and **monitorOpCompleted** attributes are gathered based on this LDAP query:
```(|(objectClass=monitorCounterObject)(objectClass=monitorOperation))``` ```(|(objectClass=monitorCounterObject)(objectClass=monitorOperation)(objectClass=monitoredObject))```
Metric names are based on their entry DN. Metric names are based on their entry DN with the cn=Monitor base removed. If `reverse_metric_names` is not set, metrics are based on their DN. If `reverse_metric_names` is set to `true`, the names are reversed. This is recommended as it allows the names to sort more naturally.
Metrics for the **monitorOp*** attributes have **_initiated** and **_completed** added to the base name. Metrics for the **monitorOp*** attributes have **_initiated** and **_completed** added to the base name as appropriate.
An OpenLDAP 2.4 server will provide these metrics: An OpenLDAP 2.4 server will provide these metrics:
- openldap - openldap
- max_file_descriptors_connections - connections_current
- current_connections - connections_max_file_descriptors
- total_connections - connections_total
- abandon_operations_completed - operations_abandon_completed
- abandon_operations_initiated - operations_abandon_initiated
- add_operations_completed - operations_add_completed
- add_operations_initiated - operations_add_initiated
- bind_operations_completed - operations_bind_completed
- bind_operations_initiated - operations_bind_initiated
- compare_operations_completed - operations_compare_completed
- compare_operations_initiated - operations_compare_initiated
- delete_operations_completed - operations_delete_completed
- delete_operations_initiated - operations_delete_initiated
- extended_operations_completed - operations_extended_completed
- extended_operations_initiated - operations_extended_initiated
- modify_operations_completed - operations_modify_completed
- modify_operations_initiated - operations_modify_initiated
- modrdn_operations_completed - operations_modrdn_completed
- modrdn_operations_initiated - operations_modrdn_initiated
- search_operations_completed - operations_search_completed
- search_operations_initiated - operations_search_initiated
- unbind_operations_completed - operations_unbind_completed
- unbind_operations_initiated - operations_unbind_initiated
- bytes_statistics - statistics_bytes
- entries_statistics - statistics_entries
- pdu_statistics - statistics_pdu
- referrals_statistics - statistics_referrals
- read_waiters - threads_active
- write_waiters - threads_backload
- threads_max
- threads_max_pending
- threads_open
- threads_pending
- threads_starting
- time_uptime
- waiters_read
- waiters_write
### Tags: ### Tags:
@ -80,5 +92,5 @@ An OpenLDAP 2.4 server will provide these metrics:
``` ```
$ telegraf -config telegraf.conf -input-filter openldap -test --debug $ telegraf -config telegraf.conf -input-filter openldap -test --debug
* Plugin: inputs.openldap, Collection 1 * Plugin: inputs.openldap, Collection 1
> openldap,server=localhost,port=389,host=zirzla search_operations_completed=2i,delete_operations_completed=0i,read_waiters=1i,total_connections=1004i,bind_operations_completed=3i,unbind_operations_completed=3i,referrals_statistics=0i,current_connections=1i,bind_operations_initiated=3i,compare_operations_completed=0i,add_operations_completed=2i,delete_operations_initiated=0i,unbind_operations_initiated=3i,search_operations_initiated=3i,add_operations_initiated=2i,max_file_descriptors_connections=4096i,abandon_operations_initiated=0i,write_waiters=0i,modrdn_operations_completed=0i,abandon_operations_completed=0i,pdu_statistics=23i,modify_operations_initiated=0i,bytes_statistics=1660i,entries_statistics=17i,compare_operations_initiated=0i,modrdn_operations_initiated=0i,extended_operations_completed=0i,modify_operations_completed=0i,extended_operations_initiated=0i 1499990455000000000 > openldap,server=localhost,port=389,host=niska.ait.psu.edu operations_bind_initiated=10i,operations_unbind_initiated=6i,operations_modrdn_completed=0i,operations_delete_initiated=0i,operations_add_completed=2i,operations_delete_completed=0i,operations_abandon_completed=0i,statistics_entries=1516i,threads_open=2i,threads_active=1i,waiters_read=1i,operations_modify_completed=0i,operations_extended_initiated=4i,threads_pending=0i,operations_search_initiated=36i,operations_compare_initiated=0i,connections_max_file_descriptors=4096i,operations_modify_initiated=0i,operations_modrdn_initiated=0i,threads_max=16i,time_uptime=6017i,connections_total=1037i,connections_current=1i,operations_add_initiated=2i,statistics_bytes=162071i,operations_unbind_completed=6i,operations_abandon_initiated=0i,statistics_pdu=1566i,threads_max_pending=0i,threads_backload=1i,waiters_write=0i,operations_bind_completed=10i,operations_search_completed=35i,operations_compare_completed=0i,operations_extended_completed=4i,statistics_referrals=0i,threads_starting=0i 1516912070000000000
``` ```

View File

@ -20,6 +20,7 @@ type Openldap struct {
SslCa string SslCa string
BindDn string BindDn string
BindPassword string BindPassword string
ReverseMetricNames bool
} }
const sampleConfig string = ` const sampleConfig string = `
@ -40,13 +41,18 @@ const sampleConfig string = `
# dn/password to bind with. If bind_dn is empty, an anonymous bind is performed. # dn/password to bind with. If bind_dn is empty, an anonymous bind is performed.
bind_dn = "" bind_dn = ""
bind_password = "" bind_password = ""
# Reverse metric names so they sort more naturally. Recommended.
# This defaults to false if unset, but is set to true when generating a new config
reverse_metric_names = true
` `
var searchBase = "cn=Monitor" var searchBase = "cn=Monitor"
var searchFilter = "(|(objectClass=monitorCounterObject)(objectClass=monitorOperation))" var searchFilter = "(|(objectClass=monitorCounterObject)(objectClass=monitorOperation)(objectClass=monitoredObject))"
var searchAttrs = []string{"monitorCounter", "monitorOpInitiated", "monitorOpCompleted"} var searchAttrs = []string{"monitorCounter", "monitorOpInitiated", "monitorOpCompleted", "monitoredInfo"}
var attrTranslate = map[string]string{ var attrTranslate = map[string]string{
"monitorCounter": "", "monitorCounter": "",
"monitoredInfo": "",
"monitorOpInitiated": "_initiated", "monitorOpInitiated": "_initiated",
"monitorOpCompleted": "_completed", "monitorOpCompleted": "_completed",
} }
@ -69,6 +75,7 @@ func NewOpenldap() *Openldap {
SslCa: "", SslCa: "",
BindDn: "", BindDn: "",
BindPassword: "", BindPassword: "",
ReverseMetricNames: false,
} }
} }
@ -149,7 +156,7 @@ func gatherSearchResult(sr *ldap.SearchResult, o *Openldap, acc telegraf.Accumul
"port": strconv.Itoa(o.Port), "port": strconv.Itoa(o.Port),
} }
for _, entry := range sr.Entries { for _, entry := range sr.Entries {
metricName := dnToMetric(entry.DN, searchBase) metricName := dnToMetric(entry.DN, o)
for _, attr := range entry.Attributes { for _, attr := range entry.Attributes {
if len(attr.Values[0]) >= 1 { if len(attr.Values[0]) >= 1 {
if v, err := strconv.ParseInt(attr.Values[0], 10, 64); err == nil { if v, err := strconv.ParseInt(attr.Values[0], 10, 64); err == nil {
@ -162,15 +169,30 @@ func gatherSearchResult(sr *ldap.SearchResult, o *Openldap, acc telegraf.Accumul
return return
} }
// Convert a DN to metric name, eg cn=Read,cn=Waiters,cn=Monitor to read_waiters // Convert a DN to metric name, eg cn=Read,cn=Waiters,cn=Monitor becomes waiters_read
func dnToMetric(dn, searchBase string) string { // Assumes the last part of the DN is cn=Monitor and we want to drop it
func dnToMetric(dn string, o *Openldap) string {
if o.ReverseMetricNames {
var metricParts []string
dn = strings.Trim(dn, " ")
dn = strings.Replace(dn, " ", "_", -1)
dn = strings.Replace(dn, "cn=", "", -1)
dn = strings.ToLower(dn)
metricParts = strings.Split(dn, ",")
for i, j := 0, len(metricParts)-1; i < j; i, j = i+1, j-1 {
metricParts[i], metricParts[j] = metricParts[j], metricParts[i]
}
return strings.Join(metricParts[1:], "_")
} else {
metricName := strings.Trim(dn, " ") metricName := strings.Trim(dn, " ")
metricName = strings.Replace(metricName, " ", "_", -1) metricName = strings.Replace(metricName, " ", "_", -1)
metricName = strings.ToLower(metricName) metricName = strings.ToLower(metricName)
metricName = strings.TrimPrefix(metricName, "cn=") metricName = strings.TrimPrefix(metricName, "cn=")
metricName = strings.Replace(metricName, strings.ToLower(searchBase), "", -1) metricName = strings.Replace(metricName, strings.ToLower("cn=Monitor"), "", -1)
metricName = strings.Replace(metricName, "cn=", "_", -1) metricName = strings.Replace(metricName, "cn=", "_", -1)
return strings.Replace(metricName, ",", "", -1) return strings.Replace(metricName, ",", "", -1)
}
} }
func init() { func init() {

View File

@ -148,3 +148,24 @@ func commonTests(t *testing.T, o *Openldap, acc *testutil.Accumulator) {
assert.Equal(t, strconv.Itoa(o.Port), acc.TagValue("openldap", "port"), "Has a tag value of port=o.Port") assert.Equal(t, strconv.Itoa(o.Port), acc.TagValue("openldap", "port"), "Has a tag value of port=o.Port")
assert.True(t, acc.HasInt64Field("openldap", "total_connections"), "Has an integer field called total_connections") assert.True(t, acc.HasInt64Field("openldap", "total_connections"), "Has an integer field called total_connections")
} }
func TestOpenldapReverseMetrics(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
}
o := &Openldap{
Host: testutil.GetLocalHost(),
Port: 389,
Ssl: "",
InsecureSkipVerify: true,
BindDn: "cn=manager,cn=config",
BindPassword: "secret",
ReverseMetricNames: true,
}
var acc testutil.Accumulator
err := o.Gather(&acc)
require.NoError(t, err)
assert.True(t, acc.HasInt64Field("openldap", "connections_total"), "Has an integer field called connections_total")
}