Skip to content

Commit 45f97af

Browse files
committed
[processor/transform] Add support for profiles
1 parent 579ce11 commit 45f97af

File tree

19 files changed

+1981
-37
lines changed

19 files changed

+1981
-37
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: transformprocessor
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add profiles support to transformprocessor.
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [39009]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

processor/transformprocessor/README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
<!-- status autogenerated section -->
33
| Status | |
44
| ------------- |-----------|
5-
| Stability | [alpha]: traces, metrics, logs |
5+
| Stability | [development]: profiles |
6+
| | [alpha]: traces, metrics, logs |
67
| Distributions | [contrib], [k8s] |
78
| Warnings | [Unsound Transformations, Identity Conflict, Orphaned Telemetry, Other](#warnings) |
89
| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aprocessor%2Ftransform%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aprocessor%2Ftransform) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aprocessor%2Ftransform%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aprocessor%2Ftransform) |
910
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@TylerHelmuth](https://www.github.com/TylerHelmuth), [@kentquirk](https://www.github.com/kentquirk), [@bogdandrutu](https://www.github.com/bogdandrutu), [@evan-bradley](https://www.github.com/evan-bradley), [@edmocosta](https://www.github.com/edmocosta) |
1011

12+
[development]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#development
1113
[alpha]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#alpha
1214
[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib
1315
[k8s]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-k8s
@@ -42,19 +44,20 @@ transform:
4244
<trace|metric|log>_statements: []
4345
```
4446
45-
The Transform Processor's primary configuration section is broken down by signal (traces, metrics, and logs)
47+
The Transform Processor's primary configuration section is broken down by signal (traces, metrics, logs, and profiles)
4648
and allows you to configure a list of statements for the processor to execute. The list can be made of:
4749
4850
- OTTL statements. This option will meet most user's needs. See [Basic Config](#basic-config) for more details.
4951
- Objects, which allows users to apply configuration options to a specific list of statements. See [Advanced Config](#advanced-config) for more details.
5052
5153
Within each `<signal_statements>` list, only certain OTTL Path prefixes can be used:
5254

53-
| Signal | Path Prefix Values |
54-
|-------------------|------------------------------------------------|
55-
| trace_statements | `resource`, `scope`, `span`, and `spanevent` |
56-
| metric_statements | `resource`, `scope`, `metric`, and `datapoint` |
57-
| log_statements | `resource`, `scope`, and `log` |
55+
| Signal | Path Prefix Values |
56+
|--------------------|------------------------------------------------|
57+
| trace_statements | `resource`, `scope`, `span`, and `spanevent` |
58+
| metric_statements | `resource`, `scope`, `metric`, and `datapoint` |
59+
| log_statements | `resource`, `scope`, and `log` |
60+
| profile_statements | `resource`, `scope`, and `profile` |
5861

5962
This means, for example, that you cannot use the Path `span.attributes` within the `log_statements` configuration section.
6063

processor/transformprocessor/config.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/common"
1919
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/logs"
2020
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/metrics"
21+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/profiles"
2122
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/traces"
2223
)
2324

@@ -39,9 +40,10 @@ type Config struct {
3940
// The default value is `propagate`.
4041
ErrorMode ottl.ErrorMode `mapstructure:"error_mode"`
4142

42-
TraceStatements []common.ContextStatements `mapstructure:"trace_statements"`
43-
MetricStatements []common.ContextStatements `mapstructure:"metric_statements"`
44-
LogStatements []common.ContextStatements `mapstructure:"log_statements"`
43+
TraceStatements []common.ContextStatements `mapstructure:"trace_statements"`
44+
MetricStatements []common.ContextStatements `mapstructure:"metric_statements"`
45+
LogStatements []common.ContextStatements `mapstructure:"log_statements"`
46+
ProfileStatements []common.ContextStatements `mapstructure:"profile_statements"`
4547

4648
FlattenData bool `mapstructure:"flatten_data"`
4749
logger *zap.Logger
@@ -72,9 +74,10 @@ func (c *Config) Unmarshal(conf *confmap.Conf) error {
7274
}
7375

7476
contextStatementsFields := map[string]*[]common.ContextStatements{
75-
"trace_statements": &c.TraceStatements,
76-
"metric_statements": &c.MetricStatements,
77-
"log_statements": &c.LogStatements,
77+
"trace_statements": &c.TraceStatements,
78+
"metric_statements": &c.MetricStatements,
79+
"log_statements": &c.LogStatements,
80+
"profile_statements": &c.ProfileStatements,
7881
}
7982

8083
contextStatementsPatch := map[string]any{}
@@ -171,6 +174,19 @@ func (c *Config) Validate() error {
171174
}
172175
}
173176

177+
if len(c.ProfileStatements) > 0 {
178+
pc, err := common.NewProfileParserCollection(component.TelemetrySettings{Logger: zap.NewNop()}, common.WithProfileParser(profiles.ProfileFunctions()))
179+
if err != nil {
180+
return err
181+
}
182+
for _, cs := range c.ProfileStatements {
183+
_, err = pc.ParseContextStatements(cs)
184+
if err != nil {
185+
errors = multierr.Append(errors, err)
186+
}
187+
}
188+
}
189+
174190
if c.FlattenData && !flatLogsFeatureGate.IsEnabled() {
175191
errors = multierr.Append(errors, errFlatLogsGateDisabled)
176192
}

processor/transformprocessor/config_test.go

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ func TestLoadConfig(t *testing.T) {
7575
},
7676
},
7777
},
78+
ProfileStatements: []common.ContextStatements{
79+
{
80+
Context: "profile",
81+
Statements: []string{
82+
`set(original_payload_format, "bear") where attributes["http.path"] == "/animal"`,
83+
`keep_keys(attributes, ["http.method", "http.path"])`,
84+
},
85+
},
86+
{
87+
Context: "resource",
88+
Statements: []string{
89+
`set(attributes["name"], "bear")`,
90+
},
91+
},
92+
},
7893
},
7994
},
8095
{
@@ -108,6 +123,15 @@ func TestLoadConfig(t *testing.T) {
108123
},
109124
},
110125
},
126+
ProfileStatements: []common.ContextStatements{
127+
{
128+
Context: "profile",
129+
Conditions: []string{`attributes["http.path"] == "/animal"`},
130+
Statements: []string{
131+
`set(original_payload_format, "bear")`,
132+
},
133+
},
134+
},
111135
},
112136
},
113137
{
@@ -122,8 +146,9 @@ func TestLoadConfig(t *testing.T) {
122146
},
123147
},
124148
},
125-
MetricStatements: []common.ContextStatements{},
126-
LogStatements: []common.ContextStatements{},
149+
MetricStatements: []common.ContextStatements{},
150+
LogStatements: []common.ContextStatements{},
151+
ProfileStatements: []common.ContextStatements{},
127152
},
128153
},
129154
{
@@ -144,6 +169,12 @@ func TestLoadConfig(t *testing.T) {
144169
{
145170
id: component.NewIDWithName(metadata.Type, "unknown_function_log"),
146171
},
172+
{
173+
id: component.NewIDWithName(metadata.Type, "bad_syntax_profile"),
174+
},
175+
{
176+
id: component.NewIDWithName(metadata.Type, "unknown_function_profile"),
177+
},
147178
{
148179
id: component.NewIDWithName(metadata.Type, "bad_syntax_multi_signal"),
149180
errors: []error{
@@ -174,6 +205,12 @@ func TestLoadConfig(t *testing.T) {
174205
Statements: []string{`set(log.body, "bear") where log.attributes["http.path"] == "/animal"`},
175206
},
176207
},
208+
ProfileStatements: []common.ContextStatements{
209+
{
210+
Context: "profile",
211+
Statements: []string{`set(profile.original_payload_format, "bear") where profile.attributes["http.path"] == "/animal"`},
212+
},
213+
},
177214
},
178215
},
179216
{
@@ -204,6 +241,14 @@ func TestLoadConfig(t *testing.T) {
204241
},
205242
},
206243
},
244+
ProfileStatements: []common.ContextStatements{
245+
{
246+
Statements: []string{
247+
`set(profile.original_payload_format, "bear") where profile.attributes["http.path"] == "/animal"`,
248+
`set(resource.attributes["name"], "bear")`,
249+
},
250+
},
251+
},
207252
},
208253
},
209254
{
@@ -234,6 +279,14 @@ func TestLoadConfig(t *testing.T) {
234279
},
235280
},
236281
},
282+
ProfileStatements: []common.ContextStatements{
283+
{
284+
Statements: []string{
285+
`set(profile.original_payload_format, "bear") where profile.attributes["http.path"] == "/animal"`,
286+
`set(resource.attributes["name"], "bear")`,
287+
},
288+
},
289+
},
237290
},
238291
},
239292
{
@@ -270,6 +323,16 @@ func TestLoadConfig(t *testing.T) {
270323
ErrorMode: "",
271324
},
272325
},
326+
ProfileStatements: []common.ContextStatements{
327+
{
328+
Statements: []string{`set(resource.attributes["name"], "propagate")`},
329+
ErrorMode: ottl.PropagateError,
330+
},
331+
{
332+
Statements: []string{`set(resource.attributes["name"], "ignore")`},
333+
ErrorMode: "",
334+
},
335+
},
273336
},
274337
},
275338
}

processor/transformprocessor/factory.go

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,41 @@ import (
99

1010
"go.opentelemetry.io/collector/component"
1111
"go.opentelemetry.io/collector/consumer"
12+
"go.opentelemetry.io/collector/consumer/xconsumer"
1213
"go.opentelemetry.io/collector/processor"
1314
"go.opentelemetry.io/collector/processor/processorhelper"
15+
"go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper"
16+
"go.opentelemetry.io/collector/processor/xprocessor"
1417

1518
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
1619
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/common"
1720
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/logs"
1821
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/metadata"
1922
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/metrics"
23+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/profiles"
2024
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor/internal/traces"
2125
)
2226

2327
var processorCapabilities = consumer.Capabilities{MutatesData: true}
2428

2529
func NewFactory() processor.Factory {
26-
return processor.NewFactory(
30+
return xprocessor.NewFactory(
2731
metadata.Type,
2832
createDefaultConfig,
29-
processor.WithLogs(createLogsProcessor, metadata.LogsStability),
30-
processor.WithTraces(createTracesProcessor, metadata.TracesStability),
31-
processor.WithMetrics(createMetricsProcessor, metadata.MetricsStability),
33+
xprocessor.WithLogs(createLogsProcessor, metadata.LogsStability),
34+
xprocessor.WithTraces(createTracesProcessor, metadata.TracesStability),
35+
xprocessor.WithMetrics(createMetricsProcessor, metadata.MetricsStability),
36+
xprocessor.WithProfiles(createProfilesProcessor, metadata.ProfilesStability),
3237
)
3338
}
3439

3540
func createDefaultConfig() component.Config {
3641
return &Config{
37-
ErrorMode: ottl.PropagateError,
38-
TraceStatements: []common.ContextStatements{},
39-
MetricStatements: []common.ContextStatements{},
40-
LogStatements: []common.ContextStatements{},
42+
ErrorMode: ottl.PropagateError,
43+
TraceStatements: []common.ContextStatements{},
44+
MetricStatements: []common.ContextStatements{},
45+
LogStatements: []common.ContextStatements{},
46+
ProfileStatements: []common.ContextStatements{},
4147
}
4248
}
4349

@@ -104,3 +110,25 @@ func createMetricsProcessor(
104110
proc.ProcessMetrics,
105111
processorhelper.WithCapabilities(processorCapabilities))
106112
}
113+
114+
func createProfilesProcessor(
115+
ctx context.Context,
116+
set processor.Settings,
117+
cfg component.Config,
118+
nextConsumer xconsumer.Profiles,
119+
) (xprocessor.Profiles, error) {
120+
oCfg := cfg.(*Config)
121+
oCfg.logger = set.Logger
122+
123+
proc, err := profiles.NewProcessor(oCfg.ProfileStatements, oCfg.ErrorMode, set.TelemetrySettings)
124+
if err != nil {
125+
return nil, fmt.Errorf("invalid config for \"transform\" processor %w", err)
126+
}
127+
return xprocessorhelper.NewProfiles(
128+
ctx,
129+
set,
130+
cfg,
131+
nextConsumer,
132+
proc.ProcessProfiles,
133+
xprocessorhelper.WithCapabilities(processorCapabilities))
134+
}

0 commit comments

Comments
 (0)