Skip to content

Commit 6802fe9

Browse files
authored
Merge branch 'main' into extension/encoding/googlecloudlogentryencodingextension
2 parents d05f751 + 519deff commit 6802fe9

24 files changed

Lines changed: 1249 additions & 73 deletions

.chloggen/add-lambda-helpers.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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. receiver/filelog)
7+
component: pkg/ottl
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add `ottl.NewTestingLambdaExpression` and internal helpers for implementing lambda-based OTTL functions.
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: [49180]
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+
Adds `ottl.NewTestingLambdaExpression`, a test helper that builds a `LambdaExpression`
20+
with a custom value body. The callback receives `resolveBinding func(string) any` to
21+
read formal parameters from the active local scope during evaluation.
22+
23+
Also introduces internal helpers to support lambda-based OTTL functions:
24+
- `funcutil.GetSliceOrMapValue` coerces a getter result to `pcommon.Slice` or `pcommon.Map`.
25+
- `funcutil.EvaluateBiFunction` and `funcutil.EvaluateBiPredicate` bind two positional
26+
arguments, normalize them, and evaluate a `LambdaActivation`.
27+
- `ottlcommon.NormalizeValue` converts values, including `pcommon.Value`, into types
28+
used by OTTL comparisons.
29+
30+
# If your change doesn't affect end users or the exported elements of any package,
31+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
32+
# Optional: The change log or logs in which this entry should be included.
33+
# e.g. '[user]' or '[user, api]'
34+
# Include 'user' if the change is relevant to end users.
35+
# Include 'api' if there is a change to a library API.
36+
# Default: '[user]'
37+
change_logs: [api]
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: extension/file_storage
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Added `max_size` support to the filestorage extension to cap per-component database growth.
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: [38620]
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: []
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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. receiver/filelog)
7+
component: receiver/prometheus
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Promote `receiver.prometheusreceiver.IgnoreScopeInfoMetric` feature gate to beta.
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: [47312]
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+
The `otel_scope_info` metric is now ignored for scope attribute extraction by default.
20+
To temporarily restore the previous behavior, disable the feature gate with `--feature-gates=-receiver.prometheusreceiver.IgnoreScopeInfoMetric`.
21+
22+
# If your change doesn't affect end users or the exported elements of any package,
23+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
24+
# Optional: The change log or logs in which this entry should be included.
25+
# e.g. '[user]' or '[user, api]'
26+
# Include 'user' if the change is relevant to end users.
27+
# Include 'api' if there is a change to a library API.
28+
# Default: '[user]'
29+
change_logs: [user]

