Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the setting of labels for snmp exporter for both target and targets #1876

Merged
merged 5 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ Main (unreleased)
### Features

- Add the function `path_join` to the stdlib. (@wildum)

- Add support to `loki.source.syslog` for the RFC3164 format ("BSD syslog"). (@sushain97)

- Add support to `loki.source.api` to be able to extract the tenant from the HTTP `X-Scope-OrgID` header (@QuentinBisson)
-
- (_Experimental_) Add a `loki.secretfilter` component to redact secrets from collected logs.

### Enhancements
Expand All @@ -31,6 +34,9 @@ Main (unreleased)

- Fix an issue where some `faro.receiver` would drop multiple fields defined in `payload.meta.browser`, as fields were defined in the struct.

- SNMP exporter now supports labels in both `target` and `targets` parameters. (@mattdurham)


### Bugfixes

- Fixed a bug in `import.git` which caused a `"non-fast-forward update"` error message. (@ptodev)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ The following labels can be set to a target:
* `auth`: The SNMP authentication profile to use.
* `walk_params`: The config to use for this target.

Any other labels defined are added to the scraped metrics.

## Blocks

The following blocks are supported inside the definition of
Expand All @@ -83,13 +85,15 @@ The following blocks are supported inside the definition of
The `target` block defines an individual SNMP target.
The `target` block may be specified multiple times to define multiple targets. The label of the block is required and will be used in the target's `job` label.

| Name | Type | Description | Default | Required |
| -------------- | -------- | --------------------------------------------------------------------- | ------- | -------- |
| `address` | `string` | The address of SNMP device. | | yes |
| `module` | `string` | SNMP module to use for polling. | `""` | no |
| `auth` | `string` | SNMP authentication profile to use. | `""` | no |
| `walk_params` | `string` | Config to use for this target. | `""` | no |
| `snmp_context` | `string` | Override the `context_name` parameter in the SNMP configuration file. | `""` | no |
| Name | Type | Description | Default | Required |
|----------------|---------------| --------------------------------------------------------------------- | ------- | -------- |
| `address` | `string` | The address of SNMP device. | | yes |
| `module` | `string` | SNMP module to use for polling. | `""` | no |
| `auth` | `string` | SNMP authentication profile to use. | `""` | no |
| `walk_params` | `string` | Config to use for this target. | `""` | no |
| `snmp_context` | `string` | Override the `context_name` parameter in the SNMP configuration file. | `""` | no |
| `labels` | `map(string)` | Override the `context_name` parameter in the SNMP configuration file. | `""` | no |
mattdurham marked this conversation as resolved.
Show resolved Hide resolved

mattdurham marked this conversation as resolved.
Show resolved Hide resolved

### walk_param block

Expand Down
38 changes: 32 additions & 6 deletions internal/component/prometheus/exporter/snmp/snmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package snmp
import (
"errors"
"fmt"
"slices"
"time"

"github.com/grafana/alloy/internal/component"
Expand Down Expand Up @@ -44,12 +45,17 @@ func buildSNMPTargets(baseTarget discovery.Target, args component.Arguments) []d

for _, tgt := range snmpTargets {
target := make(discovery.Target)
// Set extra labels first, meaning that any other labels will override
for k, v := range tgt.Labels {
target[k] = v
}
for k, v := range baseTarget {
target[k] = v
}

target["job"] = target["job"] + "/" + tgt.Name
target["__param_target"] = tgt.Target
target["__param_name"] = tgt.Name
if tgt.Module != "" {
target["__param_module"] = tgt.Module
}
Expand All @@ -71,12 +77,13 @@ func buildSNMPTargets(baseTarget discovery.Target, args component.Arguments) []d

// SNMPTarget defines a target to be used by the exporter.
type SNMPTarget struct {
Name string `alloy:",label"`
Target string `alloy:"address,attr"`
Module string `alloy:"module,attr,optional"`
Auth string `alloy:"auth,attr,optional"`
WalkParams string `alloy:"walk_params,attr,optional"`
SNMPContext string `alloy:"snmp_context,attr,optional"`
Name string `alloy:",label"`
Target string `alloy:"address,attr"`
Module string `alloy:"module,attr,optional"`
Auth string `alloy:"auth,attr,optional"`
WalkParams string `alloy:"walk_params,attr,optional"`
SNMPContext string `alloy:"snmp_context,attr,optional"`
Labels map[string]string `alloy:"labels,attr,optional"`
}

type TargetBlock []SNMPTarget
Expand All @@ -92,6 +99,7 @@ func (t TargetBlock) Convert() []snmp_exporter.SNMPTarget {
Auth: target.Auth,
WalkParams: target.WalkParams,
SNMPContext: target.SNMPContext,
Labels: target.Labels,
})
}
return targets
Expand Down Expand Up @@ -134,6 +142,22 @@ type Arguments struct {

type TargetsList []map[string]string

// target technically isnt required but its so overloaded within snmp I dont want it leaking.
var ignoredLabels = []string{"name", "module", "auth", "walk_params", "snmp_context", "address", "__address__", "target"}

func createUserLabels(t map[string]string) map[string]string {
// Need to create labels.
userLabels := make(map[string]string)
for k, v := range t {
// ignore the special labels
if slices.Contains(ignoredLabels, k) {
continue
}
userLabels[k] = v
}
return userLabels
}

func (t TargetsList) Convert() []snmp_exporter.SNMPTarget {
targets := make([]snmp_exporter.SNMPTarget, 0, len(t))
for _, target := range t {
Expand All @@ -145,6 +169,7 @@ func (t TargetsList) Convert() []snmp_exporter.SNMPTarget {
Auth: target["auth"],
WalkParams: target["walk_params"],
SNMPContext: target["snmp_context"],
Labels: createUserLabels(target),
})
}
return targets
Expand All @@ -161,6 +186,7 @@ func (t TargetsList) convert() []SNMPTarget {
Auth: target["auth"],
WalkParams: target["walk_params"],
SNMPContext: target["snmp_context"],
Labels: createUserLabels(target),
})
}
return targets
Expand Down
41 changes: 41 additions & 0 deletions internal/component/prometheus/exporter/snmp/snmp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@ func TestConvertConfig(t *testing.T) {
require.Equal(t, "network_switch_1", res.SnmpTargets[0].Name)
}

