Skip to content

Commit

Permalink
Add receiver for sapm protocol (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
codesmith14 authored and Paulo Janotti committed Dec 6, 2019
1 parent 056258e commit e9cdcd5
Show file tree
Hide file tree
Showing 13 changed files with 1,991 additions and 10 deletions.
2 changes: 2 additions & 0 deletions cmd/otelcontribcol/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/signalfxexporter"
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/stackdriverexporter"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/collectdreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sapmreceiver"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinscribereceiver"
)

Expand All @@ -37,6 +38,7 @@ func components() (config.Factories, error) {

receivers := []receiver.Factory{
&collectdreceiver.Factory{},
&sapmreceiver.Factory{},
&zipkinscribereceiver.Factory{},
}
for _, rcv := range factories.Receivers {
Expand Down
15 changes: 7 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,21 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azure

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/collectdreceiver => ./receiver/collectdreceiver

replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sapmreceiver => ./receiver/sapmreceiver

require (
github.com/client9/misspell v0.3.4
github.com/google/addlicense v0.0.0-20190907113143-be125746c2c4
github.com/onsi/ginkgo v1.10.1 // indirect
github.com/onsi/gomega v1.7.0 // indirect
github.com/open-telemetry/opentelemetry-collector v0.2.1-0.20191126183205-e94dd19191e0
github.com/open-telemetry/opentelemetry-collector v0.2.1-0.20191205151336-8e2473c5e754
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitorexporter v0.0.0
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/signalfxexporter v0.0.0-20191203211755-8ae89debd6c5
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/stackdriverexporter v0.0.0-20191126142441-b2a048090ad6
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/collectdreceiver v0.0.0-00010101000000-000000000000
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/sapmreceiver v0.0.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinscribereceiver v0.0.0-20191126142441-b2a048090ad6
github.com/pavius/impi v0.0.0-20180302134524-c1cbdcb8df2b
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 // indirect
golang.org/x/lint v0.0.0-20190930215403-16217165b5de
golang.org/x/tools v0.0.0-20191119175705-11e13f1c3fd7
gopkg.in/yaml.v2 v2.2.4 // indirect
github.com/pierrec/lz4 v2.0.5+incompatible // indirect
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f
golang.org/x/tools v0.0.0-20191205225056-3393d29bb9fe
honnef.co/go/tools v0.0.1-2019.2.3
)
192 changes: 190 additions & 2 deletions go.sum

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions receiver/sapmreceiver/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2019, 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 sapmreceiver

import (
"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
)

// Config defines configuration for SAPM receiver.
type Config struct {
configmodels.ReceiverSettings `mapstructure:",squash"`
}
54 changes: 54 additions & 0 deletions receiver/sapmreceiver/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2019, 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 sapmreceiver

import (
"path"
"testing"

"github.com/open-telemetry/opentelemetry-collector/config"
"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

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

factory := &Factory{}
factories.Receivers[typeStr] = factory
cfg, err := config.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories)

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

// The receiver `sapm/disabled` doesn't count because disabled receivers
// are excluded from the final list.
assert.Equal(t, len(cfg.Receivers), 2)

r0 := cfg.Receivers["sapm"]
assert.Equal(t, r0, factory.CreateDefaultConfig())

r1 := cfg.Receivers["sapm/customname"].(*Config)
assert.Equal(t, r1,
&Config{
ReceiverSettings: configmodels.ReceiverSettings{
TypeVal: typeStr,
NameVal: "sapm/customname",
Endpoint: "0.0.0.0:7276",
},
})
}
17 changes: 17 additions & 0 deletions receiver/sapmreceiver/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2019, 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 sapmreceiver implements a receiver that can be used by the
// Opentelemetry collector to receive traces in the Splunk SAPM format.
package sapmreceiver
117 changes: 117 additions & 0 deletions receiver/sapmreceiver/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright 2019, 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 sapmreceiver

// This file implements factory for SAPM receiver.

import (
"context"
"fmt"
"net"
"strconv"

"github.com/open-telemetry/opentelemetry-collector/config/configerror"
"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
"github.com/open-telemetry/opentelemetry-collector/consumer"
"github.com/open-telemetry/opentelemetry-collector/receiver"
"go.uber.org/zap"
)

const (
// The value of "type" key in configuration.
typeStr = "sapm"

// Default endpoints to bind to.
defaultEndpoint = ":7276"
)

// Factory is the factory for SAPM receiver.
type Factory struct {
}

// Type gets the type of the Receiver config created by this factory.
func (f *Factory) Type() string {
return typeStr
}

// CustomUnmarshaler returns nil because we don't need custom unmarshaling for this config.
func (f *Factory) CustomUnmarshaler() receiver.CustomUnmarshaler {
return nil
}

// CreateDefaultConfig creates the default configuration for SAPM receiver.
func (f *Factory) CreateDefaultConfig() configmodels.Receiver {
return &Config{
ReceiverSettings: configmodels.ReceiverSettings{
TypeVal: typeStr,
NameVal: typeStr,
Endpoint: defaultEndpoint,
},
}
}

// extract the port number from string in "address:port" format. If the
// port number cannot be extracted returns an error.
// TODO make this a utility function
func extractPortFromEndpoint(endpoint string) (int, error) {
_, portStr, err := net.SplitHostPort(endpoint)
if err != nil {
return 0, fmt.Errorf("endpoint is not formatted correctly: %s", err.Error())
}
port, err := strconv.ParseInt(portStr, 10, 0)
if err != nil {
return 0, fmt.Errorf("endpoint port is not a number: %s", err.Error())
}
if port < 1 || port > 65535 {
return 0, fmt.Errorf("port number must be between 1 and 65535")
}
return int(port), nil
}

// CreateTraceReceiver creates a trace receiver based on provided config.
func (f *Factory) CreateTraceReceiver(
ctx context.Context,
logger *zap.Logger,
cfg configmodels.Receiver,
nextConsumer consumer.TraceConsumer,
) (receiver.TraceReceiver, error) {
// assert config is SAPM config
rCfg := cfg.(*Config)

port, err := extractPortFromEndpoint(rCfg.Endpoint)
if err != nil {
return nil, err
}

// verify that the configured port is not 0
if port == 0 {
err = fmt.Errorf("endpoint with non-zero port must be enabled for %s receiver",
rCfg.Name(),
)
return nil, err
}

// Create the receiver.
return New(ctx, logger, rCfg, nextConsumer)
}

// CreateMetricsReceiver creates a metrics receiver based on provided config.
func (f *Factory) CreateMetricsReceiver(
logger *zap.Logger,
cfg configmodels.Receiver,
consumer consumer.MetricsConsumer,
) (receiver.MetricsReceiver, error) {
return nil, configerror.ErrDataTypeIsNotSupported
}
75 changes: 75 additions & 0 deletions receiver/sapmreceiver/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2019, 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 sapmreceiver

import (
"context"
"testing"

"github.com/open-telemetry/opentelemetry-collector/config/configcheck"
"github.com/open-telemetry/opentelemetry-collector/config/configerror"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
)

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

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

tReceiver, err := factory.CreateTraceReceiver(context.Background(), zap.NewNop(), cfg, nil)
assert.NoError(t, err, "receiver creation failed")
assert.NotNil(t, tReceiver, "receiver creation failed")

mReceiver, err := factory.CreateMetricsReceiver(zap.NewNop(), cfg, nil)
assert.Equal(t, err, configerror.ErrDataTypeIsNotSupported)
assert.Nil(t, mReceiver)
}

