diff --git a/Makefile.common b/Makefile.common index 7642c448..e358db69 100644 --- a/Makefile.common +++ b/Makefile.common @@ -55,7 +55,7 @@ ifneq ($(shell which gotestsum),) endif endif -PROMU_VERSION ?= 0.13.0 +PROMU_VERSION ?= 0.14.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz SKIP_GOLANGCI_LINT := diff --git a/collector/collector.go b/collector/collector.go index 0ffe7ece..4532e1ad 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -115,7 +115,7 @@ type ScrapeResults struct { retries uint64 } -func ScrapeTarget(ctx context.Context, target string, config *config.Module, logger log.Logger) (ScrapeResults, error) { +func ScrapeTarget(ctx context.Context, target string, snmp_context string, config *config.Module, logger log.Logger) (ScrapeResults, error) { results := ScrapeResults{} // Set the options. snmp := gosnmp.GoSNMP{} @@ -158,7 +158,7 @@ func ScrapeTarget(ctx context.Context, target string, config *config.Module, log } // Configure auth. - config.WalkParams.ConfigureSNMP(&snmp) + config.WalkParams.ConfigureSNMP(&snmp, snmp_context) // Do the actual walk. err := snmp.Connect() @@ -259,14 +259,15 @@ func buildMetricTree(metrics []*config.Metric) *MetricNode { } type collector struct { - ctx context.Context - target string - module *config.Module - logger log.Logger + ctx context.Context + target string + snmp_context string + module *config.Module + logger log.Logger } -func New(ctx context.Context, target string, module *config.Module, logger log.Logger) *collector { - return &collector{ctx: ctx, target: target, module: module, logger: logger} +func New(ctx context.Context, target string, snmp_context string, module *config.Module, logger log.Logger) *collector { + return &collector{ctx: ctx, target: target, snmp_context: snmp_context, module: module, logger: logger} } // Describe implements Prometheus.Collector. @@ -277,7 +278,7 @@ func (c collector) Describe(ch chan<- *prometheus.Desc) { // Collect implements Prometheus.Collector. func (c collector) Collect(ch chan<- prometheus.Metric) { start := time.Now() - results, err := ScrapeTarget(c.ctx, c.target, c.module, c.logger) + results, err := ScrapeTarget(c.ctx, c.target, c.snmp_context, c.module, c.logger) if err != nil { level.Info(c.logger).Log("msg", "Error scraping target", "err", err) ch <- prometheus.NewInvalidMetric(prometheus.NewDesc("snmp_error", "Error scraping target", nil, nil), err) diff --git a/config/config.go b/config/config.go index f8fd56d1..efcba266 100644 --- a/config/config.go +++ b/config/config.go @@ -125,7 +125,7 @@ func (c *Module) UnmarshalYAML(unmarshal func(interface{}) error) error { } // ConfigureSNMP sets the various version and auth settings. -func (c WalkParams) ConfigureSNMP(g *gosnmp.GoSNMP) { +func (c WalkParams) ConfigureSNMP(g *gosnmp.GoSNMP, snmp_context string) { switch c.Version { case 1: g.Version = gosnmp.Version1 @@ -135,8 +135,11 @@ func (c WalkParams) ConfigureSNMP(g *gosnmp.GoSNMP) { g.Version = gosnmp.Version3 } g.Community = string(c.Auth.Community) - g.ContextName = c.Auth.ContextName - + if snmp_context == "" { + g.ContextName = c.Auth.ContextName + } else { + g.ContextName = snmp_context + } // v3 security settings. g.SecurityModel = gosnmp.UserSecurityModel usm := &gosnmp.UsmSecurityParameters{ diff --git a/main.go b/main.go index c249ffd6..e9808239 100644 --- a/main.go +++ b/main.go @@ -84,6 +84,14 @@ func handler(w http.ResponseWriter, r *http.Request, logger log.Logger) { if moduleName == "" { moduleName = "if_mib" } + + snmp_context := query.Get("snmp_context") + if len(query["snmp_context"]) > 1 { + http.Error(w, "'snmp_context' parameter must only be specified once", 400) + snmpRequestErrors.Inc() + return + } + sc.RLock() module, ok := (*(sc.C))[moduleName] sc.RUnlock() @@ -98,7 +106,7 @@ func handler(w http.ResponseWriter, r *http.Request, logger log.Logger) { start := time.Now() registry := prometheus.NewRegistry() - c := collector.New(r.Context(), target, module, logger) + c := collector.New(r.Context(), target, snmp_context, module, logger) registry.MustRegister(c) // Delegate http serving to Prometheus client library, which will call collector.Collect. h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})