diff --git a/examples/server2.status b/examples/server2.status index d5499ed..a82eb23 100644 --- a/examples/server2.status +++ b/examples/server2.status @@ -6,11 +6,13 @@ CLIENT_LIST,redacted2,0.0.0.0:60536,0.0.0.0,2925752,3145665,Thu Mar 16 17:08:57 CLIENT_LIST,redacted3,0.0.0.0:28331,0.0.0.0,57316467,611736741,Thu Mar 16 17:08:57 2017,1489680537,UNDEF CLIENT_LIST,redacted4,0.0.0.0:52335,0.0.0.0,24289622392,70914674697,Fri Mar 17 11:16:29 2017,1489745789,UNDEF CLIENT_LIST,redacted5,0.0.0.0:51865,0.0.0.0,277017840,1544465106,Thu Mar 16 17:09:01 2017,1489680541,UNDEF +CLIENT_LIST,redacted1,0.0.0.0:19021,0.0.0.0,693438277,228390856,Thu Mar 16 17:09:03 2017,1489680543,UNDEF HEADER,ROUTING_TABLE,Virtual Address,Common Name,Real Address,Last Ref,Last Ref (time_t) ROUTING_TABLE,0.0.0.0,redacted1,0.0.0.0:19021,Tue Mar 21 10:26:48 2017,1490088408 ROUTING_TABLE,0.0.0.0,redacted5,0.0.0.0:51865,Tue Mar 21 10:38:26 2017,1490089106 ROUTING_TABLE,0.0.0.0,redacted3,0.0.0.0:28331,Tue Mar 21 10:39:06 2017,1490089146 ROUTING_TABLE,0.0.0.0,redacted4,0.0.0.0:52335,Tue Mar 21 10:39:13 2017,1490089153 ROUTING_TABLE,0.0.0.0,redacted2,0.0.0.0:60536,Thu Mar 16 17:08:58 2017,1489680538 +ROUTING_TABLE,0.0.0.0,redacted1,0.0.0.0:19021,Tue Mar 21 10:26:48 2017,1490088408 GLOBAL_STATS,Max bcast/mcast queue length,0 END diff --git a/exporters/openvpn_exporter.go b/exporters/openvpn_exporter.go index 559b42e..556b749 100644 --- a/exporters/openvpn_exporter.go +++ b/exporters/openvpn_exporter.go @@ -184,6 +184,8 @@ func (e *OpenVPNExporter) collectServerStatusFromReader(statusPath string, file // counter of connected client numberConnectedClient := 0 + recordedMetrics := map[OpenvpnServerHeaderField][]string{} + for scanner.Scan() { fields := strings.Split(scanner.Text(), separator) if fields[0] == "END" && len(fields) == 1 { @@ -237,15 +239,20 @@ func (e *OpenVPNExporter) collectServerStatusFromReader(statusPath string, file // Export relevant columns as individual metrics. for _, metric := range header.Metrics { if columnValue, ok := columnValues[metric.Column]; ok { - value, err := strconv.ParseFloat(columnValue, 64) - if err != nil { - return err + if l, _ := recordedMetrics[metric]; ! subslice(labels, l) { + value, err := strconv.ParseFloat(columnValue, 64) + if err != nil { + return err + } + ch <- prometheus.MustNewConstMetric( + metric.Desc, + metric.ValueType, + value, + labels...) + recordedMetrics[metric] = append(recordedMetrics[metric], labels...) + } else { + log.Printf("Metric entry with same labels: %s, %s", metric.Column, labels) } - ch <- prometheus.MustNewConstMetric( - metric.Desc, - metric.ValueType, - value, - labels...) } } } else { @@ -261,6 +268,27 @@ func (e *OpenVPNExporter) collectServerStatusFromReader(statusPath string, file return scanner.Err() } +// Does slice contain string +func contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} + +// Is a sub-slice of slice +func subslice(sub []string, main []string) bool { + if len(sub) > len(main) {return false} + for _, s := range sub { + if ! contains(main, s) { + return false + } + } + return true +} + // Converts OpenVPN client status information into Prometheus metrics. func (e *OpenVPNExporter) collectClientStatusFromReader(statusPath string, file io.Reader, ch chan<- prometheus.Metric) error { scanner := bufio.NewScanner(file)