-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Synthetic Telemetry Generator Receiver (#1506)
* 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
1 parent
61b4557
commit eb2562c
Showing
27 changed files
with
1,531 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.