Skip to content
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 support for logs in cloudfoundryreceiver #33044

Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
37b090f
[receiver/cloudfoundryreceiver] Move shardID check to validate in the…
CemDK May 2, 2024
ec3815c
[receiver/cloudfoundryreceiver] WIP adding functionality to receive l…
CemDK May 2, 2024
2f41118
[receiver/cloudfoundryreceiver] Add tests for shardid validation
jriguera May 7, 2024
225202b
[receiver/cloudfoundryreceiver] Add configuration for shardid tests
jriguera May 7, 2024
bce29d4
Added mvd file
CemDK May 13, 2024
b63ab5c
[receiver/cloudfoundryreceiver] Delete shardid empty test from stream…
jriguera May 13, 2024
05c6974
[receiver/cloudfoundryreceiver] Set the observed time of the envelope…
CemDK May 13, 2024
241167a
[receiver/cloudfoundryreceiver] WIP: Add functionality to fill trace …
CemDK May 13, 2024
a3900d5
[receiver/cloudfoundryreceiver] fix tests
CemDK May 13, 2024
3853b98
[receiver/cloudfoundryreceiver] Remove unused code and set the teleme…
jriguera May 14, 2024
262b5ef
[receiver/cloudfoundryreceiver] Update metadata stability level to De…
jriguera May 14, 2024
9b389e3
[receiver/cloudfoundryreceiver] Refactor condition for RTR logs
jriguera May 14, 2024
1039ec4
[receiver/cloudfoundryreceiver] Add autogenerated tests for logs
jriguera May 14, 2024
6366f8e
Merge remote-tracking branch 'upstream/main'
jriguera May 14, 2024
36beb48
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera May 14, 2024
6dcf1fc
[receiver/cloudfoundryreceiver] Remove internal company policy stuff
jriguera May 14, 2024
af160a4
[recevier/cloudfoundryreceiver] WIP: Reimplement function to parse RT…
jriguera May 23, 2024
928f6a4
[receiver/cloudfoundryreceiver] Rename nextConsumers fields and remov…
jriguera May 23, 2024
6994583
[receiver/cloudfoundryreceiver] Simplify code by combining method calls
jriguera May 23, 2024
fba8d9a
[receiver/cloudfoundryreceiver] Update Readme to explain the new shar…
jriguera May 24, 2024
0a6b517
[receiver/cloudfoundryreceiver] Refactor CreateStream in two functions
jriguera May 24, 2024
68ca2eb
Merge remote-tracking branch 'upstream/main'
jriguera May 24, 2024
9e23312
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera May 24, 2024
361fd8e
[receiver/cloudfoundryreceiver] Refactor logic and tests to set traci…
jriguera May 29, 2024
6487d4e
[receiver/cloudfoundryreceiver] Fix parseLogLine function when last c…
jriguera May 29, 2024
2d504e3
Merge remote-tracking branch 'upstream/main'
jriguera May 29, 2024
4a34be2
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera May 29, 2024
762c25b
[receiver/cloudfoundryreceiver] Fix linter interface{} -> any
jriguera May 29, 2024
6ea60d5
[receiver/cloudfoundryreceiver] Remove old const
jriguera May 29, 2024
e289d45
[receiver/cloudfoundryreceiver] Fix RTR log detection
jriguera May 29, 2024
875bc1b
[receiver/cloudfoundryreceiver] Fix argument order for assertAttribut…
jriguera May 29, 2024
e0f4fd5
[receiver/cloudfoundryreceiver] Improve tests for log conversion
jriguera May 29, 2024
47e4ae3
[receiver/cloudfoundryreceiver] Add support for W3C tracing flags in …
jriguera May 29, 2024
ae1c749
[receiver/cloudfoundryreceiver] Fix error creating streams for a diff…
jriguera May 30, 2024
0bffb29
[receiver/cloudfoundryreceiver] Improve error messages during initial…
jriguera May 30, 2024
19e94c1
[receiver/cloudfoundryreceiver] Change json test with error type log
jriguera May 30, 2024
e8c9ec3
Merge remote-tracking branch 'upstream/main' into receiver/cloudfound…
jriguera May 30, 2024
30932f9
[receiver/cloudfoundryreceiver] Remove tracing support on logs (it wi…
jriguera May 31, 2024
ed2861a
[receiver/cloudfoundryreceiver] Update Changelog for logs enhancement
jriguera May 31, 2024
2dc0a1c
[receiver/cloudfoundryreceiver] Update comments in receiver.go
CemDK Jun 3, 2024
68d3134
[receiver/cloudfoundryreceiver] Remove commented lines from stream.go
CemDK Jun 3, 2024
59fd679
[receiver/cloudfoundryreceiver] Add //exhaustive:enforce flag to log …
CemDK Jun 3, 2024
81a5cb0
[receiver/cloudfoundryreceiver] remove unnecessary test
CemDK Jun 10, 2024
1f0e300
[receiver/cloudfoundryreceiver] remove unused constants
CemDK Jun 10, 2024
80b9505
[receiver/cloudfoundryreceiver] improved error message
CemDK Jun 10, 2024
c648a09
[receiver/cloudfoundryreceiver] Update readme
CemDK Jun 10, 2024
5333fd2
[receiver/cloudfoundryreceiver] correct documentation
CemDK Jun 11, 2024
107fe2c
Merge remote-tracking branch 'upstream/main' into receiver/cloudfound…
jriguera Jun 12, 2024
b6334c7
[receiver/cloudfoundryreceiver] Fix deprecation warnings SA1019: NewN…
jriguera Jun 12, 2024
361f3af
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera Jun 13, 2024
c1e9852
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera Jul 2, 2024
02afa45
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera Jul 2, 2024
ecffbe3
Merge branch 'main' into receiver/cloudfoundryreceiver
tomasmota Jul 2, 2024
985e94d
[receiver/cloudfoundryreceiver] FIX 601: Implicit memory aliasing in…
jriguera Jul 2, 2024
ebc3b2a
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera Jul 2, 2024
f8d9d73
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera Jul 2, 2024
ee8e749
Update receiver/cloudfoundryreceiver/doc.go
jriguera Jul 3, 2024
13fc98d
Merge branch 'main' into receiver/cloudfoundryreceiver
jriguera Jul 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion receiver/cloudfoundryreceiver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
<!-- status autogenerated section -->
| Status | |
| ------------- |-----------|
| Stability | [beta]: metrics |
| Stability | [development]: logs |
| | [beta]: metrics |
| Distributions | [contrib] |
| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Fcloudfoundry%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Fcloudfoundry) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Fcloudfoundry%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Fcloudfoundry) |
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@pellared](https://www.github.com/pellared), [@crobert-1](https://www.github.com/crobert-1) |
| Emeritus | [@agoallikmaa](https://www.github.com/agoallikmaa) |

[development]: https://github.com/open-telemetry/opentelemetry-collector#development
[beta]: https://github.com/open-telemetry/opentelemetry-collector#beta
[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib
<!-- end autogenerated section -->
Expand Down
5 changes: 5 additions & 0 deletions receiver/cloudfoundryreceiver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"net/url"
"strings"

"go.opentelemetry.io/collector/config/confighttp"
"go.opentelemetry.io/collector/config/configopaque"
Expand Down Expand Up @@ -47,6 +48,10 @@ func (c *Config) Validate() error {
return err
}

if strings.TrimSpace(c.RLPGateway.ShardID) == "" {
TylerHelmuth marked this conversation as resolved.
Show resolved Hide resolved
return errors.New("shardID cannot be empty")
}

err = validateURLOption("uaa.endpoint", c.UAA.Endpoint)
if err != nil {
return err
Expand Down
33 changes: 33 additions & 0 deletions receiver/cloudfoundryreceiver/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,31 @@ func TestLoadConfig(t *testing.T) {
id: component.NewIDWithName(metadata.Type, "invalid"),
errorMessage: "failed to parse rlp_gateway.endpoint as url: parse \"https://[invalid\": missing ']' in host",
},
{
id: component.NewIDWithName(metadata.Type, "shardidnotdefined"),
expected: &Config{
RLPGateway: RLPGatewayConfig{
ClientConfig: confighttp.ClientConfig{
Endpoint: "https://log-stream.sys.example.internal",
TLSSetting: configtls.ClientConfig{
InsecureSkipVerify: true,
},
Timeout: time.Second * 20,
},
ShardID: "opentelemetry",
},
UAA: UAAConfig{
LimitedClientConfig: LimitedClientConfig{
Endpoint: "https://uaa.sys.example.internal",
TLSSetting: LimitedTLSClientSetting{
InsecureSkipVerify: true,
},
},
Username: "admin",
Password: "test",
},
},
},
}
for _, tt := range tests {
t.Run(tt.id.String(), func(t *testing.T) {
Expand Down Expand Up @@ -96,6 +121,14 @@ func TestInvalidConfigValidation(t *testing.T) {
configuration.UAA.Password = ""
require.Error(t, configuration.Validate())

configuration = loadSuccessfulConfig(t)
configuration.RLPGateway.ShardID = ""
require.Error(t, configuration.Validate())

jriguera marked this conversation as resolved.
Show resolved Hide resolved
configuration = loadSuccessfulConfig(t)
configuration.RLPGateway.ShardID = ""
require.Error(t, configuration.Validate())

configuration = loadSuccessfulConfig(t)
configuration.UAA.Endpoint = "https://[invalid"
require.Error(t, configuration.Validate())
Expand Down
60 changes: 59 additions & 1 deletion receiver/cloudfoundryreceiver/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
package cloudfoundryreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/cloudfoundryreceiver"

import (
"strings"
"time"

"code.cloudfoundry.org/go-loggregator/rpc/loggregator_v2"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/otel/trace"
)

const (
Expand All @@ -19,7 +22,6 @@ func convertEnvelopeToMetrics(envelope *loggregator_v2.Envelope, metricSlice pme
namePrefix := envelope.Tags["origin"] + "."

switch message := envelope.Message.(type) {
case *loggregator_v2.Envelope_Log:
case *loggregator_v2.Envelope_Counter:
metric := metricSlice.AppendEmpty()
metric.SetName(namePrefix + message.Counter.GetName())
Expand All @@ -41,6 +43,27 @@ func convertEnvelopeToMetrics(envelope *loggregator_v2.Envelope, metricSlice pme
}
}

func convertEnvelopeToLogs(envelope *loggregator_v2.Envelope, logSlice plog.LogRecordSlice, startTime time.Time) {
switch envelope.Message.(type) {
case *loggregator_v2.Envelope_Log:
log := logSlice.AppendEmpty()
log.SetTimestamp(pcommon.Timestamp(envelope.GetTimestamp()))
log.SetObservedTimestamp(pcommon.NewTimestampFromTime(startTime))
log.Body().SetStr(string(envelope.GetLog().GetPayload()))
switch envelope.GetLog().GetType() {
case loggregator_v2.Log_OUT:
log.SetSeverityText(plog.SeverityNumberInfo.String())
log.SetSeverityNumber(plog.SeverityNumberInfo)
case loggregator_v2.Log_ERR:
log.SetSeverityText(plog.SeverityNumberError.String())
log.SetSeverityNumber(plog.SeverityNumberError)
}
copyEnvelopeAttributes(log.Attributes(), envelope)
_ = parseLogTracingFields(log)
default:
jriguera marked this conversation as resolved.
Show resolved Hide resolved
}
}

func copyEnvelopeAttributes(attributes pcommon.Map, envelope *loggregator_v2.Envelope) {
for key, value := range envelope.Tags {
attributes.PutStr(attributeNamePrefix+key, value)
Expand All @@ -54,3 +77,38 @@ func copyEnvelopeAttributes(attributes pcommon.Map, envelope *loggregator_v2.Env
attributes.PutStr(attributeNamePrefix+"instance_id", envelope.InstanceId)
}
}

func parseLogTracingFields(log plog.LogRecord) error {
jriguera marked this conversation as resolved.
Show resolved Hide resolved
if value, found := log.Attributes().Get("org.cloudfoundry.source_type"); !found || value.AsString() != "RTR" {
return nil
}
s := log.Body().AsString()
quoted := false
a := strings.FieldsFunc(s, func(r rune) bool {
if r == '"' {
quoted = !quoted
}
return !quoted && r == ' '
})

traceIDStr := strings.Split(a[21], ":")[1]
traceIDStr = strings.Trim(traceIDStr, "\"")

spanIDStr := strings.Split(a[22], ":")[1]
spanIDStr = strings.Trim(spanIDStr, "\"")

traceID, err := trace.TraceIDFromHex(traceIDStr)
if err != nil {
return err
jriguera marked this conversation as resolved.
Show resolved Hide resolved
}

spanID, err := trace.SpanIDFromHex(spanIDStr)
if err != nil {
return err
}

log.SetTraceID([16]byte(traceID))
log.SetSpanID([8]byte(spanID))

return nil
}
45 changes: 45 additions & 0 deletions receiver/cloudfoundryreceiver/converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/pdata/pmetric"
)

Expand Down Expand Up @@ -142,6 +143,50 @@ func TestConvertGaugeEnvelope(t *testing.T) {
assertAttributes(t, dataPoint.Attributes(), expectedAttributes)
}

func TestConvertLogsEnvelope(t *testing.T) {
now := time.Now()
before := time.Now().Add(-time.Second)

envelope := loggregator_v2.Envelope{
Timestamp: before.UnixNano(),
SourceId: "uaa",
Tags: map[string]string{
"origin": "gorouter",
"deployment": "cf",
"job": "router",
"index": "bc276108-8282-48a5-bae7-c009c4392246",
"ip": "10.244.0.34",
},
Message: &loggregator_v2.Envelope_Log{
Log: &loggregator_v2.Log{
Payload: []byte("log message payload"),
Type: loggregator_v2.Log_OUT,
},
},
}

logSlice := plog.NewLogRecordSlice()

convertEnvelopeToLogs(&envelope, logSlice, now)

require.Equal(t, 1, logSlice.Len())

log := logSlice.At(0)
assert.Equal(t, "log message payload", log.Body().AsString())
assert.Equal(t, plog.SeverityNumberInfo.String(), log.SeverityText())
assert.Equal(t, pcommon.NewTimestampFromTime(before), log.Timestamp())
assert.Equal(t, pcommon.NewTimestampFromTime(now), log.ObservedTimestamp())

assertAttributes(t, log.Attributes(), map[string]string{
"org.cloudfoundry.source_id": "uaa",
"org.cloudfoundry.origin": "gorouter",
"org.cloudfoundry.deployment": "cf",
"org.cloudfoundry.job": "router",
"org.cloudfoundry.index": "bc276108-8282-48a5-bae7-c009c4392246",
"org.cloudfoundry.ip": "10.244.0.34",
})
}

func assertAttributes(t *testing.T, attributes pcommon.Map, expected map[string]string) {
assert.Equal(t, len(expected), attributes.Len())

Expand Down
2 changes: 1 addition & 1 deletion receiver/cloudfoundryreceiver/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//go:generate mdatagen metadata.yaml

// Package cloudfoundryreceiver implements a receiver that can be used by the
// Opentelemetry collector to receive Cloud Foundry metrics via its Reverse
// Opentelemetry collector to receive Cloud Foundry metrics and logs via its Reverse
jriguera marked this conversation as resolved.
Show resolved Hide resolved
// Log Proxy (RLP) Gateway component. The protocol is handled by the
// go-loggregator library, which uses HTTP to connect to the gateway and receive
// JSON-protobuf encoded v2 Envelope messages as documented by loggregator-api.
Expand Down
15 changes: 13 additions & 2 deletions receiver/cloudfoundryreceiver/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ func NewFactory() receiver.Factory {
return receiver.NewFactory(
metadata.Type,
createDefaultConfig,
receiver.WithMetrics(createMetricsReceiver, metadata.MetricsStability))
receiver.WithMetrics(createMetricsReceiver, metadata.MetricsStability),
receiver.WithLogs(createLogsReceiver, metadata.LogsStability))
}

func createDefaultConfig() component.Config {
Expand Down Expand Up @@ -61,5 +62,15 @@ func createMetricsReceiver(
nextConsumer consumer.Metrics,
) (receiver.Metrics, error) {
c := cfg.(*Config)
return newCloudFoundryReceiver(params, *c, nextConsumer)
return newCloudFoundryMetricsReceiver(params, *c, nextConsumer)
}

func createLogsReceiver(
_ context.Context,
params receiver.CreateSettings,
cfg component.Config,
nextConsumer consumer.Logs,
) (receiver.Logs, error) {
c := cfg.(*Config)
return newCloudFoundryLogsReceiver(params, *c, nextConsumer)
}
14 changes: 12 additions & 2 deletions receiver/cloudfoundryreceiver/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,22 @@ func TestCreateDefaultConfig(t *testing.T) {
assert.NoError(t, componenttest.CheckConfigStruct(cfg))
}

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

params := receivertest.NewNopCreateSettings()
tReceiver, err := factory.CreateMetricsReceiver(context.Background(), params, cfg, consumertest.NewNop())
assert.NoError(t, err)
assert.NotNil(t, tReceiver, "receiver creation failed")
assert.NotNil(t, tReceiver, "metrics receiver creation failed")
}

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

params := receivertest.NewNopCreateSettings()
tReceiver, err := factory.CreateLogsReceiver(context.Background(), params, cfg, consumertest.NewNop())
assert.NoError(t, err)
assert.NotNil(t, tReceiver, "logs receiver creation failed")
}
7 changes: 7 additions & 0 deletions receiver/cloudfoundryreceiver/generated_component_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions receiver/cloudfoundryreceiver/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ status:
class: receiver
stability:
beta: [metrics]
development: [logs]
distributions: [contrib]
codeowners:
active: [pellared, crobert-1]
Expand Down
Loading
Loading