func TestConfigLabels(t *testing.T) {
lbls := map[string]string{"env": "dev"}
args := Arguments{
ConfigFile: "modules.yml",
Targets: TargetBlock{{Name: "network_switch_1", Target: "192.168.1.2", Module: "if_mib", Labels: lbls}},
WalkParams: WalkParams{{Name: "public", Retries: 2}},
}

res := args.Convert()
require.Equal(t, "modules.yml", res.SnmpConfigFile)
require.Equal(t, 1, len(res.SnmpTargets))
require.Equal(t, "network_switch_1", res.SnmpTargets[0].Name)
require.Equal(t, res.SnmpTargets[0].Labels["env"], "dev")
}

func TestConvertConfigWithInlineConfig(t *testing.T) {
args := Arguments{
ConfigStruct: config.Config{Modules: map[string]*config.Module{"if_mib": {Walk: []string{"1.3.6.1.2.1.2"}}}},
Expand Down Expand Up @@ -177,6 +192,32 @@ func TestConvertTargetsList(t *testing.T) {
require.Equal(t, "1.3.6.1.2.1.2", res[0].WalkParams)
}

func TestConvertTargetsListWithLabels(t *testing.T) {
targets := TargetsList{
{
"name": "network_switch_1",
"address": "192.168.1.2",
"module": "if_mib",
"auth": "public_v2",
"walk_params": "1.3.6.1.2.1.2",
"env": "dev",
"app": "falcon",
},
}

res := targets.Convert()
require.Equal(t, 1, len(res))
require.Equal(t, "network_switch_1", res[0].Name)
require.Equal(t, "192.168.1.2", res[0].Target)
require.Equal(t, "if_mib", res[0].Module)
require.Equal(t, "public_v2", res[0].Auth)
require.Equal(t, "1.3.6.1.2.1.2", res[0].WalkParams)
require.Len(t, res[0].Labels, 2)
require.Equal(t, "dev", res[0].Labels["env"])
require.Equal(t, "falcon", res[0].Labels["app"])

}

func TestConvertTargetsListAlternativeAddress(t *testing.T) {
targets := TargetsList{
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ func toSnmpExporter(config *snmp_exporter.Config) *snmp.Arguments {
target["auth"] = t.Auth
target["walk_params"] = t.WalkParams
target["snmp_context"] = t.SNMPContext
for k, v := range t.Labels {
target[k] = v
}
wildum marked this conversation as resolved.
Show resolved Hide resolved
targets = append(targets, target)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type SNMPTarget struct {
Auth string `yaml:"auth"`
WalkParams string `yaml:"walk_params,omitempty"`
SNMPContext string `yaml:"snmp_context,omitempty"`
Labels map[string]string
}

// Config configures the SNMP integration.
Expand Down