github.com/jincm/wesharechain@v0.0.0-20210122032815-1537409ce26a/chain/swarm/tracing/tracing.go (about) 1 package tracing 2 3 import ( 4 "context" 5 "io" 6 "os" 7 "strings" 8 "sync" 9 "time" 10 11 "github.com/ethereum/go-ethereum/log" 12 "github.com/ethereum/go-ethereum/swarm/spancontext" 13 14 opentracing "github.com/opentracing/opentracing-go" 15 jaeger "github.com/uber/jaeger-client-go" 16 jaegercfg "github.com/uber/jaeger-client-go/config" 17 cli "gopkg.in/urfave/cli.v1" 18 ) 19 20 var ( 21 // Enabled turns tracing on for the current swarm instance 22 Enabled bool = false 23 store = spanStore{} 24 ) 25 26 const ( 27 // TracingEnabledFlag is the CLI flag name to use to enable trace collections. 28 TracingEnabledFlag = "tracing" 29 30 // StoreLabelId is the context value key of the name of the span to be saved 31 StoreLabelId = "span_save_id" 32 33 // StoreLabelMeta is the context value key that together with StoreLabelId constitutes the retrieval key for saved spans in the span store 34 // StartSaveSpan and ShiftSpanByKey 35 StoreLabelMeta = "span_save_meta" 36 ) 37 38 var ( 39 Closer io.Closer 40 ) 41 42 var ( 43 TracingFlag = cli.BoolFlag{ 44 Name: TracingEnabledFlag, 45 Usage: "Enable tracing", 46 } 47 TracingEndpointFlag = cli.StringFlag{ 48 Name: "tracing.endpoint", 49 Usage: "Tracing endpoint", 50 Value: "0.0.0.0:6831", 51 } 52 TracingSvcFlag = cli.StringFlag{ 53 Name: "tracing.svc", 54 Usage: "Tracing service name", 55 Value: "swarm", 56 } 57 ) 58 59 // Flags holds all command-line flags required for tracing collection. 60 var Flags = []cli.Flag{ 61 TracingFlag, 62 TracingEndpointFlag, 63 TracingSvcFlag, 64 } 65 66 // Init enables or disables the open tracing system. 67 func init() { 68 for _, arg := range os.Args { 69 if flag := strings.TrimLeft(arg, "-"); flag == TracingEnabledFlag { 70 Enabled = true 71 } 72 } 73 } 74 75 func Setup(ctx *cli.Context) { 76 if Enabled { 77 log.Info("Enabling opentracing") 78 var ( 79 endpoint = ctx.GlobalString(TracingEndpointFlag.Name) 80 svc = ctx.GlobalString(TracingSvcFlag.Name) 81 ) 82 83 Closer = initTracer(endpoint, svc) 84 } 85 } 86 87 func initTracer(endpoint, svc string) (closer io.Closer) { 88 // Sample configuration for testing. Use constant sampling to sample every trace 89 // and enable LogSpan to log every span via configured Logger. 90 cfg := jaegercfg.Configuration{ 91 Sampler: &jaegercfg.SamplerConfig{ 92 Type: jaeger.SamplerTypeConst, 93 Param: 1, 94 }, 95 Reporter: &jaegercfg.ReporterConfig{ 96 LogSpans: true, 97 BufferFlushInterval: 1 * time.Second, 98 LocalAgentHostPort: endpoint, 99 }, 100 } 101 102 // Example logger and metrics factory. Use github.com/uber/jaeger-client-go/log 103 // and github.com/uber/jaeger-lib/metrics respectively to bind to real logging and metrics 104 // frameworks. 105 //jLogger := jaegerlog.StdLogger 106 //jMetricsFactory := metrics.NullFactory 107 108 // Initialize tracer with a logger and a metrics factory 109 closer, err := cfg.InitGlobalTracer( 110 svc, 111 //jaegercfg.Logger(jLogger), 112 //jaegercfg.Metrics(jMetricsFactory), 113 //jaegercfg.Observer(rpcmetrics.NewObserver(jMetricsFactory, rpcmetrics.DefaultNameNormalizer)), 114 ) 115 if err != nil { 116 log.Error("Could not initialize Jaeger tracer", "err", err) 117 } 118 119 return closer 120 } 121 122 // spanStore holds saved spans 123 type spanStore struct { 124 spans sync.Map 125 } 126 127 // StartSaveSpan stores the span specified in the passed context for later retrieval 128 // The span object but be context value on the key StoreLabelId. 129 // It will be stored under the the following string key context.Value(StoreLabelId)|.|context.Value(StoreLabelMeta) 130 func StartSaveSpan(ctx context.Context) context.Context { 131 if !Enabled { 132 return ctx 133 } 134 traceId := ctx.Value(StoreLabelId) 135 136 if traceId != nil { 137 traceStr := traceId.(string) 138 var sp opentracing.Span 139 ctx, sp = spancontext.StartSpan( 140 ctx, 141 traceStr, 142 ) 143 traceMeta := ctx.Value(StoreLabelMeta) 144 if traceMeta != nil { 145 traceStr = traceStr + "." + traceMeta.(string) 146 } 147 store.spans.Store(traceStr, sp) 148 } 149 return ctx 150 } 151 152 // ShiftSpanByKey retrieves the span stored under the key of the string given as argument 153 // The span is then deleted from the store 154 func ShiftSpanByKey(k string) opentracing.Span { 155 if !Enabled { 156 return nil 157 } 158 span, spanOk := store.spans.Load(k) 159 if !spanOk { 160 return nil 161 } 162 store.spans.Delete(k) 163 return span.(opentracing.Span) 164 } 165 166 // FinishSpans calls `Finish()` on all stored spans 167 // It should be called on instance shutdown 168 func FinishSpans() { 169 store.spans.Range(func(_, v interface{}) bool { 170 v.(opentracing.Span).Finish() 171 return true 172 }) 173 }