Skip to content

Commit

Permalink
[receiver/cloudfoundry]: move datapoint level attributes to resource …
Browse files Browse the repository at this point in the history
…level

Signed-off-by: odubajDT <[email protected]>
  • Loading branch information
odubajDT committed Nov 7, 2024
1 parent 5032867 commit 3aca4ad
Show file tree
Hide file tree
Showing 8 changed files with 1,063 additions and 95 deletions.
27 changes: 27 additions & 0 deletions .chloggen/move-attributes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: breaking

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: cloudfoundryreceiver

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Introduce a feature gate enable copying envelope tags to the metrics as resource attributes instead of datapoint attributes.

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [34824]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
33 changes: 32 additions & 1 deletion receiver/cloudfoundryreceiver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,35 @@ The receiver maps the envelope attribute tags to the following OpenTelemetry att
* `instance_id` - numerical index of the origin. If origin is `rep` (`source_type` is `APP`) this is the application index. However, for other cases this is the instance index.
* `process_id` - process ID (GUID)
* `process_instance_id` - unique ID of a process instance, should be treated as an opaque string
* `process_type` - process type. Each application has exactly one process of type `web`, but many have any number of other processes
* `process_type` - process type. Each application has exactly one process of type `web`, but many have any number of other processes

## Feature Gate

### `cloudfoundry.resourceAttributes.allow`

#### Purpose

The `cloudfoundry.resourceAttributes.allow` [feature gate](https://github.com/open-telemetry/opentelemetry-collector/blob/main/featuregate/README.md#collector-feature-gates) allows the envelope tags being copied to the metrics as resource attributes instead of datapoint attributes (default `false`).
Therefore all `org.cloudfoundry.*` datapoint attributes won't be present anymore on metrics datapoint level, but on resource level instead, since the attributes describe the resource and not the datapoints itself.

The `cloudfoundry.resourceAttributes.allow` feature gate is available since version `v0.109.0` and will be held at least for 2 versions (`v0.111.0`) until promoting to `beta` and another 2 vesions (`v0.113.0`) until promoting to `stable`.

Below you can see the list of attributes that are present the resource level instead of datapoint level (when `cloudfoundry.resourceAttributes.allow` feature gate is enabled):

```
- org.cloudfoundry.index
- org.cloudfoundry.ip
- org.cloudfoundry.deployment
- org.cloudfoundry.id
- org.cloudfoundry.job
- org.cloudfoundry.product
- org.cloudfoundry.instance_group
- org.cloudfoundry.instance_id
- org.cloudfoundry.origin
- org.cloudfoundry.system_domain
- org.cloudfoundry.source_id
- org.cloudfoundry.source_type
- org.cloudfoundry.process_type
- org.cloudfoundry.process_id
- org.cloudfoundry.process_instance_id
```
74 changes: 71 additions & 3 deletions receiver/cloudfoundryreceiver/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ package cloudfoundryreceiver // import "github.com/open-telemetry/opentelemetry-

import (
"fmt"
"slices"
"time"

"code.cloudfoundry.org/go-loggregator/rpc/loggregator_v2"
"go.opentelemetry.io/collector/featuregate"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/pdata/pmetric"
Expand All @@ -17,6 +19,31 @@ const (
attributeNamePrefix = "org.cloudfoundry."
)

var ResourceAttributesKeys = []string{
"index",
"ip",
"deployment",
"id",
"job",
"product",
"instance_group",
"instance_id",
"origin",
"system_domain",
"source_id",
"source_type",
"process_type",
"process_id",
"process_instance_id",
}

var allowResourceAttributes = featuregate.GlobalRegistry().MustRegister(
"cloudfoundry.resourceAttributes.allow",
featuregate.StageAlpha,
featuregate.WithRegisterDescription("When enabled, envelope tags are copied to the metrics as resource attributes instead of datapoint attributes"),
featuregate.WithRegisterFromVersion("v0.109.0"),
)

func convertEnvelopeToMetrics(envelope *loggregator_v2.Envelope, metricSlice pmetric.MetricSlice, startTime time.Time) {
namePrefix := envelope.Tags["origin"] + "."

Expand All @@ -28,7 +55,12 @@ func convertEnvelopeToMetrics(envelope *loggregator_v2.Envelope, metricSlice pme
dataPoint.SetDoubleValue(float64(message.Counter.GetTotal()))
dataPoint.SetTimestamp(pcommon.Timestamp(envelope.GetTimestamp()))
dataPoint.SetStartTimestamp(pcommon.NewTimestampFromTime(startTime))
copyEnvelopeAttributes(dataPoint.Attributes(), envelope)
if allowResourceAttributes.IsEnabled() {
attrs := getEnvelopeDatapointAttributes(envelope)
attrs.CopyTo(dataPoint.Attributes())
} else {
copyEnvelopeAttributes(dataPoint.Attributes(), envelope)
}
case *loggregator_v2.Envelope_Gauge:
for name, value := range message.Gauge.GetMetrics() {
metric := metricSlice.AppendEmpty()
Expand All @@ -37,7 +69,12 @@ func convertEnvelopeToMetrics(envelope *loggregator_v2.Envelope, metricSlice pme
dataPoint.SetDoubleValue(value.Value)
dataPoint.SetTimestamp(pcommon.Timestamp(envelope.GetTimestamp()))
dataPoint.SetStartTimestamp(pcommon.NewTimestampFromTime(startTime))
copyEnvelopeAttributes(dataPoint.Attributes(), envelope)
if allowResourceAttributes.IsEnabled() {
attrs := getEnvelopeDatapointAttributes(envelope)
attrs.CopyTo(dataPoint.Attributes())
} else {
copyEnvelopeAttributes(dataPoint.Attributes(), envelope)
}
}
}
}
Expand All @@ -59,7 +96,12 @@ func convertEnvelopeToLogs(envelope *loggregator_v2.Envelope, logSlice plog.LogR
default:
return fmt.Errorf("unsupported envelope log type: %s", envelope.GetLog().GetType())
}
copyEnvelopeAttributes(log.Attributes(), envelope)
if allowResourceAttributes.IsEnabled() {
attrs := getEnvelopeDatapointAttributes(envelope)
attrs.CopyTo(log.Attributes())
} else {
copyEnvelopeAttributes(log.Attributes(), envelope)
}
return nil
}

Expand All @@ -74,3 +116,29 @@ func copyEnvelopeAttributes(attributes pcommon.Map, envelope *loggregator_v2.Env
attributes.PutStr(attributeNamePrefix+"instance_id", envelope.InstanceId)
}
}

func getEnvelopeDatapointAttributes(envelope *loggregator_v2.Envelope) pcommon.Map {
attrs := pcommon.NewMap()
for key, value := range envelope.Tags {
if !slices.Contains(ResourceAttributesKeys, key) {
attrs.PutStr(attributeNamePrefix+key, value)
}
}
return attrs
}

func getEnvelopeResourceAttributes(envelope *loggregator_v2.Envelope) pcommon.Map {
attrs := pcommon.NewMap()
for key, value := range envelope.Tags {
if slices.Contains(ResourceAttributesKeys, key) {
attrs.PutStr(attributeNamePrefix+key, value)
}
}
if envelope.SourceId != "" {
attrs.PutStr(attributeNamePrefix+"source_id", envelope.SourceId)
}
if envelope.InstanceId != "" {
attrs.PutStr(attributeNamePrefix+"instance_id", envelope.InstanceId)
}
return attrs
}
Loading

0 comments on commit 3aca4ad

Please sign in to comment.