* swarm/newtork: WIP Span request span until delivery and put * swarm/storage: Introduce new trace across single fetcher lifespan * swarm/network: Put span ids for sendpriority in context value * swarm: Add global span store in tracing * swarm/tracing: Add context key constants * swarm/tracing: Add comments * swarm/storage: Remove redundant fix for filestore * swarm/tracing: Elaborate constants comments * swarm/network, swarm/storage, swarm:tracing: Minor cleanup
		
			
				
	
	
		
			174 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package tracing
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"strings"
 | 
						|
	"sync"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/ethereum/go-ethereum/log"
 | 
						|
	"github.com/ethereum/go-ethereum/swarm/spancontext"
 | 
						|
 | 
						|
	opentracing "github.com/opentracing/opentracing-go"
 | 
						|
	jaeger "github.com/uber/jaeger-client-go"
 | 
						|
	jaegercfg "github.com/uber/jaeger-client-go/config"
 | 
						|
	cli "gopkg.in/urfave/cli.v1"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	// Enabled turns tracing on for the current swarm instance
 | 
						|
	Enabled bool = false
 | 
						|
	store        = spanStore{}
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	// TracingEnabledFlag is the CLI flag name to use to enable trace collections.
 | 
						|
	TracingEnabledFlag = "tracing"
 | 
						|
 | 
						|
	// StoreLabelId is the context value key of the name of the span to be saved
 | 
						|
	StoreLabelId = "span_save_id"
 | 
						|
 | 
						|
	// StoreLabelMeta is the context value key that together with StoreLabelId constitutes the retrieval key for saved spans in the span store
 | 
						|
	// StartSaveSpan and ShiftSpanByKey
 | 
						|
	StoreLabelMeta = "span_save_meta"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	Closer io.Closer
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	TracingFlag = cli.BoolFlag{
 | 
						|
		Name:  TracingEnabledFlag,
 | 
						|
		Usage: "Enable tracing",
 | 
						|
	}
 | 
						|
	TracingEndpointFlag = cli.StringFlag{
 | 
						|
		Name:  "tracing.endpoint",
 | 
						|
		Usage: "Tracing endpoint",
 | 
						|
		Value: "0.0.0.0:6831",
 | 
						|
	}
 | 
						|
	TracingSvcFlag = cli.StringFlag{
 | 
						|
		Name:  "tracing.svc",
 | 
						|
		Usage: "Tracing service name",
 | 
						|
		Value: "swarm",
 | 
						|
	}
 | 
						|
)
 | 
						|
 | 
						|
// Flags holds all command-line flags required for tracing collection.
 | 
						|
var Flags = []cli.Flag{
 | 
						|
	TracingFlag,
 | 
						|
	TracingEndpointFlag,
 | 
						|
	TracingSvcFlag,
 | 
						|
}
 | 
						|
 | 
						|
// Init enables or disables the open tracing system.
 | 
						|
func init() {
 | 
						|
	for _, arg := range os.Args {
 | 
						|
		if flag := strings.TrimLeft(arg, "-"); flag == TracingEnabledFlag {
 | 
						|
			Enabled = true
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func Setup(ctx *cli.Context) {
 | 
						|
	if Enabled {
 | 
						|
		log.Info("Enabling opentracing")
 | 
						|
		var (
 | 
						|
			endpoint = ctx.GlobalString(TracingEndpointFlag.Name)
 | 
						|
			svc      = ctx.GlobalString(TracingSvcFlag.Name)
 | 
						|
		)
 | 
						|
 | 
						|
		Closer = initTracer(endpoint, svc)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func initTracer(endpoint, svc string) (closer io.Closer) {
 | 
						|
	// Sample configuration for testing. Use constant sampling to sample every trace
 | 
						|
	// and enable LogSpan to log every span via configured Logger.
 | 
						|
	cfg := jaegercfg.Configuration{
 | 
						|
		Sampler: &jaegercfg.SamplerConfig{
 | 
						|
			Type:  jaeger.SamplerTypeConst,
 | 
						|
			Param: 1,
 | 
						|
		},
 | 
						|
		Reporter: &jaegercfg.ReporterConfig{
 | 
						|
			LogSpans:            true,
 | 
						|
			BufferFlushInterval: 1 * time.Second,
 | 
						|
			LocalAgentHostPort:  endpoint,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	// Example logger and metrics factory. Use github.com/uber/jaeger-client-go/log
 | 
						|
	// and github.com/uber/jaeger-lib/metrics respectively to bind to real logging and metrics
 | 
						|
	// frameworks.
 | 
						|
	//jLogger := jaegerlog.StdLogger
 | 
						|
	//jMetricsFactory := metrics.NullFactory
 | 
						|
 | 
						|
	// Initialize tracer with a logger and a metrics factory
 | 
						|
	closer, err := cfg.InitGlobalTracer(
 | 
						|
		svc,
 | 
						|
		//jaegercfg.Logger(jLogger),
 | 
						|
		//jaegercfg.Metrics(jMetricsFactory),
 | 
						|
		//jaegercfg.Observer(rpcmetrics.NewObserver(jMetricsFactory, rpcmetrics.DefaultNameNormalizer)),
 | 
						|
	)
 | 
						|
	if err != nil {
 | 
						|
		log.Error("Could not initialize Jaeger tracer", "err", err)
 | 
						|
	}
 | 
						|
 | 
						|
	return closer
 | 
						|
}
 | 
						|
 | 
						|
// spanStore holds saved spans
 | 
						|
type spanStore struct {
 | 
						|
	spans sync.Map
 | 
						|
}
 | 
						|
 | 
						|
// StartSaveSpan stores the span specified in the passed context for later retrieval
 | 
						|
// The span object but be context value on the key StoreLabelId.
 | 
						|
// It will be stored under the the following string key context.Value(StoreLabelId)|.|context.Value(StoreLabelMeta)
 | 
						|
func StartSaveSpan(ctx context.Context) context.Context {
 | 
						|
	if !Enabled {
 | 
						|
		return ctx
 | 
						|
	}
 | 
						|
	traceId := ctx.Value(StoreLabelId)
 | 
						|
 | 
						|
	if traceId != nil {
 | 
						|
		traceStr := traceId.(string)
 | 
						|
		var sp opentracing.Span
 | 
						|
		ctx, sp = spancontext.StartSpan(
 | 
						|
			ctx,
 | 
						|
			traceStr,
 | 
						|
		)
 | 
						|
		traceMeta := ctx.Value(StoreLabelMeta)
 | 
						|
		if traceMeta != nil {
 | 
						|
			traceStr = traceStr + "." + traceMeta.(string)
 | 
						|
		}
 | 
						|
		store.spans.Store(traceStr, sp)
 | 
						|
	}
 | 
						|
	return ctx
 | 
						|
}
 | 
						|
 | 
						|
// ShiftSpanByKey retrieves the span stored under the key of the string given as argument
 | 
						|
// The span is then deleted from the store
 | 
						|
func ShiftSpanByKey(k string) opentracing.Span {
 | 
						|
	if !Enabled {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	span, spanOk := store.spans.Load(k)
 | 
						|
	if !spanOk {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	store.spans.Delete(k)
 | 
						|
	return span.(opentracing.Span)
 | 
						|
}
 | 
						|
 | 
						|
// FinishSpans calls `Finish()` on all stored spans
 | 
						|
// It should be called on instance shutdown
 | 
						|
func FinishSpans() {
 | 
						|
	store.spans.Range(func(_, v interface{}) bool {
 | 
						|
		v.(opentracing.Span).Finish()
 | 
						|
		return true
 | 
						|
	})
 | 
						|
}
 |