Skip to content

Commit

Permalink
feat: search traces by column, attributes and resources #290
Browse files Browse the repository at this point in the history
  • Loading branch information
sunface committed Nov 4, 2023
1 parent f502cff commit 8ada905
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 31 deletions.
40 changes: 21 additions & 19 deletions query/internal/plugins/builtin/datav/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,28 @@ import (
)

const (
TestDatasourceAPI = "testDatasource"
GetServiceInfoListAPI = "getServiceInfoList"
GetNamespacesAPI = "getNamespaces"
GetServiceNamesAPI = "getServiceNames"
GetServiceOperationsAPI = "getServiceOperations"
GetDependencyGraphAPI = "getDependencyGraph"
GetLogsAPI = "getLogs"
GetTracesAPI = "getTraces"
GetTraceAPI = "getTrace"
GetTraceTagKeysAPI = "getTraceTagKeys"
TestDatasourceAPI = "testDatasource"
GetServiceInfoListAPI = "getServiceInfoList"
GetNamespacesAPI = "getNamespaces"
GetServiceNamesAPI = "getServiceNames"
GetServiceOperationsAPI = "getServiceOperations"
GetServiceRootOperationsAPI = "getServiceRootOperations"
GetDependencyGraphAPI = "getDependencyGraph"
GetLogsAPI = "getLogs"
GetTracesAPI = "getTraces"
GetTraceAPI = "getTrace"
GetTraceTagKeysAPI = "getTraceTagKeys"
)

var APIRoutes = map[string]func(c *gin.Context, ds *models.Datasource, conn ch.Conn, params map[string]interface{}) models.PluginResult{
GetServiceInfoListAPI: GetServiceInfoList,
GetNamespacesAPI: GetNamespaces,
GetServiceNamesAPI: GetServiceNames,
GetServiceOperationsAPI: GetServiceOperations,
GetLogsAPI: GetLogs,
GetDependencyGraphAPI: GetDependencyGraph,
GetTracesAPI: GetTraces,
GetTraceAPI: GetTrace,
GetTraceTagKeysAPI: GetTraceTagKeys,
GetServiceInfoListAPI: GetServiceInfoList,
GetNamespacesAPI: GetNamespaces,
GetServiceNamesAPI: GetServiceNames,
GetServiceOperationsAPI: GetServiceOperations,
GetServiceRootOperationsAPI: GetServiceRootOperations,
GetLogsAPI: GetLogs,
GetDependencyGraphAPI: GetDependencyGraph,
GetTracesAPI: GetTraces,
GetTraceAPI: GetTrace,
GetTraceTagKeysAPI: GetTraceTagKeys,
}
27 changes: 27 additions & 0 deletions query/internal/plugins/builtin/datav/api/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,33 @@ func GetServiceOperations(c *gin.Context, ds *models.Datasource, conn ch.Conn, p
return models.GenPluginResult(models.PluginStatusSuccess, "", res)
}

func GetServiceRootOperations(c *gin.Context, ds *models.Datasource, conn ch.Conn, params map[string]interface{}) models.PluginResult {
tenant := models.DefaultTenant
domainQuery := datavutils.BuildBasicDomainQuery(tenant, params)

service := datavutils.GetValueListFromParams(params, "service")
if service != nil {
domainQuery += fmt.Sprintf(" AND serviceName in ('%s')", strings.Join(service, "','"))
}

query := fmt.Sprintf("SELECT DISTINCT name FROM %s.%s WHERE %s", config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTopLevelOperationsTable, domainQuery)
rows, err := conn.Query(c.Request.Context(), query)
if err != nil {
logger.Warn("Error Query service operations", "query", query, "error", err)
return models.GenPluginResult(models.PluginStatusError, err.Error(), nil)
}
defer rows.Close()

logger.Info("Query service operations", "query", query)

res, err := pluginUtils.ConvertDbRowsToPluginData(rows)
if err != nil {
return models.GenPluginResult(models.PluginStatusError, err.Error(), nil)
}

return models.GenPluginResult(models.PluginStatusSuccess, "", res)
}