extension/storage/filestorage/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ The default directory is `%ProgramData%\Otelcol\FileStorage` on Windows and `/va
2727
`timeout` is the maximum time to wait for a file lock. This value does not need to be modified in most circumstances.
2828
The default timeout is `1s`.
2929

30+
`max_size` sets the maximum on-disk size of each bbolt database file in bytes.
31+
When a write would need the file to grow past this limit, the write is rejected with a storage-full error.
32+
A value of `0` means unlimited size.
33+
Writes that fit into already-allocated free space are still allowed, even when the file is already at the configured limit.
34+
When rebound compaction is enabled, `max_size` must be greater than or equal to both
35+
`compaction.rebound_needed_threshold_mib * 1,048,576` and `compaction.rebound_trigger_threshold_mib * 1,048,576`.
36+
3037
`fsync` when set, will force the database to perform an fsync after each write. This helps to ensure database integrity if there is an interruption to the database process, but at the cost of performance. See [DB.NoSync](https://pkg.go.dev/go.etcd.io/bbolt#DB) for more information.
3138

3239
`create_directory` when set, will create the data storage and compaction directories if they do not already exist.
@@ -56,6 +63,9 @@ A value of zero will ignore transaction sizes.
5663
It will remove all temporary files in the compaction directory (those which start with `tempdb`),
5764
temp files will be left if a previous run of the process is killed while compacting.
5865

66+
If `max_size` is set, both `compaction.rebound_needed_threshold_mib` and `compaction.rebound_trigger_threshold_mib`
67+
must be less than or equal to that limit after converting MiB to bytes.
68+
5969
### Rebound (online) compaction
6070

6171
For rebound compaction, there are two additional parameters available:
@@ -94,6 +104,7 @@ extensions:
94104
file_storage/all_settings:
95105
directory: /var/lib/otelcol/mydir
96106
timeout: 1s
107+
max_size: 268435456
97108
recreate: true
98109
compaction:
99110
on_start: true

extension/storage/filestorage/client.go

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
"go.etcd.io/bbolt"
16+
berrors "go.etcd.io/bbolt/errors"
1617
"go.opentelemetry.io/collector/extension/xextension/storage"
1718
"go.uber.org/zap"
1819
)
@@ -38,25 +39,29 @@ type fileStorageClient struct {
3839
logger *zap.Logger
3940
compactionMutex sync.RWMutex
4041
db *bbolt.DB
42+
dbOptions bbolt.Options
4143
compactionCfg *CompactionConfig
42-
openTimeout time.Duration
4344
stopCh chan struct{}
4445
wg sync.WaitGroup
4546
closed bool
4647
}
4748

48-
func bboltOptions(timeout time.Duration, noSync bool) *bbolt.Options {
49-
return &bbolt.Options{
50-
Timeout: timeout,
51-
NoSync: noSync,
49+
func bboltOptions(cfg *Config) bbolt.Options {
50+
options := bbolt.Options{
51+
Timeout: cfg.Timeout,
52+
NoSync: !cfg.FSync,
5253
NoFreelistSync: true,
5354
FreelistType: bbolt.FreelistMapType,
5455
}
56+
if cfg.MaxSize > 0 {
57+
options.MaxSize = int(cfg.MaxSize)
58+
}
59+
return options
5560
}
5661

57-
func newClient(logger *zap.Logger, filePath string, timeout time.Duration, compactionCfg *CompactionConfig, noSync bool) (*fileStorageClient, error) {
58-
options := bboltOptions(timeout, noSync)
59-
db, err := bbolt.Open(filePath, 0o600, options)
62+
func newClient(logger *zap.Logger, filePath string, cfg *Config) (*fileStorageClient, error) {
63+
options := bboltOptions(cfg)
64+
db, err := bbolt.Open(filePath, 0o600, &options)
6065
if err != nil {
6166
return nil, err
6267
}
@@ -73,12 +78,12 @@ func newClient(logger *zap.Logger, filePath string, timeout time.Duration, compa
7378
client := &fileStorageClient{
7479
logger: logger,
7580
db: db,
76-
compactionCfg: compactionCfg,
77-
openTimeout: timeout,
81+
dbOptions: options,
82+
compactionCfg: cfg.Compaction,
7883
stopCh: make(chan struct{}),
7984
wg: sync.WaitGroup{},
8085
}
81-
if compactionCfg.OnRebound {
86+
if cfg.Compaction.OnRebound {
8287
client.startCompactionLoop()
8388
}
8489

@@ -119,7 +124,7 @@ func (c *fileStorageClient) Batch(_ context.Context, ops ...*storage.Operation)
119124

120125
c.compactionMutex.RLock()
121126
defer c.compactionMutex.RUnlock()
122-
return c.db.Update(batch)
127+
return normalizeStorageError(c.db.Update(batch))
123128
}
124129

125130
// Walk implements storage.Walker.
@@ -135,7 +140,7 @@ func (c *fileStorageClient) Walk(ctx context.Context, fn storage.WalkFunc) error
135140
return errors.New("storage is closed")
136141
}
137142

138-
return c.db.Update(func(tx *bbolt.Tx) error {
143+
return normalizeStorageError(c.db.Update(func(tx *bbolt.Tx) error {
139144
bucket := tx.Bucket(defaultBucket)
140145
if bucket == nil {
141146
return errors.New("storage not initialized")
@@ -157,8 +162,9 @@ func (c *fileStorageClient) Walk(ctx context.Context, fn storage.WalkFunc) error
157162
}
158163
opBatch = append(opBatch, ops...)
159164
}
165+
160166
return updateBucket(bucket, opBatch...)
161-
})
167+
}))
162168
}
163169

164170
// updateBucket executes the specified operations in order for a given bucket. Get operation results are updated in place
@@ -212,7 +218,6 @@ func (c *fileStorageClient) Close(_ context.Context) error {
212218
func (c *fileStorageClient) Compact(compactionDirectory string, timeout time.Duration, maxTransactionSize int64) error {
213219
var err error
214220
var file *os.File
215-
var compactedDb *bbolt.DB
216221

217222
// create temporary file in compactionDirectory
218223
file, err = os.CreateTemp(compactionDirectory, TempDbPrefix)
@@ -235,7 +240,8 @@ func (c *fileStorageClient) Compact(compactionDirectory string, timeout time.Dur
235240
}()
236241

237242
// use temporary file as compaction target
238-
options := bboltOptions(timeout, c.db.NoSync)
243+
options := c.dbOptions
244+
options.Timeout = timeout
239245

240246
c.compactionMutex.Lock()
241247
defer c.compactionMutex.Unlock()
@@ -249,7 +255,7 @@ func (c *fileStorageClient) Compact(compactionDirectory string, timeout time.Dur
249255
zap.String(tempDirectoryKey, file.Name()))
250256

251257
// cannot reuse newClient as db shouldn't contain any bucket
252-
compactedDb, err = bbolt.Open(file.Name(), 0o600, options)
258+
compactedDb, err := bbolt.Open(file.Name(), 0o600, &options)
253259
if err != nil {
254260
return err
255261
}
@@ -258,6 +264,7 @@ func (c *fileStorageClient) Compact(compactionDirectory string, timeout time.Dur
258264

259265
err = bbolt.Compact(compactedDb, c.db, maxTransactionSize)
260266
if err != nil {
267+
_ = compactedDb.Close()
261268
return err
262269
}
263270

@@ -270,7 +277,7 @@ func (c *fileStorageClient) Compact(compactionDirectory string, timeout time.Dur
270277
// replace current db file with compacted db file
271278
// we reopen the DB file irrespective of the success of the replace, as we can't leave it closed
272279
moveErr := moveFileWithFallback(compactedDbPath, dbPath)
273-
newDb, openErr := bbolt.Open(dbPath, 0o600, options)
280+
newDb, openErr := bbolt.Open(dbPath, 0o600, &options)
274281
if openErr != nil {
275282
// Leave c.db pointing at the old (closed) DB so that callers get
276283
// errors from the closed DB instead of panicking on a nil pointer.
@@ -314,7 +321,7 @@ func (c *fileStorageClient) startCompactionLoop() {
314321
select {
315322
case <-compactionTicker.C:
316323
if c.shouldCompact() {
317-
err := c.Compact(c.compactionCfg.Directory, c.openTimeout, c.compactionCfg.MaxTransactionSize)
324+
err := c.Compact(c.compactionCfg.Directory, c.dbOptions.Timeout, c.compactionCfg.MaxTransactionSize)
318325
if err != nil {
319326
c.logger.Error("compaction failure",
320327
zap.String(directoryKey, c.compactionCfg.Directory),
@@ -329,6 +336,13 @@ func (c *fileStorageClient) startCompactionLoop() {
329336
})
330337
}
331338

339+
func normalizeStorageError(err error) error {
340+
if errors.Is(err, berrors.ErrMaxSizeReached) {
341+
return storage.ErrStorageFull
342+
}
343+
return err
344+
}
345+
332346
// shouldCompact checks whether the conditions for online compaction are met
333347
func (c *fileStorageClient) shouldCompact() bool {
334348
if !c.compactionCfg.OnRebound {

0 commit comments

Comments
 (0)