Skip to content

Commit 95ee2fc

Browse files
committed
[processor/transform] Add support for profiles
1 parent 7396e40 commit 95ee2fc

File tree

17 files changed

+1856
-33
lines changed

17 files changed

+1856
-33
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: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,20 @@ transform:
4646
<trace|metric|log>_statements: []
4747
```
4848
49-
The Transform Processor's primary configuration section is broken down by signal (traces, metrics, and logs)
49+
The Transform Processor's primary configuration section is broken down by signal (traces, metrics, logs, and profiles)
5050
and allows you to configure a list of statements for the processor to execute. The list can be made of:
5151
5252
- OTTL statements. This option will meet most user's needs. See [Basic Config](#basic-config) for more details.
5353
- Objects, which allows users to apply configuration options to a specific list of statements. See [Advanced Config](#advanced-config) for more details.
5454
5555
Within each `<signal_statements>` list, only certain OTTL Path prefixes can be used:
5656

57-
| Signal | Path Prefix Values |
58-
|-------------------|------------------------------------------------|
59-
| trace_statements | `resource`, `scope`, `span`, and `spanevent` |
60-
| metric_statements | `resource`, `scope`, `metric`, and `datapoint` |
61-
| log_statements | `resource`, `scope`, and `log` |
57+
| Signal | Path Prefix Values |
58+
|--------------------|------------------------------------------------|
59+
| trace_statements | `resource`, `scope`, `span`, and `spanevent` |
60+
| metric_statements | `resource`, `scope`, `metric`, and `datapoint` |
61+
| log_statements | `resource`, `scope`, and `log` |
62+
| profile_statements | `resource`, `scope`, and `profile` |
6263

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

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: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ 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 original_payload_format == "/animal"`,
83+
},
84+
},
85+
{
86+
Context: "resource",
87+
Statements: []string{
88+
`set(attributes["name"], "bear")`,
89+
},
90+
},
91+
},
7892
},
7993
},
8094
{
@@ -108,6 +122,15 @@ func TestLoadConfig(t *testing.T) {
108122
},
109123
},
110124
},
125+
ProfileStatements: []common.ContextStatements{
126+
{
127+
Context: "profile",
128+
Conditions: []string{`original_payload_format == "/animal"`},
129+
Statements: []string{
130+
`set(original_payload_format, "bear")`,
131+
},
132+
},
133+
},
111134
},
112135
},
113136
{
@@ -122,8 +145,9 @@ func TestLoadConfig(t *testing.T) {
122145
},
123146
},
124147
},
125-
MetricStatements: []common.ContextStatements{},
126-
LogStatements: []common.ContextStatements{},
148+
MetricStatements: []common.ContextStatements{},
149+
LogStatements: []common.ContextStatements{},
150+
ProfileStatements: []common.ContextStatements{},
127151
},
128152
},
129153
{
@@ -144,6 +168,12 @@ func TestLoadConfig(t *testing.T) {
144168
{
145169
id: component.NewIDWithName(metadata.Type, "unknown_function_log"),
146170
},
171+
{
172+
id: component.NewIDWithName(metadata.Type, "bad_syntax_profile"),
173+
},
174+
{
175+
id: component.NewIDWithName(metadata.Type, "unknown_function_profile"),
176+
},
147177
{
148178
id: component.NewIDWithName(metadata.Type, "bad_syntax_multi_signal"),
149179
errors: []error{
@@ -174,6 +204,12 @@ func TestLoadConfig(t *testing.T) {
174204
Statements: []string{`set(log.body, "bear") where log.attributes["http.path"] == "/animal"`},
175205
},
176206
},
207+
ProfileStatements: []common.ContextStatements{
208+
{
209+
Context: "profile",
210+
Statements: []string{`set(profile.original_payload_format, "bear") where profile.original_payload_format == "/animal"`},
211+
},
212+
},
177213
},
178214
},
179215
{
@@ -204,6 +240,14 @@ func TestLoadConfig(t *testing.T) {
204240
},
205241
},
206242
},
243+
ProfileStatements: []common.ContextStatements{
244+
{
245+
Statements: []string{
246+
`set(profile.original_payload_format, "bear") where profile.original_payload_format == "/animal"`,
247+
`set(resource.attributes["name"], "bear")`,
248+
},
249+
},
250+
},
207251
},
208252
},
209253
{
@@ -234,6 +278,14 @@ func TestLoadConfig(t *testing.T) {
234278
},
235279
},
236280
},
281+
ProfileStatements: []common.ContextStatements{
282+
{
283+
Statements: []string{
284+
`set(profile.original_payload_format, "bear") where profile.original_payload_format == "/animal"`,
285+
`set(resource.attributes["name"], "bear")`,
286+
},
287+
},
288+
},
237289
},
238290
},
239291
{
@@ -270,6 +322,16 @@ func TestLoadConfig(t *testing.T) {
270322
ErrorMode: "",
271323
},
272324
},
325+
ProfileStatements: []common.ContextStatements{
326+
{
327+
Statements: []string{`set(resource.attributes["name"], "propagate")`},
328+
ErrorMode: ottl.PropagateError,
329+
},
330+
{
331+
Statements: []string{`set(resource.attributes["name"], "ignore")`},
332+
ErrorMode: "",
333+
},
334+
},
273335
},
274336
},
275337
}

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)