type ServiceInfo struct {
ServiceName string
P99 float64
Expand Down
23 changes: 19 additions & 4 deletions query/internal/plugins/builtin/datav/api/traces.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ func GetTraces(c *gin.Context, ds *models.Datasource, conn ch.Conn, params map[s
domainQuery += fmt.Sprintf(" AND serviceName='%s'", service)

var operationNameQuery string
var operationNameQuery1 string
if operation == "" || operation == models.VarialbeAllOption {
// if min > 0 || max > 0 || rawTags != "" {
query := fmt.Sprintf("select name from %s.%s where %s", config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTopLevelOperationsTable, domainQuery)
Expand All @@ -58,8 +57,8 @@ func GetTraces(c *gin.Context, ds *models.Datasource, conn ch.Conn, params map[s

} else {
operationNameQuery = fmt.Sprintf(" AND name='%s'", operation)
operationNameQuery1 = operationNameQuery
}
domainQuery += operationNameQuery

var durationQuery string
if min != 0 {
Expand Down Expand Up @@ -93,6 +92,22 @@ func GetTraces(c *gin.Context, ds *models.Datasource, conn ch.Conn, params map[s
} else {
domainQuery += fmt.Sprintf(" AND resourcesMap['%s'] = '%s'", realKey, v)
}
} else {
if v == models.VarialbeAllOption {
domainQuery += fmt.Sprintf(" AND %s != ''", k)
} else {
switch v.(type) {
case string:
domainQuery += fmt.Sprintf(" AND %s = '%s'", k, v)
case float64:
domainQuery += fmt.Sprintf(" AND %s = %f", k, v)
case bool:
domainQuery += fmt.Sprintf(" AND %s = %t", k, v)
default:
domainQuery += fmt.Sprintf(" AND %s = '%s'", k, v)
}

}
}
}

Expand All @@ -105,7 +120,7 @@ func GetTraces(c *gin.Context, ds *models.Datasource, conn ch.Conn, params map[s
if traceIds != "" {
query = fmt.Sprintf("SELECT startTime as ts,serviceName,name,traceId, duration as maxDuration FROM %s.%s WHERE traceId in ('%s') AND parentId=''", config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTraceIndexTable, strings.Join(strings.Split(traceIds, ","), "','"))
} else if service != "" {
query0 := fmt.Sprintf("SELECT DISTINCT traceId FROM %s.%s WHERE startTime >= %d AND startTime <= %d AND %s ORDER BY startTime DESC limit %d", config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTraceIndexTable, start*1e9, end*1e9, domainQuery+operationNameQuery, limit)
query0 := fmt.Sprintf("SELECT DISTINCT traceId FROM %s.%s WHERE startTime >= %d AND startTime <= %d AND %s ORDER BY startTime DESC limit %d", config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTraceIndexTable, start*1e9, end*1e9, domainQuery, limit)
query = fmt.Sprintf("SELECT min(startTime) as ts,serviceName,name,traceId,max(duration) as maxDuration FROM %s.%s WHERE traceId in (%s) AND serviceName='%s' %s %s GROUP BY serviceName,name,traceId", config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTraceIndexTable, query0, service, operationNameQuery, durationQuery)
} else {
query = fmt.Sprintf("SELECT startTime as ts,serviceName,name,traceId, duration as maxDuration FROM %s.%s WHERE tartTime >= %d AND startTime <= %d AND %s AND parentId='' ORDER BY ts DESC limit %d", config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTraceIndexTable, start*1e9, end*1e9, domainQuery, limit)
Expand Down Expand Up @@ -272,7 +287,7 @@ func GetTraces(c *gin.Context, ds *models.Datasource, conn ch.Conn, params map[s
aggregateQuery = "round(quantile(0.99)(duration) / 1e6,2) as p99"
}

metricsQuery := fmt.Sprintf("SELECT toStartOfInterval(fromUnixTimestamp64Nano(startTime), INTERVAL %d SECOND) AS ts_bucket, %s %s from %s.%s where (startTime >= %d AND startTime <= %d AND %s) group by %s order by ts_bucket", step, groupby, aggregateQuery, config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTraceIndexTable, start*1e9, end*1e9, domainQuery+operationNameQuery1, groupBy)
metricsQuery := fmt.Sprintf("SELECT toStartOfInterval(fromUnixTimestamp64Nano(startTime), INTERVAL %d SECOND) AS ts_bucket, %s %s from %s.%s where (startTime >= %d AND startTime <= %d AND %s) group by %s order by ts_bucket", step, groupby, aggregateQuery, config.Data.Observability.DefaultTraceDB, datavmodels.DefaultTraceIndexTable, start*1e9, end*1e9, domainQuery, groupBy)

rows, err := conn.Query(c.Request.Context(), metricsQuery)
if err != nil {
Expand Down
8 changes: 0 additions & 8 deletions ui/src/views/dashboard/plugins/built-in/panel/trace/Trace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,5 @@ export function convTagsLogfmt(tags) {


const data = logfmtParser.parse(tags);
Object.keys(data).forEach(key => {
const value = data[key];
// make sure all values are strings
// https://github.com/jaegertracing/jaeger/issues/550#issuecomment-352850811
if (typeof value !== 'string') {
data[key] = String(value);
}
});
return JSON.stringify(data);
}

0 comments on commit 8ada905

Please sign in to comment.