mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 17:35:55 +08:00
Feat trace ordering on the basis of span_count or Trace_duration (#7842)
* feat: added order by span_count in traces tab * feat: added order by span_count in traces tab * feat: added order by span_count in traces tab * feat: added order by span_count in traces tab * feat: added order by span_count in traces tab * feat: added order by span_count in traces tab --------- Co-authored-by: Nityananda Gohain <nityanandagohain@gmail.com>
This commit is contained in:
parent
224f952da7
commit
503e4cdf00
@ -292,12 +292,31 @@ func buildTracesQuery(start, end, step int64, mq *v3.BuilderQuery, panelType v3.
|
|||||||
if mq.AggregateOperator == v3.AggregateOperatorNoOp {
|
if mq.AggregateOperator == v3.AggregateOperatorNoOp {
|
||||||
var query string
|
var query string
|
||||||
if panelType == v3.PanelTypeTrace {
|
if panelType == v3.PanelTypeTrace {
|
||||||
withSubQuery := fmt.Sprintf(constants.TracesExplorerViewSQLSelectWithSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3_LOCAL_TABLENAME, timeFilter)
|
if len(mq.OrderBy) > 1 {
|
||||||
afterSubQuery := tracesV3.AddLimitToQuery(constants.TracesExplorerViewSQLSelectAfterSubQuery, mq.Limit)
|
return "", fmt.Errorf("multiple orderBy criteria are not supported for trace queries")
|
||||||
if mq.Offset != 0 {
|
}
|
||||||
afterSubQuery = tracesV3.AddOffsetToQuery(afterSubQuery, mq.Offset)
|
orderBySpanCount := false
|
||||||
|
|
||||||
|
// Check if orderBy contains a specific reference to span_count
|
||||||
|
if len(mq.OrderBy) == 1 && mq.OrderBy[0].ColumnName == constants.OrderBySpanCount {
|
||||||
|
orderBySpanCount = true
|
||||||
|
}
|
||||||
|
if !orderBySpanCount {
|
||||||
|
withSubQuery := fmt.Sprintf(constants.TracesExplorerViewSQLSelectWithSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3_LOCAL_TABLENAME, timeFilter)
|
||||||
|
afterSubQuery := tracesV3.AddLimitToQuery(constants.TracesExplorerViewSQLSelectAfterSubQuery, mq.Limit)
|
||||||
|
if mq.Offset != 0 {
|
||||||
|
afterSubQuery = tracesV3.AddOffsetToQuery(afterSubQuery, mq.Offset)
|
||||||
|
}
|
||||||
|
query = fmt.Sprintf(constants.TracesExplorerViewSQLSelectBeforeSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3) + withSubQuery + ") " + fmt.Sprintf(afterSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3, timeFilter, filterSubQuery)
|
||||||
|
} else {
|
||||||
|
withSubQueryWithLimits := tracesV3.AddLimitToQuery(constants.TracesExplorerSpanCountWithSubQuery, mq.Limit)
|
||||||
|
withSubQuery := fmt.Sprintf(withSubQueryWithLimits, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3_LOCAL_TABLENAME, timeFilter, filterSubQuery)
|
||||||
|
afterSubQuery := tracesV3.AddLimitToQuery(constants.TraceExplorerSpanCountAfterSubQuery, mq.Limit)
|
||||||
|
if mq.Offset != 0 {
|
||||||
|
afterSubQuery = tracesV3.AddOffsetToQuery(afterSubQuery, mq.Offset)
|
||||||
|
}
|
||||||
|
query = fmt.Sprintf(constants.TraceExplorerSpanCountBeforeSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3) + withSubQuery + ") " + fmt.Sprintf(afterSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3, timeFilter)
|
||||||
}
|
}
|
||||||
query = fmt.Sprintf(constants.TracesExplorerViewSQLSelectBeforeSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3) + withSubQuery + ") " + fmt.Sprintf(afterSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3, timeFilter, filterSubQuery)
|
|
||||||
// adding this to avoid the distributed product mode error which doesn't allow global in
|
// adding this to avoid the distributed product mode error which doesn't allow global in
|
||||||
query += " settings distributed_product_mode='allow', max_memory_usage=10000000000"
|
query += " settings distributed_product_mode='allow', max_memory_usage=10000000000"
|
||||||
} else if panelType == v3.PanelTypeList {
|
} else if panelType == v3.PanelTypeList {
|
||||||
|
@ -655,6 +655,56 @@ func Test_buildTracesQuery(t *testing.T) {
|
|||||||
"(seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'myService' AND labels like '%service.name%myService%')) GROUP BY subQuery.traceID, subQuery.durationNano, subQuery.name, subQuery.serviceName ORDER BY " +
|
"(seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'myService' AND labels like '%service.name%myService%')) GROUP BY subQuery.traceID, subQuery.durationNano, subQuery.name, subQuery.serviceName ORDER BY " +
|
||||||
"subQuery.durationNano desc LIMIT 1 BY subQuery.traceID LIMIT 100 settings distributed_product_mode='allow', max_memory_usage=10000000000",
|
"subQuery.durationNano desc LIMIT 1 BY subQuery.traceID LIMIT 100 settings distributed_product_mode='allow', max_memory_usage=10000000000",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "test noop trace view with span_count ordering of Traces",
|
||||||
|
args: args{
|
||||||
|
panelType: v3.PanelTypeTrace,
|
||||||
|
start: 1680066360726210000,
|
||||||
|
end: 1680066458000000000,
|
||||||
|
mq: &v3.BuilderQuery{
|
||||||
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
||||||
|
OrderBy: []v3.OrderBy{{ColumnName: "span_count", Order: "DESC"}},
|
||||||
|
Filters: &v3.FilterSet{
|
||||||
|
Items: []v3.FilterItem{
|
||||||
|
{Key: v3.AttributeKey{Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: "GET", Operator: "="},
|
||||||
|
{Key: v3.AttributeKey{Key: "service.name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource}, Value: "myService", Operator: "="},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: "SELECT serviceName, name, subQuery.span_count as span_count, durationNano, trace_id as traceID from signoz_traces.distributed_signoz_index_v3 GLOBAL INNER JOIN " +
|
||||||
|
"( SELECT * FROM (SELECT trace_id, count() as span_count FROM signoz_traces.signoz_index_v3 WHERE (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||||
|
"AND attributes_string['method'] = 'GET' AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM signoz_traces.distributed_traces_v3_resource WHERE " +
|
||||||
|
"(seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'myService' AND labels like '%service.name%myService%')) " +
|
||||||
|
"GROUP BY trace_id ORDER BY span_count DESC LIMIT 1 BY trace_id LIMIT 100) AS inner_subquery ) AS subQuery ON signoz_traces.distributed_signoz_index_v3.trace_id = subQuery.trace_id " +
|
||||||
|
"WHERE parent_span_id = '' AND (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||||
|
"ORDER BY subQuery.span_count DESC LIMIT 100 settings distributed_product_mode='allow', max_memory_usage=10000000000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test noop trace view with trace_duration ordering of Traces",
|
||||||
|
args: args{
|
||||||
|
panelType: v3.PanelTypeTrace,
|
||||||
|
start: 1680066360726210000,
|
||||||
|
end: 1680066458000000000,
|
||||||
|
mq: &v3.BuilderQuery{
|
||||||
|
AggregateOperator: v3.AggregateOperatorNoOp,
|
||||||
|
OrderBy: []v3.OrderBy{{ColumnName: "timestamp", Order: "DESC"}},
|
||||||
|
Filters: &v3.FilterSet{
|
||||||
|
Items: []v3.FilterItem{
|
||||||
|
{Key: v3.AttributeKey{Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: "GET", Operator: "="},
|
||||||
|
{Key: v3.AttributeKey{Key: "service.name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeResource}, Value: "myService", Operator: "="},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: "SELECT subQuery.serviceName, subQuery.name, count() AS span_count, subQuery.durationNano, subQuery.traceID AS traceID FROM signoz_traces.distributed_signoz_index_v3 INNER JOIN " +
|
||||||
|
"( SELECT * FROM (SELECT traceID, durationNano, serviceName, name FROM signoz_traces.signoz_index_v3 WHERE parentSpanID = '' AND (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND " +
|
||||||
|
"(ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||||
|
"ORDER BY durationNano DESC LIMIT 1 BY traceID) AS inner_subquery ) AS subQuery ON signoz_traces.distributed_signoz_index_v3.traceID = subQuery.traceID WHERE (timestamp >= '1680066360726210000' AND " +
|
||||||
|
"timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['method'] = 'GET' AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM signoz_traces.distributed_traces_v3_resource WHERE " +
|
||||||
|
"(seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'myService' AND labels like '%service.name%myService%')) GROUP BY subQuery.traceID, subQuery.durationNano, subQuery.name, subQuery.serviceName ORDER BY " +
|
||||||
|
"subQuery.durationNano desc LIMIT 1 BY subQuery.traceID LIMIT 100 settings distributed_product_mode='allow', max_memory_usage=10000000000",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Test order by value with having",
|
name: "Test order by value with having",
|
||||||
args: args{
|
args: args{
|
||||||
|
@ -46,6 +46,7 @@ const LogsTTL = "logs"
|
|||||||
|
|
||||||
const SpanSearchScopeRoot = "isroot"
|
const SpanSearchScopeRoot = "isroot"
|
||||||
const SpanSearchScopeEntryPoint = "isentrypoint"
|
const SpanSearchScopeEntryPoint = "isentrypoint"
|
||||||
|
const OrderBySpanCount = "span_count"
|
||||||
|
|
||||||
var TELEMETRY_HEART_BEAT_DURATION_MINUTES = GetOrDefaultEnvInt("TELEMETRY_HEART_BEAT_DURATION_MINUTES", 720)
|
var TELEMETRY_HEART_BEAT_DURATION_MINUTES = GetOrDefaultEnvInt("TELEMETRY_HEART_BEAT_DURATION_MINUTES", 720)
|
||||||
|
|
||||||
@ -256,6 +257,9 @@ const (
|
|||||||
TracesExplorerViewSQLSelectQuery = "SELECT subQuery.serviceName, subQuery.name, count() AS " +
|
TracesExplorerViewSQLSelectQuery = "SELECT subQuery.serviceName, subQuery.name, count() AS " +
|
||||||
"span_count, subQuery.durationNano, traceID FROM %s.%s GLOBAL INNER JOIN subQuery ON %s.traceID = subQuery.traceID GROUP " +
|
"span_count, subQuery.durationNano, traceID FROM %s.%s GLOBAL INNER JOIN subQuery ON %s.traceID = subQuery.traceID GROUP " +
|
||||||
"BY traceID, subQuery.durationNano, subQuery.name, subQuery.serviceName ORDER BY subQuery.durationNano desc;"
|
"BY traceID, subQuery.durationNano, subQuery.name, subQuery.serviceName ORDER BY subQuery.durationNano desc;"
|
||||||
|
TracesExplorerSpanCountWithSubQuery = "(SELECT trace_id, count() as span_count FROM %s.%s WHERE %s %s GROUP BY trace_id ORDER BY span_count DESC LIMIT 1 BY trace_id"
|
||||||
|
TraceExplorerSpanCountBeforeSubQuery = "SELECT serviceName, name, subQuery.span_count as span_count, durationNano, trace_id as traceID from %s.%s GLOBAL INNER JOIN ( SELECT * FROM "
|
||||||
|
TraceExplorerSpanCountAfterSubQuery = "AS inner_subquery ) AS subQuery ON %s.%s.trace_id = subQuery.trace_id WHERE parent_span_id = '' AND %s ORDER BY subQuery.span_count DESC"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReservedColumnTargetAliases identifies result value from a user
|
// ReservedColumnTargetAliases identifies result value from a user
|
||||||
|
Loading…
x
Reference in New Issue
Block a user