Skip to content

Commit

Permalink
Smart Agent Receiver skeleton (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
rmfitzpatrick authored Jan 5, 2021
1 parent 7d839a8 commit 0f65733
Show file tree
Hide file tree
Showing 10 changed files with 361 additions and 40 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ require (
github.com/securego/gosec/v2 v2.5.0
github.com/stretchr/testify v1.6.1
go.opentelemetry.io/collector v0.15.0
go.uber.org/zap v1.16.0
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211
honnef.co/go/tools v0.0.1-2020.1.6
)
Expand Down
40 changes: 0 additions & 40 deletions go.sum

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions internal/receiver/smartagentreceiver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# SignalFx Smart Agent Receiver

The Smart Agent Receiver allows you to utilize existing [SignalFx Smart Agent monitors](https://github.com/signalfx/signalfx-agent#monitors)
as OpenTelemetry Collector metric receivers. It assumes that you have a properly configured environment with a
functional [Smart Agent release bundle](https://github.com/signalfx/signalfx-agent/releases/latest) on your system.

**pre-alpha: Not intended to be used and no stability or functional guarantees are made of any kind at this time.**

## Configuration

Each `smartagent` receiver configuration acts a drop-in replacement for each supported Smart Agent Monitor
[configuration](https://github.com/signalfx/signalfx-agent/blob/master/docs/monitor-config.md) with some exceptions:

1. In lieu of `discoveryRule` support, the Collector's
[`receivercreator`](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/master/receiver/receivercreator/README.md)
and associated [Observer extensions](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/master/extension/observer/README.md)
should be used.
1. All metric content replacement and transformation rules should utilize existing
[Collector processors](https://github.com/open-telemetry/opentelemetry-collector/blob/master/processor/README.md).

Example:

```yaml
receivers:
smartagent/haproxy:
type: haproxy
host: myhaproxyinstance
port: 8080
smartagent/postgresql:
type: postgresql
host: mypostgresinstance
port: 5432
```
The full list of settings exposed for this receiver are documented for
[each monitor](https://github.com/signalfx/signalfx-agent/tree/master/docs/monitors), and the implementation is
[here](./config.go)
33 changes: 33 additions & 0 deletions internal/receiver/smartagentreceiver/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2021, OpenTelemetry Authors
//
// 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 smartagentreceiver

import (
"fmt"

"go.opentelemetry.io/collector/config/configmodels"
)

type Config struct {
configmodels.ReceiverSettings `mapstructure:",squash"`
}

func (cfg *Config) validate() error {
if cfg.NameVal == "" || cfg.TypeVal == "" {
// validation placeholder for coverage
return fmt.Errorf("name and type are required")
}
return nil
}
51 changes: 51 additions & 0 deletions internal/receiver/smartagentreceiver/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2021, OpenTelemetry Authors
//
// 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 smartagentreceiver

import (
"path"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/config/configmodels"
"go.opentelemetry.io/collector/config/configtest"
)

func TestLoadConfig(t *testing.T) {
factories, err := componenttest.ExampleComponents()
assert.Nil(t, err)

factory := NewFactory()
factories.Receivers[configmodels.Type(typeStr)] = factory
cfg, err := configtest.LoadConfigFile(
t, path.Join(".", "testdata", "config.yaml"), factories,
)

require.NoError(t, err)
require.NotNil(t, cfg)

assert.Equal(t, len(cfg.Receivers), 1)

smartAgentCfg := cfg.Receivers["smartagent"].(*Config)
require.Equal(t, &Config{
ReceiverSettings: configmodels.ReceiverSettings{
TypeVal: typeStr,
NameVal: typeStr,
},
}, smartAgentCfg)
require.NoError(t, smartAgentCfg.validate())
}
61 changes: 61 additions & 0 deletions internal/receiver/smartagentreceiver/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2021, OpenTelemetry Authors
//
// 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 smartagentreceiver

import (
"context"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configmodels"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/receiver/receiverhelper"
)

const (
typeStr = "smartagent"
)

func NewFactory() component.ReceiverFactory {
return receiverhelper.NewFactory(
typeStr,
CreateDefaultConfig,
receiverhelper.WithMetrics(createMetricsReceiver),
)
}

func CreateDefaultConfig() configmodels.Receiver {
return &Config{
ReceiverSettings: configmodels.ReceiverSettings{
TypeVal: typeStr,
NameVal: typeStr,
},
}
}

func createMetricsReceiver(
_ context.Context,
params component.ReceiverCreateParams,
cfg configmodels.Receiver,
consumer consumer.MetricsConsumer,
) (component.MetricsReceiver, error) {
receiverConfig := cfg.(*Config)

err := receiverConfig.validate()
if err != nil {
return nil, err
}

return NewReceiver(params.Logger, *receiverConfig, consumer), nil
}
55 changes: 55 additions & 0 deletions internal/receiver/smartagentreceiver/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2021, OpenTelemetry Authors
//
// 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 smartagentreceiver

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configcheck"
"go.opentelemetry.io/collector/consumer/consumertest"
"go.uber.org/zap"
)

func TestCreateDefaultConfig(t *testing.T) {
factory := NewFactory()
cfg := factory.CreateDefaultConfig()
assert.NotNil(t, cfg, "failed to create default config")
assert.NoError(t, configcheck.ValidateConfig(cfg))
}

func TestCreateReceiver(t *testing.T) {
factory := NewFactory()
cfg := factory.CreateDefaultConfig()

params := component.ReceiverCreateParams{Logger: zap.NewNop()}
receiver, err := factory.CreateMetricsReceiver(context.Background(), params, cfg, consumertest.NewMetricsNop())
assert.NoError(t, err)
assert.NotNil(t, receiver)
}

func TestCreateReceiverWithInvalidConfig(t *testing.T) {
factory := NewFactory()
cfg := &Config{}
require.Error(t, cfg.validate())

params := component.ReceiverCreateParams{Logger: zap.NewNop()}
receiver, err := factory.CreateMetricsReceiver(context.Background(), params, cfg, consumertest.NewMetricsNop())
assert.Error(t, err)
assert.Nil(t, receiver)
}
47 changes: 47 additions & 0 deletions internal/receiver/smartagentreceiver/receiver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2021, OpenTelemetry Authors
//
// 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 smartagentreceiver

import (
"context"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/consumer"
"go.uber.org/zap"
)

type Receiver struct {
logger *zap.Logger
config *Config
nextConsumer consumer.MetricsConsumer
}

var _ component.MetricsReceiver = (*Receiver)(nil)

func NewReceiver(logger *zap.Logger, config Config, nextConsumer consumer.MetricsConsumer) *Receiver {
return &Receiver{
logger: logger,
config: &config,
nextConsumer: nextConsumer,
}
}

func (r *Receiver) Start(_ context.Context, host component.Host) error {
return nil
}

func (r *Receiver) Shutdown(context.Context) error {
return nil
}
61 changes: 61 additions & 0 deletions internal/receiver/smartagentreceiver/receiver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2021, OpenTelemetry Authors
//
// 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 smartagentreceiver

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/config/configmodels"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/consumer/consumertest"
"go.uber.org/zap"
)

func TestSmartAgentReceiver(t *testing.T) {
type args struct {
config Config
nextConsumer consumer.MetricsConsumer
}
tests := []struct {
name string
args args
}{
{
name: "default",
args: args{
config: Config{
ReceiverSettings: configmodels.ReceiverSettings{
TypeVal: typeStr,
NameVal: typeStr + "/default",
},
},
nextConsumer: consumertest.NewMetricsNop(),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
consumer := tt.args.nextConsumer
receiver := NewReceiver(zap.NewNop(), tt.args.config, consumer)
err := receiver.Start(context.Background(), componenttest.NewNopHost())
assert.NoError(t, err)
err = receiver.Shutdown(context.Background())
assert.NoError(t, err)
})
}
}
15 changes: 15 additions & 0 deletions internal/receiver/smartagentreceiver/testdata/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
receivers:
smartagent:

processors:
exampleprocessor:

exporters:
exampleexporter:

service:
pipelines:
metrics:
receivers: [smartagent]
processors: [exampleprocessor]
exporters: [exampleexporter]

0 comments on commit 0f65733

Please sign in to comment.