| 546 | } |
| 547 | |
| 548 | func searchTraceql(client httpclient.TempoHTTPClient, seed time.Time, config vultureConfiguration, l *zap.Logger) (traceMetrics, error) { |
| 549 | tm := traceMetrics{ |
| 550 | requested: 1, |
| 551 | } |
| 552 | |
| 553 | info := util.NewTraceInfo(seed, config.tempoOrgID) |
| 554 | hexID := info.HexID() |
| 555 | |
| 556 | // Get the expected |
| 557 | expected, err := info.ConstructTraceFromEpoch() |
| 558 | if err != nil { |
| 559 | l.Error("unable to construct trace from epoch", zap.Error(err)) |
| 560 | return traceMetrics{}, err |
| 561 | } |
| 562 | |
| 563 | attr := util.RandomAttrFromTrace(expected) |
| 564 | if attr == nil { |
| 565 | tm.notFoundSearchAttribute++ |
| 566 | return tm, fmt.Errorf("no search attr selected from trace") |
| 567 | } |
| 568 | |
| 569 | logger := l.With( |
| 570 | zap.Int64("seed", seed.Unix()), |
| 571 | zap.String("hexID", hexID), |
| 572 | zap.Duration("ago", time.Since(seed)), |
| 573 | zap.String("key", attr.Key), |
| 574 | zap.String("value", util.StringifyAnyValue(attr.Value)), |
| 575 | ) |
| 576 | logger.Info("searching Tempo via traceql") |
| 577 | |
| 578 | start := seed.Add(-30 * time.Minute).Unix() |
| 579 | end := seed.Add(30 * time.Minute).Unix() |
| 580 | resp, err := client.SearchTraceQLWithRange(fmt.Sprintf(`{.%s = "%s"}`, attr.Key, util.StringifyAnyValue(attr.Value)), start, end) |
| 581 | if err != nil { |
| 582 | logger.Error(fmt.Sprintf("failed to search traces with traceql %s: %s", attr.Key, err.Error())) |
| 583 | tm.requestFailed++ |
| 584 | return tm, err |
| 585 | } |
| 586 | |
| 587 | if !traceInTraces(hexID, resp.Traces) { |
| 588 | tm.notFoundTraceQL++ |
| 589 | return tm, fmt.Errorf("trace %s not found in search traceql response: %+v", hexID, resp.Traces) |
| 590 | } |
| 591 | |
| 592 | return tm, nil |
| 593 | } |
| 594 | |
| 595 | func queryTrace(client httpclient.TempoHTTPClient, info *util.TraceInfo, l *zap.Logger) (traceMetrics, error) { |
| 596 | tm := traceMetrics{ |