Example #1
0
func createRandomTestSpans(amount int) common.SpanSlice {
	rnd := rand.New(rand.NewSource(2))
	allSpans := make(common.SpanSlice, amount)
	allSpans[0] = test.NewRandomSpan(rnd, allSpans[0:0])
	for i := 1; i < amount; i++ {
		allSpans[i] = test.NewRandomSpan(rnd, allSpans[1:i])
	}
	allSpans[1].SpanData.Parents = []common.SpanId{common.SpanId(allSpans[0].Id)}
	return allSpans
}
func BenchmarkDatastoreWrites(b *testing.B) {
	htraceBld := &MiniHTracedBuilder{Name: "BenchmarkDatastoreWrites",
		WrittenSpans: make(chan *common.Span, b.N)}
	ht, err := htraceBld.Build()
	if err != nil {
		panic(err)
	}
	defer ht.Close()
	rnd := rand.New(rand.NewSource(1))
	allSpans := make([]*common.Span, b.N)
	// Write many random spans.
	for n := 0; n < b.N; n++ {
		span := test.NewRandomSpan(rnd, allSpans[0:n])
		ht.Store.WriteSpan(span)
		allSpans[n] = span
	}
	// Wait for all the spans to be written.
	for n := 0; n < b.N; n++ {
		<-ht.Store.WrittenSpans
	}
	spansWritten := ht.Store.GetStatistics().NumSpansWritten
	if spansWritten < uint64(b.N) {
		b.Fatal("incorrect statistics: expected %d spans to be written, but only got %d",
			b.N, spansWritten)
	}
}
func TestReapingOldSpans(t *testing.T) {
	const NUM_TEST_SPANS = 20
	testSpans := make([]*common.Span, NUM_TEST_SPANS)
	rnd := rand.New(rand.NewSource(2))
	now := common.TimeToUnixMs(time.Now().UTC())
	for i := range testSpans {
		testSpans[i] = test.NewRandomSpan(rnd, testSpans[0:i])
		testSpans[i].Begin = now - int64(NUM_TEST_SPANS-1-i)
		testSpans[i].Description = fmt.Sprintf("Span%02d", i)
	}
	htraceBld := &MiniHTracedBuilder{Name: "TestReapingOldSpans",
		Cnf: map[string]string{
			conf.HTRACE_SPAN_EXPIRY_MS:                fmt.Sprintf("%d", 60*60*1000),
			conf.HTRACE_REAPER_HEARTBEAT_PERIOD_MS:    "1",
			conf.HTRACE_DATASTORE_HEARTBEAT_PERIOD_MS: "1",
		},
		WrittenSpans: common.NewSemaphore(0),
		DataDirs:     make([]string, 2),
	}
	ht, err := htraceBld.Build()
	if err != nil {
		t.Fatalf("failed to create mini htraced cluster: %s\n", err.Error())
	}
	ing := ht.Store.NewSpanIngestor(ht.Store.lg, "127.0.0.1", "")
	for spanIdx := range testSpans {
		ing.IngestSpan(testSpans[spanIdx])
	}
	ing.Close(time.Now())
	// Wait the spans to be created
	ht.Store.WrittenSpans.Waits(NUM_TEST_SPANS)
	// Set a reaper date that will remove all the spans except final one.
	ht.Store.rpr.SetReaperDate(now)

	common.WaitFor(5*time.Minute, time.Millisecond, func() bool {
		for i := 0; i < NUM_TEST_SPANS-1; i++ {
			span := ht.Store.FindSpan(testSpans[i].Id)
			if span != nil {
				ht.Store.lg.Debugf("Waiting for %s to be removed...\n",
					testSpans[i].Description)
				return false
			}
		}
		span := ht.Store.FindSpan(testSpans[NUM_TEST_SPANS-1].Id)
		if span == nil {
			ht.Store.lg.Debugf("Did not expect %s to be removed\n",
				testSpans[NUM_TEST_SPANS-1].Description)
			return false
		}
		return true
	})
	defer ht.Close()
}
Example #4
0
func BenchmarkDatastoreWrites(b *testing.B) {
	htraceBld := &MiniHTracedBuilder{Name: "BenchmarkDatastoreWrites",
		Cnf: map[string]string{
			conf.HTRACE_DATASTORE_HEARTBEAT_PERIOD_MS: "30000",
			conf.HTRACE_LOG_LEVEL:                     "INFO",
		},
		WrittenSpans: common.NewSemaphore(0),
	}
	ht, err := htraceBld.Build()
	if err != nil {
		b.Fatalf("Error creating MiniHTraced: %s\n", err.Error())
	}
	ht.Store.lg.Infof("BenchmarkDatastoreWrites: b.N = %d\n", b.N)
	defer func() {
		if r := recover(); r != nil {
			ht.Store.lg.Infof("panic: %s\n", r.(error))
		}
		ht.Close()
	}()
	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
	allSpans := make([]*common.Span, b.N)
	for n := range allSpans {
		allSpans[n] = test.NewRandomSpan(rnd, allSpans[0:n])
	}

	// Reset the timer to avoid including the time required to create new
	// random spans in the benchmark total.
	b.ResetTimer()

	// Write many random spans.
	ing := ht.Store.NewSpanIngestor(ht.Store.lg, "127.0.0.1", "")
	for n := 0; n < b.N; n++ {
		ing.IngestSpan(allSpans[n])
	}
	ing.Close(time.Now())
	// Wait for all the spans to be written.
	ht.Store.WrittenSpans.Waits(int64(b.N))
	assertNumWrittenEquals(b, ht.Store.msink, b.N)
}
func doWriteSpans(name string, N int, maxSpansPerRpc uint32, b *testing.B) {
	htraceBld := &MiniHTracedBuilder{Name: "doWriteSpans",
		Cnf: map[string]string{
			conf.HTRACE_LOG_LEVEL:         "INFO",
			conf.HTRACE_NUM_HRPC_HANDLERS: "20",
		},
		WrittenSpans: common.NewSemaphore(int64(1 - N)),
	}
	ht, err := htraceBld.Build()
	if err != nil {
		panic(err)
	}
	defer ht.Close()
	rnd := rand.New(rand.NewSource(1))
	allSpans := make([]*common.Span, N)
	for n := 0; n < N; n++ {
		allSpans[n] = test.NewRandomSpan(rnd, allSpans[0:n])
	}
	// Determine how many calls to WriteSpans we should make.  Each writeSpans
	// message should be small enough so that it doesn't exceed the max RPC
	// body length limit.  TODO: a production-quality golang client would do
	// this internally rather than needing us to do it here in the unit test.
	bodyLen := (4 * common.MAX_HRPC_BODY_LENGTH) / 5
	reqs := make([][]*common.Span, 0, 4)
	curReq := -1
	curReqLen := bodyLen
	var curReqSpans uint32
	mh := new(codec.MsgpackHandle)
	mh.WriteExt = true
	var mbuf [8192]byte
	buf := mbuf[:0]
	enc := codec.NewEncoderBytes(&buf, mh)
	for n := 0; n < N; n++ {
		span := allSpans[n]
		if (curReqSpans >= maxSpansPerRpc) ||
			(curReqLen >= bodyLen) {
			reqs = append(reqs, make([]*common.Span, 0, 16))
			curReqLen = 0
			curReq++
			curReqSpans = 0
		}
		buf = mbuf[:0]
		enc.ResetBytes(&buf)
		err := enc.Encode(span)
		if err != nil {
			panic(fmt.Sprintf("Error encoding span %s: %s\n",
				span.String(), err.Error()))
		}
		bufLen := len(buf)
		if bufLen > (bodyLen / 5) {
			panic(fmt.Sprintf("Span too long at %d bytes\n", bufLen))
		}
		curReqLen += bufLen
		reqs[curReq] = append(reqs[curReq], span)
		curReqSpans++
	}
	ht.Store.lg.Infof("num spans: %d.  num WriteSpansReq calls: %d\n", N, len(reqs))
	var hcl *htrace.Client
	hcl, err = htrace.NewClient(ht.ClientConf(), nil)
	if err != nil {
		panic(fmt.Sprintf("failed to create client: %s", err.Error()))
	}
	defer hcl.Close()

	// Reset the timer to avoid including the time required to create new
	// random spans in the benchmark total.
	if b != nil {
		b.ResetTimer()
	}

	// Write many random spans.
	for reqIdx := range reqs {
		go func(i int) {
			err = hcl.WriteSpans(reqs[i])
			if err != nil {
				panic(fmt.Sprintf("failed to send WriteSpans request %d: %s",
					i, err.Error()))
			}
		}(reqIdx)
	}
	// Wait for all the spans to be written.
	ht.Store.WrittenSpans.Wait()
}