github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/function/ctl/cmd_tracespan_test.go (about)

     1  // Copyright 2023 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 ctl
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"sync"
    21  	"testing"
    22  	"time"
    23  
    24  	uuid2 "github.com/google/uuid"
    25  	"github.com/matrixorigin/matrixone/pkg/clusterservice"
    26  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    27  	"github.com/matrixorigin/matrixone/pkg/common/morpc"
    28  	"github.com/matrixorigin/matrixone/pkg/common/runtime"
    29  	"github.com/matrixorigin/matrixone/pkg/defines"
    30  	logpb "github.com/matrixorigin/matrixone/pkg/pb/logservice"
    31  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    32  	"github.com/matrixorigin/matrixone/pkg/pb/query"
    33  	"github.com/matrixorigin/matrixone/pkg/queryservice"
    34  	qclient "github.com/matrixorigin/matrixone/pkg/queryservice/client"
    35  	"github.com/matrixorigin/matrixone/pkg/util/trace"
    36  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    37  	"github.com/mohae/deepcopy"
    38  	"github.com/stretchr/testify/require"
    39  )
    40  
    41  func TestCanHandleServiceAndCmdWrong(t *testing.T) {
    42  	var a1, a2 struct {
    43  		proc      *process.Process
    44  		service   serviceType
    45  		parameter string
    46  		sender    requestSender
    47  	}
    48  
    49  	// testing query with wrong serviceType
    50  	a1.service = serviceType("log")
    51  	ret, err := handleTraceSpan(a1.proc, a1.service, a1.parameter, a1.sender)
    52  	require.Equal(t, ret, Result{})
    53  	require.Equal(t, err, moerr.NewWrongServiceNoCtx("CN or DN", string(a1.service)))
    54  
    55  	// testing query with wrong cmd
    56  	a2.service = cn
    57  	a2.parameter = "xxx:open:s3:0"
    58  	ret, err = handleTraceSpan(a2.proc, a2.service, a2.parameter, a2.sender)
    59  	require.Equal(t, ret, Result{})
    60  	require.Equal(t, err, moerr.NewInternalErrorNoCtx("cmd invalid, expected enable or disable"))
    61  }
    62  
    63  func initRuntime(uuids []string, queryAddress []string) {
    64  	cns := make([]metadata.CNService, len(uuids))
    65  	for idx := range uuids {
    66  		cns[idx] = metadata.CNService{
    67  			ServiceID:    uuids[idx],
    68  			QueryAddress: queryAddress[idx],
    69  		}
    70  	}
    71  
    72  	runtime.SetupProcessLevelRuntime(runtime.DefaultRuntime())
    73  	moCluster := clusterservice.NewMOCluster(new(testHAKeeperClient),
    74  		time.Duration(time.Second),
    75  		clusterservice.WithDisableRefresh(),
    76  		clusterservice.WithServices(cns, nil))
    77  	runtime.ProcessLevelRuntime().SetGlobalVariables(runtime.ClusterService, moCluster)
    78  	runtime.ProcessLevelRuntime().SetGlobalVariables(runtime.MOProtocolVersion, defines.MORPCLatestVersion)
    79  }
    80  
    81  func TestCanHandleSelfCmd(t *testing.T) {
    82  	var a1 struct {
    83  		proc      *process.Process
    84  		service   serviceType
    85  		parameter string
    86  		sender    requestSender
    87  	}
    88  
    89  	trace.InitMOCtledSpan()
    90  
    91  	initRuntime(nil, nil)
    92  
    93  	uuid := uuid2.New().String()
    94  	cli, err := qclient.NewQueryClient(uuid, morpc.Config{})
    95  	require.Nil(t, err)
    96  
    97  	a1.proc = new(process.Process)
    98  	a1.proc.QueryClient = cli
    99  	a1.service = cn
   100  	a1.parameter = fmt.Sprintf("%s:enable:s3,local:10", uuid)
   101  
   102  	ret, err := handleTraceSpan(a1.proc, a1.service, a1.parameter, a1.sender)
   103  	require.Nil(t, err)
   104  	require.Equal(t, ret, Result{
   105  		Method: TraceSpanMethod,
   106  		Data:   fmt.Sprintf("%s:[s3 local] enabled, [] failed; ", uuid),
   107  	})
   108  
   109  	k1 := trace.MOCtledSpanEnableConfig.NameToKind["s3"]
   110  	k2 := trace.MOCtledSpanEnableConfig.NameToKind["local"]
   111  	require.Equal(t, true, trace.MOCtledSpanEnableConfig.KindToState[k1].Enable)
   112  	require.Equal(t, int64(10), trace.MOCtledSpanEnableConfig.KindToState[k1].Threshold.Milliseconds())
   113  	require.Equal(t, true, trace.MOCtledSpanEnableConfig.KindToState[k2].Enable)
   114  	require.Equal(t, int64(10), trace.MOCtledSpanEnableConfig.KindToState[k2].Threshold.Milliseconds())
   115  
   116  }
   117  
   118  func TestCanTransferQuery(t *testing.T) {
   119  	var a1 struct {
   120  		proc      *process.Process
   121  		service   serviceType
   122  		parameter string
   123  		sender    requestSender
   124  	}
   125  	uuids := []string{
   126  		uuid2.New().String(),
   127  		uuid2.New().String(),
   128  	}
   129  	addrs := []string{
   130  		"127.0.0.1:7777",
   131  		"127.0.0.1:5555",
   132  	}
   133  
   134  	a1.proc = new(process.Process)
   135  	a1.service = cn
   136  	a1.parameter = fmt.Sprintf("%s,%s:enable:s3,local:0", uuids[0], uuids[1])
   137  
   138  	initRuntime(uuids, addrs)
   139  	trace.InitMOCtledSpan()
   140  
   141  	qs1, err := queryservice.NewQueryService(uuids[0], addrs[0], morpc.Config{})
   142  	require.Nil(t, err)
   143  	qs2, err := queryservice.NewQueryService(uuids[1], addrs[1], morpc.Config{})
   144  	require.Nil(t, err)
   145  	qt1, err := qclient.NewQueryClient(uuids[1], morpc.Config{})
   146  	require.Nil(t, err)
   147  
   148  	qs1.AddHandleFunc(query.CmdMethod_TraceSpan, mockHandleTraceSpan, false)
   149  	qs2.AddHandleFunc(query.CmdMethod_TraceSpan, mockHandleTraceSpan, false)
   150  
   151  	a1.proc.QueryClient = qt1
   152  
   153  	err = qs1.Start()
   154  	require.Nil(t, err)
   155  	err = qs2.Start()
   156  	require.Nil(t, err)
   157  
   158  	defer func() {
   159  		qs1.Close()
   160  		qs2.Close()
   161  	}()
   162  
   163  	ret, err := handleTraceSpan(a1.proc, a1.service, a1.parameter, a1.sender)
   164  	require.Nil(t, err)
   165  
   166  	str1 := fmt.Sprintf("%s:[s3 local] enabled, [] failed; ", uuids[0])
   167  	str2 := fmt.Sprintf("%s:[s3 local] enabled, [] failed; ", uuids[1])
   168  
   169  	require.True(t, func() bool {
   170  		if ret.Data == str1+str2 ||
   171  			ret.Data == str2+str1 {
   172  			return true
   173  		}
   174  		return false
   175  	}())
   176  }
   177  
   178  type testHAKeeperClient struct {
   179  	sync.RWMutex
   180  	value logpb.ClusterDetails
   181  	err   error
   182  }
   183  
   184  func (c *testHAKeeperClient) GetClusterDetails(ctx context.Context) (logpb.ClusterDetails, error) {
   185  	c.RLock()
   186  	defer c.RUnlock()
   187  	// deep copy the cluster details to avoid data race.
   188  	copied := deepcopy.Copy(c.value)
   189  	return copied.(logpb.ClusterDetails), c.err
   190  }
   191  
   192  func mockHandleTraceSpan(ctx context.Context, req *query.Request, resp *query.Response) error {
   193  	resp.TraceSpanResponse = new(query.TraceSpanResponse)
   194  	resp.TraceSpanResponse.Resp = SelfProcess(
   195  		req.TraceSpanRequest.Cmd, req.TraceSpanRequest.Spans, req.TraceSpanRequest.Threshold)
   196  	return nil
   197  }