Skip to content

Commit b4efd26

Browse files
jmacdCopilotmx-psievan-bradley
authored
[exporterhelper] Add pkg.exporterhelper.queueBatchEnabled feature gate (#15690)
#### Description Adds a new feature gate for batching by default in exporterhelper. Updates the RFC and timeline, we are not ready to transition to Phase 2 on the stated schedule. #### Link to tracking issue Part of #14038 Fixes #13582 Part of #12022 #### Testing ✅ #### Documentation ✅ #### Authorship - [x] I, a human, wrote this pull request description myself. Assisted-by: Claude Opus 5 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Pablo Baeyens <pablo.baeyens@datadoghq.com> Co-authored-by: Evan Bradley <11745660+evan-bradley@users.noreply.github.com>
1 parent 6321378 commit b4efd26

8 files changed

Lines changed: 114 additions & 40 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
change_type: enhancement
2+
3+
component: pkg/exporterhelper
4+
5+
note: Add the `pkg.exporterhelper.queueBatchEnabled` feature gate
6+
7+
issues: [14038, 13582, 12022]
8+
9+
subtext: |
10+
When enabled, the batch settings returned by `NewDefaultQueueConfig()` have
11+
`batch::enabled` true. See [migration RFC](https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/rfcs/batching-migration.md#phase-1).
12+
13+
change_logs: [user]

docs/rfcs/batching-migration.md

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -177,44 +177,37 @@ the components, evaluating for every exporter whether a `Default` or
177177
`None` should become `Some` in each exporter's default queue config.
178178

179179
A feature flag for this change will be defined,
180-
`exporterhelper.exporterQueueBatchEnabled`.
180+
`pkg.exporterhelper.queueBatchEnabled`.
181181

182182
#### Recommended final default queue configuration
183183

184184
The `NewDefaultQueueConfig` function will begin being influenced by
185-
the `exporterhelper.exporterQueueBatchEnabled` feature flag. Only the
185+
the `pkg.exporterhelper.queueBatchEnabled` feature flag. Only the
186186
`Batch` field's default changes; `BlockOnOverflow` and `WaitForResult`
187187
remain `false`.
188188

189189
```go
190190
func NewDefaultQueueConfig() queuebatch.Config {
191+
batchCfg := queuebatch.BatchConfig{
192+
FlushTimeout: 200 * time.Millisecond,
193+
Sizer: request.SizerTypeItems,
194+
MinSize: 8192,
195+
}
196+
var batch configoptional.Optional[queuebatch.BatchConfig]
197+
if metadata.PkgExporterhelperQueueBatchEnabledFeatureGate.IsEnabled() {
198+
// CHANGED: Batching enabled by default under the feature gate.
199+
batch = configoptional.Some(batchCfg)
200+
} else {
201+
batch = configoptional.Default(batchCfg)
202+
}
191203
return queuebatch.Config{
192204
Sizer: request.SizerTypeRequests,
193205
NumConsumers: 10,
194206
QueueSize: 1_000,
195207
BlockOnOverflow: false,
196208
WaitForResult: false,
197-
Batch: configoptional.DefaultOrSome(
198-
// CHANGED: Batching is becoming enabled by default.
199-
exporterQueueBatchEnabled.IsEnabled(),
200-
queuebatch.BatchConfig{
201-
FlushTimeout: 200 * time.Millisecond,
202-
Sizer: request.SizerTypeItems,
203-
MinSize: 8192,
204-
}),
205-
}
206-
}
207-
```
208-
209-
The above makes use of an hypothetical `configoptional` helper:
210-
211-
```
212-
// DefaultOrSome ties a feature flag to a default-to-some transition.
213-
func DefaultOrSome[T any](feature bool, value T) Optional[T] {
214-
if feature {
215-
return Some(value)
209+
Batch: batch,
216210
}
217-
return Default(value)
218211
}
219212
```
220213

@@ -279,13 +272,13 @@ The sequence of events is ordered in phases. The following table
279272
summarizes what an operator running a typical pipeline observes at
280273
each phase:
281274

282-
| Phase | `batchprocessor` in config | exporterhelper defaults | Net behavior | Release version |
283-
|-------|--------------------------------------------------------------|----------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|
284-
| <1 | OK | `batch::enabled: false` | Documented behavior | |
285-
| 1 | OK | Unchanged; feature gate is Alpha (default off) | No change for users; new `queuebatchprocessor` and docs available for opt-in migration. | |
286-
| 2 | Works, prints deprecation warning pointing to migration docs | Unchanged; gate still Alpha/off | Users see warnings and have at least six releases to migrate; Helm chart switches to the new path while `batchprocessor` still works. Exit gated on early-adopter success. | v0.158.0 |
287-
| 3 | Removed from default distribution; still available to custom builds. Pipelines using the removed component in the default binary fail to start. | Gate Beta (default on): `batch::enabled: true` | Pipelines that didn't migrate fail fast; exporters batch by default; users can still opt out via gate for six releases. | v0.164.0 |
288-
| 4 | n/a | Gate Stable and removed; new default permanent | Users choose `exporterhelper` or `queuebatchprocessor` for batching | v0.170.0 |
275+
| Phase | `batchprocessor` in config | exporterhelper defaults | Net behavior | Release version |
276+
|-------|-------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|
277+
| <1 | OK | `batch::enabled: false` | Documented behavior | |
278+
| 1 | OK | Unchanged; feature gate is Alpha (default off) | No change for users; new `queuebatchprocessor` and docs available for opt-in migration. | v0.158.0+ |
279+
| 2 | Works, prints deprecation warning pointing to migration docs | Unchanged; gate still Alpha/off | Users see warnings and have at least six releases to migrate; Helm chart switches to the new path while `batchprocessor` still works. Exit gated on early-adopter success. | v0.160.0 |
280+
| 3 | Removed from default distribution; still available to custom builds. Pipelines using the removed component in the default binary fail to start. | Gate Beta (default on): `batch::enabled: true` | Pipelines that didn't migrate fail fast; exporters batch by default; users can still opt out via gate for six releases. | v0.166.0 |
281+
| 4 | n/a | Gate Stable and removed; new default permanent | Users choose `exporterhelper` or `queuebatchprocessor` for batching | v0.172.0 |
289282

290283
### Phase 1
291284

@@ -297,13 +290,12 @@ These are loosely dependent,
297290
config omits `queue_sender` or sets it to a non-standard value.
298291
Exporters that legitimately need different defaults (e.g., pull-based
299292
exporters) must declare the opt-out in their `metadata.yaml`.
300-
2. Introduce the `exporterhelper.exporterQueueBatchEnabled` feature
301-
gate at **Alpha** stability (default off).
293+
2. Introduce the `pkg.exporterhelper.queueBatchEnabled` feature
294+
gate at Alpha stability. [#15690](https://github.com/open-telemetry/opentelemetry-collector/pull/15690)
302295
3. Support a configurable metrics prefix to distinguish processor
303296
batching from exporter batching
304297
([#14038](https://github.com/open-telemetry/opentelemetry-collector/issues/14038)).
305-
4. Implement `queuebatchprocessor`
306-
([#13583](https://github.com/open-telemetry/opentelemetry-collector/pull/13583)).
298+
4. Implement `queuebatchprocessor`. [#15500](https://github.com/open-telemetry/opentelemetry-collector/pull/15500)
307299
5. Detect pipelines that combine `batchprocessor` with an
308300
exporterhelper that has batching enabled, and emit a startup warning
309301
identifying the affected pipeline and exporter. This protects users
@@ -317,10 +309,14 @@ These are loosely dependent,
317309
documentation. Create a blog post about what's happening to
318310
`batchprocessor`, get it approved.
319311

312+
#### Exit criteria for Phase 1
313+
314+
All of the above must be completed.
315+
320316
### Phase 2
321317

322318
7. Deprecate `batchprocessor`. Release the blog post. The first
323-
release where this lands is tentatively **v0.158.0** (August 2026).
319+
release where this lands is tentatively **v0.160.0** (September 2026).
324320
8. Full audit of exporters and default settings. Exporters can opt-in
325321
to the migration here by electing `Some` instead of `Default` or
326322
`None`. Exporters that do not want default blocking/batching will

exporter/exporterhelper/documentation.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,13 @@ Number of spans successfully sent to destination.
141141
| Unit | Metric Type | Value Type | Monotonic | Stability |
142142
| ---- | ----------- | ---------- | --------- | --------- |
143143
| {span} | Sum | Int | true | Alpha |
144+
145+
## Feature Gates
146+
147+
This component has the following feature gates:
148+
149+
| Feature Gate | Stage | Description | From Version | To Version | Reference |
150+
| ------------ | ----- | ----------- | ------------ | ---------- | --------- |
151+
| `pkg.exporterhelper.queueBatchEnabled` | alpha | Enables exporterhelper batching by default in NewDefaultQueueConfig, as described in the batching migration RFC. | v0.158.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector/issues/15047) |
152+
153+
For more information about feature gates, see the [Feature Gates](https://github.com/open-telemetry/opentelemetry-collector/blob/main/featuregate/README.md) documentation.

exporter/exporterhelper/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
go.opentelemetry.io/collector/exporter/exportertest v0.158.0
2020
go.opentelemetry.io/collector/extension/extensiontest v0.158.0
2121
go.opentelemetry.io/collector/extension/xextension v0.158.0
22+
go.opentelemetry.io/collector/featuregate v1.64.0
2223
go.opentelemetry.io/collector/internal/testutil v0.158.0
2324
go.opentelemetry.io/collector/pdata v1.64.0
2425
go.opentelemetry.io/collector/pdata/pprofile v0.158.0
@@ -60,7 +61,6 @@ require (
6061
go.opentelemetry.io/collector/consumer/xconsumer v0.158.0 // indirect
6162
go.opentelemetry.io/collector/exporter/xexporter v0.158.0 // indirect
6263
go.opentelemetry.io/collector/extension v1.64.0 // indirect
63-
go.opentelemetry.io/collector/featuregate v1.64.0 // indirect
6464
go.opentelemetry.io/collector/internal/componentalias v0.158.0 // indirect
6565
go.opentelemetry.io/collector/receiver v1.64.0 // indirect
6666
go.opentelemetry.io/collector/receiver/receivertest v0.158.0 // indirect

exporter/exporterhelper/internal/metadata/generated_feature_gates.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

exporter/exporterhelper/internal/queue_sender.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"go.uber.org/zap"
1111

1212
"go.opentelemetry.io/collector/config/configoptional"
13+
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadata"
1314
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/queuebatch"
1415
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/request"
1516
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/sender"
@@ -22,17 +23,28 @@ import (
2223
// - is non-blocking when full
2324
// - concurrent exports limited to 10
2425
// - emits batches of 8192 items, timeout 200ms
26+
//
27+
// Batching is disabled by default, unless the
28+
// pkg.exporterhelper.queueBatchEnabled feature gate is enabled. See
29+
// https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/rfcs/batching-migration.md.
2530
func NewDefaultQueueConfig() queuebatch.Config {
31+
batchCfg := queuebatch.BatchConfig{
32+
FlushTimeout: 200 * time.Millisecond,
33+
Sizer: request.SizerTypeItems,
34+
MinSize: 8192,
35+
}
36+
var batch configoptional.Optional[queuebatch.BatchConfig]
37+
if metadata.PkgExporterhelperQueueBatchEnabledFeatureGate.IsEnabled() {
38+
batch = configoptional.Some(batchCfg)
39+
} else {
40+
batch = configoptional.Default(batchCfg)
41+
}
2642
return queuebatch.Config{
2743
Sizer: request.SizerTypeRequests,
2844
NumConsumers: 10,
2945
QueueSize: 1_000,
3046
BlockOnOverflow: false,
31-
Batch: configoptional.Default(queuebatch.BatchConfig{
32-
FlushTimeout: 200 * time.Millisecond,
33-
Sizer: request.SizerTypeItems,
34-
MinSize: 8192,
35-
}),
47+
Batch: batch,
3648
}
3749
}
3850

exporter/exporterhelper/internal/queue_sender_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88
"errors"
99
"testing"
10+
"time"
1011

1112
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
@@ -16,11 +17,13 @@ import (
1617
"go.opentelemetry.io/collector/component"
1718
"go.opentelemetry.io/collector/component/componenttest"
1819
"go.opentelemetry.io/collector/config/configoptional"
20+
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadata"
1921
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/queuebatch"
2022
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/request"
2123
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/requesttest"
2224
"go.opentelemetry.io/collector/exporter/exporterhelper/internal/sender"
2325
"go.opentelemetry.io/collector/exporter/exportertest"
26+
"go.opentelemetry.io/collector/featuregate"
2427
"go.opentelemetry.io/collector/pipeline"
2528
)
2629

@@ -45,6 +48,24 @@ func TestNewQueueSenderFailedRequestDropped(t *testing.T) {
4548
assert.Equal(t, "Exporting failed. Dropping data.", observed.All()[0].Message)
4649
}
4750

51+
func TestNewDefaultQueueConfigBatchFeatureGate(t *testing.T) {
52+
// The batch config is present but not enabled by default.
53+
qCfg := NewDefaultQueueConfig()
54+
require.False(t, qCfg.Batch.HasValue())
55+
require.Equal(t, int64(8192), qCfg.Batch.GetOrInsertDefault().MinSize)
56+
57+
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.PkgExporterhelperQueueBatchEnabledFeatureGate.ID(), true))
58+
defer func() {
59+
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.PkgExporterhelperQueueBatchEnabledFeatureGate.ID(), false))
60+
}()
61+
62+
qCfg = NewDefaultQueueConfig()
63+
require.True(t, qCfg.Batch.HasValue())
64+
require.Equal(t, int64(8192), qCfg.Batch.Get().MinSize)
65+
require.Equal(t, 200*time.Millisecond, qCfg.Batch.Get().FlushTimeout)
66+
require.Equal(t, request.SizerTypeItems, qCfg.Batch.Get().Sizer)
67+
}
68+
4869
func TestQueueConfig_Validate(t *testing.T) {
4970
qCfg := NewDefaultQueueConfig()
5071
require.NoError(t, qCfg.Validate())

exporter/exporterhelper/metadata.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ status:
1111
stability:
1212
beta: [traces, metrics, logs]
1313

14+
feature_gates:
15+
- id: pkg.exporterhelper.queueBatchEnabled
16+
description: "Enables exporterhelper batching by default in NewDefaultQueueConfig, as described in the batching migration RFC."
17+
stage: alpha
18+
from_version: 'v0.158.0'
19+
reference_url: 'https://github.com/open-telemetry/opentelemetry-collector/issues/15047'
20+
1421
telemetry:
1522
metrics:
1623
exporter_enqueue_failed_log_records:

0 commit comments

Comments
 (0)