github.com/matrixorigin/matrixone@v1.2.0/pkg/util/trace/impl/motrace/report_log_test.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package motrace
    16  
    17  import (
    18  	"context"
    19  	"sync/atomic"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/prashantv/gostub"
    24  	"github.com/stretchr/testify/require"
    25  	"go.uber.org/zap"
    26  	"go.uber.org/zap/zapcore"
    27  
    28  	"github.com/matrixorigin/matrixone/pkg/common/runtime"
    29  	"github.com/matrixorigin/matrixone/pkg/logutil"
    30  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    31  	"github.com/matrixorigin/matrixone/pkg/util/batchpipe"
    32  	"github.com/matrixorigin/matrixone/pkg/util/stack"
    33  	"github.com/matrixorigin/matrixone/pkg/util/trace"
    34  )
    35  
    36  func TestReportZap(t *testing.T) {
    37  	type args struct {
    38  		jsonEncoder zapcore.Encoder
    39  		entry       zapcore.Entry
    40  		fields      []zapcore.Field
    41  	}
    42  	spanField := trace.ContextField(trace.ContextWithSpanContext(context.Background(), trace.SpanContext{}))
    43  	entry := zapcore.Entry{
    44  		Level:      zapcore.InfoLevel,
    45  		Time:       time.Unix(0, 0),
    46  		LoggerName: "test",
    47  		Message:    "info message",
    48  		Caller:     zapcore.NewEntryCaller(uintptr(stack.Caller(3)), "file", 123, true),
    49  	}
    50  	encoder := zapcore.NewJSONEncoder(
    51  		zapcore.EncoderConfig{
    52  			StacktraceKey:  "stacktrace",
    53  			SkipLineEnding: true,
    54  			LineEnding:     zapcore.DefaultLineEnding,
    55  			EncodeLevel:    zapcore.LowercaseLevelEncoder,
    56  			EncodeTime:     zapcore.EpochTimeEncoder,
    57  			EncodeDuration: zapcore.SecondsDurationEncoder,
    58  			EncodeCaller:   zapcore.ShortCallerEncoder,
    59  		})
    60  	intField := zap.Int("key", 1)
    61  	strField := zap.String("str", "1")
    62  	boolField := zap.Bool("bool", true)
    63  	tests := []struct {
    64  		name string
    65  		args args
    66  		want string
    67  	}{
    68  		{
    69  			name: "normal",
    70  			args: args{
    71  				jsonEncoder: encoder,
    72  				entry:       entry,
    73  				fields:      []zapcore.Field{intField},
    74  			},
    75  			want: `{"key":1}`,
    76  		},
    77  		{
    78  			name: "remove first span",
    79  			args: args{
    80  				jsonEncoder: encoder,
    81  				entry:       entry,
    82  				fields:      []zapcore.Field{spanField, intField, strField},
    83  			},
    84  			want: `{"str":"1","key":1}`,
    85  		},
    86  		{
    87  			name: "remove middle span",
    88  			args: args{
    89  				jsonEncoder: encoder,
    90  				entry:       entry,
    91  				fields:      []zapcore.Field{intField, spanField, strField},
    92  			},
    93  			want: `{"key":1,"str":"1"}`,
    94  		},
    95  		{
    96  			name: "remove double middle span",
    97  			args: args{
    98  				jsonEncoder: encoder,
    99  				entry:       entry,
   100  				fields:      []zapcore.Field{intField, spanField, spanField, strField, boolField},
   101  			},
   102  			want: `{"key":1,"bool":true,"str":"1"}`,
   103  		},
   104  		{
   105  			name: "remove end span",
   106  			args: args{
   107  				jsonEncoder: encoder,
   108  				entry:       entry,
   109  				fields:      []zapcore.Field{intField, strField, spanField, spanField},
   110  			},
   111  			want: `{"key":1,"str":"1"}`,
   112  		},
   113  		{
   114  			name: "remove multi span",
   115  			args: args{
   116  				jsonEncoder: encoder,
   117  				entry:       entry,
   118  				fields:      []zapcore.Field{intField, strField, spanField, boolField, spanField, spanField},
   119  			},
   120  			want: `{"key":1,"str":"1","bool":true}`,
   121  		},
   122  	}
   123  	for _, tt := range tests {
   124  		t.Run(tt.name, func(t *testing.T) {
   125  			got, err := ReportZap(tt.args.jsonEncoder, tt.args.entry, tt.args.fields)
   126  			require.Equal(t, nil, err)
   127  			require.Equal(t, tt.want, got.String())
   128  		})
   129  	}
   130  }
   131  
   132  var _ BatchProcessor = (*dummyCollectorCounter)(nil)
   133  var _ DiscardableCollector = (*dummyCollectorCounter)(nil)
   134  
   135  type dummyCollectorCounter struct {
   136  	collectCnt atomic.Int64
   137  	discardCnt atomic.Int64
   138  }
   139  
   140  func newDummyCollectorCounter() *dummyCollectorCounter {
   141  	return &dummyCollectorCounter{}
   142  }
   143  
   144  func (d *dummyCollectorCounter) DiscardableCollect(ctx context.Context, name batchpipe.HasName) error {
   145  	d.discardCnt.Add(1)
   146  	return nil
   147  }
   148  
   149  func (d *dummyCollectorCounter) Collect(ctx context.Context, name batchpipe.HasName) error {
   150  	d.collectCnt.Add(1)
   151  	return nil
   152  }
   153  
   154  func (d *dummyCollectorCounter) Start() bool                                    { return true }
   155  func (d *dummyCollectorCounter) Stop(graceful bool) error                       { return nil }
   156  func (d *dummyCollectorCounter) Register(name batchpipe.HasName, impl PipeImpl) {}
   157  
   158  func TestReportZap_Discardable(t *testing.T) {
   159  
   160  	exportMux.Lock()
   161  	defer exportMux.Unlock()
   162  
   163  	// Setup a Runtime
   164  	runtime.SetupProcessLevelRuntime(runtime.NewRuntime(metadata.ServiceType_CN, "test", logutil.GetGlobalLogger()))
   165  
   166  	collector := newDummyCollectorCounter()
   167  	p := newMOTracerProvider(WithFSWriterFactory(&dummyFileWriterFactory{}), EnableTracer(true), WithBatchProcessor(collector))
   168  	stubs := gostub.Stub(&GetTracerProvider, func() *MOTracerProvider {
   169  		return p
   170  	})
   171  	defer stubs.Reset()
   172  
   173  	logutil.Info("normal log 1")
   174  	require.Equal(t, int64(1), collector.collectCnt.Load())
   175  
   176  	logutil.Info("discard log 1", logutil.Discardable())
   177  	require.Equal(t, int64(1), collector.discardCnt.Load())
   178  
   179  	logger := runtime.ProcessLevelRuntime().Logger().With(logutil.Discardable())
   180  	logger.Info("discard log 2")
   181  	require.Equal(t, int64(2), collector.discardCnt.Load())
   182  	logger.Info("discard log 3")
   183  	require.Equal(t, int64(3), collector.discardCnt.Load())
   184  
   185  	logutil.Info("normal log 2")
   186  	require.Equal(t, int64(2), collector.collectCnt.Load())
   187  }