Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
package trace
import (
"context"
"time"
"github.com/google/uuid"
"go-micro.dev/v4/util/ring"
)
type memTracer struct {
// ring buffer of traces
buffer *ring.Buffer
opts Options
}
func (t *memTracer) Read(opts ...ReadOption) ([]*Span, error) {
var options ReadOptions
for _, o := range opts {
o(&options)
}
sp := t.buffer.Get(t.buffer.Size())
spans := make([]*Span, 0, len(sp))
for _, span := range sp {
val := span.Value.(*Span)
// skip if trace id is specified and doesn't match
if len(options.Trace) > 0 && val.Trace != options.Trace {
continue
}
spans = append(spans, val)
}
return spans, nil
}
func (t *memTracer) Start(ctx context.Context, name string) (context.Context, *Span) {
span := &Span{
Name: name,
Trace: uuid.New().String(),
Id: uuid.New().String(),
Started: time.Now(),
Metadata: make(map[string]string),
}
// return span if no context
if ctx == nil {
return ToContext(context.Background(), span.Trace, span.Id), span
}
traceID, parentSpanID, ok := FromContext(ctx)
// If the trace can not be found in the header,
// that means this is where the trace is created.
if !ok {
return ToContext(ctx, span.Trace, span.Id), span
}
// set trace id
span.Trace = traceID
// set parent
span.Parent = parentSpanID
// return the span
return ToContext(ctx, span.Trace, span.Id), span
}
func (t *memTracer) Finish(s *Span) error {
// set finished time
s.Duration = time.Since(s.Started)
// save the span
t.buffer.Put(s)
return nil
}
func NewTracer(opts ...Option) Tracer {
var options Options
for _, o := range opts {
o(&options)
}
return &memTracer{
opts: options,
// the last 256 requests
buffer: ring.New(256),
}
}
+21
View File
@@ -0,0 +1,21 @@
package trace
import "context"
type noop struct{}
func (n *noop) Init(...Option) error {
return nil
}
func (n *noop) Start(ctx context.Context, name string) (context.Context, *Span) {
return nil, nil
}
func (n *noop) Finish(*Span) error {
return nil
}
func (n *noop) Read(...ReadOption) ([]*Span, error) {
return nil, nil
}
+34
View File
@@ -0,0 +1,34 @@
package trace
type Options struct {
// Size is the size of ring buffer
Size int
}
type Option func(o *Options)
type ReadOptions struct {
// Trace id
Trace string
}
type ReadOption func(o *ReadOptions)
// Read the given trace.
func ReadTrace(t string) ReadOption {
return func(o *ReadOptions) {
o.Trace = t
}
}
const (
// DefaultSize of the buffer.
DefaultSize = 64
)
// DefaultOptions returns default options.
func DefaultOptions() Options {
return Options{
Size: DefaultSize,
}
}
+82
View File
@@ -0,0 +1,82 @@
// Package trace provides an interface for distributed tracing
package trace
import (
"context"
"time"
"go-micro.dev/v4/metadata"
"go-micro.dev/v4/transport/headers"
)
var (
// DefaultTracer is the default tracer.
DefaultTracer = NewTracer()
)
// Tracer is an interface for distributed tracing.
type Tracer interface {
// Start a trace
Start(ctx context.Context, name string) (context.Context, *Span)
// Finish the trace
Finish(*Span) error
// Read the traces
Read(...ReadOption) ([]*Span, error)
}
// SpanType describe the nature of the trace span.
type SpanType int
const (
// SpanTypeRequestInbound is a span created when serving a request.
SpanTypeRequestInbound SpanType = iota
// SpanTypeRequestOutbound is a span created when making a service call.
SpanTypeRequestOutbound
)
// Span is used to record an entry.
type Span struct {
// Start time
Started time.Time
// associated data
Metadata map[string]string
// Id of the trace
Trace string
// name of the span
Name string
// id of the span
Id string
// parent span id
Parent string
// Duration in nano seconds
Duration time.Duration
// Type
Type SpanType
}
// FromContext returns a span from context.
func FromContext(ctx context.Context) (traceID string, parentSpanID string, isFound bool) {
traceID, traceOk := metadata.Get(ctx, headers.TraceIDKey)
microID, microOk := metadata.Get(ctx, headers.ID)
if !traceOk && !microOk {
isFound = false
return
}
if !traceOk {
traceID = microID
}
parentSpanID, ok := metadata.Get(ctx, headers.SpanID)
return traceID, parentSpanID, ok
}
// ToContext saves the trace and span ids in the context.
func ToContext(ctx context.Context, traceID, parentSpanID string) context.Context {
return metadata.MergeContext(ctx, map[string]string{
headers.TraceIDKey: traceID,
headers.SpanID: parentSpanID,
}, true)
}