-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: dark0dave <[email protected]>
- Loading branch information
Showing
17 changed files
with
1,184 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include ../../Makefile.Common |
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,21 @@ | ||
# Faro Receiver | ||
|
||
This receiver can receive telemetry data from the [Grafana Faro Web SDK](https://github.com/grafana/faro-web-sdk). | ||
The telemetry data is in JSON format and adheres to the Faro OpenAPI schema, as defined in the [github.com/grafana/faro](https://github.com/grafana/faro) | ||
|
||
## Receiver Configuration | ||
|
||
The following receiver configuration parameters are supported. | ||
|
||
| Name | Description | Default | | ||
|:-----------|:----------------------------------|----------------| | ||
| `endpoint` | Endpoint exposed by this receiver | localhost:8080 | | ||
|
||
|
||
# Example Configuration | ||
|
||
```yaml | ||
receivers: | ||
faro: | ||
endpoint: 'localhost:8081' | ||
``` |
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,36 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package faroreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/faroreceiver" | ||
|
||
import ( | ||
"errors" | ||
|
||
"go.opentelemetry.io/collector/component" | ||
"go.opentelemetry.io/collector/config/confighttp" | ||
"go.opentelemetry.io/collector/confmap" | ||
) | ||
|
||
type Config struct { | ||
*confighttp.ServerConfig `mapstructure:",squash"` | ||
} | ||
|
||
var ( | ||
_ component.Config = (*Config)(nil) | ||
_ confmap.Unmarshaler = (*Config)(nil) | ||
) | ||
|
||
func (cfg *Config) Validate() error { | ||
if cfg.Endpoint == "" { | ||
return errors.New("must specify endpoint") | ||
} | ||
return nil | ||
} | ||
|
||
func (cfg *Config) Unmarshal(conf *confmap.Conf) error { | ||
err := conf.Unmarshal(cfg) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
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,55 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package faroreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/faroreceiver" | ||
|
||
import ( | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"go.opentelemetry.io/collector/component" | ||
"go.opentelemetry.io/collector/config/configauth" | ||
"go.opentelemetry.io/collector/config/confighttp" | ||
"go.opentelemetry.io/collector/config/configtls" | ||
"go.opentelemetry.io/collector/confmap/confmaptest" | ||
) | ||
|
||
func TestUnmarshalDefaultConfig(t *testing.T) { | ||
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "default.yaml")) | ||
require.NoError(t, err) | ||
factory := NewFactory() | ||
cfg := factory.CreateDefaultConfig() | ||
require.NoError(t, cm.Unmarshal(&cfg)) | ||
assert.Equal(t, factory.CreateDefaultConfig(), cfg) | ||
} | ||
|
||
func TestUnmarshalConfig(t *testing.T) { | ||
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) | ||
require.NoError(t, err) | ||
factory := NewFactory() | ||
cfg := factory.CreateDefaultConfig() | ||
require.NoError(t, cm.Unmarshal(&cfg)) | ||
assert.Equal(t, | ||
&Config{ | ||
ServerConfig: &confighttp.ServerConfig{ | ||
Auth: &confighttp.AuthConfig{ | ||
Authentication: configauth.Authentication{ | ||
AuthenticatorID: component.MustNewID("test"), | ||
}, | ||
}, | ||
Endpoint: "localhost:8080", | ||
TLSSetting: &configtls.ServerConfig{ | ||
Config: configtls.Config{ | ||
CertFile: "test.crt", | ||
KeyFile: "test.key", | ||
}, | ||
}, | ||
CORS: &confighttp.CORSConfig{ | ||
AllowedOrigins: []string{"https://*.test.com", "https://test.com"}, | ||
MaxAge: 7200, | ||
}, | ||
}, | ||
}, cfg) | ||
} |
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,91 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package faroreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/faroreceiver" | ||
|
||
import ( | ||
"bytes" | ||
|
||
"github.com/gogo/protobuf/jsonpb" | ||
"go.opentelemetry.io/collector/pdata/plog/plogotlp" | ||
"go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp" | ||
"go.opentelemetry.io/collector/pdata/pprofile/pprofileotlp" | ||
"go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" | ||
spb "google.golang.org/genproto/googleapis/rpc/status" | ||
) | ||
|
||
const ( | ||
jsonContentType = "application/json" | ||
) | ||
|
||
var ( | ||
jsEncoder = &jsonEncoder{} | ||
jsonPbMarshaler = &jsonpb.Marshaler{} | ||
) | ||
|
||
type encoder interface { | ||
unmarshalTracesRequest(buf []byte) (ptraceotlp.ExportRequest, error) | ||
unmarshalMetricsRequest(buf []byte) (pmetricotlp.ExportRequest, error) | ||
unmarshalLogsRequest(buf []byte) (plogotlp.ExportRequest, error) | ||
unmarshalProfilesRequest(buf []byte) (pprofileotlp.ExportRequest, error) | ||
|
||
marshalTracesResponse(ptraceotlp.ExportResponse) ([]byte, error) | ||
marshalMetricsResponse(pmetricotlp.ExportResponse) ([]byte, error) | ||
marshalLogsResponse(plogotlp.ExportResponse) ([]byte, error) | ||
marshalProfilesResponse(pprofileotlp.ExportResponse) ([]byte, error) | ||
|
||
marshalStatus(rsp *spb.Status) ([]byte, error) | ||
|
||
contentType() string | ||
} | ||
|
||
type jsonEncoder struct{} | ||
|
||
func (jsonEncoder) unmarshalTracesRequest(buf []byte) (ptraceotlp.ExportRequest, error) { | ||
req := ptraceotlp.NewExportRequest() | ||
err := req.UnmarshalJSON(buf) | ||
return req, err | ||
} | ||
|
||
func (jsonEncoder) unmarshalMetricsRequest(buf []byte) (pmetricotlp.ExportRequest, error) { | ||
req := pmetricotlp.NewExportRequest() | ||
err := req.UnmarshalJSON(buf) | ||
return req, err | ||
} | ||
|
||
func (jsonEncoder) unmarshalLogsRequest(buf []byte) (plogotlp.ExportRequest, error) { | ||
req := plogotlp.NewExportRequest() | ||
err := req.UnmarshalJSON(buf) | ||
return req, err | ||
} | ||
|
||
func (jsonEncoder) unmarshalProfilesRequest(buf []byte) (pprofileotlp.ExportRequest, error) { | ||
req := pprofileotlp.NewExportRequest() | ||
err := req.UnmarshalJSON(buf) | ||
return req, err | ||
} | ||
|
||
func (jsonEncoder) marshalTracesResponse(resp ptraceotlp.ExportResponse) ([]byte, error) { | ||
return resp.MarshalJSON() | ||
} | ||
|
||
func (jsonEncoder) marshalMetricsResponse(resp pmetricotlp.ExportResponse) ([]byte, error) { | ||
return resp.MarshalJSON() | ||
} | ||
|
||
func (jsonEncoder) marshalLogsResponse(resp plogotlp.ExportResponse) ([]byte, error) { | ||
return resp.MarshalJSON() | ||
} | ||
|
||
func (jsonEncoder) marshalProfilesResponse(resp pprofileotlp.ExportResponse) ([]byte, error) { | ||
return resp.MarshalJSON() | ||
} | ||
|
||
func (jsonEncoder) marshalStatus(resp *spb.Status) ([]byte, error) { | ||
buf := new(bytes.Buffer) | ||
err := jsonPbMarshaler.Marshal(buf, resp) | ||
return buf.Bytes(), err | ||
} | ||
|
||
func (jsonEncoder) contentType() string { | ||
return jsonContentType | ||
} |
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,100 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package faroreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/faroreceiver" | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"go.opentelemetry.io/collector/component" | ||
"go.opentelemetry.io/collector/config/confighttp" | ||
"go.opentelemetry.io/collector/consumer" | ||
"go.opentelemetry.io/collector/receiver" | ||
|
||
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent" | ||
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/faroreceiver/internal/metadata" | ||
) | ||
|
||
const ( | ||
defaultFaroEndpoint = "localhost:8080" | ||
) | ||
|
||
// This is the map of already created Faro receivers for particular configurations. | ||
// We maintain this map because the receiver.Factory is asked trace and metric receivers separately | ||
// when it gets createFaroReceiverTraces() and createFaroReceiverLogs() but they must not | ||
// create separate objects, they must use one faroReceiver object per configuration. | ||
// When the receiver is shutdown it should be removed from this map so the same configuration | ||
// can be recreated successfully. | ||
var receivers = sharedcomponent.NewSharedComponents() | ||
|
||
func createDefaultConfig() component.Config { | ||
return &Config{ | ||
ServerConfig: &confighttp.ServerConfig{ | ||
Endpoint: defaultFaroEndpoint, | ||
}, | ||
} | ||
} | ||
|
||
func NewFactory() receiver.Factory { | ||
return receiver.NewFactory( | ||
metadata.Type, | ||
createDefaultConfig, | ||
receiver.WithTraces(createFaroReceiverTraces, metadata.TracesStability), | ||
receiver.WithLogs(createFaroReceiverLogs, metadata.LogsStability)) | ||
} | ||
|
||
func createFaroReceiverTraces( | ||
_ context.Context, | ||
set receiver.Settings, | ||
cfg component.Config, | ||
nextTraces consumer.Traces, | ||
) (receiver.Traces, error) { | ||
fCfg, ok := cfg.(*Config) | ||
if !ok { | ||
return nil, fmt.Errorf("invalid configuration: %T", cfg) | ||
} | ||
var err error | ||
receiver := receivers.GetOrAdd( | ||
fCfg, | ||
func() component.Component { | ||
var rcv component.Component | ||
rcv, err = newFaroReceiver(fCfg, &set) | ||
return rcv | ||
}, | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
receiver.Unwrap().(*faroReceiver).RegisterTracesConsumer(nextTraces) | ||
|
||
return receiver, nil | ||
} | ||
|
||
func createFaroReceiverLogs( | ||
_ context.Context, | ||
set receiver.Settings, | ||
cfg component.Config, | ||
nextLogs consumer.Logs, | ||
) (receiver.Logs, error) { | ||
fCfg, ok := cfg.(*Config) | ||
if !ok { | ||
return nil, fmt.Errorf("invalid configuration: %T", cfg) | ||
} | ||
var err error | ||
receiver := receivers.GetOrAdd( | ||
fCfg, | ||
func() component.Component { | ||
var rcv component.Component | ||
rcv, err = newFaroReceiver(fCfg, &set) | ||
return rcv | ||
}, | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
receiver.Unwrap().(*faroReceiver).RegisterLogsConsumer(nextLogs) | ||
|
||
return receiver, nil | ||
} |
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,81 @@ | ||
module github.com/open-telemetry/opentelemetry-collector-contrib/receiver/faroreceiver | ||
|
||
go 1.23.3 | ||
|
||
require ( | ||
github.com/grafana/faro/pkg/go v0.0.0-20250212082855-b99ea3b24d33 | ||
github.com/grafana/faro/pkg/translator/faro v0.0.0-20250212082855-b99ea3b24d33 | ||
github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.120.1 | ||
go.opentelemetry.io/collector/config/confighttp v0.119.0 | ||
go.opentelemetry.io/collector/pdata/pprofile v0.119.0 | ||
) | ||
|
||
require ( | ||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/go-logfmt/logfmt v0.6.0 // indirect | ||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect | ||
github.com/google/uuid v1.6.0 // indirect | ||
github.com/json-iterator/go v1.1.12 // indirect | ||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect | ||
github.com/knadh/koanf/maps v0.1.1 // indirect | ||
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect | ||
github.com/knadh/koanf/v2 v2.1.2 // indirect | ||
github.com/mitchellh/copystructure v1.2.0 // indirect | ||
github.com/mitchellh/reflectwalk v1.0.2 // indirect | ||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | ||
github.com/modern-go/reflect2 v1.0.2 // indirect | ||
github.com/oapi-codegen/runtime v1.1.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
github.com/wk8/go-ordered-map v1.0.0 // indirect | ||
github.com/zeebo/xxh3 v1.0.2 // indirect | ||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect | ||
go.opentelemetry.io/collector/consumer/consumererror v0.119.0 // indirect | ||
go.opentelemetry.io/collector/pipeline v0.120.0 // indirect | ||
go.opentelemetry.io/collector/receiver/xreceiver v0.119.0 // indirect | ||
go.opentelemetry.io/otel/sdk v1.34.0 // indirect | ||
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) | ||
|
||
require ( | ||
github.com/felixge/httpsnoop v1.0.4 // indirect | ||
github.com/fsnotify/fsnotify v1.8.0 // indirect | ||
github.com/go-logr/logr v1.4.2 // indirect | ||
github.com/go-logr/stdr v1.2.2 // indirect | ||
github.com/gogo/protobuf v1.3.2 | ||
github.com/golang/snappy v0.0.4 // indirect | ||
github.com/klauspost/compress v1.17.11 // indirect | ||
github.com/pierrec/lz4/v4 v4.1.22 // indirect | ||
github.com/rs/cors v1.11.1 // indirect | ||
github.com/stretchr/testify v1.10.0 | ||
go.opentelemetry.io/collector/client v1.25.0 // indirect | ||
go.opentelemetry.io/collector/component v0.120.0 | ||
go.opentelemetry.io/collector/component/componentstatus v0.120.0 | ||
go.opentelemetry.io/collector/component/componenttest v0.120.0 | ||
go.opentelemetry.io/collector/config/configauth v0.119.0 | ||
go.opentelemetry.io/collector/config/configcompression v1.25.0 // indirect | ||
go.opentelemetry.io/collector/config/configopaque v1.25.0 // indirect | ||
go.opentelemetry.io/collector/config/configtls v1.25.0 | ||
go.opentelemetry.io/collector/confmap v1.25.0 | ||
go.opentelemetry.io/collector/consumer v1.25.0 | ||
go.opentelemetry.io/collector/consumer/consumertest v0.119.0 | ||
go.opentelemetry.io/collector/consumer/xconsumer v0.119.0 // indirect | ||
go.opentelemetry.io/collector/extension v0.119.0 // indirect | ||
go.opentelemetry.io/collector/extension/auth v0.119.0 // indirect | ||
go.opentelemetry.io/collector/pdata v1.26.0 | ||
go.opentelemetry.io/collector/receiver v0.119.0 | ||
go.opentelemetry.io/collector/receiver/receivertest v0.119.0 | ||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect | ||
go.opentelemetry.io/otel v1.34.0 // indirect | ||
go.opentelemetry.io/otel/metric v1.34.0 // indirect | ||
go.opentelemetry.io/otel/trace v1.34.0 // indirect | ||
go.uber.org/multierr v1.11.0 // indirect | ||
go.uber.org/zap v1.27.0 | ||
golang.org/x/net v0.35.0 // indirect | ||
golang.org/x/sys v0.30.0 // indirect | ||
golang.org/x/text v0.22.0 // indirect | ||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 | ||
google.golang.org/grpc v1.70.0 | ||
google.golang.org/protobuf v1.36.5 // indirect | ||
) |
Oops, something went wrong.