Skip to content

Commit a35d464

Browse files
committed
Add optional time window for GetTrace & SearchTrace
Signed-off-by: Zhang Xin <[email protected]>
1 parent 86f2305 commit a35d464

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

cmd/query/app/http_handler.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,12 @@ func (aH *APIHandler) search(w http.ResponseWriter, r *http.Request) {
231231
var uiErrors []structuredError
232232
var tracesFromStorage []*model.Trace
233233
if len(tQuery.traceIDs) > 0 {
234-
tracesFromStorage, uiErrors, err = aH.tracesByIDs(r.Context(), tQuery.traceIDs)
234+
tracesFromStorage, uiErrors, err = aH.tracesByIDs(
235+
r.Context(),
236+
tQuery.traceIDs,
237+
tQuery.StartTimeMin,
238+
tQuery.StartTimeMax,
239+
)
235240
if aH.handleError(w, err, http.StatusInternalServerError) {
236241
return
237242
}
@@ -262,13 +267,14 @@ func (aH *APIHandler) tracesToResponse(traces []*model.Trace, adjust bool, uiErr
262267
}
263268
}
264269

265-
func (aH *APIHandler) tracesByIDs(ctx context.Context, traceIDs []model.TraceID) ([]*model.Trace, []structuredError, error) {
270+
func (aH *APIHandler) tracesByIDs(ctx context.Context, traceIDs []model.TraceID, startTime time.Time, endTime time.Time) ([]*model.Trace, []structuredError, error) {
266271
var traceErrors []structuredError
267272
retMe := make([]*model.Trace, 0, len(traceIDs))
268273
for _, traceID := range traceIDs {
269-
// TODO: add start time & end time
270274
query := spanstore.GetTraceParameters{
271-
TraceID: traceID,
275+
TraceID: traceID,
276+
StartTime: startTime,
277+
EndTime: endTime,
272278
}
273279
if trc, err := aH.queryService.GetTrace(ctx, query); err != nil {
274280
if !errors.Is(err, spanstore.ErrTraceNotFound) {
@@ -433,10 +439,21 @@ func (aH *APIHandler) getTrace(w http.ResponseWriter, r *http.Request) {
433439
if !ok {
434440
return
435441
}
436-
// TODO: add start time & end time
437442
query := spanstore.GetTraceParameters{
438443
TraceID: traceID,
439444
}
445+
startTime := r.FormValue(startTimeParam)
446+
if startTime != "" {
447+
// No need to handle err here, since time window is optional
448+
t, _ := aH.queryParser.parseTime(r, startTimeParam, time.Microsecond)
449+
query.StartTime = t
450+
}
451+
endTime := r.FormValue(endTimeParam)
452+
if endTime != "" {
453+
// No need to handle err here, since time window is optional
454+
t, _ := aH.queryParser.parseTime(r, endTimeParam, time.Microsecond)
455+
query.EndTime = t
456+
}
440457
trc, err := aH.queryService.GetTrace(r.Context(), query)
441458
if errors.Is(err, spanstore.ErrTraceNotFound) {
442459
aH.handleError(w, err, http.StatusNotFound)
@@ -466,9 +483,13 @@ func (aH *APIHandler) archiveTrace(w http.ResponseWriter, r *http.Request) {
466483
}
467484

468485
// QueryService.ArchiveTrace can now archive this traceID.
469-
// TODO: add start time & end time
486+
// No need to handle err here, since time window is optional
487+
startTime, _ := aH.queryParser.parseTime(r, startTimeParam, time.Microsecond)
488+
endTime, _ := aH.queryParser.parseTime(r, endTimeParam, time.Microsecond)
470489
query := spanstore.GetTraceParameters{
471-
TraceID: traceID,
490+
TraceID: traceID,
491+
StartTime: startTime,
492+
EndTime: endTime,
472493
}
473494
err := aH.queryService.ArchiveTrace(r.Context(), query)
474495
if errors.Is(err, spanstore.ErrTraceNotFound) {

cmd/query/app/http_handler_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,22 @@ func TestGetTraceDedupeSuccess(t *testing.T) {
198198
}
199199
}
200200

201+
func TestGetTraceWithTimeWindowSuccess(t *testing.T) {
202+
ts := initializeTestServer(t)
203+
start_time := time.Date(1970, time.January, 1, 0, 0, 0, 1000, time.UTC).Local()
204+
end_time := time.Date(1970, time.January, 1, 0, 0, 0, 2000, time.UTC).Local()
205+
ts.spanReader.On("GetTrace", mock.AnythingOfType("*context.valueCtx"), spanstore.GetTraceParameters{
206+
TraceID: model.TraceID{High: 0, Low: 0x123456},
207+
StartTime: start_time,
208+
EndTime: end_time,
209+
}).Return(mockTrace, nil).Once()
210+
211+
var response structuredResponse
212+
err := getJSON(ts.server.URL+`/api/traces/123456?start=1&end=2`, &response)
213+
require.NoError(t, err)
214+
assert.Empty(t, response.Errors)
215+
}
216+
201217
func TestLogOnServerError(t *testing.T) {
202218
zapCore, logs := observer.New(zap.InfoLevel)
203219
logger := zap.New(zapCore)
@@ -411,6 +427,24 @@ func TestSearchByTraceIDSuccess(t *testing.T) {
411427
assert.Len(t, response.Data, 2)
412428
}
413429

430+
func TestSearchByTraceIDWithTimeWindowSuccess(t *testing.T) {
431+
ts := initializeTestServer(t)
432+
expectedTraceId, _ := model.TraceIDFromString("1")
433+
expectedQuery := spanstore.GetTraceParameters{
434+
TraceID: expectedTraceId,
435+
StartTime: time.UnixMicro(1),
436+
EndTime: time.UnixMicro(2),
437+
}
438+
ts.spanReader.On("GetTrace", mock.AnythingOfType("*context.valueCtx"), expectedQuery).
439+
Return(mockTrace, nil)
440+
441+
var response structuredResponse
442+
err := getJSON(ts.server.URL+`/api/traces?traceID=1&start=1&end=2`, &response)
443+
require.NoError(t, err)
444+
assert.Empty(t, response.Errors)
445+
assert.Len(t, response.Data, 1)
446+
}
447+
414448
func TestSearchByTraceIDSuccessWithArchive(t *testing.T) {
415449
archiveReadMock := &spanstoremocks.Reader{}
416450
ts := initializeTestServerWithOptions(t, &tenancy.Manager{}, querysvc.QueryServiceOptions{
@@ -428,6 +462,29 @@ func TestSearchByTraceIDSuccessWithArchive(t *testing.T) {
428462
assert.Len(t, response.Data, 2)
429463
}
430464

465+
func TestSearchByTraceIDSuccessWithArchiveAndTimeWindow(t *testing.T) {
466+
archiveReadMock := &spanstoremocks.Reader{}
467+
ts := initializeTestServerWithOptions(t, &tenancy.Manager{}, querysvc.QueryServiceOptions{
468+
ArchiveSpanReader: archiveReadMock,
469+
})
470+
expectedTraceId, _ := model.TraceIDFromString("1")
471+
expectedQuery := spanstore.GetTraceParameters{
472+
TraceID: expectedTraceId,
473+
StartTime: time.UnixMicro(1),
474+
EndTime: time.UnixMicro(2),
475+
}
476+
ts.spanReader.On("GetTrace", mock.AnythingOfType("*context.valueCtx"), expectedQuery).
477+
Return(nil, spanstore.ErrTraceNotFound)
478+
archiveReadMock.On("GetTrace", mock.AnythingOfType("*context.valueCtx"), expectedQuery).
479+
Return(mockTrace, nil)
480+
481+
var response structuredResponse
482+
err := getJSON(ts.server.URL+`/api/traces?traceID=1&start=1&end=2`, &response)
483+
require.NoError(t, err)
484+
assert.Empty(t, response.Errors)
485+
assert.Len(t, response.Data, 1)
486+
}
487+
431488
func TestSearchByTraceIDNotFound(t *testing.T) {
432489
ts := initializeTestServer(t)
433490
ts.spanReader.On("GetTrace", mock.AnythingOfType("*context.valueCtx"), mock.AnythingOfType("spanstore.GetTraceParameters")).

0 commit comments

Comments
 (0)