// RecordSpan converts a RawSpan into the Appdash representation of a span // and records it to the underlying collector. func (r *Recorder) RecordSpan(sp basictracer.RawSpan) { if !sp.Sampled { return } spanID := appdash.SpanID{ Span: appdash.ID(uint64(sp.SpanID)), Trace: appdash.ID(uint64(sp.TraceID)), Parent: appdash.ID(uint64(sp.ParentSpanID)), } r.collectEvent(spanID, appdash.SpanName(sp.Operation)) // Record all of the logs. Payloads are thrown out. for _, log := range sp.Logs { r.collectEvent(spanID, appdash.LogWithTimestamp(log.Event, log.Timestamp)) } for key, value := range sp.Tags { val := []byte(fmt.Sprintf("%+v", value)) r.collectAnnotation(spanID, appdash.Annotation{Key: key, Value: val}) } for key, val := range sp.Baggage { r.collectAnnotation(spanID, appdash.Annotation{Key: key, Value: []byte(val)}) } // Add the duration to the start time to get an approximate end time. approxEndTime := sp.Start.Add(sp.Duration) r.collectEvent(spanID, appdash.Timespan{S: sp.Start, E: approxEndTime}) }
func sampleData(c appdash.Collector) error { const numTraces = 60 log.Printf("Adding sample data (%d traces)", numTraces) for i := appdash.ID(1); i <= numTraces; i++ { traceID := appdash.NewRootSpanID() traceRec := appdash.NewRecorder(traceID, c) traceRec.Name(fakeHosts[rand.Intn(len(fakeHosts))]) // A random length for the trace. length := time.Duration(rand.Intn(1000)) * time.Millisecond startTime := time.Now().Add(-time.Duration(rand.Intn(100)) * time.Minute) traceRec.Event(&sqltrace.SQLEvent{ ClientSend: startTime, ClientRecv: startTime.Add(length), SQL: "SELECT * FROM table_name;", Tag: fmt.Sprintf("fakeTag%d", rand.Intn(10)), }) // We'll split the trace into N (3-7) spans (i.e. "N operations") each with // a random duration of time adding up to the length of the trace. numSpans := rand.Intn(7-3) + 3 times := randomSplit(int(length/time.Millisecond), numSpans) lastSpanID := traceID for j := 1; j <= numSpans; j++ { // The parent span is the predecessor. spanID := appdash.NewSpanID(lastSpanID) rec := appdash.NewRecorder(spanID, c) rec.Name(fakeNames[(j+int(i))%len(fakeNames)]) if j%3 == 0 { rec.Log("hello") } if j%5 == 0 { rec.Msg("hi") } // Generate a span event. spanDuration := time.Duration(times[j-1]) * time.Millisecond rec.Event(&sqltrace.SQLEvent{ ClientSend: startTime, ClientRecv: startTime.Add(spanDuration), SQL: "SELECT * FROM table_name;", Tag: fmt.Sprintf("fakeTag%d", rand.Intn(10)), }) // Shift the start time forward. startTime = startTime.Add(spanDuration) // Check for any recorder errors. if errs := rec.Errors(); len(errs) > 0 { return fmt.Errorf("recorder errors: %v", errs) } lastSpanID = spanID } } return nil }