-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tracegen utility for generating traces (#1245)
Add tracegen utility for generating traces. Signed-off-by: Yuri Shkuro <[email protected]>
- Loading branch information
1 parent
bda811b
commit 48b034c
Showing
4 changed files
with
240 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright (c) 2018 The Jaeger Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package main | ||
|
||
import ( | ||
"flag" | ||
"time" | ||
|
||
"github.com/opentracing/opentracing-go" | ||
jaegerConfig "github.com/uber/jaeger-client-go/config" | ||
jaegerZap "github.com/uber/jaeger-client-go/log/zap" | ||
"github.com/uber/jaeger-lib/metrics/prometheus" | ||
"go.uber.org/zap" | ||
|
||
"github.com/jaegertracing/jaeger/internal/tracegen" | ||
) | ||
|
||
var logger, _ = zap.NewDevelopment() | ||
|
||
func main() { | ||
fs := flag.CommandLine | ||
cfg := new(tracegen.Config) | ||
cfg.Flags(fs) | ||
flag.Parse() | ||
|
||
metricsFactory := prometheus.New() | ||
tracer, tCloser, err := jaegerConfig.Configuration{ | ||
ServiceName: "tracegen", | ||
Sampler: &jaegerConfig.SamplerConfig{ | ||
Type: "const", | ||
Param: 1, | ||
}, | ||
}.NewTracer( | ||
jaegerConfig.Metrics(metricsFactory), | ||
jaegerConfig.Logger(jaegerZap.NewLogger(logger)), | ||
) | ||
if err != nil { | ||
logger.Fatal("failed to create tracer", zap.Error(err)) | ||
} | ||
defer tCloser.Close() | ||
|
||
opentracing.InitGlobalTracer(tracer) | ||
logger.Info("Initialized global tracer") | ||
|
||
tracegen.Run(cfg, logger) | ||
|
||
logger.Info("Waiting 1.5sec for metrics to flush") | ||
time.Sleep(3 * time.Second / 2) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Test utility |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright (c) 2018 The Jaeger Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package tracegen | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"sync" | ||
"sync/atomic" | ||
"time" | ||
|
||
"go.uber.org/zap" | ||
) | ||
|
||
// Config describes the test scenario. | ||
type Config struct { | ||
Workers int | ||
Traces int | ||
Marshal bool | ||
Debug bool | ||
Pause time.Duration | ||
Duration time.Duration | ||
} | ||
|
||
// Flags registers config flags. | ||
func (c *Config) Flags(fs *flag.FlagSet) { | ||
fs.IntVar(&c.Workers, "workers", 1, "Number of workers (goroutines) to run") | ||
fs.IntVar(&c.Traces, "traces", 1, "Number of traces to generate in each worker (ignored if duration is provided") | ||
fs.BoolVar(&c.Marshal, "marshal", false, "Whether to marshal trace context via HTTP headers") | ||
fs.BoolVar(&c.Debug, "debug", false, "Whether to set DEBUG flag on the spans to force sampling") | ||
fs.DurationVar(&c.Pause, "pause", time.Microsecond, "How long to pause before finishing trace") | ||
fs.DurationVar(&c.Duration, "duration", 0, "For how long to run the test") | ||
} | ||
|
||
// Run executes the test scenario. | ||
func Run(c *Config, logger *zap.Logger) error { | ||
if c.Duration > 0 { | ||
c.Traces = 0 | ||
} else if c.Traces <= 0 { | ||
return fmt.Errorf("Either `traces` or `duration` must be greater than 0") | ||
} | ||
|
||
wg := sync.WaitGroup{} | ||
var running uint32 = 1 | ||
for i := 0; i < c.Workers; i++ { | ||
wg.Add(1) | ||
w := worker{ | ||
id: i, | ||
traces: c.Traces, | ||
marshal: c.Marshal, | ||
debug: c.Debug, | ||
pause: c.Pause, | ||
duration: c.Duration, | ||
running: &running, | ||
wg: &wg, | ||
logger: logger.With(zap.Int("worker", i)), | ||
} | ||
|
||
go w.simulateTraces() | ||
} | ||
if c.Duration > 0 { | ||
time.Sleep(c.Duration) | ||
atomic.StoreUint32(&running, 0) | ||
} | ||
wg.Wait() | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright (c) 2018 The Jaeger Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package tracegen | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"sync/atomic" | ||
"time" | ||
|
||
"github.com/opentracing/opentracing-go" | ||
"github.com/opentracing/opentracing-go/ext" | ||
"go.uber.org/zap" | ||
) | ||
|
||
type worker struct { | ||
running *uint32 // pointer to shared flag that indicates it's time to stop the test | ||
id int // worker id | ||
traces int // how many traces the worker has to generate (only when duration==0) | ||
marshal bool // whether the worker needs to marshal trace context via HTTP headers | ||
debug bool // whether to set DEBUG flag on the spans | ||
duration time.Duration // how long to run the test for (overrides `traces`) | ||
pause time.Duration // how long to pause before finishing the trace | ||
wg *sync.WaitGroup // notify when done | ||
logger *zap.Logger | ||
} | ||
|
||
const ( | ||
fakeIP uint32 = 1<<24 | 2<<16 | 3<<8 | 4 | ||
|
||
fakeSpanDuration = 123 * time.Microsecond | ||
) | ||
|
||
func (w worker) simulateTraces() { | ||
tracer := opentracing.GlobalTracer() | ||
var i int | ||
for atomic.LoadUint32(w.running) == 1 { | ||
sp := tracer.StartSpan("lets-go") | ||
ext.SpanKindRPCClient.Set(sp) | ||
ext.PeerHostIPv4.Set(sp, fakeIP) | ||
ext.PeerService.Set(sp, "tracegen-server") | ||
if w.debug { | ||
ext.SamplingPriority.Set(sp, 100) | ||
} | ||
|
||
childCtx := sp.Context() | ||
if w.marshal { | ||
m := make(map[string]string) | ||
c := opentracing.TextMapCarrier(m) | ||
if err := tracer.Inject(sp.Context(), opentracing.TextMap, c); err == nil { | ||
c := opentracing.TextMapCarrier(m) | ||
childCtx, err = tracer.Extract(opentracing.TextMap, c) | ||
if err != nil { | ||
w.logger.Error("cannot extract from TextMap", zap.Error(err)) | ||
} | ||
} else { | ||
w.logger.Error("cannot inject span", zap.Error(err)) | ||
} | ||
} | ||
child := opentracing.StartSpan( | ||
"okey-dokey", | ||
ext.RPCServerOption(childCtx), | ||
) | ||
ext.PeerHostIPv4.Set(child, fakeIP) | ||
ext.PeerService.Set(child, "tracegen-client") | ||
|
||
time.Sleep(w.pause) | ||
|
||
if w.pause == 0 { | ||
child.Finish() | ||
sp.Finish() | ||
} else { | ||
opt := opentracing.FinishOptions{FinishTime: time.Now().Add(fakeSpanDuration)} | ||
child.FinishWithOptions(opt) | ||
sp.FinishWithOptions(opt) | ||
} | ||
|
||
i++ | ||
if w.traces != 0 { | ||
if i >= w.traces { | ||
break | ||
} | ||
} | ||
} | ||
w.logger.Info(fmt.Sprintf("Worker %d generated %d traces", w.id, i)) | ||
w.wg.Done() | ||
} |