From 5f907e691aa59ec2545aa72a350da11f34058246 Mon Sep 17 00:00:00 2001 From: Paulin Todev Date: Wed, 1 May 2024 02:19:21 +0100 Subject: [PATCH] Add a "snmp_context" argument to the URL (#1163) Signed-off-by: Paulin Todev --- README.md | 4 ++++ collector/collector.go | 7 ++++--- config/config.go | 9 +++++++-- main.go | 9 ++++++++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d73cdfa0..3fb2d131 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,10 @@ is not necessary within the Prometheus configuration file. Metrics concerning the operation of the exporter itself are available at the endpoint . +It is possible to supply an optional `snmp_context` parameter in the URL, like this: + +The `snmp_context` parameter in the URL would override the `context_name` parameter in the `snmp.yml` file. + ## Multi-Module Handling The multi-module functionality allows you to specify multiple modules, enabling the retrieval of information from several modules in a single scrape. The concurrency can be specified using the snmp-exporter option `--snmp.module-concurrency` (the default is 1). diff --git a/collector/collector.go b/collector/collector.go index 1b7337ac..e4046ffa 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -299,10 +299,11 @@ type Collector struct { logger log.Logger metrics Metrics concurrency int + snmpContext string } -func New(ctx context.Context, target, authName string, auth *config.Auth, modules []*NamedModule, logger log.Logger, metrics Metrics, conc int) *Collector { - return &Collector{ctx: ctx, target: target, authName: authName, auth: auth, modules: modules, logger: logger, metrics: metrics, concurrency: conc} +func New(ctx context.Context, target, authName, snmpContext string, auth *config.Auth, modules []*NamedModule, logger log.Logger, metrics Metrics, conc int) *Collector { + return &Collector{ctx: ctx, target: target, authName: authName, auth: auth, modules: modules, logger: logger, metrics: metrics, concurrency: conc, snmpContext: snmpContext} } // Describe implements Prometheus.Collector. @@ -429,7 +430,7 @@ func (c Collector) Collect(ch chan<- prometheus.Metric) { // Set the options. client.SetOptions(func(g *gosnmp.GoSNMP) { g.Context = ctx - c.auth.ConfigureSNMP(g) + c.auth.ConfigureSNMP(g, c.snmpContext) }) if err = client.Connect(); err != nil { level.Info(logger).Log("msg", "Error connecting to target", "err", err) diff --git a/config/config.go b/config/config.go index 645e4486..f6464a1c 100644 --- a/config/config.go +++ b/config/config.go @@ -129,7 +129,7 @@ func (c *Module) UnmarshalYAML(unmarshal func(interface{}) error) error { } // ConfigureSNMP sets the various version and auth settings. -func (c Auth) ConfigureSNMP(g *gosnmp.GoSNMP) { +func (c Auth) ConfigureSNMP(g *gosnmp.GoSNMP, snmpContext string) { switch c.Version { case 1: g.Version = gosnmp.Version1 @@ -139,7 +139,12 @@ func (c Auth) ConfigureSNMP(g *gosnmp.GoSNMP) { g.Version = gosnmp.Version3 } g.Community = string(c.Community) - g.ContextName = c.ContextName + + if snmpContext == "" { + g.ContextName = c.ContextName + } else { + g.ContextName = snmpContext + } // v3 security settings. g.SecurityModel = gosnmp.UserSecurityModel diff --git a/main.go b/main.go index 72bdb2b9..90f2d868 100644 --- a/main.go +++ b/main.go @@ -102,6 +102,13 @@ func handler(w http.ResponseWriter, r *http.Request, logger log.Logger, exporter authName = "public_v2" } + snmpContext := query.Get("snmp_context") + if len(query["snmp_context"]) > 1 { + http.Error(w, "'snmp_context' parameter must only be specified once", http.StatusBadRequest) + snmpRequestErrors.Inc() + return + } + queryModule := query["module"] if len(queryModule) == 0 { queryModule = append(queryModule, "if_mib") @@ -141,7 +148,7 @@ func handler(w http.ResponseWriter, r *http.Request, logger log.Logger, exporter sc.RUnlock() logger = log.With(logger, "auth", authName, "target", target) registry := prometheus.NewRegistry() - c := collector.New(r.Context(), target, authName, auth, nmodules, logger, exporterMetrics, *concurrency) + c := collector.New(r.Context(), target, authName, snmpContext, auth, nmodules, logger, exporterMetrics, *concurrency) registry.MustRegister(c) // Delegate http serving to Prometheus client library, which will call collector.Collect. h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})