trpc.group/trpc-go/trpc-go@v1.0.3/rpcz/config_test.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  package rpcz_test
    15  
    16  import (
    17  	"errors"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/stretchr/testify/require"
    22  
    23  	"trpc.group/trpc-go/trpc-go/rpcz"
    24  )
    25  
    26  func TestRPCZ_ShouldRecord(t *testing.T) {
    27  	t.Run("checking ID", func(t *testing.T) {
    28  		r := rpcz.NewRPCZ(&rpcz.Config{
    29  			Fraction: 1.0,
    30  			Capacity: 1,
    31  			ShouldRecord: func(s rpcz.Span) bool {
    32  				return s.ID()%2 == 0
    33  			},
    34  		})
    35  		s, ender := r.NewChild("")
    36  		id := s.ID()
    37  		ender.End()
    38  		readOnlySpan, ok := r.Query(id)
    39  		if id%2 == 0 {
    40  			require.True(t, ok)
    41  			require.Equal(t, id, readOnlySpan.ID)
    42  		} else {
    43  			require.False(t, ok)
    44  		}
    45  	})
    46  	t.Run("checking Attribute", func(t *testing.T) {
    47  		const attributeName = "Error"
    48  		attributeValue := errors.New("test error")
    49  		r := rpcz.NewRPCZ(&rpcz.Config{
    50  			Fraction: 1.0,
    51  			Capacity: 1,
    52  			ShouldRecord: func(s rpcz.Span) bool {
    53  				if err, ok := s.Attribute(attributeName); ok {
    54  					err, ok := err.(error)
    55  					return ok && err != nil
    56  				}
    57  				return false
    58  			},
    59  		})
    60  		s, ender := r.NewChild("")
    61  		id := s.ID()
    62  		s.SetAttribute(attributeName, attributeValue)
    63  		ender.End()
    64  		readOnlySpan, _ := r.Query(id)
    65  		require.Contains(t, readOnlySpan.Attributes, rpcz.Attribute{Name: attributeName, Value: attributeValue})
    66  
    67  		s, ender = r.NewChild("")
    68  		id = s.ID()
    69  		ender.End()
    70  		_, ok := r.Query(id)
    71  		require.False(t, ok)
    72  	})
    73  	t.Run("checking StartTime and EndTime", func(t *testing.T) {
    74  		const maxDuration = 100 * time.Millisecond
    75  		r := rpcz.NewRPCZ(&rpcz.Config{
    76  			Fraction: 1.0,
    77  			Capacity: 1,
    78  			ShouldRecord: func(s rpcz.Span) bool {
    79  				return s.EndTime().Sub(s.StartTime()) > maxDuration
    80  			},
    81  		})
    82  		s, ender := r.NewChild("slow one")
    83  		id := s.ID()
    84  		// to mimic some time-consuming operation.
    85  		time.Sleep(150 * time.Millisecond)
    86  		ender.End()
    87  		readOnlySpan, _ := r.Query(id)
    88  		require.Contains(t, readOnlySpan.Name, "slow one")
    89  
    90  		s, ender = r.NewChild("fast one")
    91  		id = s.ID()
    92  		ender.End()
    93  		_, ok := r.Query(id)
    94  		require.False(t, ok)
    95  	})
    96  	t.Run("checking Events", func(t *testing.T) {
    97  		const specialEvent = "leave func"
    98  		r := rpcz.NewRPCZ(&rpcz.Config{
    99  			Fraction: 1.0,
   100  			Capacity: 1,
   101  			ShouldRecord: func(s rpcz.Span) bool {
   102  				_, ok := s.Event(specialEvent)
   103  				return ok
   104  			},
   105  		})
   106  		s, ender := r.NewChild("doesn't contain special event")
   107  		id := s.ID()
   108  		s.AddEvent("enter func")
   109  		ender.End()
   110  		_, ok := r.Query(id)
   111  		require.False(t, ok)
   112  
   113  		s, ender = r.NewChild("contain special event")
   114  		id = s.ID()
   115  		s.AddEvent(specialEvent)
   116  		ender.End()
   117  		readOnlySpan, _ := r.Query(id)
   118  		require.Equal(t, specialEvent, readOnlySpan.Events[0].Name)
   119  	})
   120  }