github.com/matrixorigin/matrixone@v0.7.0/pkg/util/trace/config.go (about)

     1  // Copyright The OpenTelemetry Authors
     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  // Portions of this file are additionally subject to the following
    16  // copyright.
    17  //
    18  // Copyright (C) 2022 Matrix Origin.
    19  //
    20  // Modified the behavior and the interface of the step.
    21  
    22  package trace
    23  
    24  import (
    25  	"bytes"
    26  	"context"
    27  	"encoding/hex"
    28  	"encoding/json"
    29  	"github.com/google/uuid"
    30  	"go.uber.org/zap"
    31  	"go.uber.org/zap/zapcore"
    32  	"io"
    33  )
    34  
    35  type TraceID [16]byte
    36  
    37  var NilTraceID TraceID
    38  
    39  // IsZero checks whether the trace TraceID is 0 value.
    40  func (t TraceID) IsZero() bool {
    41  	return bytes.Equal(t[:], NilTraceID[:])
    42  }
    43  
    44  func (t TraceID) String() string {
    45  	if t.IsZero() {
    46  		return "0"
    47  	}
    48  	return uuid.UUID(t).String()
    49  }
    50  
    51  type SpanID [8]byte
    52  
    53  var NilSpanID SpanID
    54  
    55  // SetByUUID use prefix of uuid as value
    56  func (s *SpanID) SetByUUID(id string) {
    57  	if u, err := uuid.Parse(id); err == nil {
    58  		copy(s[:], u[:])
    59  	} else {
    60  		copy(s[:], []byte(id)[:])
    61  	}
    62  }
    63  
    64  func (s *SpanID) IsZero() bool {
    65  	return bytes.Equal(s[:], NilSpanID[:])
    66  }
    67  
    68  func (s SpanID) String() string {
    69  	if s.IsZero() {
    70  		return "0"
    71  	}
    72  	return hex.EncodeToString(s[:])
    73  }
    74  
    75  var _ zapcore.ObjectMarshaler = (*SpanContext)(nil)
    76  
    77  const SpanFieldKey = "span"
    78  
    79  func SpanField(sc SpanContext) zap.Field {
    80  	return zap.Object(SpanFieldKey, &sc)
    81  }
    82  
    83  func IsSpanField(field zapcore.Field) bool {
    84  	return field.Key == SpanFieldKey
    85  }
    86  
    87  func ContextField(ctx context.Context) zap.Field {
    88  	return SpanField(SpanFromContext(ctx).SpanContext())
    89  }
    90  
    91  // SpanContext contains identifying trace information about a Span.
    92  type SpanContext struct {
    93  	TraceID TraceID `json:"trace_id"`
    94  	SpanID  SpanID  `json:"span_id"`
    95  	// Kind default SpanKindInternal
    96  	Kind SpanKind `json:"span_kind"`
    97  }
    98  
    99  func (c *SpanContext) Size() (n int) {
   100  	return 24
   101  }
   102  
   103  func (c *SpanContext) MarshalTo(dAtA []byte) (int, error) {
   104  	l := cap(dAtA)
   105  	if l < c.Size() {
   106  		return -1, io.ErrUnexpectedEOF
   107  	}
   108  	copy(dAtA, c.TraceID[:])
   109  	copy(dAtA[16:], c.SpanID[:])
   110  	return c.Size(), nil
   111  }
   112  
   113  // Unmarshal with default Kind: SpanKindRemote
   114  func (c *SpanContext) Unmarshal(dAtA []byte) error {
   115  	l := cap(dAtA)
   116  	if l < c.Size() {
   117  		return io.ErrUnexpectedEOF
   118  	}
   119  	copy(c.TraceID[:], dAtA[0:16])
   120  	copy(c.SpanID[:], dAtA[16:24])
   121  	c.Kind = SpanKindRemote
   122  	return nil
   123  }
   124  
   125  func (c SpanContext) GetIDs() (TraceID, SpanID) {
   126  	return c.TraceID, c.SpanID
   127  }
   128  
   129  func (c *SpanContext) Reset() {
   130  	c.TraceID = NilTraceID
   131  	c.SpanID = NilSpanID
   132  	c.Kind = SpanKindInternal
   133  }
   134  
   135  func (c *SpanContext) IsEmpty() bool {
   136  	return c.TraceID.IsZero() && c.SpanID.IsZero()
   137  }
   138  
   139  // MarshalLogObject implement zapcore.ObjectMarshaler
   140  func (c *SpanContext) MarshalLogObject(enc zapcore.ObjectEncoder) error {
   141  	if !c.TraceID.IsZero() {
   142  		enc.AddString("trace_id", c.TraceID.String())
   143  	}
   144  	if !c.SpanID.IsZero() {
   145  		enc.AddString("span_id", c.SpanID.String())
   146  	}
   147  	if c.Kind != SpanKindInternal {
   148  		enc.AddString("kind", c.Kind.String())
   149  	}
   150  	return nil
   151  }
   152  
   153  func SpanContextWithID(id TraceID, kind SpanKind) SpanContext {
   154  	return SpanContext{TraceID: id, Kind: kind}
   155  }
   156  
   157  // SpanContextWithIDs with default Kind: SpanKindInternal
   158  func SpanContextWithIDs(tid TraceID, sid SpanID) SpanContext {
   159  	return SpanContext{TraceID: tid, SpanID: sid, Kind: SpanKindInternal}
   160  }
   161  
   162  // SpanConfig is a group of options for a Span.
   163  type SpanConfig struct {
   164  	SpanContext
   165  
   166  	// NewRoot identifies a Span as the root Span for a new trace. This is
   167  	// commonly used when an existing trace crosses trust boundaries and the
   168  	// remote parent span context should be ignored for security.
   169  	NewRoot bool `json:"NewRoot"` // WithNewRoot
   170  	Parent  Span `json:"-"`
   171  }
   172  
   173  // SpanStartOption applies an option to a SpanConfig. These options are applicable
   174  // only when the span is created.
   175  type SpanStartOption interface {
   176  	ApplySpanStart(*SpanConfig)
   177  }
   178  
   179  type SpanEndOption interface {
   180  	ApplySpanEnd(*SpanConfig)
   181  }
   182  
   183  // SpanOption applies an option to a SpanConfig.
   184  type SpanOption interface {
   185  	SpanStartOption
   186  	SpanEndOption
   187  }
   188  
   189  type spanOptionFunc func(*SpanConfig)
   190  
   191  func (f spanOptionFunc) ApplySpanEnd(cfg *SpanConfig) {
   192  	f(cfg)
   193  }
   194  
   195  func (f spanOptionFunc) ApplySpanStart(cfg *SpanConfig) {
   196  	f(cfg)
   197  }
   198  
   199  func WithNewRoot(newRoot bool) spanOptionFunc {
   200  	return spanOptionFunc(func(cfg *SpanConfig) {
   201  		cfg.NewRoot = newRoot
   202  	})
   203  }
   204  
   205  func WithKind(kind SpanKind) spanOptionFunc {
   206  	return spanOptionFunc(func(cfg *SpanConfig) {
   207  		cfg.Kind = kind
   208  	})
   209  }
   210  
   211  type Resource struct {
   212  	m map[string]any
   213  }
   214  
   215  func NewResource() *Resource {
   216  	return &Resource{m: make(map[string]any)}
   217  }
   218  
   219  func (r *Resource) Put(key string, val any) {
   220  	r.m[key] = val
   221  }
   222  
   223  func (r *Resource) Get(key string) (any, bool) {
   224  	val, has := r.m[key]
   225  	return val, has
   226  }
   227  
   228  // String need to improve
   229  func (r *Resource) String() string {
   230  	buf, _ := json.Marshal(r.m)
   231  	return string(buf)
   232  
   233  }
   234  
   235  const NodeTypeStandalone = "Standalone"
   236  
   237  type MONodeResource struct {
   238  	NodeUuid string `json:"node_uuid"`
   239  	NodeType string `json:"node_type"`
   240  }
   241  
   242  // SpanKind is the role a Span plays in a Trace.
   243  type SpanKind int
   244  
   245  const (
   246  	// SpanKindInternal is a SpanKind for a Span that represents an internal
   247  	// operation within MO.
   248  	SpanKindInternal SpanKind = 0
   249  	// SpanKindStatement is a SpanKind for a Span that represents the operation
   250  	// belong to statement query
   251  	SpanKindStatement SpanKind = 1
   252  	// SpanKindRemote is a SpanKind for a Span that represents the operation
   253  	// cross rpc
   254  	SpanKindRemote SpanKind = 2
   255  	// SpanKindSession is a SpanKind for a Span that represents the operation
   256  	// start from session
   257  	SpanKindSession SpanKind = 3
   258  )
   259  
   260  func (k SpanKind) String() string {
   261  	switch k {
   262  	case SpanKindInternal:
   263  		return "internal"
   264  	case SpanKindStatement:
   265  		return "statement"
   266  	case SpanKindRemote:
   267  		return "remote"
   268  	case SpanKindSession:
   269  		return "session"
   270  	default:
   271  		return "unknown"
   272  	}
   273  }
   274  
   275  // TracerConfig is a group of options for a Tracer.
   276  type TracerConfig struct {
   277  	Name string
   278  }
   279  
   280  // TracerOption applies an option to a TracerConfig.
   281  type TracerOption interface {
   282  	Apply(*TracerConfig)
   283  }
   284  
   285  var _ TracerOption = tracerOptionFunc(nil)
   286  
   287  type tracerOptionFunc func(*TracerConfig)
   288  
   289  func (f tracerOptionFunc) Apply(cfg *TracerConfig) {
   290  	f(cfg)
   291  }
   292  
   293  const (
   294  	// FlagsSampled is a bitmask with the sampled bit set. A SpanContext
   295  	// with the sampling bit set means the span is sampled.
   296  	FlagsSampled = TraceFlags(0x01)
   297  )
   298  
   299  // TraceFlags contains flags that can be set on a SpanContext.
   300  type TraceFlags byte //nolint:revive // revive complains about stutter of `trace.TraceFlags`.
   301  
   302  // IsSampled returns if the sampling bit is set in the TraceFlags.
   303  func (tf TraceFlags) IsSampled() bool {
   304  	return tf&FlagsSampled == FlagsSampled
   305  }
   306  
   307  // WithSampled sets the sampling bit in a new copy of the TraceFlags.
   308  func (tf TraceFlags) WithSampled(sampled bool) TraceFlags { // nolint:revive  // sampled is not a control flag.
   309  	if sampled {
   310  		return tf | FlagsSampled
   311  	}
   312  
   313  	return tf &^ FlagsSampled
   314  }
   315  
   316  // String returns the hex string representation form of TraceFlags.
   317  func (tf TraceFlags) String() string {
   318  	return hex.EncodeToString([]byte{byte(tf)}[:])
   319  }