Skip to content

Commit

Permalink
Add otelcol.receiver.solace (grafana#2084)
Browse files Browse the repository at this point in the history
* Add otelcol.receiver.solace

* fix test with ptr check to support empty structs

* run doc generator

* validate only one method of auth

* Update docs/sources/reference/components/otelcol/otelcol.receiver.solace.md

Co-authored-by: Clayton Cornell <[email protected]>

* Update docs/sources/reference/components/otelcol/otelcol.receiver.solace.md

Co-authored-by: Clayton Cornell <[email protected]>

* Update docs/sources/reference/components/otelcol/otelcol.receiver.solace.md

Co-authored-by: Clayton Cornell <[email protected]>

* doc nit

* Update docs/sources/reference/components/otelcol/otelcol.receiver.solace.md

Co-authored-by: Piotr <[email protected]>

* Update internal/component/otelcol/receiver/solace/solace.go

Co-authored-by: Piotr <[email protected]>

* update error msg in test

---------

Co-authored-by: Clayton Cornell <[email protected]>
Co-authored-by: Piotr <[email protected]>
  • Loading branch information
3 people authored and vaxvms committed Nov 20, 2024
1 parent 945bddf commit 014bab3
Show file tree
Hide file tree
Showing 13 changed files with 881 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Main (unreleased)

- Add `otelcol.exporter.splunkhec` allowing to export otel data to Splunk HEC (@adlotsof)

- Add `otelcol.receiver.solace` component to receive traces from a Solace broker. (@wildum)

### Bugfixes

- Fixed an issue in the `prometheus.exporter.postgres` component that would leak goroutines when the target was not reachable (@dehaansa)
Expand Down
1 change: 1 addition & 0 deletions docs/sources/reference/compatibility/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ The following components, grouped by namespace, _consume_ OpenTelemetry `otelcol
- [otelcol.receiver.opencensus](../components/otelcol/otelcol.receiver.opencensus)
- [otelcol.receiver.otlp](../components/otelcol/otelcol.receiver.otlp)
- [otelcol.receiver.prometheus](../components/otelcol/otelcol.receiver.prometheus)
- [otelcol.receiver.solace](../components/otelcol/otelcol.receiver.solace)
- [otelcol.receiver.vcenter](../components/otelcol/otelcol.receiver.vcenter)
- [otelcol.receiver.zipkin](../components/otelcol/otelcol.receiver.zipkin)
{{< /collapse >}}
Expand Down
209 changes: 209 additions & 0 deletions docs/sources/reference/components/otelcol/otelcol.receiver.solace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
---
canonical: https://grafana.com/docs/alloy/latest/reference/components/otelcol/otelcol.receiver.solace/
description: Learn about otelcol.receiver.solace
title: otelcol.receiver.solace
---

# otelcol.receiver.solace

`otelcol.receiver.solace` accepts traces from a [Solace PubSub+ Event Broker](https://solace.com/products/event-broker/) and
forwards it to other `otelcol.*` components.

{{< admonition type="note" >}}
`otelcol.receiver.solace` is a wrapper over the upstream OpenTelemetry Collector `solace` receiver from the `otelcol-contrib` distribution.
Bug reports or feature requests will be redirected to the upstream repository, if necessary.
{{< /admonition >}}

You can specify multiple `otelcol.receiver.solace` components by giving them different labels.

## Usage

```alloy
otelcol.receiver.solace "LABEL" {
queue = "QUEUE"
auth {
// sasl_plain or sasl_xauth2 or sasl_external block
}
output {
traces = [...]
}
}
```

## Arguments

The following arguments are supported:

| Name | Type | Description | Default | Required |
| -------------------- | -------- | ------------------------------------------------------------------------- | ---------------- | -------- |
| `queue` | `string` | Name of the Solace telemetry queue to get span trace messages from. | | yes |
| `broker` | `string` | Name of the Solace broker using AMQP over TLS. | `localhost:5671` | no |
| `max_unacknowledged` | `int` | Maximum number of unacknowledged messages the Solace broker can transmit. | 10 | no |

`queue` must have the format `queue://#telemetry-myTelemetryProfile`.

## Blocks

The following blocks are supported inside the definition of
`otelcol.receiver.solace`:

| Hierarchy | Block | Description | Required |
| ------------------------------ | ------------------ | -------------------------------------------------------------------------------------------------------------------------------- | -------- |
| authentication | [authentication][] | Configures authentication for connecting to the Solace broker. | yes |
| authentication > sasl_plain | [sasl_plain][] | Authenticates against the Solace broker with SASL PLAIN. | no |
| authentication > sasl_xauth2 | [sasl_xauth2][] | Authenticates against the Solace broker with SASL XOauth2. | no |
| authentication > sasl_external | [sasl_external][] | Authenticates against the Solace broker with SASL External. | no |
| flow | [flow][] | Configures the behaviour to use when temporary errors are encountered from the next component. | no |
| flow > delayed_retry | [delayed_retry][] | Sets the flow control strategy to `delayed retry` which will wait before trying to push the message to the next component again. | no |
| tls | [tls][] | Configures TLS for connecting to the Solace broker. | no |
| debug_metrics | [debug_metrics][] | Configures the metrics which this component generates to monitor its state. | no |
| output | [output][] | Configures where to send received telemetry data. | yes |

One SASL authentication block is required in the `authentication` block.

`sasl_external` must be used together with the `tls` block.

The `>` symbol indicates deeper levels of nesting. For example,
`authentication > tls` refers to a `tls` block defined inside an
`authentication` block.

[authentication]: #authentication-block
[sasl_plain]: #sasl_plain-block
[sasl_xauth2]: #sasl_xauth2-block
[sasl_external]: #sasl_external-block
[tls]: #tls-block
[flow]: #flow-block
[delayed_retry]: #delayed_retry-block
[debug_metrics]: #debug_metrics-block
[output]: #output-block

### authentication block

The `authentication` block configures how to authenticate for connecting to the Solace broker.
It doesn't support any arguments and is configured fully through inner blocks.

### sasl_plain block

The `sasl_plain` block configures how to authenticate to the Solace broker with SASL PLAIN.

The following arguments are supported:

| Name | Type | Description | Default | Required |
| ---------- | -------- | -------------------- | ------- | -------- |
| `username` | `string` | The username to use. | | yes |
| `password` | `string` | The password to use. | | yes |

### sasl_xauth2 block

The `sasl_xauth2` block configures how to authenticate to the Solace broker with SASL XOauth2.

The following arguments are supported:

| Name | Type | Description | Default | Required |
| ---------- | -------- | ------------------------- | ------- | -------- |
| `username` | `string` | The username to use. | | yes |
| `bearer` | `string` | The bearer in plain text. | | yes |

### sasl_external block

The `sasl_xauth2` block configures how to authenticate to the Solace broker with SASL External.
It doesn't support any arguments or blocks. It must be used with the [tls][] block.

### flow block

The `flow` block configures the behaviour to use when temporary errors are encountered from the next component.
It doesn't support any arguments and is configured fully through inner blocks.

### delayed_retry block

The `delayed_retry` block sets the flow control strategy to `delayed retry` which will wait before trying to push the message to the next component again.

The following arguments are supported:

| Name | Type | Description | Default | Required |
| ------- | -------- | --------------------------------- | -------- | -------- |
| `delay` | `string` | The time to wait before retrying. | `"10ms"` | no |

### tls block

{{< docs/shared lookup="reference/components/otelcol-tls-client-block.md" source="alloy" version="<ALLOY_VERSION>" >}}

### debug_metrics block

{{< docs/shared lookup="reference/components/otelcol-debug-metrics-block.md" source="alloy" version="<ALLOY_VERSION>" >}}

### output block

{{< docs/shared lookup="reference/components/output-block.md" source="alloy" version="<ALLOY_VERSION>" >}}

{{< admonition type="warning" >}}
Having multiple consumers may result in duplicated traces in case of errors because of the retry strategy.
It is recommended to only set one consumer for this component.
{{< /admonition >}}

## Exported fields

`otelcol.receiver.solace` does not export any fields.

## Component health

`otelcol.receiver.solace` is only reported as unhealthy if given an invalid
configuration.

## Debug information

`otelcol.receiver.solace` does not expose any component-specific debug
information.

## Example

This example forwards read telemetry data through a batch processor before
finally sending it to an OTLP-capable endpoint:

```alloy
otelcol.receiver.solace "default" {
queue = "queue://#telemetry-testprofile"
broker = "localhost:5672"
auth {
sasl_plain {
username = "alloy"
password = "password"
}
}
tls {
insecure = true
insecure_skip_verify = true
}
output {
traces = [otelcol.processor.batch.default.input]
}
}
otelcol.processor.batch "default" {
output {
traces = [otelcol.exporter.otlp.default.input]
}
}
otelcol.exporter.otlp "default" {
client {
endpoint = sys.env("OTLP_ENDPOINT")
}
}
```

<!-- START GENERATED COMPATIBLE COMPONENTS -->

## Compatible components

`otelcol.receiver.solace` can accept arguments from the following components:

- Components that export [OpenTelemetry `otelcol.Consumer`](../../../compatibility/#opentelemetry-otelcolconsumer-exporters)


{{< admonition type="note" >}}
Connecting some components may not be sensible or components may require further configuration to make the connection work correctly.
Refer to the linked documentation for more details.
{{< /admonition >}}

<!-- END GENERATED COMPATIBLE COMPONENTS -->
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ require (
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver v0.112.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver v0.112.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver v0.112.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver v0.112.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver v0.112.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver v0.112.0
github.com/ory/dockertest/v3 v3.8.1
Expand Down Expand Up @@ -821,6 +822,7 @@ require (
)

require (
github.com/Azure/go-amqp v1.2.0 // indirect
github.com/DataDog/datadog-agent/comp/core/log/def v0.57.1 // indirect
github.com/antchfx/xmlquery v1.4.2 // indirect
github.com/antchfx/xpath v1.3.2 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4=
github.com/Azure/azure-storage-queue-go v0.0.0-20181215014128-6ed74e755687/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8=
github.com/Azure/go-amqp v0.12.6/go.mod h1:qApuH6OFTSKZFmCOxccvAv5rLizBQf4v8pRmG138DPo=
github.com/Azure/go-amqp v1.2.0 h1:NNyfN3/cRszWzMvjmm64yaPZDHX/2DJkowv8Ub9y01I=
github.com/Azure/go-amqp v1.2.0/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51Y5WZE=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
Expand Down Expand Up @@ -2047,6 +2049,8 @@ github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver v0.112.0/go.mod h1:v61OP6Zxu8Kx4WLuswY06uaUPiOWDt5ykW9vqNQJNXc=
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver v0.112.0 h1:X/eUpWLWBZg2fDT+jWZiIept45akvKbZXhktg1x86gE=
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver v0.112.0/go.mod h1:q2lFBHfnG+ar2DJJlIU6RviOFXDeFur9vJ083NvOMQs=
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver v0.112.0 h1:cHk8vS/D1pjeZ0o4LJJAENP847HHWjTXFe4y1RJYlfo=
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver v0.112.0/go.mod h1:2CK7Hh6UGLnBSGW7Y0nopvEhoo25D6t/395jFEephEs=
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver v0.112.0 h1:Vv1FDwd7pykzj8Wmuc7yj7bcN0qUv1mGBb/dcTMPfNE=
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver v0.112.0/go.mod h1:lklLK8ELD2Wk5z7ywjaf6XEbbViDtf7uK8jAExjRlls=
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver v0.112.0 h1:XhKHjEpQJQMaUuWVhWS1FEuaY4LJDwBgsGXE166j9SY=
Expand Down
1 change: 1 addition & 0 deletions internal/component/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import (
_ "github.com/grafana/alloy/internal/component/otelcol/receiver/opencensus" // Import otelcol.receiver.opencensus
_ "github.com/grafana/alloy/internal/component/otelcol/receiver/otlp" // Import otelcol.receiver.otlp
_ "github.com/grafana/alloy/internal/component/otelcol/receiver/prometheus" // Import otelcol.receiver.prometheus
_ "github.com/grafana/alloy/internal/component/otelcol/receiver/solace" // Import otelcol.receiver.solace
_ "github.com/grafana/alloy/internal/component/otelcol/receiver/vcenter" // Import otelcol.receiver.vcenter
_ "github.com/grafana/alloy/internal/component/otelcol/receiver/zipkin" // Import otelcol.receiver.zipkin
_ "github.com/grafana/alloy/internal/component/prometheus/exporter/apache" // Import prometheus.exporter.apache
Expand Down
4 changes: 4 additions & 0 deletions internal/component/all/all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ func sharePointer(a, b reflect.Value) (string, bool) {
return "", false

case reflect.Pointer:
// same edge case as above: skip if this is a struct ptr and that the structs are empty
if !a.IsNil() && a.Elem().Kind() == reflect.Struct && a.Elem().NumField() == 0 {
return "", false
}
if pointersMatch(a, b) {
return "", true
} else {
Expand Down
98 changes: 98 additions & 0 deletions internal/component/otelcol/receiver/solace/config_solace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package solace

import (
"time"

"github.com/grafana/alloy/syntax/alloytypes"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver"
"go.opentelemetry.io/collector/config/configopaque"
)

// Authentication defines authentication strategies.
type Authentication struct {
PlainText *SaslPlainTextConfig `alloy:"sasl_plain,block,optional"`
XAuth2 *SaslXAuth2Config `alloy:"sasl_xauth2,block,optional"`
External *SaslExternalConfig `alloy:"sasl_external,block,optional"`
}

// Convert converts args into the upstream type.
func (args Authentication) Convert() solacereceiver.Authentication {
auth := solacereceiver.Authentication{}

if args.PlainText != nil {
auth.PlainText = args.PlainText.Convert()
}
if args.XAuth2 != nil {
auth.XAuth2 = args.XAuth2.Convert()
}
if args.External != nil {
auth.External = args.External.Convert()
}

return auth
}

// SaslPlainTextConfig defines SASL PLAIN authentication.
type SaslPlainTextConfig struct {
Username string `alloy:"username,attr"`
Password alloytypes.Secret `alloy:"password,attr"`
}

func (args SaslPlainTextConfig) Convert() *solacereceiver.SaslPlainTextConfig {
return &solacereceiver.SaslPlainTextConfig{
Username: args.Username,
Password: configopaque.String(args.Password),
}
}

// SaslXAuth2Config defines the configuration for the SASL XAUTH2 authentication.
type SaslXAuth2Config struct {
Username string `alloy:"username,attr"`
Bearer string `alloy:"bearer,attr"`
}

func (args SaslXAuth2Config) Convert() *solacereceiver.SaslXAuth2Config {
return &solacereceiver.SaslXAuth2Config{
Username: args.Username,
Bearer: args.Bearer,
}
}

// SaslExternalConfig defines the configuration for the SASL External used in conjunction with TLS client authentication.
type SaslExternalConfig struct{}

func (args SaslExternalConfig) Convert() *solacereceiver.SaslExternalConfig {
return &solacereceiver.SaslExternalConfig{}
}

// FlowControl defines the configuration for what to do in backpressure scenarios, e.g. memorylimiter errors
type FlowControl struct {
DelayedRetry *FlowControlDelayedRetry `alloy:"delayed_retry,block"`
}

func (args FlowControl) Convert() solacereceiver.FlowControl {
flowControl := solacereceiver.FlowControl{}
if args.DelayedRetry != nil {
flowControl.DelayedRetry = args.DelayedRetry.Convert()
}
return flowControl
}

func (args *FlowControl) SetToDefault() {
*args = FlowControl{
DelayedRetry: &FlowControlDelayedRetry{
Delay: 10 * time.Millisecond,
},
}
}

// FlowControlDelayedRetry represents the strategy of waiting for a defined amount of time (in time.Duration) and attempt redelivery
type FlowControlDelayedRetry struct {
Delay time.Duration `alloy:"delay,attr,optional"`
}

func (args FlowControlDelayedRetry) Convert() *solacereceiver.FlowControlDelayedRetry {
return &solacereceiver.FlowControlDelayedRetry{
Delay: args.Delay,
}
}
Loading

0 comments on commit 014bab3

Please sign in to comment.