Skip to content

Commit ac69e2c

Browse files
committed
offloaded most of the route processing to exporter-toolkit
Signed-off-by: kwilt <[email protected]>
1 parent 0ec9fa8 commit ac69e2c

File tree

3 files changed

+21
-103
lines changed

3 files changed

+21
-103
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ go 1.22
44

55
toolchain go1.23.1
66

7+
replace github.com/prometheus/exporter-toolkit => /home/knapdev/exporter-toolkit
8+
79
require (
810
github.com/alecthomas/kingpin/v2 v2.4.0
911
github.com/gosnmp/gosnmp v1.38.0

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p
4444
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
4545
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
4646
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
47-
github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg=
48-
github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA=
4947
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
5048
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
5149
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=

main.go

Lines changed: 19 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,9 @@
1414
package main
1515

1616
import (
17-
"errors"
1817
"fmt"
1918
"log/slog"
20-
"net"
2119
"net/http"
22-
"net/http/pprof"
23-
"net/url"
2420
"os"
2521
"os/signal"
2622
"path"
@@ -235,37 +231,6 @@ func main() {
235231
return
236232
}
237233

238-
// Infer or set snmp exporter externalURL
239-
listenAddrs := toolkitFlags.WebListenAddresses
240-
if *externalURL == "" && *toolkitFlags.WebSystemdSocket {
241-
logger.Error("Cannot automatically infer external URL with systemd socket listener. Please provide --web.external-url")
242-
os.Exit(1)
243-
} else if *externalURL == "" && len(*listenAddrs) > 1 {
244-
logger.Info("Inferring external URL from first provided listen address")
245-
}
246-
247-
beURL, err := computeExternalURL(*externalURL, (*listenAddrs)[0])
248-
if err != nil {
249-
logger.Error("Failed to determine external URL", "err", err)
250-
os.Exit(1)
251-
}
252-
logger.Debug("External URL", "url", beURL.String())
253-
254-
// Default -web.route-prefix to path of -web.external-url
255-
if *routePrefix == "" {
256-
*routePrefix = beURL.Path
257-
}
258-
259-
// routePrefix must always be at least '/'
260-
*routePrefix = "/" + strings.Trim(*routePrefix, "/")
261-
logger.Debug("Route prefix", "prefix", *routePrefix)
262-
// routePrefix requires path to have trailing "/" in order
263-
// for browsers to interpret the path-relative path correctly, instead of stripping it.
264-
if *routePrefix != "/" {
265-
*routePrefix = *routePrefix + "/"
266-
}
267-
logger.Debug(*routePrefix)
268-
269234
hup := make(chan os.Signal, 1)
270235
reloadCh = make(chan chan error)
271236
signal.Notify(hup, syscall.SIGHUP)
@@ -331,35 +296,16 @@ func main() {
331296
),
332297
}
333298

334-
// Match Prometheus behavior and redirect over externalURL for root path only
335-
// if routePrefix is different from "/"
336-
if *routePrefix != "/" {
337-
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
338-
if r.URL.Path != "/" {
339-
http.NotFound(w, r)
340-
return
341-
}
342-
http.Redirect(w, r, beURL.String(), http.StatusFound)
343-
})
344-
}
345-
346-
http.Handle(path.Join(*routePrefix, *metricsPath), promhttp.Handler()) // Normal metrics endpoint for SNMP exporter itself.
347-
// Endpoint to do SNMP scrapes.
348-
http.HandleFunc(path.Join(*routePrefix, proberPath), func(w http.ResponseWriter, r *http.Request) {
349-
handler(w, r, logger, exporterMetrics)
350-
})
351-
http.HandleFunc(path.Join(*routePrefix, "/-/reload"), updateConfiguration) // Endpoint to reload configuration.
352-
// Serve pprof under the route prefix. These links are displayed on the landing page.
353-
http.HandleFunc(path.Join(*routePrefix, "debug/pprof/"), pprof.Index)
354-
http.HandleFunc(path.Join(*routePrefix, "debug/pprof/profile"), pprof.Profile)
355-
http.HandleFunc(path.Join(*routePrefix, "debug/pprof/heap"), pprof.Handler("heap").ServeHTTP)
356-
357299
if *metricsPath != "/" && *metricsPath != "" {
358300
landingConfig := web.LandingConfig{
359-
Name: "SNMP Exporter",
360-
Description: "Prometheus Exporter for SNMP targets",
361-
Version: version.Info(),
362-
RoutePrefix: *routePrefix,
301+
Name: "SNMP Exporter",
302+
Description: "Prometheus Exporter for SNMP targets",
303+
Version: version.Info(),
304+
RoutePrefix: *routePrefix,
305+
ExternalURL: *externalURL,
306+
ListenAddresses: *toolkitFlags.WebListenAddresses,
307+
UseSystemdSocket: *toolkitFlags.WebSystemdSocket,
308+
Logger: logger,
363309
Form: web.LandingForm{
364310
Action: proberPath,
365311
Inputs: []web.LandingFormInput{
@@ -397,14 +343,24 @@ func main() {
397343
},
398344
},
399345
}
400-
landingPage, err := web.NewLandingPage(landingConfig)
346+
landingPage, processedRoutePrefix, err := web.NewLandingPage(landingConfig)
401347
if err != nil {
402348
logger.Error("Error creating landing page", "err", err)
403349
os.Exit(1)
404350
}
351+
*routePrefix = processedRoutePrefix
405352
http.Handle(*routePrefix, landingPage)
406353
}
407354

355+
http.Handle(path.Join(*routePrefix, *metricsPath), promhttp.Handler()) // Normal metrics endpoint for SNMP exporter itself.
356+
357+
// Endpoint to do SNMP scrapes.
358+
http.HandleFunc(path.Join(*routePrefix, proberPath), func(w http.ResponseWriter, r *http.Request) {
359+
handler(w, r, logger, exporterMetrics)
360+
})
361+
362+
http.HandleFunc(path.Join(*routePrefix, "/-/reload"), updateConfiguration) // Endpoint to reload configuration.
363+
408364
http.HandleFunc(path.Join(*routePrefix, configPath), func(w http.ResponseWriter, r *http.Request) {
409365
sc.RLock()
410366
c, err := yaml.Marshal(sc.C)
@@ -423,41 +379,3 @@ func main() {
423379
os.Exit(1)
424380
}
425381
}
426-
427-
func startsOrEndsWithQuote(s string) bool {
428-
return strings.HasPrefix(s, "\"") || strings.HasPrefix(s, "'") ||
429-
strings.HasSuffix(s, "\"") || strings.HasSuffix(s, "'")
430-
}
431-
432-
// computeExternalURL computes a sanitized external URL from a raw input. It infers unset
433-
// URL parts from the OS and the given listen address.
434-
func computeExternalURL(u, listenAddr string) (*url.URL, error) {
435-
if u == "" {
436-
hostname, err := os.Hostname()
437-
if err != nil {
438-
return nil, err
439-
}
440-
_, port, err := net.SplitHostPort(listenAddr)
441-
if err != nil {
442-
return nil, err
443-
}
444-
u = fmt.Sprintf("http://%s:%s/", hostname, port)
445-
}
446-
447-
if startsOrEndsWithQuote(u) {
448-
return nil, errors.New("URL must not begin or end with quotes")
449-
}
450-
451-
eu, err := url.Parse(u)
452-
if err != nil {
453-
return nil, err
454-
}
455-
456-
ppref := strings.TrimRight(eu.Path, "/")
457-
if ppref != "" && !strings.HasPrefix(ppref, "/") {
458-
ppref = "/" + ppref
459-
}
460-
eu.Path = ppref
461-
462-
return eu, nil
463-
}

0 commit comments

Comments
 (0)