Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow users to sort traces #8497

Merged
merged 25 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b08fa95
Add sorting on traces
ccschmitz May 7, 2024
14f8ab5
Fix sorting logic
ccschmitz May 7, 2024
45415b1
Clean up
ccschmitz May 7, 2024
bd426c0
Add direction back to pagination
ccschmitz May 7, 2024
aa29f01
Add direction back
ccschmitz May 7, 2024
e62e2d4
Avoid icon shrink
ccschmitz May 7, 2024
c11000d
Don't require sort props
ccschmitz May 7, 2024
ed2ec59
Fix type error
ccschmitz May 7, 2024
74daef8
Fix typo
ccschmitz May 7, 2024
9c41cfb
Don't show sort icon unless active
ccschmitz May 7, 2024
164fe91
Merge branch 'main' of github.com:highlight/highlight into hig-4572-a…
ccschmitz May 8, 2024
d321183
Update yarn.lock
ccschmitz May 8, 2024
a9cf3c9
Update .env
ccschmitz May 8, 2024
3d10379
Update opentelemetry-sdk-workers
ccschmitz May 8, 2024
34562c7
Merge branch 'main' of github.com:highlight/highlight into hig-4572-a…
ccschmitz May 9, 2024
6d69a6d
Update yarn.lock
ccschmitz May 9, 2024
d7f666b
Make sortColumn a SQL var
ccschmitz May 10, 2024
599a465
Merge branch 'main' of github.com:highlight/highlight into hig-4572-a…
ccschmitz May 10, 2024
3831843
Use helper to build order statements
ccschmitz May 10, 2024
fc19248
Update header icons and add sort options in dropdown
ccschmitz May 10, 2024
8d08f96
Update TracesList.tsx
ccschmitz May 10, 2024
471d003
Fix types
ccschmitz May 10, 2024
169882d
Fix interpolation and add tests
ccschmitz May 10, 2024
39ce594
Revert duration change
ccschmitz May 10, 2024
35f0373
Merge branch 'main' of github.com:highlight/highlight into hig-4572-a…
ccschmitz May 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 6 additions & 11 deletions backend/clickhouse/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package clickhouse
import (
"context"
"fmt"
"github.com/openlyinc/pointy"
"math"
"strings"
"time"

"github.com/openlyinc/pointy"

"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
e "github.com/pkg/errors"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -36,6 +37,7 @@ var logKeysToColumns = map[modelInputs.ReservedLogKey]string{
modelInputs.ReservedLogKeyServiceVersion: "ServiceVersion",
modelInputs.ReservedLogKeyEnvironment: "Environment",
modelInputs.ReservedLogKeyMessage: "Body",
modelInputs.ReservedLogKeyTimestamp: "Timestamp",
}

// These keys show up as recommendations, but with no recommended values due to high cardinality
Expand Down Expand Up @@ -198,9 +200,8 @@ func (client *Client) ReadSessionLogs(ctx context.Context, projectID int, params
selectCols,
[]int{projectID},
params,
Pagination{},
OrderBackwardInverted,
OrderForwardInverted)
Pagination{Direction: modelInputs.SortDirectionAsc},
)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -251,9 +252,7 @@ func (client *Client) ReadLogsTotalCount(ctx context.Context, projectID int, par
[]string{"COUNT(*)"},
[]int{projectID},
params,
Pagination{CountOnly: true},
OrderBackwardNatural,
OrderForwardNatural)
Pagination{CountOnly: true})
if err != nil {
return 0, err
}
Expand Down Expand Up @@ -340,8 +339,6 @@ func (client *Client) ReadLogsHistogram(ctx context.Context, projectID int, para
[]int{projectID},
params,
Pagination{CountOnly: true},
OrderBackwardNatural,
OrderForwardNatural,
)
} else {
fromSb, err = makeSelectBuilder(
Expand All @@ -350,8 +347,6 @@ func (client *Client) ReadLogsHistogram(ctx context.Context, projectID int, para
[]int{projectID},
params,
Pagination{CountOnly: true},
OrderBackwardNatural,
OrderForwardNatural,
)
}
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions backend/clickhouse/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ func setupTest(tb testing.TB) (*Client, func(tb testing.TB)) {

err = client.conn.Exec(context.Background(), fmt.Sprintf("TRUNCATE TABLE %s", TracesTable))
assert.NoError(tb, err)

err = client.conn.Exec(context.Background(), fmt.Sprintf("TRUNCATE TABLE %s", TracesSamplingTable))
assert.NoError(tb, err)
}
}

