github.com/Jeffail/benthos/v3@v3.65.0/internal/bundle/tracing/bundle_test.go (about)

     1  package tracing_test
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/Jeffail/benthos/v3/internal/bundle"
    10  	"github.com/Jeffail/benthos/v3/internal/bundle/tracing"
    11  	"github.com/Jeffail/benthos/v3/lib/input"
    12  	"github.com/Jeffail/benthos/v3/lib/log"
    13  	"github.com/Jeffail/benthos/v3/lib/manager"
    14  	"github.com/Jeffail/benthos/v3/lib/message"
    15  	"github.com/Jeffail/benthos/v3/lib/metrics"
    16  	"github.com/Jeffail/benthos/v3/lib/output"
    17  	"github.com/Jeffail/benthos/v3/lib/processor"
    18  	"github.com/Jeffail/benthos/v3/lib/response"
    19  	"github.com/Jeffail/benthos/v3/lib/types"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  
    24  	_ "github.com/Jeffail/benthos/v3/public/components/all"
    25  )
    26  
    27  func TestBundleInputTracing(t *testing.T) {
    28  	tenv, summary := tracing.TracedBundle(bundle.GlobalEnvironment)
    29  
    30  	inConfig := input.NewConfig()
    31  	inConfig.Label = "foo"
    32  	inConfig.Type = input.TypeGenerate
    33  	inConfig.Generate.Count = 10
    34  	inConfig.Generate.Interval = "1us"
    35  	inConfig.Generate.Mapping = `root.count = count("counting the number of input tracing messages")`
    36  
    37  	mgr, err := manager.NewV2(
    38  		manager.NewResourceConfig(),
    39  		types.NoopMgr(),
    40  		log.Noop(),
    41  		metrics.Noop(),
    42  		manager.OptSetEnvironment(tenv),
    43  	)
    44  	require.NoError(t, err)
    45  
    46  	in, err := mgr.NewInput(inConfig, false)
    47  	require.NoError(t, err)
    48  
    49  	for i := 0; i < 10; i++ {
    50  		select {
    51  		case tran := <-in.TransactionChan():
    52  			select {
    53  			case tran.ResponseChan <- response.NewAck():
    54  			case <-time.After(time.Second):
    55  				t.Fatal("timed out")
    56  			}
    57  		case <-time.After(time.Second):
    58  			t.Fatal("timed out")
    59  		}
    60  	}
    61  
    62  	in.CloseAsync()
    63  	require.NoError(t, in.WaitForClose(time.Second))
    64  
    65  	assert.Equal(t, uint64(10), summary.Input)
    66  	assert.Equal(t, uint64(0), summary.ProcessorErrors)
    67  	assert.Equal(t, uint64(0), summary.Output)
    68  
    69  	inEvents := summary.InputEvents()
    70  	require.Contains(t, inEvents, "foo")
    71  
    72  	events := inEvents["foo"]
    73  	require.Len(t, events, 10)
    74  
    75  	for i, e := range events {
    76  		assert.Equal(t, tracing.EventProduce, e.Type)
    77  		assert.Equal(t, fmt.Sprintf(`{"count":%v}`, i+1), e.Content)
    78  	}
    79  }
    80  
    81  func TestBundleOutputTracing(t *testing.T) {
    82  	tenv, summary := tracing.TracedBundle(bundle.GlobalEnvironment)
    83  
    84  	outConfig := output.NewConfig()
    85  	outConfig.Label = "foo"
    86  	outConfig.Type = output.TypeDrop
    87  
    88  	mgr, err := manager.NewV2(
    89  		manager.NewResourceConfig(),
    90  		types.NoopMgr(),
    91  		log.Noop(),
    92  		metrics.Noop(),
    93  		manager.OptSetEnvironment(tenv),
    94  	)
    95  	require.NoError(t, err)
    96  
    97  	out, err := mgr.NewOutput(outConfig)
    98  	require.NoError(t, err)
    99  
   100  	tranChan := make(chan types.Transaction)
   101  	require.NoError(t, out.Consume(tranChan))
   102  
   103  	for i := 0; i < 10; i++ {
   104  		resChan := make(chan types.Response)
   105  		tran := types.NewTransaction(message.New([][]byte{[]byte(strconv.Itoa(i))}), resChan)
   106  		select {
   107  		case tranChan <- tran:
   108  			select {
   109  			case <-resChan:
   110  			case <-time.After(time.Second):
   111  				t.Fatal("timed out")
   112  			}
   113  		case <-time.After(time.Second):
   114  			t.Fatal("timed out")
   115  		}
   116  	}
   117  
   118  	out.CloseAsync()
   119  	require.NoError(t, out.WaitForClose(time.Second))
   120  
   121  	assert.Equal(t, uint64(0), summary.Input)
   122  	assert.Equal(t, uint64(0), summary.ProcessorErrors)
   123  	assert.Equal(t, uint64(10), summary.Output)
   124  
   125  	outEvents := summary.OutputEvents()
   126  	require.Contains(t, outEvents, "foo")
   127  
   128  	events := outEvents["foo"]
   129  	require.Len(t, events, 10)
   130  
   131  	for i, e := range events {
   132  		assert.Equal(t, tracing.EventConsume, e.Type)
   133  		assert.Equal(t, strconv.Itoa(i), e.Content)
   134  	}
   135  }
   136  
   137  func TestBundleOutputWithProcessorsTracing(t *testing.T) {
   138  	tenv, summary := tracing.TracedBundle(bundle.GlobalEnvironment)
   139  
   140  	outConfig := output.NewConfig()
   141  	outConfig.Label = "foo"
   142  	outConfig.Type = output.TypeDrop
   143  
   144  	blobConf := processor.NewConfig()
   145  	blobConf.Type = "bloblang"
   146  	blobConf.Bloblang = "root = content().uppercase()"
   147  	outConfig.Processors = append(outConfig.Processors, blobConf)
   148  
   149  	mgr, err := manager.NewV2(
   150  		manager.NewResourceConfig(),
   151  		types.NoopMgr(),
   152  		log.Noop(),
   153  		metrics.Noop(),
   154  		manager.OptSetEnvironment(tenv),
   155  	)
   156  	require.NoError(t, err)
   157  
   158  	out, err := mgr.NewOutput(outConfig)
   159  	require.NoError(t, err)
   160  
   161  	tranChan := make(chan types.Transaction)
   162  	require.NoError(t, out.Consume(tranChan))
   163  
   164  	for i := 0; i < 10; i++ {
   165  		resChan := make(chan types.Response)
   166  		tran := types.NewTransaction(message.New([][]byte{[]byte("hello world " + strconv.Itoa(i))}), resChan)
   167  		select {
   168  		case tranChan <- tran:
   169  			select {
   170  			case <-resChan:
   171  			case <-time.After(time.Second):
   172  				t.Fatal("timed out")
   173  			}
   174  		case <-time.After(time.Second):
   175  			t.Fatal("timed out")
   176  		}
   177  	}
   178  
   179  	out.CloseAsync()
   180  	require.NoError(t, out.WaitForClose(time.Second))
   181  
   182  	assert.Equal(t, uint64(0), summary.Input)
   183  	assert.Equal(t, uint64(0), summary.ProcessorErrors)
   184  	assert.Equal(t, uint64(10), summary.Output)
   185  
   186  	outEvents := summary.OutputEvents()
   187  	require.Contains(t, outEvents, "foo")
   188  
   189  	outputEvents := outEvents["foo"]
   190  	require.Len(t, outputEvents, 10)
   191  
   192  	for i, e := range outputEvents {
   193  		assert.Equal(t, tracing.EventConsume, e.Type)
   194  		assert.Equal(t, "HELLO WORLD "+strconv.Itoa(i), e.Content)
   195  	}
   196  
   197  	procEvents := summary.ProcessorEvents()
   198  	require.Contains(t, procEvents, "foo.processor.0")
   199  
   200  	processorEvents := procEvents["foo.processor.0"]
   201  	require.Len(t, processorEvents, 20)
   202  
   203  	for i := 0; i < len(processorEvents); i += 2 {
   204  		consumeEvent := processorEvents[i]
   205  		produceEvent := processorEvents[i+1]
   206  
   207  		assert.Equal(t, tracing.EventConsume, consumeEvent.Type)
   208  		assert.Equal(t, tracing.EventProduce, produceEvent.Type)
   209  
   210  		assert.Equal(t, "hello world "+strconv.Itoa(i/2), consumeEvent.Content)
   211  		assert.Equal(t, "HELLO WORLD "+strconv.Itoa(i/2), produceEvent.Content)
   212  	}
   213  }
   214  
   215  func TestBundleProcessorTracing(t *testing.T) {
   216  	tenv, summary := tracing.TracedBundle(bundle.GlobalEnvironment)
   217  
   218  	procConfig := processor.NewConfig()
   219  	procConfig.Label = "foo"
   220  	procConfig.Type = processor.TypeBloblang
   221  	procConfig.Bloblang = `
   222  let ctr = content().number()
   223  root.count = if $ctr % 2 == 0 { throw("nah %v".format($ctr)) } else { $ctr }
   224  `
   225  
   226  	mgr, err := manager.NewV2(
   227  		manager.NewResourceConfig(),
   228  		types.NoopMgr(),
   229  		log.Noop(),
   230  		metrics.Noop(),
   231  		manager.OptSetEnvironment(tenv),
   232  	)
   233  	require.NoError(t, err)
   234  
   235  	proc, err := mgr.NewProcessor(procConfig)
   236  	require.NoError(t, err)
   237  
   238  	for i := 0; i < 10; i++ {
   239  		batch, res := proc.ProcessMessage(message.New([][]byte{[]byte(strconv.Itoa(i))}))
   240  		require.Nil(t, res)
   241  		require.Len(t, batch, 1)
   242  		assert.Equal(t, 1, batch[0].Len())
   243  	}
   244  
   245  	proc.CloseAsync()
   246  	require.NoError(t, proc.WaitForClose(time.Second))
   247  
   248  	assert.Equal(t, uint64(0), summary.Input)
   249  	assert.Equal(t, uint64(5), summary.ProcessorErrors)
   250  	assert.Equal(t, uint64(0), summary.Output)
   251  
   252  	procEvents := summary.ProcessorEvents()
   253  	require.Contains(t, procEvents, "foo")
   254  
   255  	events := procEvents["foo"]
   256  	require.Len(t, events, 25)
   257  
   258  	assert.Equal(t, []tracing.NodeEvent{
   259  		{Type: "CONSUME", Content: "0"},
   260  		{Type: "PRODUCE", Content: "0"},
   261  		{Type: "ERROR", Content: "failed assignment (line 3): nah 0"},
   262  		{Type: "CONSUME", Content: "1"},
   263  		{Type: "PRODUCE", Content: "{\"count\":1}"},
   264  		{Type: "CONSUME", Content: "2"},
   265  		{Type: "PRODUCE", Content: "2"},
   266  		{Type: "ERROR", Content: "failed assignment (line 3): nah 2"},
   267  		{Type: "CONSUME", Content: "3"},
   268  		{Type: "PRODUCE", Content: "{\"count\":3}"},
   269  		{Type: "CONSUME", Content: "4"},
   270  		{Type: "PRODUCE", Content: "4"},
   271  		{Type: "ERROR", Content: "failed assignment (line 3): nah 4"},
   272  		{Type: "CONSUME", Content: "5"},
   273  		{Type: "PRODUCE", Content: "{\"count\":5}"},
   274  		{Type: "CONSUME", Content: "6"},
   275  		{Type: "PRODUCE", Content: "6"},
   276  		{Type: "ERROR", Content: "failed assignment (line 3): nah 6"},
   277  		{Type: "CONSUME", Content: "7"},
   278  		{Type: "PRODUCE", Content: "{\"count\":7}"},
   279  		{Type: "CONSUME", Content: "8"},
   280  		{Type: "PRODUCE", Content: "8"},
   281  		{Type: "ERROR", Content: "failed assignment (line 3): nah 8"},
   282  		{Type: "CONSUME", Content: "9"},
   283  		{Type: "PRODUCE", Content: "{\"count\":9}"},
   284  	}, events)
   285  }