Skip to content
This repository has been archived by the owner on Sep 1, 2024. It is now read-only.

Commit

Permalink
add support for prometheus exporter-toolkit web config
Browse files Browse the repository at this point in the history
  • Loading branch information
tomcz committed May 30, 2021
1 parent 1238e98 commit b97f88e
Show file tree
Hide file tree
Showing 701 changed files with 272,520 additions and 14,677 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ USAGE:
openldap_exporter [global options] [arguments...]
VERSION:
v2.0-7-gf81504e (f81504e)
v2.1.2
GLOBAL OPTIONS:
--promAddr value Bind address for Prometheus HTTP metrics server (default: ":9330") [$PROM_ADDR]
Expand All @@ -97,6 +97,7 @@ GLOBAL OPTIONS:
--ldapUser value OpenLDAP bind username (optional) [$LDAP_USER]
--ldapPass value OpenLDAP bind password (optional) [$LDAP_PASS]
--interval value Scrape interval (default: 30s) [$INTERVAL]
--webCfgFile FILE Prometheus metrics web config FILE (optional) [$WEB_CFG_FILE]
--config YAML_FILE Optional configuration from a YAML_FILE
--help, -h show help (default: false)
--version, -v print the version (default: false)
Expand All @@ -116,7 +117,12 @@ ldapUser: "cn=monitoring,cn=Monitor"
ldapPass: "sekret"
```
NOTES:
* `--ldapNet` allows you to configure `tcp` or `unix` socket connections to your co-located OpenLDAP server.
* `--webCfgFile` can be used to provide authentiction and TLS configuration for the [prometheus web exporter](https://github.com/prometheus/exporter-toolkit/tree/master/web).

## Build

1. Install Go 1.13 from https://golang.org/
1. Install Go 1.16 from https://golang.org/
2. Build the binaries: `make build`
61 changes: 48 additions & 13 deletions cmd/openldap_exporter/main.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
package main

import (
"context"
"log"
"os"
"os/signal"
"syscall"
"time"

exporter "github.com/tomcz/openldap_exporter"

"github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
"golang.org/x/sync/errgroup"
)

const (
promAddr = "promAddr"
ldapNet = "ldapNet"
ldapAddr = "ldapAddr"
ldapUser = "ldapUser"
ldapPass = "ldapPass"
interval = "interval"
metrics = "metrPath"
config = "config"
promAddr = "promAddr"
ldapNet = "ldapNet"
ldapAddr = "ldapAddr"
ldapUser = "ldapUser"
ldapPass = "ldapPass"
interval = "interval"
metrics = "metrPath"
webCfgFile = "webCfgFile"
config = "config"
)

func main() {
Expand Down Expand Up @@ -64,6 +69,11 @@ func main() {
Usage: "Scrape interval",
EnvVars: []string{"INTERVAL"},
}),
altsrc.NewStringFlag(&cli.StringFlag{
Name: webCfgFile,
Usage: "Prometheus metrics web config `FILE` (optional)",
EnvVars: []string{"WEB_CFG_FILE"},
}),
&cli.StringFlag{
Name: config,
Usage: "Optional configuration from a `YAML_FILE`",
Expand Down Expand Up @@ -94,8 +104,7 @@ func optionalYamlSourceFunc(flagFileName string) func(context *cli.Context) (alt
}

func runMain(c *cli.Context) error {
log.Println("starting Prometheus HTTP metrics server on", c.String(promAddr))
go exporter.StartMetricsServer(c.String(promAddr), c.String(metrics))
server := exporter.NewMetricsServer(c.String(promAddr), c.String(metrics), c.String(webCfgFile))

scraper := &exporter.Scraper{
Net: c.String(ldapNet),
Expand All @@ -104,7 +113,33 @@ func runMain(c *cli.Context) error {
Pass: c.String(ldapPass),
Tick: c.Duration(interval),
}
log.Println("starting OpenLDAP scraper for", scraper.Addr)
scraper.Start()
return nil

ctx, cancel := context.WithCancel(context.Background())
var group errgroup.Group
group.Go(func() error {
defer cancel()
log.Printf("starting Prometheus HTTP metrics server on %s\n", c.String(promAddr))
return server.Start()
})
group.Go(func() error {
defer cancel()
log.Printf("starting OpenLDAP scraper for %s://%s\n", scraper.Net, scraper.Addr)
return scraper.Start(ctx)
})
group.Go(func() error {
defer func() {
cancel()
server.Stop()
}()
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
select {
case <-signalChan:
log.Println("shutdown received")
return nil
case <-ctx.Done():
return nil
}
})
return group.Wait()
}
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ module github.com/tomcz/openldap_exporter
go 1.16

require (
github.com/hashicorp/go-multierror v1.0.0
github.com/prometheus/client_golang v1.2.1
github.com/go-kit/kit v0.10.0
github.com/prometheus/client_golang v1.7.1
github.com/prometheus/exporter-toolkit v0.5.1
github.com/urfave/cli/v2 v2.2.0
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
gopkg.in/ldap.v2 v2.5.1
)
363 changes: 347 additions & 16 deletions go.sum

Large diffs are not rendered by default.

34 changes: 21 additions & 13 deletions scraper.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package openldap_exporter

import (
"context"
"fmt"
"log"
"strconv"
"strings"
"time"

"github.com/hashicorp/go-multierror"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/ldap.v2"
)
Expand Down Expand Up @@ -113,39 +113,47 @@ type Scraper struct {
Tick time.Duration
}

func (s *Scraper) Start() {
for range time.Tick(s.Tick) {
s.runOnce()
func (s *Scraper) Start(ctx context.Context) error {
ticker := time.NewTicker(s.Tick)
for {
select {
case <-ticker.C:
s.runOnce()
case <-ctx.Done():
return nil
}
}
}

func (s *Scraper) runOnce() {
if err := s.scrape(); err != nil {
scrapeCounter.WithLabelValues("fail").Inc()
log.Println("scrape failed, error is:", err)
} else {
if s.scrape() {
scrapeCounter.WithLabelValues("ok").Inc()
} else {
scrapeCounter.WithLabelValues("fail").Inc()
}
}

func (s *Scraper) scrape() error {
func (s *Scraper) scrape() bool {
l, err := ldap.Dial(s.Net, s.Addr)
if err != nil {
return fmt.Errorf("dial failed: %w", err)
log.Printf("dial failed: %v\n", err)
return false
}
defer l.Close()

if s.User != "" && s.Pass != "" {
err = l.Bind(s.User, s.Pass)
if err != nil {
return fmt.Errorf("bind failed: %w", err)
log.Printf("bind failed: %v\n", err)
return false
}
}

var ret error
ret := true
for _, q := range queries {
if err := scrapeQuery(l, q); err != nil {
ret = multierror.Append(ret, err)
log.Println(err.Error())
ret = false
}
}
return ret
Expand Down
52 changes: 47 additions & 5 deletions server.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package openldap_exporter

import (
"context"
"errors"
"fmt"
"log"
"net/http"
"strings"
"time"

kitlog "github.com/go-kit/kit/log"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/exporter-toolkit/web"
)

var commit string
Expand All @@ -15,14 +21,32 @@ func GetVersion() string {
return fmt.Sprintf("%s (%s)", tag, commit)
}

func StartMetricsServer(bindAddr, metricsPath string) {
type Server struct {
server *http.Server
cfgPath string
}

func (s *Server) Start() error {
err := web.ListenAndServe(s.server, s.cfgPath, kitlog.LoggerFunc(logger))
if errors.Is(err, http.ErrServerClosed) {
return nil
}
return err
}

func (s *Server) Stop() {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
s.server.Shutdown(ctx)
cancel()
}

func NewMetricsServer(bindAddr, metricsPath, tlsConfigPath string) *Server {
mux := http.NewServeMux()
mux.Handle(metricsPath, promhttp.Handler())
mux.HandleFunc("/version", showVersion)

err := http.ListenAndServe(bindAddr, mux)
if err != nil {
log.Fatalln("http listener failed, error is:", err)
return &Server{
server: &http.Server{Addr: bindAddr, Handler: mux},
cfgPath: tlsConfigPath,
}
}

Expand All @@ -34,3 +58,21 @@ func showVersion(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
fmt.Fprintln(w, GetVersion())
}

func logger(kvs ...interface{}) error {
if len(kvs) == 0 {
return nil
}
if len(kvs)%2 != 0 {
kvs = append(kvs, nil)
}
var buf strings.Builder
for i := 0; i < len(kvs); i += 2 {
if i > 0 {
buf.WriteString(" ")
}
fmt.Fprintf(&buf, "%v=%v", kvs[i], kvs[i+1])
}
log.Println(buf.String())
return nil
}
12 changes: 12 additions & 0 deletions vendor/github.com/cespare/xxhash/v2/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/github.com/cespare/xxhash/v2/go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions vendor/github.com/go-kit/kit/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b97f88e

Please sign in to comment.