github.com/Jeffail/benthos/v3@v3.65.0/lib/output/stdout.go (about)

     1  package output
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"time"
     7  
     8  	"github.com/Jeffail/benthos/v3/internal/codec"
     9  	"github.com/Jeffail/benthos/v3/internal/docs"
    10  	"github.com/Jeffail/benthos/v3/internal/shutdown"
    11  	"github.com/Jeffail/benthos/v3/lib/log"
    12  	"github.com/Jeffail/benthos/v3/lib/metrics"
    13  	"github.com/Jeffail/benthos/v3/lib/output/writer"
    14  	"github.com/Jeffail/benthos/v3/lib/types"
    15  )
    16  
    17  //------------------------------------------------------------------------------
    18  
    19  var multipartCodecDoc = (`
    20  ## Batches and Multipart Messages
    21  
    22  When writing multipart (batched) messages using the ` + "`lines`" + ` codec the last message ends with double delimiters. E.g. the messages "foo", "bar" and "baz" would be written as:
    23  
    24  ` + "```" + `
    25  foo\n
    26  bar\n
    27  baz\n
    28  ` + "```" + `
    29  
    30  Whereas a multipart message [ "foo", "bar", "baz" ] would be written as:
    31  
    32  ` + "```" + `
    33  foo\n
    34  bar\n
    35  baz\n\n
    36  ` + "```" + `
    37  
    38  This enables consumers of this output feed to reconstruct the original batches. However, if you wish to avoid this behaviour then add a ` + "[`split` processor](/docs/components/processors/split)" + ` before messages reach this output.`)[1:]
    39  
    40  func init() {
    41  	Constructors[TypeSTDOUT] = TypeSpec{
    42  		constructor: fromSimpleConstructor(NewSTDOUT),
    43  		Summary: `
    44  Prints messages to stdout as a continuous stream of data, dividing messages according to the specified codec.`,
    45  		Description: multipartCodecDoc,
    46  		FieldSpecs: docs.FieldSpecs{
    47  			codec.WriterDocs.AtVersion("3.46.0"),
    48  			docs.FieldDeprecated("delimiter"),
    49  		},
    50  		Categories: []Category{
    51  			CategoryLocal,
    52  		},
    53  	}
    54  }
    55  
    56  //------------------------------------------------------------------------------
    57  
    58  // STDOUTConfig contains configuration fields for the stdout based output type.
    59  type STDOUTConfig struct {
    60  	Codec string `json:"codec" yaml:"codec"`
    61  	Delim string `json:"delimiter" yaml:"delimiter"`
    62  }
    63  
    64  // NewSTDOUTConfig creates a new STDOUTConfig with default values.
    65  func NewSTDOUTConfig() STDOUTConfig {
    66  	return STDOUTConfig{
    67  		Codec: "lines",
    68  		Delim: "",
    69  	}
    70  }
    71  
    72  //------------------------------------------------------------------------------
    73  
    74  // NewSTDOUT creates a new STDOUT output type.
    75  func NewSTDOUT(conf Config, mgr types.Manager, log log.Modular, stats metrics.Type) (Type, error) {
    76  	if len(conf.STDOUT.Delim) > 0 {
    77  		conf.STDOUT.Codec = "delim:" + conf.STDOUT.Delim
    78  	}
    79  	f, err := newStdoutWriter(conf.STDOUT.Codec, log, stats)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	w, err := NewAsyncWriter(TypeSTDOUT, 1, f, log, stats)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	if aw, ok := w.(*AsyncWriter); ok {
    88  		aw.SetNoCancel()
    89  	}
    90  	return w, nil
    91  }
    92  
    93  type stdoutWriter struct {
    94  	handle  codec.Writer
    95  	shutSig *shutdown.Signaller
    96  }
    97  
    98  func newStdoutWriter(codecStr string, log log.Modular, stats metrics.Type) (*stdoutWriter, error) {
    99  	codec, _, err := codec.GetWriter(codecStr)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	handle, err := codec(os.Stdout)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	return &stdoutWriter{
   110  		handle:  handle,
   111  		shutSig: shutdown.NewSignaller(),
   112  	}, nil
   113  }
   114  
   115  func (w *stdoutWriter) ConnectWithContext(ctx context.Context) error {
   116  	return nil
   117  }
   118  
   119  func (w *stdoutWriter) WriteWithContext(ctx context.Context, msg types.Message) error {
   120  	err := writer.IterateBatchedSend(msg, func(i int, p types.Part) error {
   121  		return w.handle.Write(ctx, p)
   122  	})
   123  	if err != nil {
   124  		return err
   125  	}
   126  	if msg.Len() > 1 {
   127  		if w.handle != nil {
   128  			w.handle.EndBatch()
   129  		}
   130  	}
   131  	return nil
   132  }
   133  
   134  func (w *stdoutWriter) CloseAsync() {
   135  }
   136  
   137  func (w *stdoutWriter) WaitForClose(timeout time.Duration) error {
   138  	return nil
   139  }