Example #1
0
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
}
Example #2
0
func getSpanID(h http.Header) (spanID *appdash.SpanID, fromHeader string, err error) {
	// Check for Span-ID.
	fromHeader = HeaderSpanID
	spanID, err = getSpanIDHeader(h, HeaderSpanID)
	if err != nil {
		return nil, fromHeader, err
	}

	// Check for Parent-Span-ID.
	if spanID == nil {
		fromHeader = HeaderParentSpanID
		spanID, err = getSpanIDHeader(h, HeaderParentSpanID)
		if err != nil {
			return nil, fromHeader, err
		}
		if spanID != nil {
			newSpanID := appdash.NewSpanID(*spanID)
			spanID = &newSpanID
		}
	}

	// Create a new root span ID.
	if spanID == nil {
		fromHeader = ""
		newSpanID := appdash.NewRootSpanID()
		spanID = &newSpanID
	}
	return spanID, fromHeader, nil
}
Example #3
0
// RoundTrip implements the RoundTripper interface.
func (t *Transport) RoundTrip(original *http.Request) (*http.Response, error) {
	// To set extra querystring params, we must make a copy of the Request so
	// that we don't modify the Request we were given. This is required by the
	// specification of http.RoundTripper.
	req := cloneRequest(original)
	t.setCloneRequest(original, req)
	defer t.setCloneRequest(original, nil)

	child := t.Recorder.Child()
	if t.SetName {
		child.Name("Request " + req.URL.Host)
	}

	// New child span is created and set as HTTP header instead of using `child`
	// in order to have a single span recording operation per httptrace event
	// (HTTPClient or HTTPServer).
	span := appdash.NewSpanID(t.Recorder.SpanID)

	SetSpanIDHeader(req.Header, span)

	e := NewClientEvent(req)
	e.ClientSend = time.Now()

	// Make the HTTP request.
	transport := t.getTransport()
	resp, err := transport.RoundTrip(req)

	e.ClientRecv = time.Now()
	if err == nil {
		e.Response = responseInfo(resp)
	} else {
		e.Response.StatusCode = -1
	}
	child.Event(e)
	child.Finish()
	return resp, err
}