Skip to content

Commit

Permalink
feat: Synthetic Telemetry Generator Receiver (#1506)
Browse files Browse the repository at this point in the history
* WIP telemetry generator

* Add logs generator

* Factor out common receiver code

* Split up recievers into their own files, use context

* Add validation and tests

* Remove unused id

* Handle error, fix comments

* go.mod merge fix

* Add generator interface, stub out generators

* Fix lint

* Apply review suggestions

* Split generator interface, add defaultLogGenerator tests

* Remove unused errors

* Stub out tests, README, comments, add severity validation

* Apply review suggestions

* Update go.mod

Co-authored-by: Brandon Johnson <brandon.johnson@bluemedora.com>

* Remove unused supportedTelemetry field

---------

Co-authored-by: Brandon Johnson <brandon.johnson@bluemedora.com>
  • Loading branch information
shazlehu and BinaryFissionGames authored Mar 6, 2024
1 parent 61b4557 commit eb2562c
Show file tree
Hide file tree
Showing 27 changed files with 1,531 additions and 3 deletions.
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,14 @@ updates:
commit-message:
prefix: "deps"
include: "scope"
- package-ecosystem: "gomod"
directory: "/receiver/telemetrygeneratorreceiver"
schedule:
interval: "weekly"
ignore:
# Opentelemetry updates will be done manually
- dependency-name: "go.opentelemetry.io/*"
- dependency-name: "github.com/open-telemetry/opentelemetry-collector*"
commit-message:
prefix: "deps"
include: "scope"
2 changes: 2 additions & 0 deletions factories/receivers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/observiq/bindplane-agent/receiver/pluginreceiver"
"github.com/observiq/bindplane-agent/receiver/routereceiver"
"github.com/observiq/bindplane-agent/receiver/sapnetweaverreceiver"
"github.com/observiq/bindplane-agent/receiver/telemetrygeneratorreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/activedirectorydsreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/aerospikereceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/apachereceiver"
Expand Down Expand Up @@ -157,6 +158,7 @@ var defaultReceivers = []receiver.Factory{
statsdreceiver.NewFactory(),
syslogreceiver.NewFactory(),
tcplogreceiver.NewFactory(),
telemetrygeneratorreceiver.NewFactory(),
udplogreceiver.NewFactory(),
vcenterreceiver.NewFactory(),
windowseventlogreceiver.NewFactory(),
Expand Down
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module github.com/observiq/bindplane-agent

go 1.21

toolchain go1.21.6
go 1.21.6

require (
github.com/google/uuid v1.6.0
Expand Down Expand Up @@ -32,6 +30,7 @@ require (
github.com/observiq/bindplane-agent/receiver/pluginreceiver v1.46.0
github.com/observiq/bindplane-agent/receiver/routereceiver v1.46.0
github.com/observiq/bindplane-agent/receiver/sapnetweaverreceiver v1.46.0
github.com/observiq/bindplane-agent/receiver/telemetrygeneratorreceiver v1.46.0
github.com/oklog/ulid/v2 v2.1.0
github.com/open-telemetry/opamp-go v0.9.0
github.com/open-telemetry/opentelemetry-collector-contrib/connector/countconnector v0.95.0
Expand Down Expand Up @@ -676,6 +675,8 @@ replace github.com/observiq/bindplane-agent/receiver/routereceiver => ./receiver

replace github.com/observiq/bindplane-agent/receiver/sapnetweaverreceiver => ./receiver/sapnetweaverreceiver

replace github.com/observiq/bindplane-agent/receiver/telemetrygeneratorreceiver => ./receiver/telemetrygeneratorreceiver

replace github.com/observiq/bindplane-agent/exporter/googlecloudexporter => ./exporter/googlecloudexporter

replace github.com/observiq/bindplane-agent/exporter/azureblobexporter => ./exporter/azureblobexporter
Expand Down
60 changes: 60 additions & 0 deletions receiver/telemetrygeneratorreceiver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Telemetry Generator Receiver
This receiver is used to generate synthetic telemetry for testing and configuration purposes.

## Minimum Agent Versions
- Introduced: [v1.46.0](https://github.com/observIQ/bindplane-agent/releases/tag/v1.46.0)

## Supported Pipelines
- Logs
- Metrics
- Traces

## How It Works
1. The user configures this receiver in a pipeline.
2. The user configures a supported component to route telemetry from this receiver.

## Configuration
| Field | Type | Default | Required | Description |
|----------------------|-----------|-----------|----------|-------------|
| payloads_per_second | int | `1` | `false` | The number of payloads this receiver will generate per second.|
| generators | list | | `true` | A list of generators to use.|
### Generator Configuration
| Field | Type | Default | Required | Description |
|----------------------|-----------|------------------|----------|--------------|
| type | string | | `true` | The type of generator to use. Currently only `logs` is supported. |
| resource_attributes | map | | `false` | A map of resource attributes to be included in the generated telemetry. Values can be `any`. |
| attributes | map | | `false` | A map of attributes to be included in the generated telemetry. Values can be `any`. |
| additional_config | map | | `false` | A map of additional configuration options to be included in the generated telemetry. Values can be `any`.|

### Log Generator Configuration
| Field | Type | Default | Required | Description |
|----------------------|-----------|---------|----------|-------------|
| body | string | | `false` | The body of the log, set in additional_config |
| severity | int | | `false` | The severity of the log message, set in additional_config |

### Example Configuration
```yaml
telemetrygeneratorreceiver:
payloads_per_second: 1
generators:
- type: logs
resource_attributes:
res_key1: res_value1
res_key2: res_value2
attributes:
attr_key1: attr_value1
attr_key2: attr_value2
additional_config:
body: this is the body
severity: 4
- type: logs
resource_attributes:
res_key3: res_value3
res_key4: res_value4
attributes:
attr_key3: attr_value3
attr_key4: attr_value4
additional_config:
body: this is another body
severity: 10
```
114 changes: 114 additions & 0 deletions receiver/telemetrygeneratorreceiver/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright observIQ, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package telemetrygeneratorreceiver generates telemetry for testing purposes
package telemetrygeneratorreceiver //import "github.com/observiq/bindplane-agent/receiver/telemetrygeneratorreceiver"

import (
"errors"
"fmt"

"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
)

// Config is the configuration for the telemetry generator receiver
type Config struct {
PayloadsPerSecond int `mapstructure:"payloads_per_second"`
Generators []GeneratorConfig `mapstructure:"generators"`
}

// GeneratorConfig is the configuration for a single generator
type GeneratorConfig struct {
// Type of generator to use, either "logs", "host_metrics", or "windows_events"
Type generatorType `mapstructure:"type"`

// ResourceAttributes are additional key-value pairs to add to the resource attributes of telemetry.
ResourceAttributes map[string]any `mapstructure:"resource_attributes"`

// Attributes are Additional key-value pairs to add to the telemetry attributes
Attributes map[string]any `mapstructure:"attributes"`

// AdditionalConfig are any additional config that a generator might need.
AdditionalConfig map[string]any `mapstructure:"additional_config"`
}

// Validate validates the config
func (c *Config) Validate() error {

if c.PayloadsPerSecond < 1 {
return errors.New("payloads_per_second must be at least 1")
}

for _, generator := range c.Generators {
if err := generator.Validate(); err != nil {
return err
}
}

return nil
}

// Validate validates the generator config
func (g *GeneratorConfig) Validate() error {

switch g.Type {
case generatorTypeLogs:
return validateLogGeneratorConfig(g)
case generatorTypeHostMetrics:
return validateHostMetricsGeneratorConfig(g)
case generatorTypeWindowsEvents:
return validateWindowsEventsGeneratorConfig(g)

default:
return fmt.Errorf("invalid generator type: %s", g.Type)
}
}

func validateLogGeneratorConfig(g *GeneratorConfig) error {
err := pcommon.NewMap().FromRaw(g.Attributes)
if err != nil {
return fmt.Errorf("error in attributes config: %s", err)
}

// severity and body validation
if body, ok := g.AdditionalConfig["body"]; ok {
// check if body is a valid string, if not, return an error
_, ok := body.(string)
if !ok {
return errors.New("body must be a string")
}
}

// if severity is set, it must be a valid severity
if severity, ok := g.AdditionalConfig["severity"]; ok {
severityVal, ok := severity.(int)
if !ok {
return errors.New("severity must be an integer")
}
sn := plog.SeverityNumber(severityVal)
if sn.String() == "" {
return fmt.Errorf("invalid severity: %d", severityVal)
}
}
return nil
}

func validateHostMetricsGeneratorConfig(_ *GeneratorConfig) error {
return nil
}

func validateWindowsEventsGeneratorConfig(_ *GeneratorConfig) error {
return nil
}
Loading

0 comments on commit eb2562c

Please sign in to comment.