Skip to content

Commit 187b345

Browse files
add WriterOperator::WriteBatch and Operator::ProcessBatch methods
The File input's `emitBatch` function now calls `ProcessBatch` instead of `Process`. The added `ProcessBatch` method will make each Stanza operator capable of accepting a batch of entries.
1 parent 8780b9a commit 187b345

File tree

5 files changed

+65
-13
lines changed

5 files changed

+65
-13
lines changed

pkg/stanza/operator/helper/emitter.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func (e *LogEmitter) Stop() error {
9494
return nil
9595
}
9696

97-
// Process will emit an entry to the output channel
97+
// Process emits an entry to the consumerFunc
9898
func (e *LogEmitter) Process(ctx context.Context, ent *entry.Entry) error {
9999
if oldBatch := e.appendEntry(ent); len(oldBatch) > 0 {
100100
e.consumerFunc(ctx, oldBatch)
@@ -103,6 +103,15 @@ func (e *LogEmitter) Process(ctx context.Context, ent *entry.Entry) error {
103103
return nil
104104
}
105105

106+
// ProcessBatch emits the entries to the consumerFunc
107+
func (e *LogEmitter) ProcessBatch(ctx context.Context, entries []entry.Entry) error {
108+
for _, entry := range entries {
109+
e.Process(ctx, &entry)
110+
}
111+
112+
return nil
113+
}
114+
106115
// appendEntry appends the entry to the current batch. If maxBatchSize is reached, a new batch will be made, and the old batch
107116
// (which should be flushed) will be returned
108117
func (e *LogEmitter) appendEntry(ent *entry.Entry) []*entry.Entry {

pkg/stanza/operator/helper/input.go

+9
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,12 @@ func (i *InputOperator) Process(_ context.Context, _ *entry.Entry) error {
9090
"Ensure that operator is not configured to receive logs from other operators",
9191
)
9292
}
93+
94+
// ProcessBatch will always return an error if called.
95+
func (i *InputOperator) ProcessBatch(_ context.Context, _ []entry.Entry) error {
96+
i.Logger().Error("Operator received a batch of entries, but can not process")
97+
return errors.NewError(
98+
"Operator can not process logs.",
99+
"Ensure that operator is not configured to receive logs from other operators",
100+
)
101+
}

pkg/stanza/operator/helper/writer.go

+19
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ func (w *WriterOperator) Write(ctx context.Context, e *entry.Entry) error {
6161
return nil
6262
}
6363

64+
// Write writes a batch of entries to the outputs of the operator.
65+
// A batch is a collection of entries that are sent in one go.
66+
func (w *WriterOperator) WriteBatch(ctx context.Context, entries []entry.Entry) error {
67+
for i, op := range w.OutputOperators {
68+
if i == len(w.OutputOperators)-1 {
69+
return op.ProcessBatch(ctx, entries)
70+
}
71+
copyOfEntries := make([]entry.Entry, 0, len(entries))
72+
for _, entry := range entries {
73+
copyOfEntries = append(copyOfEntries, *entry.Copy())
74+
}
75+
err := op.ProcessBatch(ctx, copyOfEntries)
76+
if err != nil {
77+
w.Logger().Error("Failed to process entries", zap.Error(err))
78+
}
79+
}
80+
return nil
81+
}
82+
6483
// CanOutput always returns true for a writer operator.
6584
func (w *WriterOperator) CanOutput() bool {
6685
return true

pkg/stanza/operator/input/file/input.go

+25-12
Original file line numberDiff line numberDiff line change
@@ -39,33 +39,46 @@ func (i *Input) Stop() error {
3939
}
4040

4141
func (i *Input) emitBatch(ctx context.Context, tokens []emit.Token) error {
42+
entries, conversionError := i.convertTokens(tokens)
43+
if conversionError != nil {
44+
conversionError = fmt.Errorf("convert tokens: %w", conversionError)
45+
}
46+
47+
consumeError := i.WriteBatch(ctx, entries)
48+
if consumeError != nil {
49+
consumeError = fmt.Errorf("consume entries: %w", consumeError)
50+
}
51+
52+
return errors.Join(conversionError, consumeError)
53+
}
54+
55+
func (i *Input) convertTokens(tokens []emit.Token) ([]entry.Entry, error) {
56+
entries := make([]entry.Entry, 0, len(tokens))
4257
var errs []error
4358
for _, token := range tokens {
44-
err := i.emit(ctx, token)
59+
if len(token.Body) == 0 {
60+
continue
61+
}
62+
entry, err := i.convertToken(token)
4563
if err != nil {
4664
errs = append(errs, err)
65+
continue
4766
}
67+
entries = append(entries, *entry)
4868
}
49-
if len(errs) > 0 {
50-
return errors.Join(errs...)
51-
}
52-
return nil
69+
return entries, errors.Join(errs...)
5370
}
5471

55-
func (i *Input) emit(ctx context.Context, token emit.Token) error {
56-
if len(token.Body) == 0 {
57-
return nil
58-
}
59-
72+
func (i *Input) convertToken(token emit.Token) (*entry.Entry, error) {
6073
ent, err := i.NewEntry(i.toBody(token.Body))
6174
if err != nil {
62-
return fmt.Errorf("create entry: %w", err)
75+
return nil, fmt.Errorf("create entry: %w", err)
6376
}
6477

6578
for k, v := range token.Attributes {
6679
if err := ent.Set(entry.NewAttributeField(k), v); err != nil {
6780
i.Logger().Error("set attribute", zap.Error(err))
6881
}
6982
}
70-
return i.Write(ctx, ent)
83+
return ent, nil
7184
}

pkg/stanza/operator/operator.go

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ type Operator interface {
3838
CanProcess() bool
3939
// Process will process an entry from an operator.
4040
Process(context.Context, *entry.Entry) error
41+
// Process processes a batch of entries from an operator.
42+
ProcessBatch(context.Context, []entry.Entry) error
4143
// Logger returns the operator's logger
4244
Logger() *zap.Logger
4345
}

0 commit comments

Comments
 (0)