Skip to content

Commit

Permalink
Use a "name" argument for "target" and "walk_param" blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
ptodev committed Sep 30, 2024
1 parent d5f67d6 commit 9e364e4
Show file tree
Hide file tree
Showing 5 changed files with 248 additions and 44 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Main (unreleased)
- The `mimir.rules.kubernetes` component now supports adding extra label matchers
to all queries discovered via `PrometheusRule` CRDs. (@thampiotr)

- `prometheus.exporter.snmp`: The names of `target` and `walk_param` blocks can now be set
via an argument instead of block label. The block label syntax for
the `target` and `walk_param` blocks will be removed in Alloy 2.0. (@ptodev)

### Bugfixes

- Update windows_exporter from v0.27.2 vo v0.27.3: (@jkroepke)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ The `prometheus.exporter.snmp` component embeds
prometheus.exporter.snmp "LABEL" {
config_file = SNMP_CONFIG_FILE_PATH
target "TARGET_NAME" {
target {
name = TARGET_NAME
address = TARGET_ADDRESS
}
}
Expand All @@ -48,7 +49,7 @@ Omitted fields take their default values.
| `targets` | `list(map(string))` | SNMP targets. | | no |

The `config_file` argument points to a YAML file defining which snmp_exporter modules to use.
Refer to [snmp_exporter](https://github.com/prometheus/snmp_exporter#generating-configuration) for details on how to generate a configuration file.
Refer to [snmp_exporter][snmp_exporter-cfg] for details on how to generate a configuration file.

The `config` argument must be a YAML document as string defining which SNMP modules and auths to use.
`config` is typically loaded by using the exports of another component. For example,
Expand All @@ -65,6 +66,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.

[snmp_exporter-cfg]: https://github.com/prometheus/snmp_exporter#generating-configuration

## Blocks

The following blocks are supported inside the definition of
Expand All @@ -81,28 +84,43 @@ The following blocks are supported inside the definition of
### target block

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.
The `target` block may be specified multiple times to define multiple targets.

| Name | Type | Description | Default | Required |
| -------------- | -------- | --------------------------------------------------------------------- | ------- | -------- |
| `name` | `string` | The name of the target. | | yes |
| `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 |

The value of the `name` argument will be set as the value of the target's `job` label.

{{< admonition type="note" >}}
Instead of a `name` argument, previous versions of Alloy used to use a block label.
See the [Deprecated features](#deprecated-features) section for more information.
{{< /admonition >}}

If `name` is not set, the target's `job` label will be set to the label of the `target` block.

### walk_param block

The `walk_param` block defines an individual SNMP connection profile that can be used to override default SNMP settings.
The `walk_param` block may be specified multiple times to define multiple SNMP connection profiles.

| Name | Type | Description | Default | Required |
| ----------------- | ---------- | --------------------------------------------- | ------- | -------- |
| `name` | `string` | Name of the module to override. | | no |
| `name` | `string` | Name of the module to override. | | yes |
| `max_repetitions` | `int` | How many objects to request with GET/GETBULK. | `25` | no |
| `retries` | `int` | How many times to retry a failed request. | `3` | no |
| `timeout` | `duration` | Timeout for each individual SNMP request. | | no |

{{< admonition type="note" >}}
Instead of a `name` argument, previous versions of Alloy used to use a block label.
See the [Deprecated features](#deprecated-features) section for more information.
{{< /admonition >}}

## Exported fields

{{< docs/shared lookup="reference/components/exporter-component-exports.md" source="alloy" version="<ALLOY_VERSION>" >}}
Expand All @@ -123,6 +141,46 @@ debug information.
`prometheus.exporter.snmp` does not expose any component-specific
debug metrics.

## Deprecated features

In previous versions of Alloy, the names `target` blocks and `walk_param` blocks were specified via a block label:

```alloy
target "example_name_of_target" {
...
}
walk_param "example_name_of_walk_param" {
...
}
```

Users are now advised to switch to using a `name` attribute instead:

```alloy
target {
name = "example_name_of_target"
...
}
walk_param {
name = "example_name_of_walk_param"
...
}
```

Block labels for `target` and `walk_param` are deprecated and will be removed in version 2.0 of Alloy.
In Alloy version 1, it will remain possible to use a block label instead of the `name` attribute.
However, the `name` attribute is documented as "required" to encourage users to use it and to remove confusion.

The benefits of using a `name` attribute include:
* Not being subject to restrictions on [Alloy Syntax Identifiers][syntax-identifiers].
* It is possible to get the value of a `name` argument from a component such as [local.file][] or [remote.http][].

[syntax-identifiers]: ../../../../get-started/configuration-syntax/syntax/#identifiers
[local.file]: ../../local.file
[remote.http]: ../../remote.http

## Example

This example uses a [`prometheus.scrape` component][scrape] to collect metrics
Expand All @@ -132,23 +190,27 @@ from `prometheus.exporter.snmp`:
prometheus.exporter.snmp "example" {
config_file = "snmp_modules.yml"
target "network_switch_1" {
target {
name = "network_switch_1"
address = "192.168.1.2"
module = "if_mib"
walk_params = "public"
}
target "network_router_2" {
target {
name = "network_router_2"
address = "192.168.1.3"
module = "mikrotik"
walk_params = "private"
}
walk_param "private" {
walk_param {
name = "private"
retries = "2"
}
walk_param "public" {
walk_param {
name = "public"
retries = "2"
}
}
Expand All @@ -171,23 +233,27 @@ local.file "snmp_config" {
prometheus.exporter.snmp "example" {
config = local.file.snmp_config.content
target "network_switch_1" {
target {
name = "network_switch_1"
address = "192.168.1.2"
module = "if_mib"
walk_params = "public"
}
target "network_router_2" {
target {
name = "network_router_2"
address = "192.168.1.3"
module = "mikrotik"
walk_params = "private"
}
walk_param "private" {
walk_param {
name = "private"
retries = "2"
}
walk_param "public" {
walk_param {
name = "public"
retries = "2"
}
}
Expand Down Expand Up @@ -236,11 +302,13 @@ prometheus.exporter.snmp "example" {
},
]
walk_param "private" {
walk_param {
name = "private"
retries = "2"
}
walk_param "public" {
walk_param {
name = "public"
retries = "2"
}
}
Expand All @@ -264,11 +332,13 @@ prometheus.exporter.snmp "example" {
targets = encoding.from_yaml(local.file.targets.content)
walk_param "private" {
walk_param {
name = "private"
retries = "2"
}
walk_param "public" {
walk_param {
name = "public"
retries = "2"
}
}
Expand Down
66 changes: 60 additions & 6 deletions internal/component/prometheus/exporter/snmp/snmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func buildSNMPTargets(baseTarget discovery.Target, args component.Arguments) []d
target[k] = v
}

target["job"] = target["job"] + "/" + tgt.Name
target["job"] = target["job"] + "/" + tgt.Name()
target["__param_target"] = tgt.Target
if tgt.Module != "" {
target["__param_module"] = tgt.Module
Expand All @@ -71,7 +71,9 @@ 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"`
//TODO: For Alloy 2.0: Remove NameLbl and make NameArg mandatory.
NameLbl string `alloy:",label,optional"`
NameArg string `alloy:"name,attr,optional"`
Target string `alloy:"address,attr"`
Module string `alloy:"module,attr,optional"`
Auth string `alloy:"auth,attr,optional"`
Expand All @@ -86,7 +88,7 @@ func (t TargetBlock) Convert() []snmp_exporter.SNMPTarget {
targets := make([]snmp_exporter.SNMPTarget, 0, len(t))
for _, target := range t {
targets = append(targets, snmp_exporter.SNMPTarget{
Name: target.Name,
Name: target.Name(),
Target: target.Target,
Module: target.Module,
Auth: target.Auth,
Expand All @@ -97,8 +99,25 @@ func (t TargetBlock) Convert() []snmp_exporter.SNMPTarget {
return targets
}

// Name() assumes that either NameLbl or NameArg is set.
// It also that both NameLbl and NameArg are not set at the same time,
// as this is checked during unmarshalling.
func (t *SNMPTarget) Name() string {
if t == nil {
return ""
}

if len(t.NameArg) > 0 {
return t.NameArg
}

return t.NameLbl
}

type WalkParam struct {
Name string `alloy:",label"`
//TODO: For Alloy 2.0: Remove NameLbl and make NameArg mandatory.
NameLbl string `alloy:",label,optional"`
NameArg string `alloy:"name,attr,optional"`
MaxRepetitions uint32 `alloy:"max_repetitions,attr,optional"`
Retries int `alloy:"retries,attr,optional"`
Timeout time.Duration `alloy:"timeout,attr,optional"`
Expand All @@ -111,7 +130,7 @@ type WalkParams []WalkParam
func (w WalkParams) Convert() map[string]snmp_config.WalkParams {
walkParams := make(map[string]snmp_config.WalkParams)
for _, walkParam := range w {
walkParams[walkParam.Name] = snmp_config.WalkParams{
walkParams[walkParam.Name()] = snmp_config.WalkParams{
MaxRepetitions: walkParam.MaxRepetitions,
Retries: &walkParam.Retries,
Timeout: walkParam.Timeout,
Expand All @@ -121,6 +140,21 @@ func (w WalkParams) Convert() map[string]snmp_config.WalkParams {
return walkParams
}

// Name() assumes that either NameLbl or NameArg is set.
// It also that both NameLbl and NameArg are not set at the same time,
// as this is checked during unmarshalling.
func (p *WalkParam) Name() string {
if p == nil {
return ""
}

if len(p.NameArg) > 0 {
return p.NameArg
}

return p.NameLbl
}

type Arguments struct {
ConfigFile string `alloy:"config_file,attr,optional"`
Config alloytypes.OptionalSecret `alloy:"config,attr,optional"`
Expand Down Expand Up @@ -155,7 +189,7 @@ func (t TargetsList) convert() []SNMPTarget {
for _, target := range t {
address, _ := getAddress(target)
targets = append(targets, SNMPTarget{
Name: target["name"],
NameArg: target["name"],
Target: address,
Module: target["module"],
Auth: target["auth"],
Expand All @@ -181,6 +215,26 @@ func (a *Arguments) UnmarshalAlloy(f func(interface{}) error) error {
return fmt.Errorf("the block `target` and the attribute `targets` are mutually exclusive")
}

for _, walkParam := range a.WalkParams {
if walkParam.NameArg != "" && walkParam.NameLbl != "" {
return errors.New("the label of a `walk_param` block and the `name` argument are mutually exclusive")
}

if walkParam.NameArg == "" && walkParam.NameLbl == "" {
return errors.New("either the label of a `walk_param` block or the `name` argument must be set")
}
}

for _, target := range a.Targets {
if target.NameArg != "" && target.NameLbl != "" {
return errors.New("the label of a `target` block and the `name` argument are mutually exclusive")
}

if target.NameArg == "" && target.NameLbl == "" {
return errors.New("either the label of a `target` block or the `name` argument must be set")
}
}

for _, target := range a.TargetsList {
if _, hasName := target["name"]; !hasName {
return fmt.Errorf("all targets must have a `name`")
Expand Down
Loading

0 comments on commit 9e364e4

Please sign in to comment.