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

Add otelcol.receiver.solace #2084

Merged
merged 11 commits into from
Nov 15, 2024
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 @@ -359,6 +359,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
wildum marked this conversation as resolved.
Show resolved Hide resolved

`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
Loading