-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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 receiver for sapm protocol #48
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
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"` | ||
} |
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", | ||
}, | ||
}) | ||
} |
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 |
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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably make this a utility func available for all components. No need to change anything in this PR, maybe just a TODO note for future improvement. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added a TODO |
||
_, 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) | ||
pjanotti marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 | ||
} |
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") | ||
} |
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 | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@owais I assume this is no longer needed. Can you please remove it in a separate PR?