func TestCreateInvalidHTTPEndpoint(t *testing.T) {
factory := Factory{}
cfg := factory.CreateDefaultConfig()
rCfg := cfg.(*Config)

rCfg.Endpoint = ""
_, err := factory.CreateTraceReceiver(context.Background(), zap.NewNop(), cfg, nil)
assert.Error(t, err, "receiver creation with no endpoints must fail")
}

func TestCreateNoPort(t *testing.T) {
factory := Factory{}
cfg := factory.CreateDefaultConfig()
rCfg := cfg.(*Config)

rCfg.Endpoint = "localhost:"
_, err := factory.CreateTraceReceiver(context.Background(), zap.NewNop(), cfg, nil)
assert.Error(t, err, "receiver creation with no port number must fail")
}

func TestCreateLargePort(t *testing.T) {
factory := Factory{}
cfg := factory.CreateDefaultConfig()
rCfg := cfg.(*Config)

rCfg.Endpoint = "localhost:65536"
_, err := factory.CreateTraceReceiver(context.Background(), zap.NewNop(), cfg, nil)
assert.Error(t, err, "receiver creation with too large port number must fail")
}
32 changes: 32 additions & 0 deletions receiver/sapmreceiver/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module github.com/optelemetry-collector-contrib/receiver/sapmreceiver

go 1.12

require (
cloud.google.com/go v0.49.0 // indirect
github.com/census-instrumentation/opencensus-proto v0.2.1
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 // indirect
github.com/golang/protobuf v1.3.2
github.com/google/go-cmp v0.3.1
github.com/gorilla/mux v1.7.3
github.com/jaegertracing/jaeger v1.15.1
github.com/jstemmer/go-junit-report v0.9.1 // indirect
github.com/open-telemetry/opentelemetry-collector v0.2.1-0.20191205151336-8e2473c5e754
github.com/prometheus/client_model v0.0.0-20191202183732-d1d2010b5bee // indirect
github.com/signalfx/sapm-proto v0.0.2
github.com/stretchr/testify v1.4.0
go.opencensus.io v0.22.2
go.uber.org/zap v1.13.0
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd // indirect
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f // indirect
golang.org/x/net v0.0.0-20191206103017-1ddd1de85cb0 // indirect
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 // indirect
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
golang.org/x/tools v0.0.0-20191205225056-3393d29bb9fe // indirect
google.golang.org/appengine v1.6.5 // indirect
google.golang.org/genproto v0.0.0-20191205163323-51378566eb59 // indirect
google.golang.org/grpc v1.25.1 // indirect
gopkg.in/yaml.v2 v2.2.7 // indirect
)
Loading

0 comments on commit e9cdcd5

Please sign in to comment.