Expand Down
64 changes: 40 additions & 24 deletions backend/clickhouse/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,7 @@ func readObjects[TObj interface{}, TReservedKey ~string](ctx context.Context, cl
var err error
var args []interface{}

orderForward := OrderForwardNatural
orderBackward := OrderBackwardNatural
if pagination.Direction == modelInputs.SortDirectionAsc {
orderForward = OrderForwardInverted
orderBackward = OrderBackwardInverted
}
orderForward, _ := getSortOrders[TReservedKey](sb, pagination.Direction, config, params)

outerSelect := strings.Join(config.SelectColumns, ", ")
innerSelect := []string{"Timestamp", "UUID"}
Expand All @@ -58,9 +53,7 @@ func readObjects[TObj interface{}, TReservedKey ~string](ctx context.Context, cl
params,
Pagination{
Before: pagination.At,
},
orderBackward,
orderForward)
})
if err != nil {
return nil, err
}
Expand All @@ -73,9 +66,7 @@ func readObjects[TObj interface{}, TReservedKey ~string](ctx context.Context, cl
params,
Pagination{
At: pagination.At,
},
orderBackward,
orderForward)
})
if err != nil {
return nil, err
}
Expand All @@ -88,9 +79,7 @@ func readObjects[TObj interface{}, TReservedKey ~string](ctx context.Context, cl
params,
Pagination{
After: pagination.At,
},
orderBackward,
orderForward)
})
if err != nil {
return nil, err
}
Expand All @@ -109,9 +98,7 @@ func readObjects[TObj interface{}, TReservedKey ~string](ctx context.Context, cl
innerSelect,
[]int{projectID},
params,
pagination,
orderBackward,
orderForward)
pagination)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -163,11 +150,11 @@ func makeSelectBuilder[T ~string](
projectIDs []int,
params modelInputs.QueryInput,
pagination Pagination,
orderBackward string,
orderForward string,
) (*sqlbuilder.SelectBuilder, error) {
sb := sqlbuilder.NewSelectBuilder()

orderForward, orderBackward := getSortOrders[T](sb, pagination.Direction, config, params)

sb.Select(selectCols...)
sb.From(config.TableName)
sb.Where(sb.In("ProjectId", projectIDs))
Expand Down Expand Up @@ -612,8 +599,6 @@ func readWorkspaceMetrics[T ~string](ctx context.Context, client *Client, sample
projectIDs,
params,
Pagination{CountOnly: true},
OrderBackwardNatural,
OrderForwardNatural,
)

var col string
Expand Down Expand Up @@ -897,8 +882,6 @@ func logLines[T ~string](ctx context.Context, client *Client, tableConfig model.
[]int{projectID},
params,
Pagination{CountOnly: true},
OrderBackwardNatural,
OrderForwardNatural,
)
if err != nil {
return nil, err
Expand Down Expand Up @@ -961,3 +944,36 @@ func repr(val reflect.Value) string {
return val.String()
}
}

func getSortOrders[TReservedKey ~string](
sb *sqlbuilder.SelectBuilder,
paginationDirection modelInputs.SortDirection,
config model.TableConfig[TReservedKey],
params modelInputs.QueryInput,
) (string, string) {
sortColumn := "timestamp"
sortDirection := modelInputs.SortDirectionDesc
if params.Sort != nil {
sortColumn = params.Sort.Column
sortDirection = params.Sort.Direction
}

if col, found := config.KeysToColumns[TReservedKey(sortColumn)]; found {
sortColumn = col
} else {
sortColumn = fmt.Sprintf("%s[%s]", config.AttributesColumn, sb.Var(sortColumn))
ccschmitz marked this conversation as resolved.
Show resolved Hide resolved
}

forwardDirection := "DESC"
backwardDirection := "ASC"
if paginationDirection == modelInputs.SortDirectionAsc || sortDirection == modelInputs.SortDirectionAsc {
forwardDirection = "ASC"
} else {
backwardDirection = "DESC"
}

orderForward := fmt.Sprintf("%s %s, UUID %s", sortColumn, forwardDirection, forwardDirection)
orderBackward := fmt.Sprintf("%s %s, UUID %s", sortColumn, backwardDirection, backwardDirection)

return orderForward, orderBackward
}
4 changes: 2 additions & 2 deletions backend/clickhouse/trace_row.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ func (t *TraceRow) WithSpanKind(spanKind string) *TraceRow {
return t
}

func (t *TraceRow) WithDuration(startTime time.Time, endTime time.Time) *TraceRow {
t.Duration = int64(endTime.Sub(startTime).Nanoseconds())
func (t *TraceRow) WithDuration(duration time.Duration) *TraceRow {
t.Duration = duration.Nanoseconds()
return t
}

Expand Down
8 changes: 7 additions & 1 deletion backend/clickhouse/traces.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var traceKeysToColumns = map[modelInputs.ReservedTraceKey]string{
modelInputs.ReservedTraceKeyMetric: "Events.Attributes[1]['metric.name']",
modelInputs.ReservedTraceKeyEnvironment: "Environment",
modelInputs.ReservedTraceKeyHasErrors: "HasErrors",
modelInputs.ReservedTraceKeyTimestamp: "Timestamp",
}

var traceColumns = []string{
Expand Down Expand Up @@ -268,7 +269,12 @@ func (client *Client) ReadTraces(ctx context.Context, projectID int, params mode
}, nil
}

conn, err := readObjects(ctx, client, TracesTableConfig, projectID, params, pagination, scanTrace)
tableConfig := TracesTableConfig
if params.Sort != nil {
tableConfig = tracesSamplingTableConfig
}

conn, err := readObjects(ctx, client, tableConfig, projectID, params, pagination, scanTrace)
if err != nil {
return nil, err
}
Expand Down
49 changes: 49 additions & 0 deletions backend/clickhouse/traces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package clickhouse

import (
"context"
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -191,3 +192,51 @@ func TestReadTracesWithEnvironmentFilter(t *testing.T) {
assert.NoError(t, err)
assert.Len(t, payload.Edges, 2)
}

func TestReadTracesWithSorting(t *testing.T) {
ctx := context.Background()
client, teardown := setupTest(t)
defer teardown(t)

now := time.Now()
rows := []*ClickhouseTraceRow{
NewTraceRow(now, 1).WithSpanName("Span A").WithDuration(100).WithTraceAttributes(map[string]string{"host.name": "b"}).AsClickhouseTraceRow(),
NewTraceRow(now, 1).WithSpanName("Span B").WithDuration(300).WithTraceAttributes(map[string]string{"host.name": "c"}).AsClickhouseTraceRow(),
NewTraceRow(now, 1).WithSpanName("Span C").WithDuration(200).WithTraceAttributes(map[string]string{"host.name": "a"}).AsClickhouseTraceRow(),
}

assert.NoError(t, client.BatchWriteTraceRows(ctx, rows))

payload, err := client.ReadTraces(ctx, 1, modelInputs.QueryInput{
DateRange: makeDateWithinRange(now),
Query: "",
Sort: &modelInputs.SortInput{
Column: "duration",
Direction: "DESC",
},
}, Pagination{})
assert.NoError(t, err)
assert.Len(t, payload.Edges, 3)

assert.Equal(t, "Span B", payload.Edges[0].Node.SpanName)
assert.Equal(t, "Span C", payload.Edges[1].Node.SpanName)
assert.Equal(t, "Span A", payload.Edges[2].Node.SpanName)

payload, err = client.ReadTraces(ctx, 1, modelInputs.QueryInput{
DateRange: makeDateWithinRange(now),
Query: "",
Sort: &modelInputs.SortInput{
Column: "host.name",
Direction: "DESC",
},
}, Pagination{})
assert.NoError(t, err)
assert.Len(t, payload.Edges, 3)

for i, edge := range payload.Edges {
fmt.Printf("Edge %d: %v\n", i, edge.Node)
}
assert.Equal(t, "Span B", payload.Edges[0].Node.SpanName)
assert.Equal(t, "Span A", payload.Edges[1].Node.SpanName)
assert.Equal(t, "Span C", payload.Edges[2].Node.SpanName)
}