-
Notifications
You must be signed in to change notification settings - Fork 486
/
snmp.go
118 lines (102 loc) · 3.23 KB
/
snmp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package snmp_exporter
import (
"fmt"
"net/http"
"time"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/snmp_exporter/collector"
snmp_config "github.com/prometheus/snmp_exporter/config"
)
type snmpHandler struct {
cfg *Config
snmpCfg *snmp_config.Config
log log.Logger
}
func Handler(w http.ResponseWriter, r *http.Request, logger log.Logger, snmpCfg *snmp_config.Config,
targets []SNMPTarget, wParams map[string]snmp_config.WalkParams) {
query := r.URL.Query()
snmpTargets := make(map[string]SNMPTarget)
for _, target := range targets {
snmpTargets[target.Name] = target
}
var target string
targetName := query.Get("target")
if len(query["target"]) != 1 || targetName == "" {
http.Error(w, "'target' parameter must be specified once", http.StatusBadRequest)
return
}
t, ok := snmpTargets[targetName]
if ok {
target = t.Target
} else {
target = targetName
}
moduleName := query.Get("module")
if len(query["module"]) > 1 {
http.Error(w, "'module' parameter must only be specified once", http.StatusBadRequest)
return
}
if moduleName == "" {
moduleName = "if_mib"
}
authName := query.Get("auth")
if len(query["auth"]) > 1 {
http.Error(w, "'auth' parameter must only be specified once", http.StatusBadRequest)
return
}
if authName == "" {
authName = "public_v2"
}
module, ok := (*snmpCfg).Modules[moduleName]
if !ok {
http.Error(w, fmt.Sprintf("Unknown module '%s'", moduleName), http.StatusBadRequest)
return
}
auth, ok := (*snmpCfg).Auths[authName]
if !ok {
http.Error(w, fmt.Sprintf("Unknown auth '%s'", authName), http.StatusBadRequest)
return
}
// override module connection details with custom walk params if provided
walkParams := query.Get("walk_params")
if len(query["walk_params"]) > 1 {
http.Error(w, "'walk_params' parameter must only be specified once", http.StatusBadRequest)
return
}
if walkParams != "" {
zeroRetries := 0
if wp, ok := wParams[walkParams]; ok {
if wp.MaxRepetitions != 0 {
module.WalkParams.MaxRepetitions = wp.MaxRepetitions
}
if wp.Retries != &zeroRetries {
module.WalkParams.Retries = wp.Retries
}
if wp.Timeout != 0 {
module.WalkParams.Timeout = wp.Timeout
}
} else {
http.Error(w, fmt.Sprintf("Unknown walk_params '%s'", walkParams), http.StatusBadRequest)
return
}
logger = log.With(logger, "module", moduleName, "target", target, "walk_params", walkParams)
} else {
logger = log.With(logger, "module", moduleName, "target", target)
}
level.Debug(logger).Log("msg", "Starting scrape")
start := time.Now()
registry := prometheus.NewRegistry()
c := collector.New(r.Context(), target, auth, module, logger, registry)
registry.MustRegister(c)
// Delegate http serving to Prometheus client library, which will call collector.Collect.
h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
h.ServeHTTP(w, r)
duration := time.Since(start).Seconds()
level.Debug(logger).Log("msg", "Finished scrape", "duration_seconds", duration)
}
func (sh snmpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Handler(w, r, sh.log, sh.snmpCfg, sh.cfg.SnmpTargets, sh.cfg.WalkParams)
}